]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/shadanim.cxx
Don't modify OSG Registry with file path
[simgear.git] / simgear / scene / model / shadanim.cxx
1 // non fixed Opengl pipeline rendering
2 //
3 // Written by Harald JOHNSEN, started Jully 2005.
4 //
5 // Copyright (C) 2005  Harald JOHNSEN
6 //
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.
11 //
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.
16 //
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.
20 //
21 //
22
23 #ifdef HAVE_CONFIG_H
24 #  include <simgear_config.h>
25 #endif
26
27 #include <map>
28
29 #include <osg/Group>
30 #include <osg/Program>
31 #include <osg/Shader>
32 #include <osg/StateSet>
33 #include <osg/TextureCubeMap>
34 #include <osg/TexEnvCombine>
35 #include <osg/TexGen>
36 #include <osg/Texture1D>
37 #include <osgUtil/HighlightMapGenerator>
38
39 #include <simgear/scene/util/SGUpdateVisitor.hxx>
40 #include <simgear/threads/SGThread.hxx>
41 #include <simgear/threads/SGGuard.hxx>
42
43 #include <simgear/props/condition.hxx>
44 #include <simgear/props/props.hxx>
45
46 #include <simgear/debug/logstream.hxx>
47
48 #include "animation.hxx"
49 #include "model.hxx"
50 /*
51     <animation>
52         <type>shader</type>
53         <shader>fresnel</shader>
54         <object-name>...</object-name>
55     </animation>
56
57     <animation>
58         <type>shader</type>
59         <shader>heat-haze</shader>
60         <object-name>...</object-name>
61         <speed>...</speed>
62         <speed-prop>...</speed-prop>
63         <factor>...</factor>
64         <factor-prop>...</factor-prop>
65     </animation>
66
67     <animation>
68         <type>shader</type>
69         <shader>chrome</shader>
70         <texture>...</texture>
71         <object-name>...</object-name>
72     </animation>
73
74     <animation>
75         <type>shader</type>
76         <shader></shader>
77         <object-name>...</object-name>
78         <depth-test>false</depth-test>
79     </animation>
80
81 */
82
83
84 class SGMapGenCallback :
85   public osg::StateAttribute::Callback {
86 public:
87   virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
88   {
89     SGUpdateVisitor* updateVisitor = dynamic_cast<SGUpdateVisitor*>(nv);
90     if (!updateVisitor)
91       return;
92
93     if (distSqr(_lastLightDirection, updateVisitor->getLightDirection()) < 1e-4
94         && distSqr(_lastLightColor, updateVisitor->getAmbientLight()) < 1e-4)
95       return;
96
97     _lastLightDirection = updateVisitor->getLightDirection();
98     _lastLightColor = updateVisitor->getAmbientLight();
99
100     osg::TextureCubeMap *tcm = static_cast<osg::TextureCubeMap*>(sa);
101
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();
108
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));
122   }
123 private:
124   SGVec3f _lastLightDirection;
125   SGVec4f _lastLightColor;
126 };
127
128 static osg::TextureCubeMap*
129 getOrCreateTextureCubeMap()
130 {
131   static osg::ref_ptr<osg::TextureCubeMap> textureCubeMap;
132   if (textureCubeMap.get())
133     return textureCubeMap.get();
134
135   static SGMutex mutex;
136   SGGuard<SGMutex> locker(mutex);
137   if (textureCubeMap.get())
138     return textureCubeMap.get();
139
140   // create and setup the texture object
141   textureCubeMap = new osg::TextureCubeMap;
142
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);    
148   
149   textureCubeMap->setUpdateCallback(new SGMapGenCallback);
150
151   return textureCubeMap.get();
152 }
153
154 static void create_specular_highlights(osg::Node *node)
155 {
156   osg::StateSet *ss = node->getOrCreateStateSet();
157   
158   // create and setup the texture object
159   osg::TextureCubeMap *tcm = getOrCreateTextureCubeMap();
160   
161   // enable texturing, replacing any textures in the subgraphs
162   ss->setTextureAttributeAndModes(0, tcm, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
163   
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);
168   
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);
177 }
178
179
180 SGShaderAnimation::SGShaderAnimation(const SGPropertyNode* configNode,
181                                      SGPropertyNode* modelRoot,
182                                      const osgDB::ReaderWriter::Options*
183                                      options) :
184   SGAnimation(configNode, modelRoot)
185 {
186   const SGPropertyNode* node = configNode->getChild("texture");
187   if (node)
188     _effect_texture = SGLoadTexture2D(node->getStringValue(), options);
189 }
190
191 namespace {
192 class ChromeLightingCallback :
193   public osg::StateAttribute::Callback {
194 public:
195   virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
196   {
197     SGUpdateVisitor* updateVisitor = dynamic_cast<SGUpdateVisitor*>(nv);
198     if (!updateVisitor)
199       return;
200     osg::TexEnvCombine *combine = dynamic_cast<osg::TexEnvCombine *>(sa);
201     if (!combine)
202         return;
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);
208   }
209 };
210     
211 typedef map<osg::ref_ptr<osg::Texture2D>, osg::ref_ptr<osg::StateSet> >
212 StateSetMap;
213 }
214
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)
219 {
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();
227     } else {
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,
235                                   GL_UNSIGNED_BYTE);
236         unsigned char* imageBytes = dummyImage->data(0, 0);
237         imageBytes[0] = 255;
238         imageBytes[1] = 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
249         // unit 0
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);
257
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);
271     
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;
280     }
281     group->setStateSet(stateSet);
282 }
283
284 osg::Group*
285 SGShaderAnimation::createAnimationGroup(osg::Group& parent)
286 {
287   osg::Group* group = new osg::Group;
288   group->setName("shader animation");
289   parent.addChild(group);
290
291   std::string shader_name = getConfig()->getStringValue("shader", "");
292 //   if( shader_name == "fresnel" || shader_name == "reflection" )
293 //     _shader_type = 1;
294 //   else if( shader_name == "heat-haze" )
295 //     _shader_type = 2;
296 //   else
297   if( shader_name == "chrome")
298 #if 0
299     create_specular_highlights(group);
300 #endif
301   create_chrome(group, _effect_texture.get());
302   return group;
303 }
304
305 #if 0
306 // static Shader *shFresnel=NULL;
307 // static GLuint texFresnel = 0;
308
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;
316
317 // static glActiveTextureProc glActiveTexturePtr = 0;
318 // static sgMat4 shadIdentMatrix;
319
320
321 // static int null_shader_callback( ssgEntity *e ) {
322 //      GLuint dlist = 0;
323 //     ssgLeaf *leaf = (ssgLeaf *) e;
324 // #ifdef _SSG_USE_DLIST
325 //     dlist = leaf->getDListIndex();
326 //     if( ! dlist ) {
327 //         leaf->makeDList();
328 //         dlist = leaf->getDListIndex();
329 //     }
330 // #endif
331 //     if( ! dlist )
332 //         return true;
333 //     ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
334 //     if ( sst )
335 //         sst->apply();
336
337 //     SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
338 //     if( ! my_shader->_depth_test )
339 //         glDisable( GL_DEPTH_TEST );
340 //     glCallList ( dlist ) ;
341 //     // restore states
342 //     if( ! my_shader->_depth_test )
343 //         glEnable( GL_DEPTH_TEST );
344
345 //     // don't draw !
346 //     return false;
347 // }
348
349 // static int heat_haze_shader_callback( ssgEntity *e ) {
350 //    if( ! ((SGShadowAnimation *)e->getUserData())->get_condition_value() )
351 //        return true;
352
353 //      GLuint dlist = 0;
354 //     ssgLeaf *leaf = (ssgLeaf *) e;
355 // #ifdef _SSG_USE_DLIST
356 //     dlist = leaf->getDListIndex();
357 //     if( ! dlist ) {
358 //         leaf->makeDList();
359 //         dlist = leaf->getDListIndex();
360 //     }
361 // #endif
362 //     if( ! dlist )
363 //         return true;
364
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;
380 //             }
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;
392 //                 else
393 //                     internalFormat = GL_RGB5_A1;
394 //             } else {
395 //                 if( alphaBits != 0 )
396 //                     internalFormat = GL_RGBA8;
397 //             }
398 //             glTexImage2D(texBackgroundTarget, 0, internalFormat, 
399 //                             texBackgroundWidth, texBackgroundHeight, 0, GL_RGB, GL_FLOAT, NULL);
400
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);
405 //         }
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 );
414 //         } else {
415 //             glCopyTexSubImage2D( texBackgroundTarget, 0, 0, 0, 
416 //                 (screen_width - texBackgroundWidth) / 2, 
417 //                 (screen_height - texBackgroundHeight) / 2, 
418 //                 texBackgroundWidth, texBackgroundHeight );
419 //         }
420 //         haveBackground = true;
421 //         glBindTexture(texBackgroundTarget, 0);
422 //         glDisable(texBackgroundTarget);
423 //     }
424 //     ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
425 //     if ( sst )
426 //         sst->apply();
427
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 );
433 //     if(1) {
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);
439 //             glLoadIdentity();
440 //             glTranslatef( noiseDist, 0.0f, 0.0f );
441 //         glMatrixMode(GL_MODELVIEW);
442
443 //         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
444
445 //         // background texture
446 //         glActiveTexturePtr( GL_TEXTURE1_ARB );
447 //         glEnable(texBackgroundTarget);
448 //         glBindTexture(texBackgroundTarget, texBackground);
449
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);
458 //             glLoadIdentity();
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 );
464 //             } else {
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 );
468 //             }
469 //             glMultMatrixf( (GLfloat *) CameraProjM );
470 //             glMultMatrixf( (GLfloat *) CameraViewM );
471 //             glTranslatef( deltaPos, deltaPos, deltaPos );
472 //         glMatrixMode(GL_MODELVIEW);
473
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 );
486
487 //         sgVec4 enviro = {1.00f, 1.00f, 1.00f, 0.85f};
488
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);
496
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 ); 
502
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 ) ;
508
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 ); 
513
514 //         glMatrixMode(GL_TEXTURE);
515 //         glTranslatef( deltaPos*0.7f, deltaPos*1.7f, deltaPos*0.7f );
516 //         glMatrixMode(GL_MODELVIEW);
517 //         glCallList ( dlist ) ;
518
519
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);
526 //             glLoadIdentity();
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);
532 //             glLoadIdentity();
533 //         glMatrixMode(GL_MODELVIEW);
534 //         glEnable(GL_TEXTURE_2D);
535 //         glBindTexture(GL_TEXTURE_2D, 0);
536 //     }
537 //     // restore states
538 //     if( ! my_shader->_depth_test )
539 //         glEnable( GL_DEPTH_TEST );
540
541 //     glEnable( GL_LIGHTING );
542 //     glDepthMask( GL_TRUE );
543 //     if( sst )
544 //         sst->force();
545
546 //    // don't draw !
547 //     return false;
548 // }
549
550 // static int fresnel_shader_callback( ssgEntity *e ) {
551 //    if( ! ((SGShadowAnimation *)e->getUserData())->get_condition_value() )
552 //        return true;
553
554 //      GLuint dlist = 0;
555 //     ssgLeaf *leaf = (ssgLeaf *) e;
556 // #ifdef _SSG_USE_DLIST
557 //     dlist = leaf->getDListIndex();
558 //     if( ! dlist ) {
559 //         leaf->makeDList();
560 //         dlist = leaf->getDListIndex();
561 //     }
562 // #endif
563 //     if( ! dlist )
564 //         return true;
565 //     ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
566 //     if ( sst )
567 //         sst->apply();
568
569 //     sgVec4 sunColor, ambientColor;
570 //     ssgGetLight( 0 )->getColour(GL_DIFFUSE, sunColor );
571 //     ssgGetLight( 0 )->getColour(GL_AMBIENT, ambientColor );
572
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);
578
579 //      if( true ) {
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);
612 //     }
613 //     // restore states
614 // //    glBindTexture(GL_TEXTURE_2D, 0);
615 // //    glDepthFunc(GL_LESS);
616 // //    glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
617 //    if( sst )
618 //          sst->force();
619
620 //     // don't draw !
621 //     return false;
622 // }
623
624
625
626 // static int chrome_shader_callback( ssgEntity *e ) {
627 //    if( ! ((SGShadowAnimation *)e->getUserData())->get_condition_value() )
628 //        return true;
629
630 //      GLuint dlist = 0;
631 //     ssgLeaf *leaf = (ssgLeaf *) e;
632 // #ifdef _SSG_USE_DLIST
633 //     dlist = leaf->getDListIndex();
634 //     if( ! dlist ) {
635 //         leaf->makeDList();
636 //         dlist = leaf->getDListIndex();
637 //     }
638 // #endif
639 //     if( ! dlist )
640 //         return true;
641 //     ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
642 //     if ( sst )
643 //         sst->apply();
644
645 //     SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
646 //     if( ! my_shader->_depth_test )
647 //         glDisable( GL_DEPTH_TEST );
648
649 //     GLint maskTexComponent = 3;
650 //     glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_COMPONENTS, &maskTexComponent);
651
652 //     // The fake env chrome texture
653 //     glActiveTexturePtr( GL_TEXTURE1_ARB );
654 //     glEnable(GL_TEXTURE_2D);
655 //     {
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());
663
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 );
676 //         }
677 //     }
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 ); 
688
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);
692 //     } else {
693 //         // c = chrome tex
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 ); 
697
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);
701 //     }
702 //     // automatic generation of texture coordinates
703 //     // from normals
704
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 );
709
710 //     glCallList ( dlist ) ;
711
712 //     glActiveTexturePtr( GL_TEXTURE1_ARB );
713 //     glDisable( GL_TEXTURE_GEN_S );
714 //     glDisable( GL_TEXTURE_GEN_T );
715
716 //     glMatrixMode(GL_TEXTURE);
717 //         glLoadIdentity();
718 //     glMatrixMode(GL_MODELVIEW);
719
720 //     glDisable(GL_TEXTURE_2D);
721 //     glBindTexture(GL_TEXTURE_2D, 0);
722 //     glActiveTexturePtr( GL_TEXTURE0_ARB );
723
724 //     // restore states
725 //     if( ! my_shader->_depth_test )
726 //         glEnable( GL_DEPTH_TEST );
727
728 //     if( sst )
729 //         sst->force();
730
731 //    // don't draw !
732 //     return false;
733 // }
734
735 // static void init_shaders(void) {
736 //      Shader::Init();
737 //     if( false && Shader::is_VP_supported() ) {
738 //          shFresnel = new Shader("/FlightGear/data/Textures/fresnel_vp.txt", "fresnel_vp");
739 //     }
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;
749 //     }
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 );
758
759 //     sgMakeIdentMat4( shadIdentMatrix );
760
761 //      initDone = true;
762 // }
763
764 // ////////////////////////////////////////////////////////////////////////
765 // // Implementation of SGShaderAnimation
766 // ////////////////////////////////////////////////////////////////////////
767
768 SGShaderAnimation::SGShaderAnimation ( SGPropertyNode *prop_root,
769                    SGPropertyNode_ptr props )
770   : SGAnimation(props, new osg::Group),
771     _condition(0),
772     _condition_value(true),
773     _shader_type(0),
774     _param_1(props->getFloatValue("param", 1.0f)),
775     _depth_test(props->getBoolValue("depth-test", true)),
776     _factor(props->getFloatValue("factor", 1.0f)),
777     _factor_prop(0),
778     _speed(props->getFloatValue("speed", 1.0f)),
779     _speed_prop(0),
780     _textureData(0),
781     _texWidth(0),
782     _texHeight(0)
783
784 {
785     SGPropertyNode_ptr node = props->getChild("condition");
786     if (node != 0) {
787         _condition = sgReadCondition(prop_root, node);
788         _condition_value = false;
789     }
790     node = props->getChild("factor-prop");
791     if( node )
792         _factor_prop = prop_root->getNode(node->getStringValue(), true);
793     node = props->getChild("speed-prop");
794     if( node )
795         _speed_prop = prop_root->getNode(node->getStringValue(), true);
796
797     _envColor = osg::Vec4(0, 0, 0, 1);
798     node = props->getChild("texture");
799     if( node ) {
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);
804
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 );
808     }
809     string shader_name = props->getStringValue("shader");
810     if( shader_name == "fresnel" || shader_name == "reflection" )
811         _shader_type = 1;
812     else if( shader_name == "heat-haze" )
813         _shader_type = 2;
814     else if( shader_name == "chrome" && _effectTexture.valid())
815         _shader_type = 3;
816 }
817
818 void SGShaderAnimation::init()
819 {
820 //     if( ! initDone )
821 //         init_shaders();
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 );
830 //     }
831 //     else if( _shader_type == 3 )
832 //         setCallBack( getBranch(), (ssgBase *) this, chrome_shader_callback );
833 //     else
834 //         setCallBack( getBranch(), (ssgBase *) this, null_shader_callback );
835 }
836
837 SGShaderAnimation::~SGShaderAnimation()
838 {
839   delete _condition;
840   delete _textureData;
841 }
842
843 void
844 SGShaderAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
845
846   if (_condition)
847     _condition_value = _condition->test();
848   if( _factor_prop)
849     _factor = _factor_prop->getFloatValue();
850   if( _speed_prop)
851     _speed = _speed_prop->getFloatValue();
852
853   // OSGFIXME fiddle with totalTime
854   totalTime = nv->getFrameStamp()->getReferenceTime();
855
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.
859   traverse(node, nv);
860 }
861 #endif