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 <simgear/scene/util/SGUpdateVisitor.hxx>
40 #include <simgear/threads/SGThread.hxx>
41 #include <simgear/threads/SGGuard.hxx>
43 #include <simgear/props/condition.hxx>
44 #include <simgear/props/props.hxx>
46 #include <simgear/debug/logstream.hxx>
48 #include "animation.hxx"
53 <shader>fresnel</shader>
54 <object-name>...</object-name>
59 <shader>heat-haze</shader>
60 <object-name>...</object-name>
62 <speed-prop>...</speed-prop>
64 <factor-prop>...</factor-prop>
69 <shader>chrome</shader>
70 <texture>...</texture>
71 <object-name>...</object-name>
77 <object-name>...</object-name>
78 <depth-test>false</depth-test>
84 class SGMapGenCallback :
85 public osg::StateAttribute::Callback {
87 virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
89 SGUpdateVisitor* updateVisitor = dynamic_cast<SGUpdateVisitor*>(nv);
93 if (distSqr(_lastLightDirection, updateVisitor->getLightDirection()) < 1e-4
94 && distSqr(_lastLightColor, updateVisitor->getAmbientLight()) < 1e-4)
97 _lastLightDirection = updateVisitor->getLightDirection();
98 _lastLightColor = updateVisitor->getAmbientLight();
100 osg::TextureCubeMap *tcm = static_cast<osg::TextureCubeMap*>(sa);
102 // FIXME: need an update or callback ...
103 // generate the six highlight map images (light direction = [1, 1, -1])
104 osg::ref_ptr<osgUtil::HighlightMapGenerator> mapgen;
105 mapgen = new osgUtil::HighlightMapGenerator(_lastLightDirection.osg(),
106 _lastLightColor.osg(), 5);
107 mapgen->generateMap();
109 // assign the six images to the texture object
110 tcm->setImage(osg::TextureCubeMap::POSITIVE_X,
111 mapgen->getImage(osg::TextureCubeMap::POSITIVE_X));
112 tcm->setImage(osg::TextureCubeMap::NEGATIVE_X,
113 mapgen->getImage(osg::TextureCubeMap::NEGATIVE_X));
114 tcm->setImage(osg::TextureCubeMap::POSITIVE_Y,
115 mapgen->getImage(osg::TextureCubeMap::POSITIVE_Y));
116 tcm->setImage(osg::TextureCubeMap::NEGATIVE_Y,
117 mapgen->getImage(osg::TextureCubeMap::NEGATIVE_Y));
118 tcm->setImage(osg::TextureCubeMap::POSITIVE_Z,
119 mapgen->getImage(osg::TextureCubeMap::POSITIVE_Z));
120 tcm->setImage(osg::TextureCubeMap::NEGATIVE_Z,
121 mapgen->getImage(osg::TextureCubeMap::NEGATIVE_Z));
124 SGVec3f _lastLightDirection;
125 SGVec4f _lastLightColor;
128 static osg::TextureCubeMap*
129 getOrCreateTextureCubeMap()
131 static osg::ref_ptr<osg::TextureCubeMap> textureCubeMap;
132 if (textureCubeMap.get())
133 return textureCubeMap.get();
135 static SGMutex mutex;
136 SGGuard<SGMutex> locker(mutex);
137 if (textureCubeMap.get())
138 return textureCubeMap.get();
140 // create and setup the texture object
141 textureCubeMap = new osg::TextureCubeMap;
143 textureCubeMap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);
144 textureCubeMap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);
145 textureCubeMap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP);
146 textureCubeMap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
147 textureCubeMap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
149 textureCubeMap->setUpdateCallback(new SGMapGenCallback);
151 return textureCubeMap.get();
154 static void create_specular_highlights(osg::Node *node)
156 osg::StateSet *ss = node->getOrCreateStateSet();
158 // create and setup the texture object
159 osg::TextureCubeMap *tcm = getOrCreateTextureCubeMap();
161 // enable texturing, replacing any textures in the subgraphs
162 ss->setTextureAttributeAndModes(0, tcm, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
164 // texture coordinate generation
165 osg::TexGen *tg = new osg::TexGen;
166 tg->setMode(osg::TexGen::REFLECTION_MAP);
167 ss->setTextureAttributeAndModes(0, tg, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
169 // use TexEnvCombine to add the highlights to the original lighting
170 osg::TexEnvCombine *te = new osg::TexEnvCombine;
171 te->setCombine_RGB(osg::TexEnvCombine::ADD);
172 te->setSource0_RGB(osg::TexEnvCombine::TEXTURE);
173 te->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
174 te->setSource1_RGB(osg::TexEnvCombine::PRIMARY_COLOR);
175 te->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
176 ss->setTextureAttributeAndModes(0, te, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
180 SGShaderAnimation::SGShaderAnimation(const SGPropertyNode* configNode,
181 SGPropertyNode* modelRoot,
182 const osgDB::ReaderWriter::Options*
184 SGAnimation(configNode, modelRoot)
186 const SGPropertyNode* node = configNode->getChild("texture");
188 _effect_texture = SGLoadTexture2D(node->getStringValue(), options);
192 class ChromeLightingCallback :
193 public osg::StateAttribute::Callback {
195 virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
197 SGUpdateVisitor* updateVisitor = dynamic_cast<SGUpdateVisitor*>(nv);
200 osg::TexEnvCombine *combine = dynamic_cast<osg::TexEnvCombine *>(sa);
203 // An approximation for light reflected back by chrome.
204 osg::Vec4 globalColor = (updateVisitor->getAmbientLight().osg() * .4f
205 + updateVisitor->getDiffuseLight().osg());
206 globalColor.a() = 1.0f;
207 combine->setConstantColor(globalColor);
211 typedef std::map<osg::ref_ptr<osg::Texture2D>, osg::ref_ptr<osg::StateSet> >
215 // The chrome effect is mixed by the alpha channel of the texture
216 // on the model, which will be attached to a node lower in the scene
217 // graph: 0 -> completely chrome, 1 -> completely model texture.
218 static void create_chrome(osg::Group* group, osg::Texture2D* texture)
220 static SGMutex mutex;
221 SGGuard<SGMutex> locker(mutex);
222 static StateSetMap chromeMap;
223 osg::StateSet *stateSet;
224 StateSetMap::iterator iterator = chromeMap.find(texture);
225 if (iterator != chromeMap.end()) {
226 stateSet = iterator->second.get();
228 stateSet = new osg::StateSet;
229 // If the model doesn't have any texture, we need to have one
230 // activated so that we don't need a seperate combiner
231 // attribute for the non-textured case. This texture will be
232 // shadowed by any attached to the model.
233 osg::Image *dummyImage = new osg::Image;
234 dummyImage->allocateImage(1, 1, 1, GL_LUMINANCE_ALPHA,
236 unsigned char* imageBytes = dummyImage->data(0, 0);
239 osg::Texture2D* dummyTexture = new osg::Texture2D;
240 dummyTexture->setImage(dummyImage);
241 dummyTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
242 dummyTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
243 stateSet->setTextureAttributeAndModes(0, dummyTexture,
244 osg::StateAttribute::ON);
245 osg::TexEnvCombine* combine0 = new osg::TexEnvCombine;
246 osg::TexEnvCombine* combine1 = new osg::TexEnvCombine;
247 osg::TexGen* texGen = new osg::TexGen;
248 // Mix the environmental light color and the chrome map on texture
250 combine0->setCombine_RGB(osg::TexEnvCombine::MODULATE);
251 combine0->setSource0_RGB(osg::TexEnvCombine::CONSTANT);
252 combine0->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
253 combine0->setSource1_RGB(osg::TexEnvCombine::TEXTURE1);
254 combine0->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
255 combine0->setDataVariance(osg::Object::DYNAMIC);
256 combine0->setUpdateCallback(new ChromeLightingCallback);
258 // Interpolate the colored chrome map with the texture on the
259 // model, using the model texture's alpha.
260 combine1->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE);
261 combine1->setSource0_RGB(osg::TexEnvCombine::TEXTURE0);
262 combine1->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
263 combine1->setSource1_RGB(osg::TexEnvCombine::PREVIOUS);
264 combine1->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
265 combine1->setSource2_RGB(osg::TexEnvCombine::TEXTURE0);
266 combine1->setOperand2_RGB(osg::TexEnvCombine::SRC_ALPHA);
267 // Are these used for anything?
268 combine1->setCombine_Alpha(osg::TexEnvCombine::REPLACE);
269 combine1->setSource0_Alpha(osg::TexEnvCombine::TEXTURE1);
270 combine1->setOperand0_Alpha(osg::TexEnvCombine::SRC_ALPHA);
272 texGen->setMode(osg::TexGen::SPHERE_MAP);
273 stateSet->setTextureAttribute(0, combine0);
274 stateSet->setTextureAttribute(1, combine1);
275 stateSet->setTextureAttributeAndModes(1, texture,
276 osg::StateAttribute::ON);
277 stateSet->setTextureAttributeAndModes(1, texGen,
278 osg::StateAttribute::ON);
279 chromeMap[texture] = stateSet;
281 group->setStateSet(stateSet);
285 SGShaderAnimation::createAnimationGroup(osg::Group& parent)
287 osg::Group* group = new osg::Group;
288 group->setName("shader animation");
289 parent.addChild(group);
291 std::string shader_name = getConfig()->getStringValue("shader", "");
292 // if( shader_name == "fresnel" || shader_name == "reflection" )
294 // else if( shader_name == "heat-haze" )
297 if( shader_name == "chrome")
299 create_specular_highlights(group);
301 create_chrome(group, _effect_texture.get());
306 // static Shader *shFresnel=NULL;
307 // static GLuint texFresnel = 0;
309 // static GLuint texBackground = 0;
310 // static int texBackgroundWidth = 1024, texBackgroundHeight = 1024;
311 // static GLenum texBackgroundTarget = GL_TEXTURE_2D;
312 // static bool isRectangleTextureSupported = false;
313 // static bool istexBackgroundRectangle = false;
314 // static bool initDone = false;
315 static bool haveBackground = false;
317 // static glActiveTextureProc glActiveTexturePtr = 0;
318 // static sgMat4 shadIdentMatrix;
321 // static int null_shader_callback( ssgEntity *e ) {
323 // ssgLeaf *leaf = (ssgLeaf *) e;
324 // #ifdef _SSG_USE_DLIST
325 // dlist = leaf->getDListIndex();
327 // leaf->makeDList();
328 // dlist = leaf->getDListIndex();
333 // ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
337 // SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
338 // if( ! my_shader->_depth_test )
339 // glDisable( GL_DEPTH_TEST );
340 // glCallList ( dlist ) ;
342 // if( ! my_shader->_depth_test )
343 // glEnable( GL_DEPTH_TEST );
349 // static int heat_haze_shader_callback( ssgEntity *e ) {
350 // if( ! ((SGShadowAnimation *)e->getUserData())->get_condition_value() )
354 // ssgLeaf *leaf = (ssgLeaf *) e;
355 // #ifdef _SSG_USE_DLIST
356 // dlist = leaf->getDListIndex();
358 // leaf->makeDList();
359 // dlist = leaf->getDListIndex();
365 // GLint viewport[4];
366 // glGetIntegerv( GL_VIEWPORT, viewport );
367 // const int screen_width = viewport[2];
368 // const int screen_height = viewport[3];
369 // if( ! haveBackground ) {
370 // // store the backbuffer in a texture
371 // if( ! texBackground ) {
372 // // allocate our texture here so we don't waste memory if no model use that effect
373 // // check if we need a rectangle texture and if the card support it
374 // if( (screen_width > 1024 || screen_height > 1024) && isRectangleTextureSupported ) {
375 // // Note that the 3 (same) extensions use the same enumerants
376 // texBackgroundTarget = GL_TEXTURE_RECTANGLE_NV;
377 // istexBackgroundRectangle = true;
378 // texBackgroundWidth = screen_width;
379 // texBackgroundHeight = screen_height;
381 // glGenTextures(1, &texBackground);
382 // glEnable(texBackgroundTarget);
383 // glBindTexture(texBackgroundTarget, texBackground);
384 // // trying to match the backbuffer pixel format
385 // GLint internalFormat = GL_RGB8;
386 // GLint colorBits = 0, alphaBits = 0;
387 // glGetIntegerv( GL_BLUE_BITS, &colorBits );
388 // glGetIntegerv( GL_ALPHA_BITS, &alphaBits );
389 // if(colorBits == 5) {
390 // if( alphaBits == 0 )
391 // internalFormat = GL_RGB5;
393 // internalFormat = GL_RGB5_A1;
395 // if( alphaBits != 0 )
396 // internalFormat = GL_RGBA8;
398 // glTexImage2D(texBackgroundTarget, 0, internalFormat,
399 // texBackgroundWidth, texBackgroundHeight, 0, GL_RGB, GL_FLOAT, NULL);
401 // glTexParameteri(texBackgroundTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
402 // glTexParameteri(texBackgroundTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
403 // glTexParameteri(texBackgroundTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
404 // glTexParameteri(texBackgroundTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
406 // glEnable(texBackgroundTarget);
407 // glBindTexture(texBackgroundTarget, texBackground);
408 // // center of texture = center of screen
409 // // obviously we don't have the whole screen if screen_width > texBackgroundWidth
410 // // if rectangle textures are not supported, this give some artifacts on the borders
411 // if( istexBackgroundRectangle ) {
412 // glCopyTexSubImage2D( texBackgroundTarget, 0, 0, 0,
413 // 0, 0, texBackgroundWidth, texBackgroundHeight );
415 // glCopyTexSubImage2D( texBackgroundTarget, 0, 0, 0,
416 // (screen_width - texBackgroundWidth) / 2,
417 // (screen_height - texBackgroundHeight) / 2,
418 // texBackgroundWidth, texBackgroundHeight );
420 // haveBackground = true;
421 // glBindTexture(texBackgroundTarget, 0);
422 // glDisable(texBackgroundTarget);
424 // ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
428 // SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
429 // if( ! my_shader->_depth_test )
430 // glDisable( GL_DEPTH_TEST );
431 // glDepthMask( GL_FALSE );
432 // glDisable( GL_LIGHTING );
434 // // noise texture, tex coord from the model translated by a time factor
435 // glActiveTexturePtr( GL_TEXTURE0_ARB );
436 // glEnable(GL_TEXTURE_2D);
437 // const float noiseDist = fmod(- totalTime * my_shader->_factor * my_shader->_speed, 4.0);
438 // glMatrixMode(GL_TEXTURE);
440 // glTranslatef( noiseDist, 0.0f, 0.0f );
441 // glMatrixMode(GL_MODELVIEW);
443 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
445 // // background texture
446 // glActiveTexturePtr( GL_TEXTURE1_ARB );
447 // glEnable(texBackgroundTarget);
448 // glBindTexture(texBackgroundTarget, texBackground);
450 // // automatic generation of texture coordinates
451 // // map to screen space
452 // sgMat4 CameraProjM, CameraViewM;
453 // glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *) CameraProjM);
454 // glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) CameraViewM);
455 // // const float dummy_scale = 1.0f; //0.95f;
456 // const float deltaPos = 0.05f;
457 // glMatrixMode(GL_TEXTURE);
459 // if( istexBackgroundRectangle ) {
460 // // coords go from 0.0 to n, not from 0.0 to 1.0
461 // glTranslatef( texBackgroundWidth * 0.5f, texBackgroundHeight * 0.5f, 0.0f );
462 // glScalef( texBackgroundWidth * 0.5f,
463 // texBackgroundHeight * 0.5f, 1.0f );
465 // glTranslatef( 0.5f, 0.5f, 0.0f );
466 // glScalef( float( screen_width ) / float( texBackgroundWidth ) * 0.5f,
467 // float( screen_height ) / float( texBackgroundHeight ) * 0.5f, 1.0f );
469 // glMultMatrixf( (GLfloat *) CameraProjM );
470 // glMultMatrixf( (GLfloat *) CameraViewM );
471 // glTranslatef( deltaPos, deltaPos, deltaPos );
472 // glMatrixMode(GL_MODELVIEW);
474 // glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
475 // glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
476 // glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
477 // glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
478 // glTexGenfv( GL_S, GL_EYE_PLANE, shadIdentMatrix[0] );
479 // glTexGenfv( GL_T, GL_EYE_PLANE, shadIdentMatrix[1] );
480 // glTexGenfv( GL_R, GL_EYE_PLANE, shadIdentMatrix[2] );
481 // glTexGenfv( GL_Q, GL_EYE_PLANE, shadIdentMatrix[3] );
482 // glEnable( GL_TEXTURE_GEN_S );
483 // glEnable( GL_TEXTURE_GEN_T );
484 // glEnable( GL_TEXTURE_GEN_R );
485 // glEnable( GL_TEXTURE_GEN_Q );
487 // sgVec4 enviro = {1.00f, 1.00f, 1.00f, 0.85f};
489 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
490 // glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE );
491 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE );
492 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
493 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT_ARB );
494 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
495 // glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, enviro);
497 // glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
498 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE0_ARB);
499 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
500 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PRIMARY_COLOR_ARB );
501 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA );
503 // glCallList ( dlist ) ;
504 // glMatrixMode(GL_TEXTURE);
505 // glTranslatef( - deltaPos*2.0f, -deltaPos*2.5f, -deltaPos*2.0f );
506 // glMatrixMode(GL_MODELVIEW);
507 // glCallList ( dlist ) ;
509 // // alter colors only on last rendering
510 // // sgVec4 fLight = {0.93f, 0.93f, 1.00f, 0.85f};
511 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB );
512 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
514 // glMatrixMode(GL_TEXTURE);
515 // glTranslatef( deltaPos*0.7f, deltaPos*1.7f, deltaPos*0.7f );
516 // glMatrixMode(GL_MODELVIEW);
517 // glCallList ( dlist ) ;
520 // glActiveTexturePtr( GL_TEXTURE1_ARB );
521 // glDisable( GL_TEXTURE_GEN_S );
522 // glDisable( GL_TEXTURE_GEN_T );
523 // glDisable( GL_TEXTURE_GEN_R );
524 // glDisable( GL_TEXTURE_GEN_Q );
525 // glMatrixMode(GL_TEXTURE);
527 // glMatrixMode(GL_MODELVIEW);
528 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
529 // glDisable(texBackgroundTarget);
530 // glActiveTexturePtr( GL_TEXTURE0_ARB );
531 // glMatrixMode(GL_TEXTURE);
533 // glMatrixMode(GL_MODELVIEW);
534 // glEnable(GL_TEXTURE_2D);
535 // glBindTexture(GL_TEXTURE_2D, 0);
538 // if( ! my_shader->_depth_test )
539 // glEnable( GL_DEPTH_TEST );
541 // glEnable( GL_LIGHTING );
542 // glDepthMask( GL_TRUE );
550 // static int fresnel_shader_callback( ssgEntity *e ) {
551 // if( ! ((SGShadowAnimation *)e->getUserData())->get_condition_value() )
555 // ssgLeaf *leaf = (ssgLeaf *) e;
556 // #ifdef _SSG_USE_DLIST
557 // dlist = leaf->getDListIndex();
559 // leaf->makeDList();
560 // dlist = leaf->getDListIndex();
565 // ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
569 // sgVec4 sunColor, ambientColor;
570 // ssgGetLight( 0 )->getColour(GL_DIFFUSE, sunColor );
571 // ssgGetLight( 0 )->getColour(GL_AMBIENT, ambientColor );
573 // // SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
574 // glEnable(GL_BLEND);
575 // glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
576 // glEnable(GL_ALPHA_TEST);
577 // glAlphaFunc(GL_GREATER, 0.0f);
580 // // sgVec4 R = {0.5,0.0,0.0,0.0};
581 // sgVec4 enviro = {1.0,0.0,0.0,1.0};
582 // // sgCopyVec4( enviro, sunColor );
583 // glActiveTexturePtr( GL_TEXTURE0_ARB );
584 // glEnable(GL_TEXTURE_2D);
585 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
586 // glActiveTexturePtr( GL_TEXTURE1_ARB );
587 // glDisable(GL_TEXTURE_2D);
588 // glEnable(GL_TEXTURE_1D);
589 // glBindTexture(GL_TEXTURE_1D, texFresnel);
590 // // c = a0 * a2 + a1 * (1-a2)
591 // // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
592 // // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
593 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
594 // glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB );
595 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_CONSTANT_ARB );
596 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
597 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB );
598 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
599 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE );
600 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR );
601 // glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, enviro);
602 // shFresnel->enable();
603 // shFresnel->bind();
604 // glCallList ( dlist ) ;
605 // shFresnel->disable();
606 // glActiveTexturePtr( GL_TEXTURE1_ARB );
607 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
608 // glDisable(GL_TEXTURE_1D);
609 // glActiveTexturePtr( GL_TEXTURE0_ARB );
610 // glDisable(GL_TEXTURE_1D);
611 // glEnable(GL_TEXTURE_2D);
614 // // glBindTexture(GL_TEXTURE_2D, 0);
615 // // glDepthFunc(GL_LESS);
616 // // glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
626 // static int chrome_shader_callback( ssgEntity *e ) {
627 // if( ! ((SGShadowAnimation *)e->getUserData())->get_condition_value() )
631 // ssgLeaf *leaf = (ssgLeaf *) e;
632 // #ifdef _SSG_USE_DLIST
633 // dlist = leaf->getDListIndex();
635 // leaf->makeDList();
636 // dlist = leaf->getDListIndex();
641 // ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
645 // SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
646 // if( ! my_shader->_depth_test )
647 // glDisable( GL_DEPTH_TEST );
649 // GLint maskTexComponent = 3;
650 // glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_COMPONENTS, &maskTexComponent);
652 // // The fake env chrome texture
653 // glActiveTexturePtr( GL_TEXTURE1_ARB );
654 // glEnable(GL_TEXTURE_2D);
656 // // No lighting is computed in spherical mapping mode because the environment
657 // // is supposed to be allready lighted. We must reshade our environment texture.
658 // sgVec4 sunColor, ambientColor, envColor;
659 // ssgGetLight( 0 )->getColour(GL_DIFFUSE, sunColor );
660 // ssgGetLight( 0 )->getColour(GL_AMBIENT, ambientColor );
661 // sgAddScaledVec3( envColor, ambientColor, sunColor, 0.4f);
662 // glBindTexture(GL_TEXTURE_2D, my_shader->_effectTexture->getHandle());
664 // sgVec3 delta_light;
665 // sgSubVec3(delta_light, envColor, my_shader->_envColor);
666 // if( (fabs(delta_light[0]) + fabs(delta_light[1]) + fabs(delta_light[2])) > 0.05f ) {
667 // sgCopyVec3( my_shader->_envColor, envColor );
668 // // reload the texture data and let the driver reshade it for us
669 // glPixelTransferf( GL_RED_SCALE, envColor[0] );
670 // glPixelTransferf( GL_GREEN_SCALE, envColor[1] );
671 // glPixelTransferf( GL_BLUE_SCALE, envColor[2] );
672 // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, my_shader->_texWidth, my_shader->_texHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, my_shader->_textureData);
673 // glPixelTransferf( GL_RED_SCALE, 1.0f );
674 // glPixelTransferf( GL_GREEN_SCALE, 1.0f );
675 // glPixelTransferf( GL_BLUE_SCALE, 1.0f );
678 // if( maskTexComponent == 4 ) {
679 // // c = lerp(model tex, chrome tex, model tex alpha)
680 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
681 // glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB );
682 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB );
683 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
684 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE );
685 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
686 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_PREVIOUS_ARB );
687 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA );
689 // glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
690 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
691 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
694 // glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
695 // glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE );
696 // glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
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);
702 // // automatic generation of texture coordinates
705 // glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
706 // glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
707 // glEnable( GL_TEXTURE_GEN_S );
708 // glEnable( GL_TEXTURE_GEN_T );
710 // glCallList ( dlist ) ;
712 // glActiveTexturePtr( GL_TEXTURE1_ARB );
713 // glDisable( GL_TEXTURE_GEN_S );
714 // glDisable( GL_TEXTURE_GEN_T );
716 // glMatrixMode(GL_TEXTURE);
718 // glMatrixMode(GL_MODELVIEW);
720 // glDisable(GL_TEXTURE_2D);
721 // glBindTexture(GL_TEXTURE_2D, 0);
722 // glActiveTexturePtr( GL_TEXTURE0_ARB );
725 // if( ! my_shader->_depth_test )
726 // glEnable( GL_DEPTH_TEST );
735 // static void init_shaders(void) {
737 // if( false && Shader::is_VP_supported() ) {
738 // shFresnel = new Shader("/FlightGear/data/Textures/fresnel_vp.txt", "fresnel_vp");
740 // glActiveTexturePtr = (glActiveTextureProc) SGLookupFunction("glActiveTextureARB");
741 // const int fresnelSize = 512;
742 // unsigned char imageFresnel[ fresnelSize * 3 ];
743 // for(int i = 0; i < fresnelSize; i++) {
744 // const float R0 = 0.2f;
745 // float NdotV = float( i ) / float( fresnelSize );
746 // float f = R0 + (1.0f-R0)*pow(1.0f - NdotV, 5);
747 // unsigned char ff = (unsigned char) (f * 255.0);
748 // imageFresnel[i*3+0] = imageFresnel[i*3+1] = imageFresnel[i*3+2] = ff;
750 // glGenTextures( 1, &texFresnel );
751 // glBindTexture(GL_TEXTURE_1D, texFresnel );
752 // glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
753 // glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
754 // glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
755 // glTexParameteri(GL_TEXTURE_1D, GL_GENERATE_MIPMAP_SGIS, true);
756 // glTexImage1D(GL_TEXTURE_1D, 0, 3, fresnelSize, 0, GL_RGB, GL_UNSIGNED_BYTE, imageFresnel);
757 // glBindTexture(GL_TEXTURE_1D, 0 );
759 // sgMakeIdentMat4( shadIdentMatrix );
764 // ////////////////////////////////////////////////////////////////////////
765 // // Implementation of SGShaderAnimation
766 // ////////////////////////////////////////////////////////////////////////
768 SGShaderAnimation::SGShaderAnimation ( SGPropertyNode *prop_root,
769 SGPropertyNode_ptr props )
770 : SGAnimation(props, new osg::Group),
772 _condition_value(true),
774 _param_1(props->getFloatValue("param", 1.0f)),
775 _depth_test(props->getBoolValue("depth-test", true)),
776 _factor(props->getFloatValue("factor", 1.0f)),
778 _speed(props->getFloatValue("speed", 1.0f)),
785 SGPropertyNode_ptr node = props->getChild("condition");
787 _condition = sgReadCondition(prop_root, node);
788 _condition_value = false;
790 node = props->getChild("factor-prop");
792 _factor_prop = prop_root->getNode(node->getStringValue(), true);
793 node = props->getChild("speed-prop");
795 _speed_prop = prop_root->getNode(node->getStringValue(), true);
797 _envColor = osg::Vec4(0, 0, 0, 1);
798 node = props->getChild("texture");
800 _effectTexture = SGLoadTexture2D(node->getStringValue());
801 // glBindTexture(GL_TEXTURE_2D, _effectTexture->getHandle() );
802 // glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &_texWidth);
803 // glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &_texHeight);
805 // _textureData = new unsigned char[_texWidth * _texHeight * 3];
806 // glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, _textureData);
807 // glBindTexture(GL_TEXTURE_2D, 0 );
809 string shader_name = props->getStringValue("shader");
810 if( shader_name == "fresnel" || shader_name == "reflection" )
812 else if( shader_name == "heat-haze" )
814 else if( shader_name == "chrome" && _effectTexture.valid())
818 void SGShaderAnimation::init()
822 // if( _shader_type == 1 && Shader::is_VP_supported() && shFresnel)
823 // setCallBack( getBranch(), (ssgBase *) this, fresnel_shader_callback );
824 // else if( _shader_type == 2 ) {
825 // // this is the same extension with different names
826 // isRectangleTextureSupported = SGIsOpenGLExtensionSupported("GL_EXT_texture_rectangle") ||
827 // SGIsOpenGLExtensionSupported("GL_ARB_texture_rectangle") ||
828 // SGIsOpenGLExtensionSupported("GL_NV_texture_rectangle");
829 // setCallBack( getBranch(), (ssgBase *) this, heat_haze_shader_callback );
831 // else if( _shader_type == 3 )
832 // setCallBack( getBranch(), (ssgBase *) this, chrome_shader_callback );
834 // setCallBack( getBranch(), (ssgBase *) this, null_shader_callback );
837 SGShaderAnimation::~SGShaderAnimation()
844 SGShaderAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
847 _condition_value = _condition->test();
849 _factor = _factor_prop->getFloatValue();
851 _speed = _speed_prop->getFloatValue();
853 // OSGFIXME fiddle with totalTime
854 totalTime = nv->getFrameStamp()->getReferenceTime();
856 // note, callback is responsible for scenegraph traversal so
857 // should always include call traverse(node,nv) to ensure
858 // that the rest of cullbacks and the scene graph are traversed.