00001 // non fixed Opengl pipeline rendering 00002 // 00003 // Written by Harald JOHNSEN, started Jully 2005. 00004 // 00005 // Copyright (C) 2005 Harald JOHNSEN 00006 // 00007 // This program is free software; you can redistribute it and/or 00008 // modify it under the terms of the GNU General Public License as 00009 // published by the Free Software Foundation; either version 2 of the 00010 // License, or (at your option) any later version. 00011 // 00012 // This program is distributed in the hope that it will be useful, but 00013 // WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 // General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU General Public License 00018 // along with this program; if not, write to the Free Software 00019 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00020 // 00021 // 00022 00023 #ifdef HAVE_CONFIG_H 00024 # include <simgear_config.h> 00025 #endif 00026 00027 #include <map> 00028 00029 #include <osg/Group> 00030 #include <osg/Program> 00031 #include <osg/Shader> 00032 #include <osg/StateSet> 00033 #include <osg/TextureCubeMap> 00034 #include <osg/TexEnvCombine> 00035 #include <osg/TexGen> 00036 #include <osg/Texture1D> 00037 #include <osgUtil/HighlightMapGenerator> 00038 00039 #include <OpenThreads/Mutex> 00040 #include <OpenThreads/ScopedLock> 00041 00042 #include <simgear/scene/util/SGUpdateVisitor.hxx> 00043 00044 #include <simgear/props/condition.hxx> 00045 #include <simgear/props/props.hxx> 00046 00047 #include <simgear/debug/logstream.hxx> 00048 00049 #include "animation.hxx" 00050 #include "model.hxx" 00051 00052 using OpenThreads::Mutex; 00053 using OpenThreads::ScopedLock; 00054 00055 /* 00056 <animation> 00057 <type>shader</type> 00058 <shader>fresnel</shader> 00059 <object-name>...</object-name> 00060 </animation> 00061 00062 <animation> 00063 <type>shader</type> 00064 <shader>heat-haze</shader> 00065 <object-name>...</object-name> 00066 <speed>...</speed> 00067 <speed-prop>...</speed-prop> 00068 <factor>...</factor> 00069 <factor-prop>...</factor-prop> 00070 </animation> 00071 00072 <animation> 00073 <type>shader</type> 00074 <shader>chrome</shader> 00075 <texture>...</texture> 00076 <object-name>...</object-name> 00077 </animation> 00078 00079 <animation> 00080 <type>shader</type> 00081 <shader></shader> 00082 <object-name>...</object-name> 00083 <depth-test>false</depth-test> 00084 </animation> 00085 00086 */ 00087 00088 00089 class SGMapGenCallback : 00090 public osg::StateAttribute::Callback { 00091 public: 00092 virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv) 00093 { 00094 SGUpdateVisitor* updateVisitor = dynamic_cast<SGUpdateVisitor*>(nv); 00095 if (!updateVisitor) 00096 return; 00097 00098 if (distSqr(_lastLightDirection, updateVisitor->getLightDirection()) < 1e-4 00099 && distSqr(_lastLightColor, updateVisitor->getAmbientLight()) < 1e-4) 00100 return; 00101 00102 _lastLightDirection = updateVisitor->getLightDirection(); 00103 _lastLightColor = updateVisitor->getAmbientLight(); 00104 00105 osg::TextureCubeMap *tcm = static_cast<osg::TextureCubeMap*>(sa); 00106 00107 // FIXME: need an update or callback ... 00108 // generate the six highlight map images (light direction = [1, 1, -1]) 00109 osg::ref_ptr<osgUtil::HighlightMapGenerator> mapgen; 00110 mapgen = new osgUtil::HighlightMapGenerator(toOsg(_lastLightDirection), 00111 toOsg(_lastLightColor), 5); 00112 mapgen->generateMap(); 00113 00114 // assign the six images to the texture object 00115 tcm->setImage(osg::TextureCubeMap::POSITIVE_X, 00116 mapgen->getImage(osg::TextureCubeMap::POSITIVE_X)); 00117 tcm->setImage(osg::TextureCubeMap::NEGATIVE_X, 00118 mapgen->getImage(osg::TextureCubeMap::NEGATIVE_X)); 00119 tcm->setImage(osg::TextureCubeMap::POSITIVE_Y, 00120 mapgen->getImage(osg::TextureCubeMap::POSITIVE_Y)); 00121 tcm->setImage(osg::TextureCubeMap::NEGATIVE_Y, 00122 mapgen->getImage(osg::TextureCubeMap::NEGATIVE_Y)); 00123 tcm->setImage(osg::TextureCubeMap::POSITIVE_Z, 00124 mapgen->getImage(osg::TextureCubeMap::POSITIVE_Z)); 00125 tcm->setImage(osg::TextureCubeMap::NEGATIVE_Z, 00126 mapgen->getImage(osg::TextureCubeMap::NEGATIVE_Z)); 00127 } 00128 private: 00129 SGVec3f _lastLightDirection; 00130 SGVec4f _lastLightColor; 00131 }; 00132 00133 static Mutex cubeMutex; 00134 00135 #if 0 00136 static osg::TextureCubeMap* 00137 getOrCreateTextureCubeMap() 00138 { 00139 static osg::ref_ptr<osg::TextureCubeMap> textureCubeMap; 00140 if (textureCubeMap.get()) 00141 return textureCubeMap.get(); 00142 00143 ScopedLock<Mutex> lock(cubeMutex); 00144 if (textureCubeMap.get()) 00145 return textureCubeMap.get(); 00146 00147 // create and setup the texture object 00148 textureCubeMap = new osg::TextureCubeMap; 00149 00150 textureCubeMap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP); 00151 textureCubeMap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP); 00152 textureCubeMap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP); 00153 textureCubeMap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR); 00154 textureCubeMap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); 00155 00156 textureCubeMap->setUpdateCallback(new SGMapGenCallback); 00157 00158 return textureCubeMap.get(); 00159 } 00160 00161 static void create_specular_highlights(osg::Node *node) 00162 { 00163 osg::StateSet *ss = node->getOrCreateStateSet(); 00164 00165 // create and setup the texture object 00166 osg::TextureCubeMap *tcm = getOrCreateTextureCubeMap(); 00167 00168 // enable texturing, replacing any textures in the subgraphs 00169 ss->setTextureAttributeAndModes(0, tcm, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON); 00170 00171 // texture coordinate generation 00172 osg::TexGen *tg = new osg::TexGen; 00173 tg->setMode(osg::TexGen::REFLECTION_MAP); 00174 ss->setTextureAttributeAndModes(0, tg, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON); 00175 00176 // use TexEnvCombine to add the highlights to the original lighting 00177 osg::TexEnvCombine *te = new osg::TexEnvCombine; 00178 te->setCombine_RGB(osg::TexEnvCombine::ADD); 00179 te->setSource0_RGB(osg::TexEnvCombine::TEXTURE); 00180 te->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR); 00181 te->setSource1_RGB(osg::TexEnvCombine::PRIMARY_COLOR); 00182 te->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR); 00183 ss->setTextureAttributeAndModes(0, te, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON); 00184 } 00185 #endif 00186 00187 00188 SGShaderAnimation::SGShaderAnimation(const SGPropertyNode* configNode, 00189 SGPropertyNode* modelRoot, 00190 const osgDB::ReaderWriter::Options* 00191 options) : 00192 SGAnimation(configNode, modelRoot) 00193 { 00194 const SGPropertyNode* node = configNode->getChild("texture"); 00195 if (node) 00196 _effect_texture = SGLoadTexture2D(node->getStringValue(), options); 00197 } 00198 00199 namespace { 00200 class ChromeLightingCallback : 00201 public osg::StateAttribute::Callback { 00202 public: 00203 virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv) 00204 { 00205 SGUpdateVisitor* updateVisitor = dynamic_cast<SGUpdateVisitor*>(nv); 00206 if (!updateVisitor) 00207 return; 00208 osg::TexEnvCombine *combine = dynamic_cast<osg::TexEnvCombine *>(sa); 00209 if (!combine) 00210 return; 00211 // An approximation for light reflected back by chrome. 00212 osg::Vec4 globalColor = toOsg(updateVisitor->getAmbientLight() * .4f 00213 + updateVisitor->getDiffuseLight()); 00214 globalColor.a() = 1.0f; 00215 combine->setConstantColor(globalColor); 00216 } 00217 }; 00218 00219 typedef std::map<osg::ref_ptr<osg::Texture2D>, osg::ref_ptr<osg::StateSet> > 00220 StateSetMap; 00221 } 00222 00223 static Mutex chromeMutex; 00224 00225 // The chrome effect is mixed by the alpha channel of the texture 00226 // on the model, which will be attached to a node lower in the scene 00227 // graph: 0 -> completely chrome, 1 -> completely model texture. 00228 static void create_chrome(osg::Group* group, osg::Texture2D* texture) 00229 { 00230 ScopedLock<Mutex> lock(chromeMutex); 00231 static StateSetMap chromeMap; 00232 osg::StateSet *stateSet; 00233 StateSetMap::iterator iterator = chromeMap.find(texture); 00234 if (iterator != chromeMap.end()) { 00235 stateSet = iterator->second.get(); 00236 } else { 00237 stateSet = new osg::StateSet; 00238 // If the model doesn't have any texture, we need to have one 00239 // activated so that we don't need a seperate combiner 00240 // attribute for the non-textured case. This texture will be 00241 // shadowed by any attached to the model. 00242 osg::Image *dummyImage = new osg::Image; 00243 dummyImage->allocateImage(1, 1, 1, GL_LUMINANCE_ALPHA, 00244 GL_UNSIGNED_BYTE); 00245 unsigned char* imageBytes = dummyImage->data(0, 0); 00246 imageBytes[0] = 255; 00247 imageBytes[1] = 0; 00248 osg::Texture2D* dummyTexture = new osg::Texture2D; 00249 dummyTexture->setImage(dummyImage); 00250 dummyTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); 00251 dummyTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); 00252 stateSet->setTextureAttributeAndModes(0, dummyTexture, 00253 osg::StateAttribute::ON); 00254 osg::TexEnvCombine* combine0 = new osg::TexEnvCombine; 00255 osg::TexEnvCombine* combine1 = new osg::TexEnvCombine; 00256 osg::TexGen* texGen = new osg::TexGen; 00257 // Mix the environmental light color and the chrome map on texture 00258 // unit 0 00259 combine0->setCombine_RGB(osg::TexEnvCombine::MODULATE); 00260 combine0->setSource0_RGB(osg::TexEnvCombine::CONSTANT); 00261 combine0->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR); 00262 combine0->setSource1_RGB(osg::TexEnvCombine::TEXTURE1); 00263 combine0->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR); 00264 combine0->setDataVariance(osg::Object::DYNAMIC); 00265 combine0->setUpdateCallback(new ChromeLightingCallback); 00266 00267 // Interpolate the colored chrome map with the texture on the 00268 // model, using the model texture's alpha. 00269 combine1->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE); 00270 combine1->setSource0_RGB(osg::TexEnvCombine::TEXTURE0); 00271 combine1->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR); 00272 combine1->setSource1_RGB(osg::TexEnvCombine::PREVIOUS); 00273 combine1->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR); 00274 combine1->setSource2_RGB(osg::TexEnvCombine::TEXTURE0); 00275 combine1->setOperand2_RGB(osg::TexEnvCombine::SRC_ALPHA); 00276 // Are these used for anything? 00277 combine1->setCombine_Alpha(osg::TexEnvCombine::REPLACE); 00278 combine1->setSource0_Alpha(osg::TexEnvCombine::TEXTURE1); 00279 combine1->setOperand0_Alpha(osg::TexEnvCombine::SRC_ALPHA); 00280 00281 texGen->setMode(osg::TexGen::SPHERE_MAP); 00282 stateSet->setTextureAttribute(0, combine0); 00283 stateSet->setTextureAttribute(1, combine1); 00284 stateSet->setTextureAttributeAndModes(1, texture, 00285 osg::StateAttribute::ON); 00286 stateSet->setTextureAttributeAndModes(1, texGen, 00287 osg::StateAttribute::ON); 00288 chromeMap[texture] = stateSet; 00289 } 00290 group->setStateSet(stateSet); 00291 } 00292 00293 osg::Group* 00294 SGShaderAnimation::createAnimationGroup(osg::Group& parent) 00295 { 00296 osg::Group* group = new osg::Group; 00297 group->setName("shader animation"); 00298 parent.addChild(group); 00299 00300 std::string shader_name = getConfig()->getStringValue("shader", ""); 00301 // if( shader_name == "fresnel" || shader_name == "reflection" ) 00302 // _shader_type = 1; 00303 // else if( shader_name == "heat-haze" ) 00304 // _shader_type = 2; 00305 // else 00306 if( shader_name == "chrome") 00307 #if 0 00308 create_specular_highlights(group); 00309 #endif 00310 create_chrome(group, _effect_texture.get()); 00311 return group; 00312 } 00313 00314 #if 0 00315 // static Shader *shFresnel=NULL; 00316 // static GLuint texFresnel = 0; 00317 00318 // static GLuint texBackground = 0; 00319 // static int texBackgroundWidth = 1024, texBackgroundHeight = 1024; 00320 // static GLenum texBackgroundTarget = GL_TEXTURE_2D; 00321 // static bool isRectangleTextureSupported = false; 00322 // static bool istexBackgroundRectangle = false; 00323 // static bool initDone = false; 00324 static bool haveBackground = false; 00325 00326 // static glActiveTextureProc glActiveTexturePtr = 0; 00327 // static sgMat4 shadIdentMatrix; 00328 00329 00330 // static int null_shader_callback( ssgEntity *e ) { 00331 // GLuint dlist = 0; 00332 // ssgLeaf *leaf = (ssgLeaf *) e; 00333 // #ifdef _SSG_USE_DLIST 00334 // dlist = leaf->getDListIndex(); 00335 // if( ! dlist ) { 00336 // leaf->makeDList(); 00337 // dlist = leaf->getDListIndex(); 00338 // } 00339 // #endif 00340 // if( ! dlist ) 00341 // return true; 00342 // ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState()); 00343 // if ( sst ) 00344 // sst->apply(); 00345 00346 // SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() ); 00347 // if( ! my_shader->_depth_test ) 00348 // glDisable( GL_DEPTH_TEST ); 00349 // glCallList ( dlist ) ; 00350 // // restore states 00351 // if( ! my_shader->_depth_test ) 00352 // glEnable( GL_DEPTH_TEST ); 00353 00354 // // don't draw ! 00355 // return false; 00356 // } 00357 00358 // static int heat_haze_shader_callback( ssgEntity *e ) { 00359 // if( ! ((SGShadowAnimation *)e->getUserData())->get_condition_value() ) 00360 // return true; 00361 00362 // GLuint dlist = 0; 00363 // ssgLeaf *leaf = (ssgLeaf *) e; 00364 // #ifdef _SSG_USE_DLIST 00365 // dlist = leaf->getDListIndex(); 00366 // if( ! dlist ) { 00367 // leaf->makeDList(); 00368 // dlist = leaf->getDListIndex(); 00369 // } 00370 // #endif 00371 // if( ! dlist ) 00372 // return true; 00373 00374 // GLint viewport[4]; 00375 // glGetIntegerv( GL_VIEWPORT, viewport ); 00376 // const int screen_width = viewport[2]; 00377 // const int screen_height = viewport[3]; 00378 // if( ! haveBackground ) { 00379 // // store the backbuffer in a texture 00380 // if( ! texBackground ) { 00381 // // allocate our texture here so we don't waste memory if no model use that effect 00382 // // check if we need a rectangle texture and if the card support it 00383 // if( (screen_width > 1024 || screen_height > 1024) && isRectangleTextureSupported ) { 00384 // // Note that the 3 (same) extensions use the same enumerants 00385 // texBackgroundTarget = GL_TEXTURE_RECTANGLE_NV; 00386 // istexBackgroundRectangle = true; 00387 // texBackgroundWidth = screen_width; 00388 // texBackgroundHeight = screen_height; 00389 // } 00390 // glGenTextures(1, &texBackground); 00391 // glEnable(texBackgroundTarget); 00392 // glBindTexture(texBackgroundTarget, texBackground); 00393 // // trying to match the backbuffer pixel format 00394 // GLint internalFormat = GL_RGB8; 00395 // GLint colorBits = 0, alphaBits = 0; 00396 // glGetIntegerv( GL_BLUE_BITS, &colorBits ); 00397 // glGetIntegerv( GL_ALPHA_BITS, &alphaBits ); 00398 // if(colorBits == 5) { 00399 // if( alphaBits == 0 ) 00400 // internalFormat = GL_RGB5; 00401 // else 00402 // internalFormat = GL_RGB5_A1; 00403 // } else { 00404 // if( alphaBits != 0 ) 00405 // internalFormat = GL_RGBA8; 00406 // } 00407 // glTexImage2D(texBackgroundTarget, 0, internalFormat, 00408 // texBackgroundWidth, texBackgroundHeight, 0, GL_RGB, GL_FLOAT, NULL); 00409 00410 // glTexParameteri(texBackgroundTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 00411 // glTexParameteri(texBackgroundTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 00412 // glTexParameteri(texBackgroundTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 00413 // glTexParameteri(texBackgroundTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 00414 // } 00415 // glEnable(texBackgroundTarget); 00416 // glBindTexture(texBackgroundTarget, texBackground); 00417 // // center of texture = center of screen 00418 // // obviously we don't have the whole screen if screen_width > texBackgroundWidth 00419 // // if rectangle textures are not supported, this give some artifacts on the borders 00420 // if( istexBackgroundRectangle ) { 00421 // glCopyTexSubImage2D( texBackgroundTarget, 0, 0, 0, 00422 // 0, 0, texBackgroundWidth, texBackgroundHeight ); 00423 // } else { 00424 // glCopyTexSubImage2D( texBackgroundTarget, 0, 0, 0, 00425 // (screen_width - texBackgroundWidth) / 2, 00426 // (screen_height - texBackgroundHeight) / 2, 00427 // texBackgroundWidth, texBackgroundHeight ); 00428 // } 00429 // haveBackground = true; 00430 // glBindTexture(texBackgroundTarget, 0); 00431 // glDisable(texBackgroundTarget); 00432 // } 00433 // ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState()); 00434 // if ( sst ) 00435 // sst->apply(); 00436 00437 // SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() ); 00438 // if( ! my_shader->_depth_test ) 00439 // glDisable( GL_DEPTH_TEST ); 00440 // glDepthMask( GL_FALSE ); 00441 // glDisable( GL_LIGHTING ); 00442 // if(1) { 00443 // // noise texture, tex coord from the model translated by a time factor 00444 // glActiveTexturePtr( GL_TEXTURE0_ARB ); 00445 // glEnable(GL_TEXTURE_2D); 00446 // const float noiseDist = fmod(- totalTime * my_shader->_factor * my_shader->_speed, 4.0); 00447 // glMatrixMode(GL_TEXTURE); 00448 // glLoadIdentity(); 00449 // glTranslatef( noiseDist, 0.0f, 0.0f ); 00450 // glMatrixMode(GL_MODELVIEW); 00451 00452 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); 00453 00454 // // background texture 00455 // glActiveTexturePtr( GL_TEXTURE1_ARB ); 00456 // glEnable(texBackgroundTarget); 00457 // glBindTexture(texBackgroundTarget, texBackground); 00458 00459 // // automatic generation of texture coordinates 00460 // // map to screen space 00461 // sgMat4 CameraProjM, CameraViewM; 00462 // glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *) CameraProjM); 00463 // glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) CameraViewM); 00464 // // const float dummy_scale = 1.0f; //0.95f; 00465 // const float deltaPos = 0.05f; 00466 // glMatrixMode(GL_TEXTURE); 00467 // glLoadIdentity(); 00468 // if( istexBackgroundRectangle ) { 00469 // // coords go from 0.0 to n, not from 0.0 to 1.0 00470 // glTranslatef( texBackgroundWidth * 0.5f, texBackgroundHeight * 0.5f, 0.0f ); 00471 // glScalef( texBackgroundWidth * 0.5f, 00472 // texBackgroundHeight * 0.5f, 1.0f ); 00473 // } else { 00474 // glTranslatef( 0.5f, 0.5f, 0.0f ); 00475 // glScalef( float( screen_width ) / float( texBackgroundWidth ) * 0.5f, 00476 // float( screen_height ) / float( texBackgroundHeight ) * 0.5f, 1.0f ); 00477 // } 00478 // glMultMatrixf( (GLfloat *) CameraProjM ); 00479 // glMultMatrixf( (GLfloat *) CameraViewM ); 00480 // glTranslatef( deltaPos, deltaPos, deltaPos ); 00481 // glMatrixMode(GL_MODELVIEW); 00482 00483 // glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); 00484 // glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); 00485 // glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); 00486 // glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); 00487 // glTexGenfv( GL_S, GL_EYE_PLANE, shadIdentMatrix[0] ); 00488 // glTexGenfv( GL_T, GL_EYE_PLANE, shadIdentMatrix[1] ); 00489 // glTexGenfv( GL_R, GL_EYE_PLANE, shadIdentMatrix[2] ); 00490 // glTexGenfv( GL_Q, GL_EYE_PLANE, shadIdentMatrix[3] ); 00491 // glEnable( GL_TEXTURE_GEN_S ); 00492 // glEnable( GL_TEXTURE_GEN_T ); 00493 // glEnable( GL_TEXTURE_GEN_R ); 00494 // glEnable( GL_TEXTURE_GEN_Q ); 00495 00496 // sgVec4 enviro = {1.00f, 1.00f, 1.00f, 0.85f}; 00497 00498 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB ); 00499 // glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE ); 00500 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE ); 00501 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR ); 00502 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT_ARB ); 00503 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); 00504 // glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, enviro); 00505 00506 // glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); 00507 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE0_ARB); 00508 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); 00509 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PRIMARY_COLOR_ARB ); 00510 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA ); 00511 00512 // glCallList ( dlist ) ; 00513 // glMatrixMode(GL_TEXTURE); 00514 // glTranslatef( - deltaPos*2.0f, -deltaPos*2.5f, -deltaPos*2.0f ); 00515 // glMatrixMode(GL_MODELVIEW); 00516 // glCallList ( dlist ) ; 00517 00518 // // alter colors only on last rendering 00519 // // sgVec4 fLight = {0.93f, 0.93f, 1.00f, 0.85f}; 00520 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB ); 00521 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); 00522 00523 // glMatrixMode(GL_TEXTURE); 00524 // glTranslatef( deltaPos*0.7f, deltaPos*1.7f, deltaPos*0.7f ); 00525 // glMatrixMode(GL_MODELVIEW); 00526 // glCallList ( dlist ) ; 00527 00528 00529 // glActiveTexturePtr( GL_TEXTURE1_ARB ); 00530 // glDisable( GL_TEXTURE_GEN_S ); 00531 // glDisable( GL_TEXTURE_GEN_T ); 00532 // glDisable( GL_TEXTURE_GEN_R ); 00533 // glDisable( GL_TEXTURE_GEN_Q ); 00534 // glMatrixMode(GL_TEXTURE); 00535 // glLoadIdentity(); 00536 // glMatrixMode(GL_MODELVIEW); 00537 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); 00538 // glDisable(texBackgroundTarget); 00539 // glActiveTexturePtr( GL_TEXTURE0_ARB ); 00540 // glMatrixMode(GL_TEXTURE); 00541 // glLoadIdentity(); 00542 // glMatrixMode(GL_MODELVIEW); 00543 // glEnable(GL_TEXTURE_2D); 00544 // glBindTexture(GL_TEXTURE_2D, 0); 00545 // } 00546 // // restore states 00547 // if( ! my_shader->_depth_test ) 00548 // glEnable( GL_DEPTH_TEST ); 00549 00550 // glEnable( GL_LIGHTING ); 00551 // glDepthMask( GL_TRUE ); 00552 // if( sst ) 00553 // sst->force(); 00554 00555 // // don't draw ! 00556 // return false; 00557 // } 00558 00559 // static int fresnel_shader_callback( ssgEntity *e ) { 00560 // if( ! ((SGShadowAnimation *)e->getUserData())->get_condition_value() ) 00561 // return true; 00562 00563 // GLuint dlist = 0; 00564 // ssgLeaf *leaf = (ssgLeaf *) e; 00565 // #ifdef _SSG_USE_DLIST 00566 // dlist = leaf->getDListIndex(); 00567 // if( ! dlist ) { 00568 // leaf->makeDList(); 00569 // dlist = leaf->getDListIndex(); 00570 // } 00571 // #endif 00572 // if( ! dlist ) 00573 // return true; 00574 // ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState()); 00575 // if ( sst ) 00576 // sst->apply(); 00577 00578 // sgVec4 sunColor, ambientColor; 00579 // ssgGetLight( 0 )->getColour(GL_DIFFUSE, sunColor ); 00580 // ssgGetLight( 0 )->getColour(GL_AMBIENT, ambientColor ); 00581 00582 // // SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() ); 00583 // glEnable(GL_BLEND); 00584 // glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ; 00585 // glEnable(GL_ALPHA_TEST); 00586 // glAlphaFunc(GL_GREATER, 0.0f); 00587 00588 // if( true ) { 00589 // // sgVec4 R = {0.5,0.0,0.0,0.0}; 00590 // sgVec4 enviro = {1.0,0.0,0.0,1.0}; 00591 // // sgCopyVec4( enviro, sunColor ); 00592 // glActiveTexturePtr( GL_TEXTURE0_ARB ); 00593 // glEnable(GL_TEXTURE_2D); 00594 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); 00595 // glActiveTexturePtr( GL_TEXTURE1_ARB ); 00596 // glDisable(GL_TEXTURE_2D); 00597 // glEnable(GL_TEXTURE_1D); 00598 // glBindTexture(GL_TEXTURE_1D, texFresnel); 00599 // // c = a0 * a2 + a1 * (1-a2) 00600 // // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); 00601 // // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); 00602 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB ); 00603 // glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB ); 00604 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_CONSTANT_ARB ); 00605 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR ); 00606 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB ); 00607 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); 00608 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE ); 00609 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR ); 00610 // glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, enviro); 00611 // shFresnel->enable(); 00612 // shFresnel->bind(); 00613 // glCallList ( dlist ) ; 00614 // shFresnel->disable(); 00615 // glActiveTexturePtr( GL_TEXTURE1_ARB ); 00616 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); 00617 // glDisable(GL_TEXTURE_1D); 00618 // glActiveTexturePtr( GL_TEXTURE0_ARB ); 00619 // glDisable(GL_TEXTURE_1D); 00620 // glEnable(GL_TEXTURE_2D); 00621 // } 00622 // // restore states 00623 // // glBindTexture(GL_TEXTURE_2D, 0); 00624 // // glDepthFunc(GL_LESS); 00625 // // glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ; 00626 // if( sst ) 00627 // sst->force(); 00628 00629 // // don't draw ! 00630 // return false; 00631 // } 00632 00633 00634 00635 // static int chrome_shader_callback( ssgEntity *e ) { 00636 // if( ! ((SGShadowAnimation *)e->getUserData())->get_condition_value() ) 00637 // return true; 00638 00639 // GLuint dlist = 0; 00640 // ssgLeaf *leaf = (ssgLeaf *) e; 00641 // #ifdef _SSG_USE_DLIST 00642 // dlist = leaf->getDListIndex(); 00643 // if( ! dlist ) { 00644 // leaf->makeDList(); 00645 // dlist = leaf->getDListIndex(); 00646 // } 00647 // #endif 00648 // if( ! dlist ) 00649 // return true; 00650 // ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState()); 00651 // if ( sst ) 00652 // sst->apply(); 00653 00654 // SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() ); 00655 // if( ! my_shader->_depth_test ) 00656 // glDisable( GL_DEPTH_TEST ); 00657 00658 // GLint maskTexComponent = 3; 00659 // glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_COMPONENTS, &maskTexComponent); 00660 00661 // // The fake env chrome texture 00662 // glActiveTexturePtr( GL_TEXTURE1_ARB ); 00663 // glEnable(GL_TEXTURE_2D); 00664 // { 00665 // // No lighting is computed in spherical mapping mode because the environment 00666 // // is supposed to be allready lighted. We must reshade our environment texture. 00667 // sgVec4 sunColor, ambientColor, envColor; 00668 // ssgGetLight( 0 )->getColour(GL_DIFFUSE, sunColor ); 00669 // ssgGetLight( 0 )->getColour(GL_AMBIENT, ambientColor ); 00670 // sgAddScaledVec3( envColor, ambientColor, sunColor, 0.4f); 00671 // glBindTexture(GL_TEXTURE_2D, my_shader->_effectTexture->getHandle()); 00672 00673 // sgVec3 delta_light; 00674 // sgSubVec3(delta_light, envColor, my_shader->_envColor); 00675 // if( (fabs(delta_light[0]) + fabs(delta_light[1]) + fabs(delta_light[2])) > 0.05f ) { 00676 // sgCopyVec3( my_shader->_envColor, envColor ); 00677 // // reload the texture data and let the driver reshade it for us 00678 // glPixelTransferf( GL_RED_SCALE, envColor[0] ); 00679 // glPixelTransferf( GL_GREEN_SCALE, envColor[1] ); 00680 // glPixelTransferf( GL_BLUE_SCALE, envColor[2] ); 00681 // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, my_shader->_texWidth, my_shader->_texHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, my_shader->_textureData); 00682 // glPixelTransferf( GL_RED_SCALE, 1.0f ); 00683 // glPixelTransferf( GL_GREEN_SCALE, 1.0f ); 00684 // glPixelTransferf( GL_BLUE_SCALE, 1.0f ); 00685 // } 00686 // } 00687 // if( maskTexComponent == 4 ) { 00688 // // c = lerp(model tex, chrome tex, model tex alpha) 00689 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB ); 00690 // glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB ); 00691 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB ); 00692 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR ); 00693 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE ); 00694 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); 00695 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_PREVIOUS_ARB ); 00696 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA ); 00697 00698 // glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); 00699 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); 00700 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); 00701 // } else { 00702 // // c = chrome tex 00703 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); 00704 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE ); 00705 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR ); 00706 00707 // glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); 00708 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); 00709 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); 00710 // } 00711 // // automatic generation of texture coordinates 00712 // // from normals 00713 00714 // glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP ); 00715 // glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP ); 00716 // glEnable( GL_TEXTURE_GEN_S ); 00717 // glEnable( GL_TEXTURE_GEN_T ); 00718 00719 // glCallList ( dlist ) ; 00720 00721 // glActiveTexturePtr( GL_TEXTURE1_ARB ); 00722 // glDisable( GL_TEXTURE_GEN_S ); 00723 // glDisable( GL_TEXTURE_GEN_T ); 00724 00725 // glMatrixMode(GL_TEXTURE); 00726 // glLoadIdentity(); 00727 // glMatrixMode(GL_MODELVIEW); 00728 00729 // glDisable(GL_TEXTURE_2D); 00730 // glBindTexture(GL_TEXTURE_2D, 0); 00731 // glActiveTexturePtr( GL_TEXTURE0_ARB ); 00732 00733 // // restore states 00734 // if( ! my_shader->_depth_test ) 00735 // glEnable( GL_DEPTH_TEST ); 00736 00737 // if( sst ) 00738 // sst->force(); 00739 00740 // // don't draw ! 00741 // return false; 00742 // } 00743 00744 // static void init_shaders(void) { 00745 // Shader::Init(); 00746 // if( false && Shader::is_VP_supported() ) { 00747 // shFresnel = new Shader("/FlightGear/data/Textures/fresnel_vp.txt", "fresnel_vp"); 00748 // } 00749 // glActiveTexturePtr = (glActiveTextureProc) SGLookupFunction("glActiveTextureARB"); 00750 // const int fresnelSize = 512; 00751 // unsigned char imageFresnel[ fresnelSize * 3 ]; 00752 // for(int i = 0; i < fresnelSize; i++) { 00753 // const float R0 = 0.2f; 00754 // float NdotV = float( i ) / float( fresnelSize ); 00755 // float f = R0 + (1.0f-R0)*pow(1.0f - NdotV, 5); 00756 // unsigned char ff = (unsigned char) (f * 255.0); 00757 // imageFresnel[i*3+0] = imageFresnel[i*3+1] = imageFresnel[i*3+2] = ff; 00758 // } 00759 // glGenTextures( 1, &texFresnel ); 00760 // glBindTexture(GL_TEXTURE_1D, texFresnel ); 00761 // glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 00762 // glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 00763 // glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 00764 // glTexParameteri(GL_TEXTURE_1D, GL_GENERATE_MIPMAP_SGIS, true); 00765 // glTexImage1D(GL_TEXTURE_1D, 0, 3, fresnelSize, 0, GL_RGB, GL_UNSIGNED_BYTE, imageFresnel); 00766 // glBindTexture(GL_TEXTURE_1D, 0 ); 00767 00768 // sgMakeIdentMat4( shadIdentMatrix ); 00769 00770 // initDone = true; 00771 // } 00772 00773 // //////////////////////////////////////////////////////////////////////// 00774 // // Implementation of SGShaderAnimation 00775 // //////////////////////////////////////////////////////////////////////// 00776 00777 SGShaderAnimation::SGShaderAnimation ( SGPropertyNode *prop_root, 00778 SGPropertyNode_ptr props ) 00779 : SGAnimation(props, new osg::Group), 00780 _condition(0), 00781 _condition_value(true), 00782 _shader_type(0), 00783 _param_1(props->getFloatValue("param", 1.0f)), 00784 _depth_test(props->getBoolValue("depth-test", true)), 00785 _factor(props->getFloatValue("factor", 1.0f)), 00786 _factor_prop(0), 00787 _speed(props->getFloatValue("speed", 1.0f)), 00788 _speed_prop(0), 00789 _textureData(0), 00790 _texWidth(0), 00791 _texHeight(0) 00792 00793 { 00794 SGPropertyNode_ptr node = props->getChild("condition"); 00795 if (node != 0) { 00796 _condition = sgReadCondition(prop_root, node); 00797 _condition_value = false; 00798 } 00799 node = props->getChild("factor-prop"); 00800 if( node ) 00801 _factor_prop = prop_root->getNode(node->getStringValue(), true); 00802 node = props->getChild("speed-prop"); 00803 if( node ) 00804 _speed_prop = prop_root->getNode(node->getStringValue(), true); 00805 00806 _envColor = osg::Vec4(0, 0, 0, 1); 00807 node = props->getChild("texture"); 00808 if( node ) { 00809 _effectTexture = SGLoadTexture2D(node->getStringValue()); 00810 // glBindTexture(GL_TEXTURE_2D, _effectTexture->getHandle() ); 00811 // glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &_texWidth); 00812 // glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &_texHeight); 00813 00814 // _textureData = new unsigned char[_texWidth * _texHeight * 3]; 00815 // glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, _textureData); 00816 // glBindTexture(GL_TEXTURE_2D, 0 ); 00817 } 00818 string shader_name = props->getStringValue("shader"); 00819 if( shader_name == "fresnel" || shader_name == "reflection" ) 00820 _shader_type = 1; 00821 else if( shader_name == "heat-haze" ) 00822 _shader_type = 2; 00823 else if( shader_name == "chrome" && _effectTexture.valid()) 00824 _shader_type = 3; 00825 } 00826 00827 void SGShaderAnimation::init() 00828 { 00829 // if( ! initDone ) 00830 // init_shaders(); 00831 // if( _shader_type == 1 && Shader::is_VP_supported() && shFresnel) 00832 // setCallBack( getBranch(), (ssgBase *) this, fresnel_shader_callback ); 00833 // else if( _shader_type == 2 ) { 00834 // // this is the same extension with different names 00835 // isRectangleTextureSupported = SGIsOpenGLExtensionSupported("GL_EXT_texture_rectangle") || 00836 // SGIsOpenGLExtensionSupported("GL_ARB_texture_rectangle") || 00837 // SGIsOpenGLExtensionSupported("GL_NV_texture_rectangle"); 00838 // setCallBack( getBranch(), (ssgBase *) this, heat_haze_shader_callback ); 00839 // } 00840 // else if( _shader_type == 3 ) 00841 // setCallBack( getBranch(), (ssgBase *) this, chrome_shader_callback ); 00842 // else 00843 // setCallBack( getBranch(), (ssgBase *) this, null_shader_callback ); 00844 } 00845 00846 SGShaderAnimation::~SGShaderAnimation() 00847 { 00848 delete _condition; 00849 delete _textureData; 00850 } 00851 00852 void 00853 SGShaderAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv) 00854 { 00855 if (_condition) 00856 _condition_value = _condition->test(); 00857 if( _factor_prop) 00858 _factor = _factor_prop->getFloatValue(); 00859 if( _speed_prop) 00860 _speed = _speed_prop->getFloatValue(); 00861 00862 // OSGFIXME fiddle with totalTime 00863 totalTime = nv->getFrameStamp()->getReferenceTime(); 00864 00865 // note, callback is responsible for scenegraph traversal so 00866 // should always include call traverse(node,nv) to ensure 00867 // that the rest of cullbacks and the scene graph are traversed. 00868 traverse(node, nv); 00869 } 00870 #endif