1 // non fixed Opengl pipeline rendering
3 // Written by Harald JOHNSEN, started Jully 2005.
5 // Copyright (C) 2005 Harald JOHNSEN
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 # include <simgear_config.h>
30 #include <osg/Program>
32 #include <osg/StateSet>
33 #include <osg/TextureCubeMap>
34 #include <osg/TexEnvCombine>
36 #include <osg/Texture1D>
37 #include <osgUtil/HighlightMapGenerator>
39 #include <OpenThreads/Mutex>
40 #include <OpenThreads/ScopedLock>
42 #include <simgear/scene/util/SGUpdateVisitor.hxx>
44 #include <simgear/props/condition.hxx>
45 #include <simgear/props/props.hxx>
47 #include <simgear/debug/logstream.hxx>
49 #include "animation.hxx"
52 using OpenThreads::Mutex;
53 using OpenThreads::ScopedLock;
58 <shader>fresnel</shader>
59 <object-name>...</object-name>
64 <shader>heat-haze</shader>
65 <object-name>...</object-name>
67 <speed-prop>...</speed-prop>
69 <factor-prop>...</factor-prop>
74 <shader>chrome</shader>
75 <texture>...</texture>
76 <object-name>...</object-name>
82 <object-name>...</object-name>
83 <depth-test>false</depth-test>
89 class SGMapGenCallback :
90 public osg::StateAttribute::Callback {
92 virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
94 SGUpdateVisitor* updateVisitor = dynamic_cast<SGUpdateVisitor*>(nv);
98 if (distSqr(_lastLightDirection, updateVisitor->getLightDirection()) < 1e-4
99 && distSqr(_lastLightColor, updateVisitor->getAmbientLight()) < 1e-4)
102 _lastLightDirection = updateVisitor->getLightDirection();
103 _lastLightColor = updateVisitor->getAmbientLight();
105 osg::TextureCubeMap *tcm = static_cast<osg::TextureCubeMap*>(sa);
107 // FIXME: need an update or callback ...
108 // generate the six highlight map images (light direction = [1, 1, -1])
109 osg::ref_ptr<osgUtil::HighlightMapGenerator> mapgen;
110 mapgen = new osgUtil::HighlightMapGenerator(toOsg(_lastLightDirection),
111 toOsg(_lastLightColor), 5);
112 mapgen->generateMap();
114 // assign the six images to the texture object
115 tcm->setImage(osg::TextureCubeMap::POSITIVE_X,
116 mapgen->getImage(osg::TextureCubeMap::POSITIVE_X));
117 tcm->setImage(osg::TextureCubeMap::NEGATIVE_X,
118 mapgen->getImage(osg::TextureCubeMap::NEGATIVE_X));
119 tcm->setImage(osg::TextureCubeMap::POSITIVE_Y,
120 mapgen->getImage(osg::TextureCubeMap::POSITIVE_Y));
121 tcm->setImage(osg::TextureCubeMap::NEGATIVE_Y,
122 mapgen->getImage(osg::TextureCubeMap::NEGATIVE_Y));
123 tcm->setImage(osg::TextureCubeMap::POSITIVE_Z,
124 mapgen->getImage(osg::TextureCubeMap::POSITIVE_Z));
125 tcm->setImage(osg::TextureCubeMap::NEGATIVE_Z,
126 mapgen->getImage(osg::TextureCubeMap::NEGATIVE_Z));
129 SGVec3f _lastLightDirection;
130 SGVec4f _lastLightColor;
133 static Mutex cubeMutex;
136 static osg::TextureCubeMap*
137 getOrCreateTextureCubeMap()
139 static osg::ref_ptr<osg::TextureCubeMap> textureCubeMap;
140 if (textureCubeMap.get())
141 return textureCubeMap.get();
143 ScopedLock<Mutex> lock(cubeMutex);
144 if (textureCubeMap.get())
145 return textureCubeMap.get();
147 // create and setup the texture object
148 textureCubeMap = new osg::TextureCubeMap;
150 textureCubeMap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);
151 textureCubeMap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);
152 textureCubeMap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP);
153 textureCubeMap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
154 textureCubeMap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
156 textureCubeMap->setUpdateCallback(new SGMapGenCallback);
158 return textureCubeMap.get();
161 static void create_specular_highlights(osg::Node *node)
163 osg::StateSet *ss = node->getOrCreateStateSet();
165 // create and setup the texture object
166 osg::TextureCubeMap *tcm = getOrCreateTextureCubeMap();
168 // enable texturing, replacing any textures in the subgraphs
169 ss->setTextureAttributeAndModes(0, tcm, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
171 // texture coordinate generation
172 osg::TexGen *tg = new osg::TexGen;
173 tg->setMode(osg::TexGen::REFLECTION_MAP);
174 ss->setTextureAttributeAndModes(0, tg, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
176 // use TexEnvCombine to add the highlights to the original lighting
177 osg::TexEnvCombine *te = new osg::TexEnvCombine;
178 te->setCombine_RGB(osg::TexEnvCombine::ADD);
179 te->setSource0_RGB(osg::TexEnvCombine::TEXTURE);
180 te->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
181 te->setSource1_RGB(osg::TexEnvCombine::PRIMARY_COLOR);
182 te->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
183 ss->setTextureAttributeAndModes(0, te, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
188 SGShaderAnimation::SGShaderAnimation(const SGPropertyNode* configNode,
189 SGPropertyNode* modelRoot,
190 const osgDB::ReaderWriter::Options*
192 SGAnimation(configNode, modelRoot)
194 const SGPropertyNode* node = configNode->getChild("texture");
196 _effect_texture = SGLoadTexture2D(node->getStringValue(), options);
200 class ChromeLightingCallback :
201 public osg::StateAttribute::Callback {
203 virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
205 SGUpdateVisitor* updateVisitor = dynamic_cast<SGUpdateVisitor*>(nv);
208 osg::TexEnvCombine *combine = dynamic_cast<osg::TexEnvCombine *>(sa);
211 // An approximation for light reflected back by chrome.
212 osg::Vec4 globalColor = toOsg(updateVisitor->getAmbientLight() * .4f
213 + updateVisitor->getDiffuseLight());
214 globalColor.a() = 1.0f;
215 combine->setConstantColor(globalColor);
219 typedef std::map<osg::ref_ptr<osg::Texture2D>, osg::ref_ptr<osg::StateSet> >
223 static Mutex chromeMutex;
225 // The chrome effect is mixed by the alpha channel of the texture
226 // on the model, which will be attached to a node lower in the scene
227 // graph: 0 -> completely chrome, 1 -> completely model texture.
228 static void create_chrome(osg::Group* group, osg::Texture2D* texture)
230 ScopedLock<Mutex> lock(chromeMutex);
231 static StateSetMap chromeMap;
232 osg::StateSet *stateSet;
233 StateSetMap::iterator iterator = chromeMap.find(texture);
234 if (iterator != chromeMap.end()) {
235 stateSet = iterator->second.get();
237 stateSet = new osg::StateSet;
238 // If the model doesn't have any texture, we need to have one
239 // activated so that we don't need a seperate combiner
240 // attribute for the non-textured case. This texture will be
241 // shadowed by any attached to the model.
242 osg::Image *dummyImage = new osg::Image;
243 dummyImage->allocateImage(1, 1, 1, GL_LUMINANCE_ALPHA,
245 unsigned char* imageBytes = dummyImage->data(0, 0);
248 osg::Texture2D* dummyTexture = new osg::Texture2D;
249 dummyTexture->setImage(dummyImage);
250 dummyTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
251 dummyTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
252 stateSet->setTextureAttributeAndModes(0, dummyTexture,
253 osg::StateAttribute::ON);
254 osg::TexEnvCombine* combine0 = new osg::TexEnvCombine;
255 osg::TexEnvCombine* combine1 = new osg::TexEnvCombine;
256 osg::TexGen* texGen = new osg::TexGen;
257 // Mix the environmental light color and the chrome map on texture
259 combine0->setCombine_RGB(osg::TexEnvCombine::MODULATE);
260 combine0->setSource0_RGB(osg::TexEnvCombine::CONSTANT);
261 combine0->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
262 combine0->setSource1_RGB(osg::TexEnvCombine::TEXTURE1);
263 combine0->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
264 combine0->setDataVariance(osg::Object::DYNAMIC);
265 combine0->setUpdateCallback(new ChromeLightingCallback);
267 // Interpolate the colored chrome map with the texture on the
268 // model, using the model texture's alpha.
269 combine1->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE);
270 combine1->setSource0_RGB(osg::TexEnvCombine::TEXTURE0);
271 combine1->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
272 combine1->setSource1_RGB(osg::TexEnvCombine::PREVIOUS);
273 combine1->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
274 combine1->setSource2_RGB(osg::TexEnvCombine::TEXTURE0);
275 combine1->setOperand2_RGB(osg::TexEnvCombine::SRC_ALPHA);
276 // Are these used for anything?
277 combine1->setCombine_Alpha(osg::TexEnvCombine::REPLACE);
278 combine1->setSource0_Alpha(osg::TexEnvCombine::TEXTURE1);
279 combine1->setOperand0_Alpha(osg::TexEnvCombine::SRC_ALPHA);
281 texGen->setMode(osg::TexGen::SPHERE_MAP);
282 stateSet->setTextureAttribute(0, combine0);
283 stateSet->setTextureAttribute(1, combine1);
284 stateSet->setTextureAttributeAndModes(1, texture,
285 osg::StateAttribute::ON);
286 stateSet->setTextureAttributeAndModes(1, texGen,
287 osg::StateAttribute::ON);
288 chromeMap[texture] = stateSet;
290 group->setStateSet(stateSet);
294 SGShaderAnimation::createAnimationGroup(osg::Group& parent)
296 osg::Group* group = new osg::Group;
297 group->setName("shader animation");
298 parent.addChild(group);
300 std::string shader_name = getConfig()->getStringValue("shader", "");
301 // if( shader_name == "fresnel" || shader_name == "reflection" )
303 // else if( shader_name == "heat-haze" )
306 if( shader_name == "chrome")
308 create_specular_highlights(group);
310 create_chrome(group, _effect_texture.get());
315 // static Shader *shFresnel=NULL;
316 // static GLuint texFresnel = 0;
318 // static GLuint texBackground = 0;
319 // static int texBackgroundWidth = 1024, texBackgroundHeight = 1024;
320 // static GLenum texBackgroundTarget = GL_TEXTURE_2D;
321 // static bool isRectangleTextureSupported = false;
322 // static bool istexBackgroundRectangle = false;
323 // static bool initDone = false;
324 static bool haveBackground = false;
326 // static glActiveTextureProc glActiveTexturePtr = 0;
327 // static sgMat4 shadIdentMatrix;
330 // static int null_shader_callback( ssgEntity *e ) {
332 // ssgLeaf *leaf = (ssgLeaf *) e;
333 // #ifdef _SSG_USE_DLIST
334 // dlist = leaf->getDListIndex();
336 // leaf->makeDList();
337 // dlist = leaf->getDListIndex();
342 // ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
346 // SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
347 // if( ! my_shader->_depth_test )
348 // glDisable( GL_DEPTH_TEST );
349 // glCallList ( dlist ) ;
351 // if( ! my_shader->_depth_test )
352 // glEnable( GL_DEPTH_TEST );
358 // static int heat_haze_shader_callback( ssgEntity *e ) {
359 // if( ! ((SGShadowAnimation *)e->getUserData())->get_condition_value() )
363 // ssgLeaf *leaf = (ssgLeaf *) e;
364 // #ifdef _SSG_USE_DLIST
365 // dlist = leaf->getDListIndex();
367 // leaf->makeDList();
368 // dlist = leaf->getDListIndex();
374 // GLint viewport[4];
375 // glGetIntegerv( GL_VIEWPORT, viewport );
376 // const int screen_width = viewport[2];
377 // const int screen_height = viewport[3];
378 // if( ! haveBackground ) {
379 // // store the backbuffer in a texture
380 // if( ! texBackground ) {
381 // // allocate our texture here so we don't waste memory if no model use that effect
382 // // check if we need a rectangle texture and if the card support it
383 // if( (screen_width > 1024 || screen_height > 1024) && isRectangleTextureSupported ) {
384 // // Note that the 3 (same) extensions use the same enumerants
385 // texBackgroundTarget = GL_TEXTURE_RECTANGLE_NV;
386 // istexBackgroundRectangle = true;
387 // texBackgroundWidth = screen_width;
388 // texBackgroundHeight = screen_height;
390 // glGenTextures(1, &texBackground);
391 // glEnable(texBackgroundTarget);
392 // glBindTexture(texBackgroundTarget, texBackground);
393 // // trying to match the backbuffer pixel format
394 // GLint internalFormat = GL_RGB8;
395 // GLint colorBits = 0, alphaBits = 0;
396 // glGetIntegerv( GL_BLUE_BITS, &colorBits );
397 // glGetIntegerv( GL_ALPHA_BITS, &alphaBits );
398 // if(colorBits == 5) {
399 // if( alphaBits == 0 )
400 // internalFormat = GL_RGB5;
402 // internalFormat = GL_RGB5_A1;
404 // if( alphaBits != 0 )
405 // internalFormat = GL_RGBA8;
407 // glTexImage2D(texBackgroundTarget, 0, internalFormat,
408 // texBackgroundWidth, texBackgroundHeight, 0, GL_RGB, GL_FLOAT, NULL);
410 // glTexParameteri(texBackgroundTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
411 // glTexParameteri(texBackgroundTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
412 // glTexParameteri(texBackgroundTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
413 // glTexParameteri(texBackgroundTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
415 // glEnable(texBackgroundTarget);
416 // glBindTexture(texBackgroundTarget, texBackground);
417 // // center of texture = center of screen
418 // // obviously we don't have the whole screen if screen_width > texBackgroundWidth
419 // // if rectangle textures are not supported, this give some artifacts on the borders
420 // if( istexBackgroundRectangle ) {
421 // glCopyTexSubImage2D( texBackgroundTarget, 0, 0, 0,
422 // 0, 0, texBackgroundWidth, texBackgroundHeight );
424 // glCopyTexSubImage2D( texBackgroundTarget, 0, 0, 0,
425 // (screen_width - texBackgroundWidth) / 2,
426 // (screen_height - texBackgroundHeight) / 2,
427 // texBackgroundWidth, texBackgroundHeight );
429 // haveBackground = true;
430 // glBindTexture(texBackgroundTarget, 0);
431 // glDisable(texBackgroundTarget);
433 // ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
437 // SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
438 // if( ! my_shader->_depth_test )
439 // glDisable( GL_DEPTH_TEST );
440 // glDepthMask( GL_FALSE );
441 // glDisable( GL_LIGHTING );
443 // // noise texture, tex coord from the model translated by a time factor
444 // glActiveTexturePtr( GL_TEXTURE0_ARB );
445 // glEnable(GL_TEXTURE_2D);
446 // const float noiseDist = fmod(- totalTime * my_shader->_factor * my_shader->_speed, 4.0);
447 // glMatrixMode(GL_TEXTURE);
449 // glTranslatef( noiseDist, 0.0f, 0.0f );
450 // glMatrixMode(GL_MODELVIEW);
452 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
454 // // background texture
455 // glActiveTexturePtr( GL_TEXTURE1_ARB );
456 // glEnable(texBackgroundTarget);
457 // glBindTexture(texBackgroundTarget, texBackground);
459 // // automatic generation of texture coordinates
460 // // map to screen space
461 // sgMat4 CameraProjM, CameraViewM;
462 // glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *) CameraProjM);
463 // glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) CameraViewM);
464 // // const float dummy_scale = 1.0f; //0.95f;
465 // const float deltaPos = 0.05f;
466 // glMatrixMode(GL_TEXTURE);
468 // if( istexBackgroundRectangle ) {
469 // // coords go from 0.0 to n, not from 0.0 to 1.0
470 // glTranslatef( texBackgroundWidth * 0.5f, texBackgroundHeight * 0.5f, 0.0f );
471 // glScalef( texBackgroundWidth * 0.5f,
472 // texBackgroundHeight * 0.5f, 1.0f );
474 // glTranslatef( 0.5f, 0.5f, 0.0f );
475 // glScalef( float( screen_width ) / float( texBackgroundWidth ) * 0.5f,
476 // float( screen_height ) / float( texBackgroundHeight ) * 0.5f, 1.0f );
478 // glMultMatrixf( (GLfloat *) CameraProjM );
479 // glMultMatrixf( (GLfloat *) CameraViewM );
480 // glTranslatef( deltaPos, deltaPos, deltaPos );
481 // glMatrixMode(GL_MODELVIEW);
483 // glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
484 // glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
485 // glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
486 // glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
487 // glTexGenfv( GL_S, GL_EYE_PLANE, shadIdentMatrix[0] );
488 // glTexGenfv( GL_T, GL_EYE_PLANE, shadIdentMatrix[1] );
489 // glTexGenfv( GL_R, GL_EYE_PLANE, shadIdentMatrix[2] );
490 // glTexGenfv( GL_Q, GL_EYE_PLANE, shadIdentMatrix[3] );
491 // glEnable( GL_TEXTURE_GEN_S );
492 // glEnable( GL_TEXTURE_GEN_T );
493 // glEnable( GL_TEXTURE_GEN_R );
494 // glEnable( GL_TEXTURE_GEN_Q );
496 // sgVec4 enviro = {1.00f, 1.00f, 1.00f, 0.85f};
498 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
499 // glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE );
500 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE );
501 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
502 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT_ARB );
503 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
504 // glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, enviro);
506 // glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
507 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE0_ARB);
508 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
509 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PRIMARY_COLOR_ARB );
510 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA );
512 // glCallList ( dlist ) ;
513 // glMatrixMode(GL_TEXTURE);
514 // glTranslatef( - deltaPos*2.0f, -deltaPos*2.5f, -deltaPos*2.0f );
515 // glMatrixMode(GL_MODELVIEW);
516 // glCallList ( dlist ) ;
518 // // alter colors only on last rendering
519 // // sgVec4 fLight = {0.93f, 0.93f, 1.00f, 0.85f};
520 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB );
521 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
523 // glMatrixMode(GL_TEXTURE);
524 // glTranslatef( deltaPos*0.7f, deltaPos*1.7f, deltaPos*0.7f );
525 // glMatrixMode(GL_MODELVIEW);
526 // glCallList ( dlist ) ;
529 // glActiveTexturePtr( GL_TEXTURE1_ARB );
530 // glDisable( GL_TEXTURE_GEN_S );
531 // glDisable( GL_TEXTURE_GEN_T );
532 // glDisable( GL_TEXTURE_GEN_R );
533 // glDisable( GL_TEXTURE_GEN_Q );
534 // glMatrixMode(GL_TEXTURE);
536 // glMatrixMode(GL_MODELVIEW);
537 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
538 // glDisable(texBackgroundTarget);
539 // glActiveTexturePtr( GL_TEXTURE0_ARB );
540 // glMatrixMode(GL_TEXTURE);
542 // glMatrixMode(GL_MODELVIEW);
543 // glEnable(GL_TEXTURE_2D);
544 // glBindTexture(GL_TEXTURE_2D, 0);
547 // if( ! my_shader->_depth_test )
548 // glEnable( GL_DEPTH_TEST );
550 // glEnable( GL_LIGHTING );
551 // glDepthMask( GL_TRUE );
559 // static int fresnel_shader_callback( ssgEntity *e ) {
560 // if( ! ((SGShadowAnimation *)e->getUserData())->get_condition_value() )
564 // ssgLeaf *leaf = (ssgLeaf *) e;
565 // #ifdef _SSG_USE_DLIST
566 // dlist = leaf->getDListIndex();
568 // leaf->makeDList();
569 // dlist = leaf->getDListIndex();
574 // ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
578 // sgVec4 sunColor, ambientColor;
579 // ssgGetLight( 0 )->getColour(GL_DIFFUSE, sunColor );
580 // ssgGetLight( 0 )->getColour(GL_AMBIENT, ambientColor );
582 // // SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
583 // glEnable(GL_BLEND);
584 // glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
585 // glEnable(GL_ALPHA_TEST);
586 // glAlphaFunc(GL_GREATER, 0.0f);
589 // // sgVec4 R = {0.5,0.0,0.0,0.0};
590 // sgVec4 enviro = {1.0,0.0,0.0,1.0};
591 // // sgCopyVec4( enviro, sunColor );
592 // glActiveTexturePtr( GL_TEXTURE0_ARB );
593 // glEnable(GL_TEXTURE_2D);
594 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
595 // glActiveTexturePtr( GL_TEXTURE1_ARB );
596 // glDisable(GL_TEXTURE_2D);
597 // glEnable(GL_TEXTURE_1D);
598 // glBindTexture(GL_TEXTURE_1D, texFresnel);
599 // // c = a0 * a2 + a1 * (1-a2)
600 // // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
601 // // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
602 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
603 // glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB );
604 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_CONSTANT_ARB );
605 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
606 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB );
607 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
608 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE );
609 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR );
610 // glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, enviro);
611 // shFresnel->enable();
612 // shFresnel->bind();
613 // glCallList ( dlist ) ;
614 // shFresnel->disable();
615 // glActiveTexturePtr( GL_TEXTURE1_ARB );
616 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
617 // glDisable(GL_TEXTURE_1D);
618 // glActiveTexturePtr( GL_TEXTURE0_ARB );
619 // glDisable(GL_TEXTURE_1D);
620 // glEnable(GL_TEXTURE_2D);
623 // // glBindTexture(GL_TEXTURE_2D, 0);
624 // // glDepthFunc(GL_LESS);
625 // // glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
635 // static int chrome_shader_callback( ssgEntity *e ) {
636 // if( ! ((SGShadowAnimation *)e->getUserData())->get_condition_value() )
640 // ssgLeaf *leaf = (ssgLeaf *) e;
641 // #ifdef _SSG_USE_DLIST
642 // dlist = leaf->getDListIndex();
644 // leaf->makeDList();
645 // dlist = leaf->getDListIndex();
650 // ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
654 // SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
655 // if( ! my_shader->_depth_test )
656 // glDisable( GL_DEPTH_TEST );
658 // GLint maskTexComponent = 3;
659 // glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_COMPONENTS, &maskTexComponent);
661 // // The fake env chrome texture
662 // glActiveTexturePtr( GL_TEXTURE1_ARB );
663 // glEnable(GL_TEXTURE_2D);
665 // // No lighting is computed in spherical mapping mode because the environment
666 // // is supposed to be allready lighted. We must reshade our environment texture.
667 // sgVec4 sunColor, ambientColor, envColor;
668 // ssgGetLight( 0 )->getColour(GL_DIFFUSE, sunColor );
669 // ssgGetLight( 0 )->getColour(GL_AMBIENT, ambientColor );
670 // sgAddScaledVec3( envColor, ambientColor, sunColor, 0.4f);
671 // glBindTexture(GL_TEXTURE_2D, my_shader->_effectTexture->getHandle());
673 // sgVec3 delta_light;
674 // sgSubVec3(delta_light, envColor, my_shader->_envColor);
675 // if( (fabs(delta_light[0]) + fabs(delta_light[1]) + fabs(delta_light[2])) > 0.05f ) {
676 // sgCopyVec3( my_shader->_envColor, envColor );
677 // // reload the texture data and let the driver reshade it for us
678 // glPixelTransferf( GL_RED_SCALE, envColor[0] );
679 // glPixelTransferf( GL_GREEN_SCALE, envColor[1] );
680 // glPixelTransferf( GL_BLUE_SCALE, envColor[2] );
681 // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, my_shader->_texWidth, my_shader->_texHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, my_shader->_textureData);
682 // glPixelTransferf( GL_RED_SCALE, 1.0f );
683 // glPixelTransferf( GL_GREEN_SCALE, 1.0f );
684 // glPixelTransferf( GL_BLUE_SCALE, 1.0f );
687 // if( maskTexComponent == 4 ) {
688 // // c = lerp(model tex, chrome tex, model tex alpha)
689 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
690 // glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB );
691 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB );
692 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
693 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE );
694 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
695 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_PREVIOUS_ARB );
696 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA );
698 // glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
699 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
700 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
703 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
704 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE );
705 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
707 // glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
708 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
709 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
711 // // automatic generation of texture coordinates
714 // glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
715 // glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
716 // glEnable( GL_TEXTURE_GEN_S );
717 // glEnable( GL_TEXTURE_GEN_T );
719 // glCallList ( dlist ) ;
721 // glActiveTexturePtr( GL_TEXTURE1_ARB );
722 // glDisable( GL_TEXTURE_GEN_S );
723 // glDisable( GL_TEXTURE_GEN_T );
725 // glMatrixMode(GL_TEXTURE);
727 // glMatrixMode(GL_MODELVIEW);
729 // glDisable(GL_TEXTURE_2D);
730 // glBindTexture(GL_TEXTURE_2D, 0);
731 // glActiveTexturePtr( GL_TEXTURE0_ARB );
734 // if( ! my_shader->_depth_test )
735 // glEnable( GL_DEPTH_TEST );
744 // static void init_shaders(void) {
746 // if( false && Shader::is_VP_supported() ) {
747 // shFresnel = new Shader("/FlightGear/data/Textures/fresnel_vp.txt", "fresnel_vp");
749 // glActiveTexturePtr = (glActiveTextureProc) SGLookupFunction("glActiveTextureARB");
750 // const int fresnelSize = 512;
751 // unsigned char imageFresnel[ fresnelSize * 3 ];
752 // for(int i = 0; i < fresnelSize; i++) {
753 // const float R0 = 0.2f;
754 // float NdotV = float( i ) / float( fresnelSize );
755 // float f = R0 + (1.0f-R0)*pow(1.0f - NdotV, 5);
756 // unsigned char ff = (unsigned char) (f * 255.0);
757 // imageFresnel[i*3+0] = imageFresnel[i*3+1] = imageFresnel[i*3+2] = ff;
759 // glGenTextures( 1, &texFresnel );
760 // glBindTexture(GL_TEXTURE_1D, texFresnel );
761 // glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
762 // glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
763 // glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
764 // glTexParameteri(GL_TEXTURE_1D, GL_GENERATE_MIPMAP_SGIS, true);
765 // glTexImage1D(GL_TEXTURE_1D, 0, 3, fresnelSize, 0, GL_RGB, GL_UNSIGNED_BYTE, imageFresnel);
766 // glBindTexture(GL_TEXTURE_1D, 0 );
768 // sgMakeIdentMat4( shadIdentMatrix );
773 // ////////////////////////////////////////////////////////////////////////
774 // // Implementation of SGShaderAnimation
775 // ////////////////////////////////////////////////////////////////////////
777 SGShaderAnimation::SGShaderAnimation ( SGPropertyNode *prop_root,
778 SGPropertyNode_ptr props )
779 : SGAnimation(props, new osg::Group),
781 _condition_value(true),
783 _param_1(props->getFloatValue("param", 1.0f)),
784 _depth_test(props->getBoolValue("depth-test", true)),
785 _factor(props->getFloatValue("factor", 1.0f)),
787 _speed(props->getFloatValue("speed", 1.0f)),
794 SGPropertyNode_ptr node = props->getChild("condition");
796 _condition = sgReadCondition(prop_root, node);
797 _condition_value = false;
799 node = props->getChild("factor-prop");
801 _factor_prop = prop_root->getNode(node->getStringValue(), true);
802 node = props->getChild("speed-prop");
804 _speed_prop = prop_root->getNode(node->getStringValue(), true);
806 _envColor = osg::Vec4(0, 0, 0, 1);
807 node = props->getChild("texture");
809 _effectTexture = SGLoadTexture2D(node->getStringValue());
810 // glBindTexture(GL_TEXTURE_2D, _effectTexture->getHandle() );
811 // glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &_texWidth);
812 // glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &_texHeight);
814 // _textureData = new unsigned char[_texWidth * _texHeight * 3];
815 // glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, _textureData);
816 // glBindTexture(GL_TEXTURE_2D, 0 );
818 string shader_name = props->getStringValue("shader");
819 if( shader_name == "fresnel" || shader_name == "reflection" )
821 else if( shader_name == "heat-haze" )
823 else if( shader_name == "chrome" && _effectTexture.valid())
827 void SGShaderAnimation::init()
831 // if( _shader_type == 1 && Shader::is_VP_supported() && shFresnel)
832 // setCallBack( getBranch(), (ssgBase *) this, fresnel_shader_callback );
833 // else if( _shader_type == 2 ) {
834 // // this is the same extension with different names
835 // isRectangleTextureSupported = SGIsOpenGLExtensionSupported("GL_EXT_texture_rectangle") ||
836 // SGIsOpenGLExtensionSupported("GL_ARB_texture_rectangle") ||
837 // SGIsOpenGLExtensionSupported("GL_NV_texture_rectangle");
838 // setCallBack( getBranch(), (ssgBase *) this, heat_haze_shader_callback );
840 // else if( _shader_type == 3 )
841 // setCallBack( getBranch(), (ssgBase *) this, chrome_shader_callback );
843 // setCallBack( getBranch(), (ssgBase *) this, null_shader_callback );
846 SGShaderAnimation::~SGShaderAnimation()
853 SGShaderAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
856 _condition_value = _condition->test();
858 _factor = _factor_prop->getFloatValue();
860 _speed = _speed_prop->getFloatValue();
862 // OSGFIXME fiddle with totalTime
863 totalTime = nv->getFrameStamp()->getReferenceTime();
865 // note, callback is responsible for scenegraph traversal so
866 // should always include call traverse(node,nv) to ensure
867 // that the rest of cullbacks and the scene graph are traversed.