]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/shadanim.cxx
cleanup
[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 <OpenThreads/Mutex>
40 #include <OpenThreads/ScopedLock>
41
42 #include <simgear/scene/util/SGUpdateVisitor.hxx>
43
44 #include <simgear/props/condition.hxx>
45 #include <simgear/props/props.hxx>
46
47 #include <simgear/debug/logstream.hxx>
48
49 #include "animation.hxx"
50 #include "model.hxx"
51
52 using OpenThreads::Mutex;
53 using OpenThreads::ScopedLock;
54
55 /*
56     <animation>
57         <type>shader</type>
58         <shader>fresnel</shader>
59         <object-name>...</object-name>
60     </animation>
61
62     <animation>
63         <type>shader</type>
64         <shader>heat-haze</shader>
65         <object-name>...</object-name>
66         <speed>...</speed>
67         <speed-prop>...</speed-prop>
68         <factor>...</factor>
69         <factor-prop>...</factor-prop>
70     </animation>
71
72     <animation>
73         <type>shader</type>
74         <shader>chrome</shader>
75         <texture>...</texture>
76         <object-name>...</object-name>
77     </animation>
78
79     <animation>
80         <type>shader</type>
81         <shader></shader>
82         <object-name>...</object-name>
83         <depth-test>false</depth-test>
84     </animation>
85
86 */
87
88
89 class SGMapGenCallback :
90   public osg::StateAttribute::Callback {
91 public:
92   virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
93   {
94     SGUpdateVisitor* updateVisitor = dynamic_cast<SGUpdateVisitor*>(nv);
95     if (!updateVisitor)
96       return;
97
98     if (distSqr(_lastLightDirection, updateVisitor->getLightDirection()) < 1e-4
99         && distSqr(_lastLightColor, updateVisitor->getAmbientLight()) < 1e-4)
100       return;
101
102     _lastLightDirection = updateVisitor->getLightDirection();
103     _lastLightColor = updateVisitor->getAmbientLight();
104
105     osg::TextureCubeMap *tcm = static_cast<osg::TextureCubeMap*>(sa);
106
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(_lastLightDirection.osg(),
111                                                 _lastLightColor.osg(), 5);
112     mapgen->generateMap();
113
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));
127   }
128 private:
129   SGVec3f _lastLightDirection;
130   SGVec4f _lastLightColor;
131 };
132
133 static Mutex cubeMutex;
134
135 static osg::TextureCubeMap*
136 getOrCreateTextureCubeMap()
137 {
138   static osg::ref_ptr<osg::TextureCubeMap> textureCubeMap;
139   if (textureCubeMap.get())
140     return textureCubeMap.get();
141
142   ScopedLock<Mutex> lock(cubeMutex);
143   if (textureCubeMap.get())
144     return textureCubeMap.get();
145
146   // create and setup the texture object
147   textureCubeMap = new osg::TextureCubeMap;
148
149   textureCubeMap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);
150   textureCubeMap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);
151   textureCubeMap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP);
152   textureCubeMap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
153   textureCubeMap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);    
154   
155   textureCubeMap->setUpdateCallback(new SGMapGenCallback);
156
157   return textureCubeMap.get();
158 }
159
160 static void create_specular_highlights(osg::Node *node)
161 {
162   osg::StateSet *ss = node->getOrCreateStateSet();
163   
164   // create and setup the texture object
165   osg::TextureCubeMap *tcm = getOrCreateTextureCubeMap();
166   
167   // enable texturing, replacing any textures in the subgraphs
168   ss->setTextureAttributeAndModes(0, tcm, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
169   
170   // texture coordinate generation
171   osg::TexGen *tg = new osg::TexGen;
172   tg->setMode(osg::TexGen::REFLECTION_MAP);
173   ss->setTextureAttributeAndModes(0, tg, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
174   
175   // use TexEnvCombine to add the highlights to the original lighting
176   osg::TexEnvCombine *te = new osg::TexEnvCombine;
177   te->setCombine_RGB(osg::TexEnvCombine::ADD);
178   te->setSource0_RGB(osg::TexEnvCombine::TEXTURE);
179   te->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
180   te->setSource1_RGB(osg::TexEnvCombine::PRIMARY_COLOR);
181   te->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
182   ss->setTextureAttributeAndModes(0, te, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
183 }
184
185
186 SGShaderAnimation::SGShaderAnimation(const SGPropertyNode* configNode,
187                                      SGPropertyNode* modelRoot,
188                                      const osgDB::ReaderWriter::Options*
189                                      options) :
190   SGAnimation(configNode, modelRoot)
191 {
192   const SGPropertyNode* node = configNode->getChild("texture");
193   if (node)
194     _effect_texture = SGLoadTexture2D(node->getStringValue(), options);
195 }
196
197 namespace {
198 class ChromeLightingCallback :
199   public osg::StateAttribute::Callback {
200 public:
201   virtual void operator () (osg::StateAttribute* sa, osg::NodeVisitor* nv)
202   {
203     SGUpdateVisitor* updateVisitor = dynamic_cast<SGUpdateVisitor*>(nv);
204     if (!updateVisitor)
205       return;
206     osg::TexEnvCombine *combine = dynamic_cast<osg::TexEnvCombine *>(sa);
207     if (!combine)
208         return;
209     // An approximation for light reflected back by chrome.
210     osg::Vec4 globalColor = (updateVisitor->getAmbientLight().osg() * .4f
211                              + updateVisitor->getDiffuseLight().osg());
212     globalColor.a() = 1.0f;
213     combine->setConstantColor(globalColor);
214   }
215 };
216     
217 typedef std::map<osg::ref_ptr<osg::Texture2D>, osg::ref_ptr<osg::StateSet> >
218 StateSetMap;
219 }
220
221 static Mutex chromeMutex;
222
223 // The chrome effect is mixed by the alpha channel of the texture
224 // on the model, which will be attached to a node lower in the scene
225 // graph: 0 -> completely chrome, 1 -> completely model texture.
226 static void create_chrome(osg::Group* group, osg::Texture2D* texture)
227 {
228     ScopedLock<Mutex> lock(chromeMutex);
229     static StateSetMap chromeMap;
230     osg::StateSet *stateSet;
231     StateSetMap::iterator iterator = chromeMap.find(texture);
232     if (iterator != chromeMap.end()) {
233         stateSet = iterator->second.get();
234     } else {
235         stateSet = new osg::StateSet;
236         // If the model doesn't have any texture, we need to have one
237         // activated so that we don't need a seperate combiner
238         // attribute for the non-textured case. This texture will be
239         // shadowed by any attached to the model.
240         osg::Image *dummyImage = new osg::Image;
241         dummyImage->allocateImage(1, 1, 1, GL_LUMINANCE_ALPHA,
242                                   GL_UNSIGNED_BYTE);
243         unsigned char* imageBytes = dummyImage->data(0, 0);
244         imageBytes[0] = 255;
245         imageBytes[1] = 0;
246         osg::Texture2D* dummyTexture = new osg::Texture2D;
247         dummyTexture->setImage(dummyImage);
248         dummyTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
249         dummyTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
250         stateSet->setTextureAttributeAndModes(0, dummyTexture,
251                                               osg::StateAttribute::ON);
252         osg::TexEnvCombine* combine0 = new osg::TexEnvCombine;
253         osg::TexEnvCombine* combine1 = new osg::TexEnvCombine;
254         osg::TexGen* texGen = new osg::TexGen;
255         // Mix the environmental light color and the chrome map on texture
256         // unit 0
257         combine0->setCombine_RGB(osg::TexEnvCombine::MODULATE);
258         combine0->setSource0_RGB(osg::TexEnvCombine::CONSTANT);
259         combine0->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
260         combine0->setSource1_RGB(osg::TexEnvCombine::TEXTURE1);
261         combine0->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
262         combine0->setDataVariance(osg::Object::DYNAMIC);
263         combine0->setUpdateCallback(new ChromeLightingCallback);
264
265         // Interpolate the colored chrome map with the texture on the
266         // model, using the model texture's alpha.
267         combine1->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE);
268         combine1->setSource0_RGB(osg::TexEnvCombine::TEXTURE0);
269         combine1->setOperand0_RGB(osg::TexEnvCombine::SRC_COLOR);
270         combine1->setSource1_RGB(osg::TexEnvCombine::PREVIOUS);
271         combine1->setOperand1_RGB(osg::TexEnvCombine::SRC_COLOR);
272         combine1->setSource2_RGB(osg::TexEnvCombine::TEXTURE0);
273         combine1->setOperand2_RGB(osg::TexEnvCombine::SRC_ALPHA);
274         // Are these used for anything?
275         combine1->setCombine_Alpha(osg::TexEnvCombine::REPLACE);
276         combine1->setSource0_Alpha(osg::TexEnvCombine::TEXTURE1);
277         combine1->setOperand0_Alpha(osg::TexEnvCombine::SRC_ALPHA);
278     
279         texGen->setMode(osg::TexGen::SPHERE_MAP);
280         stateSet->setTextureAttribute(0, combine0);
281         stateSet->setTextureAttribute(1, combine1);
282         stateSet->setTextureAttributeAndModes(1, texture,
283                                               osg::StateAttribute::ON);
284         stateSet->setTextureAttributeAndModes(1, texGen,
285                                               osg::StateAttribute::ON);
286         chromeMap[texture] = stateSet;
287     }
288     group->setStateSet(stateSet);
289 }
290
291 osg::Group*
292 SGShaderAnimation::createAnimationGroup(osg::Group& parent)
293 {
294   osg::Group* group = new osg::Group;
295   group->setName("shader animation");
296   parent.addChild(group);
297
298   std::string shader_name = getConfig()->getStringValue("shader", "");
299 //   if( shader_name == "fresnel" || shader_name == "reflection" )
300 //     _shader_type = 1;
301 //   else if( shader_name == "heat-haze" )
302 //     _shader_type = 2;
303 //   else
304   if( shader_name == "chrome")
305 #if 0
306     create_specular_highlights(group);
307 #endif
308   create_chrome(group, _effect_texture.get());
309   return group;
310 }
311
312 #if 0
313 // static Shader *shFresnel=NULL;
314 // static GLuint texFresnel = 0;
315
316 // static GLuint texBackground = 0;
317 // static int texBackgroundWidth = 1024, texBackgroundHeight = 1024;
318 // static GLenum texBackgroundTarget = GL_TEXTURE_2D;
319 // static bool isRectangleTextureSupported = false;
320 // static bool istexBackgroundRectangle = false;
321 // static bool initDone = false;
322 static bool haveBackground = false;
323
324 // static glActiveTextureProc glActiveTexturePtr = 0;
325 // static sgMat4 shadIdentMatrix;
326
327
328 // static int null_shader_callback( ssgEntity *e ) {
329 //      GLuint dlist = 0;
330 //     ssgLeaf *leaf = (ssgLeaf *) e;
331 // #ifdef _SSG_USE_DLIST
332 //     dlist = leaf->getDListIndex();
333 //     if( ! dlist ) {
334 //         leaf->makeDList();
335 //         dlist = leaf->getDListIndex();
336 //     }
337 // #endif
338 //     if( ! dlist )
339 //         return true;
340 //     ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
341 //     if ( sst )
342 //         sst->apply();
343
344 //     SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
345 //     if( ! my_shader->_depth_test )
346 //         glDisable( GL_DEPTH_TEST );
347 //     glCallList ( dlist ) ;
348 //     // restore states
349 //     if( ! my_shader->_depth_test )
350 //         glEnable( GL_DEPTH_TEST );
351
352 //     // don't draw !
353 //     return false;
354 // }
355
356 // static int heat_haze_shader_callback( ssgEntity *e ) {
357 //    if( ! ((SGShadowAnimation *)e->getUserData())->get_condition_value() )
358 //        return true;
359
360 //      GLuint dlist = 0;
361 //     ssgLeaf *leaf = (ssgLeaf *) e;
362 // #ifdef _SSG_USE_DLIST
363 //     dlist = leaf->getDListIndex();
364 //     if( ! dlist ) {
365 //         leaf->makeDList();
366 //         dlist = leaf->getDListIndex();
367 //     }
368 // #endif
369 //     if( ! dlist )
370 //         return true;
371
372 //     GLint viewport[4];
373 //     glGetIntegerv( GL_VIEWPORT, viewport );
374 //     const int screen_width = viewport[2];
375 //     const int screen_height = viewport[3];
376 //     if( ! haveBackground ) {
377 //         // store the backbuffer in a texture
378 //         if( ! texBackground ) {
379 //             // allocate our texture here so we don't waste memory if no model use that effect
380 //             // check if we need a rectangle texture and if the card support it
381 //             if( (screen_width > 1024 || screen_height > 1024) && isRectangleTextureSupported ) {
382 //                 // Note that the 3 (same) extensions use the same enumerants
383 //                 texBackgroundTarget = GL_TEXTURE_RECTANGLE_NV;
384 //                 istexBackgroundRectangle = true;
385 //                 texBackgroundWidth = screen_width;
386 //                 texBackgroundHeight = screen_height;
387 //             }
388 //             glGenTextures(1, &texBackground);
389 //             glEnable(texBackgroundTarget);
390 //             glBindTexture(texBackgroundTarget, texBackground);
391 //             // trying to match the backbuffer pixel format
392 //             GLint internalFormat = GL_RGB8;
393 //             GLint colorBits = 0, alphaBits = 0;
394 //             glGetIntegerv( GL_BLUE_BITS, &colorBits );
395 //             glGetIntegerv( GL_ALPHA_BITS, &alphaBits );
396 //             if(colorBits == 5) {
397 //                 if( alphaBits == 0 )
398 //                     internalFormat = GL_RGB5;
399 //                 else
400 //                     internalFormat = GL_RGB5_A1;
401 //             } else {
402 //                 if( alphaBits != 0 )
403 //                     internalFormat = GL_RGBA8;
404 //             }
405 //             glTexImage2D(texBackgroundTarget, 0, internalFormat, 
406 //                             texBackgroundWidth, texBackgroundHeight, 0, GL_RGB, GL_FLOAT, NULL);
407
408 //             glTexParameteri(texBackgroundTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
409 //             glTexParameteri(texBackgroundTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
410 //             glTexParameteri(texBackgroundTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
411 //             glTexParameteri(texBackgroundTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
412 //         }
413 //         glEnable(texBackgroundTarget);
414 //         glBindTexture(texBackgroundTarget, texBackground);
415 //         // center of texture = center of screen
416 //         // obviously we don't have the whole screen if screen_width > texBackgroundWidth
417 //         // if rectangle textures are not supported, this give some artifacts on the borders
418 //         if( istexBackgroundRectangle ) {
419 //             glCopyTexSubImage2D( texBackgroundTarget, 0, 0, 0, 
420 //                 0, 0, texBackgroundWidth, texBackgroundHeight );
421 //         } else {
422 //             glCopyTexSubImage2D( texBackgroundTarget, 0, 0, 0, 
423 //                 (screen_width - texBackgroundWidth) / 2, 
424 //                 (screen_height - texBackgroundHeight) / 2, 
425 //                 texBackgroundWidth, texBackgroundHeight );
426 //         }
427 //         haveBackground = true;
428 //         glBindTexture(texBackgroundTarget, 0);
429 //         glDisable(texBackgroundTarget);
430 //     }
431 //     ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
432 //     if ( sst )
433 //         sst->apply();
434
435 //     SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
436 //     if( ! my_shader->_depth_test )
437 //         glDisable( GL_DEPTH_TEST );
438 //     glDepthMask( GL_FALSE );
439 //     glDisable( GL_LIGHTING );
440 //     if(1) {
441 //         // noise texture, tex coord from the model translated by a time factor
442 //         glActiveTexturePtr( GL_TEXTURE0_ARB );
443 //         glEnable(GL_TEXTURE_2D);
444 //         const float noiseDist = fmod(- totalTime * my_shader->_factor * my_shader->_speed, 4.0);
445 //         glMatrixMode(GL_TEXTURE);
446 //             glLoadIdentity();
447 //             glTranslatef( noiseDist, 0.0f, 0.0f );
448 //         glMatrixMode(GL_MODELVIEW);
449
450 //         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
451
452 //         // background texture
453 //         glActiveTexturePtr( GL_TEXTURE1_ARB );
454 //         glEnable(texBackgroundTarget);
455 //         glBindTexture(texBackgroundTarget, texBackground);
456
457 //         // automatic generation of texture coordinates
458 //         // map to screen space
459 //         sgMat4 CameraProjM, CameraViewM;
460 //         glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *) CameraProjM);
461 //         glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) CameraViewM);
462 //         // const float dummy_scale = 1.0f; //0.95f;
463 //         const float deltaPos = 0.05f;
464 //         glMatrixMode(GL_TEXTURE);
465 //             glLoadIdentity();
466 //             if( istexBackgroundRectangle ) {
467 //                 // coords go from 0.0 to n, not from 0.0 to 1.0
468 //                 glTranslatef( texBackgroundWidth * 0.5f, texBackgroundHeight * 0.5f, 0.0f );
469 //                 glScalef( texBackgroundWidth * 0.5f,
470 //                     texBackgroundHeight * 0.5f, 1.0f );
471 //             } else {
472 //                 glTranslatef( 0.5f, 0.5f, 0.0f );
473 //                 glScalef( float( screen_width ) / float( texBackgroundWidth ) * 0.5f,
474 //                     float( screen_height ) / float( texBackgroundHeight ) * 0.5f, 1.0f );
475 //             }
476 //             glMultMatrixf( (GLfloat *) CameraProjM );
477 //             glMultMatrixf( (GLfloat *) CameraViewM );
478 //             glTranslatef( deltaPos, deltaPos, deltaPos );
479 //         glMatrixMode(GL_MODELVIEW);
480
481 //         glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
482 //         glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
483 //         glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
484 //         glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
485 //         glTexGenfv( GL_S, GL_EYE_PLANE, shadIdentMatrix[0] );
486 //         glTexGenfv( GL_T, GL_EYE_PLANE, shadIdentMatrix[1] );
487 //         glTexGenfv( GL_R, GL_EYE_PLANE, shadIdentMatrix[2] );
488 //         glTexGenfv( GL_Q, GL_EYE_PLANE, shadIdentMatrix[3] );
489 //         glEnable( GL_TEXTURE_GEN_S );
490 //         glEnable( GL_TEXTURE_GEN_T );
491 //         glEnable( GL_TEXTURE_GEN_R );
492 //         glEnable( GL_TEXTURE_GEN_Q );
493
494 //         sgVec4 enviro = {1.00f, 1.00f, 1.00f, 0.85f};
495
496 //         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
497 //         glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE ); 
498 //         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE );
499 //         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR ); 
500 //         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT_ARB );
501 //         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); 
502 //              glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, enviro);
503
504 //         glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
505 //         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE0_ARB);
506 //         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
507 //         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PRIMARY_COLOR_ARB );
508 //         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA ); 
509
510 //         glCallList ( dlist ) ;
511 //         glMatrixMode(GL_TEXTURE);
512 //         glTranslatef( - deltaPos*2.0f, -deltaPos*2.5f, -deltaPos*2.0f );
513 //         glMatrixMode(GL_MODELVIEW);
514 //         glCallList ( dlist ) ;
515
516 //         // alter colors only on last rendering
517 //         // sgVec4 fLight = {0.93f, 0.93f, 1.00f, 0.85f};
518 //         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB );
519 //         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); 
520
521 //         glMatrixMode(GL_TEXTURE);
522 //         glTranslatef( deltaPos*0.7f, deltaPos*1.7f, deltaPos*0.7f );
523 //         glMatrixMode(GL_MODELVIEW);
524 //         glCallList ( dlist ) ;
525
526
527 //         glActiveTexturePtr( GL_TEXTURE1_ARB );
528 //         glDisable( GL_TEXTURE_GEN_S );
529 //         glDisable( GL_TEXTURE_GEN_T );
530 //         glDisable( GL_TEXTURE_GEN_R );
531 //         glDisable( GL_TEXTURE_GEN_Q );
532 //         glMatrixMode(GL_TEXTURE);
533 //             glLoadIdentity();
534 //         glMatrixMode(GL_MODELVIEW);
535 //         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
536 //         glDisable(texBackgroundTarget);
537 //         glActiveTexturePtr( GL_TEXTURE0_ARB );
538 //         glMatrixMode(GL_TEXTURE);
539 //             glLoadIdentity();
540 //         glMatrixMode(GL_MODELVIEW);
541 //         glEnable(GL_TEXTURE_2D);
542 //         glBindTexture(GL_TEXTURE_2D, 0);
543 //     }
544 //     // restore states
545 //     if( ! my_shader->_depth_test )
546 //         glEnable( GL_DEPTH_TEST );
547
548 //     glEnable( GL_LIGHTING );
549 //     glDepthMask( GL_TRUE );
550 //     if( sst )
551 //         sst->force();
552
553 //    // don't draw !
554 //     return false;
555 // }
556
557 // static int fresnel_shader_callback( ssgEntity *e ) {
558 //    if( ! ((SGShadowAnimation *)e->getUserData())->get_condition_value() )
559 //        return true;
560
561 //      GLuint dlist = 0;
562 //     ssgLeaf *leaf = (ssgLeaf *) e;
563 // #ifdef _SSG_USE_DLIST
564 //     dlist = leaf->getDListIndex();
565 //     if( ! dlist ) {
566 //         leaf->makeDList();
567 //         dlist = leaf->getDListIndex();
568 //     }
569 // #endif
570 //     if( ! dlist )
571 //         return true;
572 //     ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
573 //     if ( sst )
574 //         sst->apply();
575
576 //     sgVec4 sunColor, ambientColor;
577 //     ssgGetLight( 0 )->getColour(GL_DIFFUSE, sunColor );
578 //     ssgGetLight( 0 )->getColour(GL_AMBIENT, ambientColor );
579
580 //     // SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
581 //     glEnable(GL_BLEND);
582 //      glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
583 //      glEnable(GL_ALPHA_TEST);
584 //      glAlphaFunc(GL_GREATER, 0.0f);
585
586 //      if( true ) {
587 // //        sgVec4 R = {0.5,0.0,0.0,0.0};
588 //         sgVec4 enviro = {1.0,0.0,0.0,1.0};
589 // //        sgCopyVec4( enviro, sunColor );
590 //         glActiveTexturePtr( GL_TEXTURE0_ARB );
591 //         glEnable(GL_TEXTURE_2D);
592 //         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
593 //         glActiveTexturePtr( GL_TEXTURE1_ARB );
594 //         glDisable(GL_TEXTURE_2D);
595 //         glEnable(GL_TEXTURE_1D);
596 //         glBindTexture(GL_TEXTURE_1D, texFresnel);
597 //         // c = a0 * a2 + a1 * (1-a2)
598 // //        glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
599 // //        glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
600 //         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
601 //         glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB ); 
602 //         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_CONSTANT_ARB );
603 //         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR ); 
604 //         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB );
605 //         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); 
606 //         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE );
607 //         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR ); 
608 //              glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, enviro);
609 //         shFresnel->enable();
610 //             shFresnel->bind();
611 //             glCallList ( dlist ) ;
612 //         shFresnel->disable();
613 //         glActiveTexturePtr( GL_TEXTURE1_ARB );
614 //         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
615 //         glDisable(GL_TEXTURE_1D);
616 //         glActiveTexturePtr( GL_TEXTURE0_ARB );
617 //         glDisable(GL_TEXTURE_1D);
618 //         glEnable(GL_TEXTURE_2D);
619 //     }
620 //     // restore states
621 // //    glBindTexture(GL_TEXTURE_2D, 0);
622 // //    glDepthFunc(GL_LESS);
623 // //    glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
624 //    if( sst )
625 //          sst->force();
626
627 //     // don't draw !
628 //     return false;
629 // }
630
631
632
633 // static int chrome_shader_callback( ssgEntity *e ) {
634 //    if( ! ((SGShadowAnimation *)e->getUserData())->get_condition_value() )
635 //        return true;
636
637 //      GLuint dlist = 0;
638 //     ssgLeaf *leaf = (ssgLeaf *) e;
639 // #ifdef _SSG_USE_DLIST
640 //     dlist = leaf->getDListIndex();
641 //     if( ! dlist ) {
642 //         leaf->makeDList();
643 //         dlist = leaf->getDListIndex();
644 //     }
645 // #endif
646 //     if( ! dlist )
647 //         return true;
648 //     ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
649 //     if ( sst )
650 //         sst->apply();
651
652 //     SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
653 //     if( ! my_shader->_depth_test )
654 //         glDisable( GL_DEPTH_TEST );
655
656 //     GLint maskTexComponent = 3;
657 //     glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_COMPONENTS, &maskTexComponent);
658
659 //     // The fake env chrome texture
660 //     glActiveTexturePtr( GL_TEXTURE1_ARB );
661 //     glEnable(GL_TEXTURE_2D);
662 //     {
663 //         // No lighting is computed in spherical mapping mode because the environment
664 //         // is supposed to be allready lighted. We must reshade our environment texture.
665 //         sgVec4 sunColor, ambientColor, envColor;
666 //         ssgGetLight( 0 )->getColour(GL_DIFFUSE, sunColor );
667 //         ssgGetLight( 0 )->getColour(GL_AMBIENT, ambientColor );
668 //         sgAddScaledVec3( envColor, ambientColor, sunColor, 0.4f);
669 //         glBindTexture(GL_TEXTURE_2D, my_shader->_effectTexture->getHandle());
670
671 //         sgVec3 delta_light;
672 //         sgSubVec3(delta_light, envColor, my_shader->_envColor);
673 //         if( (fabs(delta_light[0]) + fabs(delta_light[1]) + fabs(delta_light[2])) > 0.05f ) {
674 //                  sgCopyVec3( my_shader->_envColor, envColor );
675 //             // reload the texture data and let the driver reshade it for us
676 //             glPixelTransferf( GL_RED_SCALE, envColor[0] );
677 //             glPixelTransferf( GL_GREEN_SCALE, envColor[1] );
678 //             glPixelTransferf( GL_BLUE_SCALE, envColor[2] );
679 //             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, my_shader->_texWidth, my_shader->_texHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, my_shader->_textureData);
680 //             glPixelTransferf( GL_RED_SCALE, 1.0f );
681 //             glPixelTransferf( GL_GREEN_SCALE, 1.0f );
682 //             glPixelTransferf( GL_BLUE_SCALE, 1.0f );
683 //         }
684 //     }
685 //     if( maskTexComponent == 4 ) {
686 //         // c = lerp(model tex, chrome tex, model tex alpha)
687 //         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
688 //         glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB ); 
689 //         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB );
690 //         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR ); 
691 //         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE );
692 //         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); 
693 //         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_PREVIOUS_ARB );
694 //         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA ); 
695
696 //         glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
697 //         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
698 //         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
699 //     } else {
700 //         // c = chrome tex
701 //         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
702 //         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE );
703 //         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR ); 
704
705 //         glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
706 //         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
707 //         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
708 //     }
709 //     // automatic generation of texture coordinates
710 //     // from normals
711
712 //     glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
713 //     glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
714 //     glEnable( GL_TEXTURE_GEN_S );
715 //     glEnable( GL_TEXTURE_GEN_T );
716
717 //     glCallList ( dlist ) ;
718
719 //     glActiveTexturePtr( GL_TEXTURE1_ARB );
720 //     glDisable( GL_TEXTURE_GEN_S );
721 //     glDisable( GL_TEXTURE_GEN_T );
722
723 //     glMatrixMode(GL_TEXTURE);
724 //         glLoadIdentity();
725 //     glMatrixMode(GL_MODELVIEW);
726
727 //     glDisable(GL_TEXTURE_2D);
728 //     glBindTexture(GL_TEXTURE_2D, 0);
729 //     glActiveTexturePtr( GL_TEXTURE0_ARB );
730
731 //     // restore states
732 //     if( ! my_shader->_depth_test )
733 //         glEnable( GL_DEPTH_TEST );
734
735 //     if( sst )
736 //         sst->force();
737
738 //    // don't draw !
739 //     return false;
740 // }
741
742 // static void init_shaders(void) {
743 //      Shader::Init();
744 //     if( false && Shader::is_VP_supported() ) {
745 //          shFresnel = new Shader("/FlightGear/data/Textures/fresnel_vp.txt", "fresnel_vp");
746 //     }
747 //      glActiveTexturePtr = (glActiveTextureProc) SGLookupFunction("glActiveTextureARB");
748 //     const int fresnelSize = 512;
749 //     unsigned char imageFresnel[ fresnelSize * 3 ];
750 //     for(int i = 0; i < fresnelSize; i++) {
751 //         const float R0 = 0.2f;
752 //         float NdotV = float( i ) / float( fresnelSize );
753 //         float f = R0 + (1.0f-R0)*pow(1.0f - NdotV, 5);
754 //         unsigned char ff = (unsigned char) (f * 255.0);
755 //         imageFresnel[i*3+0] = imageFresnel[i*3+1] = imageFresnel[i*3+2] = ff;
756 //     }
757 //     glGenTextures( 1, &texFresnel );
758 //      glBindTexture(GL_TEXTURE_1D, texFresnel );
759 //      glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
760 //     glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
761 //     glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
762 //      glTexParameteri(GL_TEXTURE_1D, GL_GENERATE_MIPMAP_SGIS, true);
763 //      glTexImage1D(GL_TEXTURE_1D, 0, 3, fresnelSize, 0, GL_RGB, GL_UNSIGNED_BYTE, imageFresnel);
764 //      glBindTexture(GL_TEXTURE_1D, 0 );
765
766 //     sgMakeIdentMat4( shadIdentMatrix );
767
768 //      initDone = true;
769 // }
770
771 // ////////////////////////////////////////////////////////////////////////
772 // // Implementation of SGShaderAnimation
773 // ////////////////////////////////////////////////////////////////////////
774
775 SGShaderAnimation::SGShaderAnimation ( SGPropertyNode *prop_root,
776                    SGPropertyNode_ptr props )
777   : SGAnimation(props, new osg::Group),
778     _condition(0),
779     _condition_value(true),
780     _shader_type(0),
781     _param_1(props->getFloatValue("param", 1.0f)),
782     _depth_test(props->getBoolValue("depth-test", true)),
783     _factor(props->getFloatValue("factor", 1.0f)),
784     _factor_prop(0),
785     _speed(props->getFloatValue("speed", 1.0f)),
786     _speed_prop(0),
787     _textureData(0),
788     _texWidth(0),
789     _texHeight(0)
790
791 {
792     SGPropertyNode_ptr node = props->getChild("condition");
793     if (node != 0) {
794         _condition = sgReadCondition(prop_root, node);
795         _condition_value = false;
796     }
797     node = props->getChild("factor-prop");
798     if( node )
799         _factor_prop = prop_root->getNode(node->getStringValue(), true);
800     node = props->getChild("speed-prop");
801     if( node )
802         _speed_prop = prop_root->getNode(node->getStringValue(), true);
803
804     _envColor = osg::Vec4(0, 0, 0, 1);
805     node = props->getChild("texture");
806     if( node ) {
807       _effectTexture = SGLoadTexture2D(node->getStringValue());
808 //         glBindTexture(GL_TEXTURE_2D, _effectTexture->getHandle() );
809 //         glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &_texWidth);
810 //         glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &_texHeight);
811
812 //         _textureData = new unsigned char[_texWidth * _texHeight * 3];
813 //         glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, _textureData);
814 //         glBindTexture(GL_TEXTURE_2D, 0 );
815     }
816     string shader_name = props->getStringValue("shader");
817     if( shader_name == "fresnel" || shader_name == "reflection" )
818         _shader_type = 1;
819     else if( shader_name == "heat-haze" )
820         _shader_type = 2;
821     else if( shader_name == "chrome" && _effectTexture.valid())
822         _shader_type = 3;
823 }
824
825 void SGShaderAnimation::init()
826 {
827 //     if( ! initDone )
828 //         init_shaders();
829 //     if( _shader_type == 1 && Shader::is_VP_supported() && shFresnel)
830 //         setCallBack( getBranch(), (ssgBase *) this, fresnel_shader_callback );
831 //     else if( _shader_type == 2 ) {
832 //         // this is the same extension with different names
833 //         isRectangleTextureSupported = SGIsOpenGLExtensionSupported("GL_EXT_texture_rectangle") ||
834 //             SGIsOpenGLExtensionSupported("GL_ARB_texture_rectangle") ||
835 //             SGIsOpenGLExtensionSupported("GL_NV_texture_rectangle");
836 //         setCallBack( getBranch(), (ssgBase *) this, heat_haze_shader_callback );
837 //     }
838 //     else if( _shader_type == 3 )
839 //         setCallBack( getBranch(), (ssgBase *) this, chrome_shader_callback );
840 //     else
841 //         setCallBack( getBranch(), (ssgBase *) this, null_shader_callback );
842 }
843
844 SGShaderAnimation::~SGShaderAnimation()
845 {
846   delete _condition;
847   delete _textureData;
848 }
849
850 void
851 SGShaderAnimation::operator()(osg::Node* node, osg::NodeVisitor* nv)
852
853   if (_condition)
854     _condition_value = _condition->test();
855   if( _factor_prop)
856     _factor = _factor_prop->getFloatValue();
857   if( _speed_prop)
858     _speed = _speed_prop->getFloatValue();
859
860   // OSGFIXME fiddle with totalTime
861   totalTime = nv->getFrameStamp()->getReferenceTime();
862
863   // note, callback is responsible for scenegraph traversal so
864   // should always include call traverse(node,nv) to ensure 
865   // that the rest of cullbacks and the scene graph are traversed.
866   traverse(node, nv);
867 }
868 #endif