]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/shadanim.cxx
f7d0d9fdbf56517694a447657b92a312c44af941
[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 <plib/sg.h>
28 #include <plib/ssg.h>
29 #include <plib/ul.h>
30
31 #include <simgear/props/condition.hxx>
32 #include <simgear/props/props.hxx>
33 #include <simgear/screen/extensions.hxx>
34
35 #include <simgear/debug/logstream.hxx>
36
37 #include <simgear/screen/shader.h>
38
39 #include "animation.hxx"
40 /*
41     <animation>
42         <type>shader</type>
43         <shader>fresnel</shader>
44         <object-name>...</object-name>
45     </animation>
46
47     <animation>
48         <type>shader</type>
49         <shader>heat-haze</shader>
50         <object-name>...</object-name>
51         <speed>...</speed>
52         <speed-prop>...</speed-prop>
53         <factor>...</factor>
54         <factor-prop>...</factor-prop>
55     </animation>
56
57     <animation>
58         <type>shader</type>
59         <shader>chrome</shader>
60         <texture>...</texture>
61         <object-name>...</object-name>
62     </animation>
63
64     <animation>
65         <type>shader</type>
66         <shader></shader>
67         <object-name>...</object-name>
68         <depth-test>false</depth-test>
69     </animation>
70
71 */
72 static Shader *shFresnel=NULL;
73 static GLuint texFresnel = 0;
74
75 static GLuint texBackground = 0;
76 static int texBackgroundWidth = 1024, texBackgroundHeight = 1024;
77 static GLenum texBackgroundTarget = GL_TEXTURE_2D;
78 static bool isRectangleTextureSupported = false;
79 static bool istexBackgroundRectangle = false;
80 static bool initDone = false;
81 static bool haveBackground = false;
82
83 static glActiveTextureProc glActiveTexturePtr = 0;
84 static double totalTime = 0.0;
85 static sgMat4 shadIdentMatrix;
86
87
88 static int null_shader_callback( ssgEntity *e ) {
89         GLuint dlist = 0;
90     ssgLeaf *leaf = (ssgLeaf *) e;
91 #ifdef _SSG_USE_DLIST
92     dlist = leaf->getDListIndex();
93     if( ! dlist ) {
94         leaf->makeDList();
95         dlist = leaf->getDListIndex();
96     }
97 #endif
98     if( ! dlist )
99         return true;
100     ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
101     if ( sst )
102         sst->apply();
103
104     SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
105     if( ! my_shader->_depth_test )
106         glDisable( GL_DEPTH_TEST );
107     glCallList ( dlist ) ;
108     // restore states
109     if( ! my_shader->_depth_test )
110         glEnable( GL_DEPTH_TEST );
111
112     // don't draw !
113     return false;
114 }
115
116 static int heat_haze_shader_callback( ssgEntity *e ) {
117    if( ! ((SGShadowAnimation *)e->getUserData())->get_condition_value() )
118        return true;
119
120         GLuint dlist = 0;
121     ssgLeaf *leaf = (ssgLeaf *) e;
122 #ifdef _SSG_USE_DLIST
123     dlist = leaf->getDListIndex();
124     if( ! dlist ) {
125         leaf->makeDList();
126         dlist = leaf->getDListIndex();
127     }
128 #endif
129     if( ! dlist )
130         return true;
131
132     GLint viewport[4];
133     glGetIntegerv( GL_VIEWPORT, viewport );
134     const int screen_width = viewport[2];
135     const int screen_height = viewport[3];
136     if( ! haveBackground ) {
137         // store the backbuffer in a texture
138         if( ! texBackground ) {
139             // allocate our texture here so we don't waste memory if no model use that effect
140             // check if we need a rectangle texture and if the card support it
141             if( (screen_width > 1024 || screen_height > 1024) && isRectangleTextureSupported ) {
142                 // Note that the 3 (same) extensions use the same enumerants
143                 texBackgroundTarget = GL_TEXTURE_RECTANGLE_NV;
144                 istexBackgroundRectangle = true;
145                 texBackgroundWidth = screen_width;
146                 texBackgroundHeight = screen_height;
147             }
148             glGenTextures(1, &texBackground);
149             glEnable(texBackgroundTarget);
150             glBindTexture(texBackgroundTarget, texBackground);
151             // trying to match the backbuffer pixel format
152             GLint internalFormat = GL_RGB8;
153             GLint colorBits = 0, alphaBits = 0;
154             glGetIntegerv( GL_BLUE_BITS, &colorBits );
155             glGetIntegerv( GL_ALPHA_BITS, &alphaBits );
156             if(colorBits == 5) {
157                 if( alphaBits == 0 )
158                     internalFormat = GL_RGB5;
159                 else
160                     internalFormat = GL_RGB5_A1;
161             } else {
162                 if( alphaBits != 0 )
163                     internalFormat = GL_RGBA8;
164             }
165             glTexImage2D(texBackgroundTarget, 0, internalFormat, 
166                             texBackgroundWidth, texBackgroundHeight, 0, GL_RGB, GL_FLOAT, NULL);
167
168             glTexParameteri(texBackgroundTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
169             glTexParameteri(texBackgroundTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
170             glTexParameteri(texBackgroundTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
171             glTexParameteri(texBackgroundTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
172         }
173         glEnable(texBackgroundTarget);
174         glBindTexture(texBackgroundTarget, texBackground);
175         // center of texture = center of screen
176         // obviously we don't have the whole screen if screen_width > texBackgroundWidth
177         // if rectangle textures are not supported, this give some artifacts on the borders
178         if( istexBackgroundRectangle ) {
179             glCopyTexSubImage2D( texBackgroundTarget, 0, 0, 0, 
180                 0, 0, texBackgroundWidth, texBackgroundHeight );
181         } else {
182             glCopyTexSubImage2D( texBackgroundTarget, 0, 0, 0, 
183                 (screen_width - texBackgroundWidth) / 2, 
184                 (screen_height - texBackgroundHeight) / 2, 
185                 texBackgroundWidth, texBackgroundHeight );
186         }
187         haveBackground = true;
188         glBindTexture(texBackgroundTarget, 0);
189         glDisable(texBackgroundTarget);
190     }
191     ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
192     if ( sst )
193         sst->apply();
194
195     SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
196     if( ! my_shader->_depth_test )
197         glDisable( GL_DEPTH_TEST );
198     glDepthMask( GL_FALSE );
199     glDisable( GL_LIGHTING );
200     if(1) {
201         // noise texture, tex coord from the model translated by a time factor
202         glActiveTexturePtr( GL_TEXTURE0_ARB );
203         glEnable(GL_TEXTURE_2D);
204         const float noiseDist = fmod(- totalTime * my_shader->_factor * my_shader->_speed, 4.0);
205         glMatrixMode(GL_TEXTURE);
206             glLoadIdentity();
207             glTranslatef( noiseDist, 0.0f, 0.0f );
208         glMatrixMode(GL_MODELVIEW);
209
210         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
211
212         // background texture
213         glActiveTexturePtr( GL_TEXTURE1_ARB );
214         glEnable(texBackgroundTarget);
215         glBindTexture(texBackgroundTarget, texBackground);
216
217         // automatic generation of texture coordinates
218         // map to screen space
219         sgMat4 CameraProjM, CameraViewM;
220         glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *) CameraProjM);
221         glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) CameraViewM);
222         // const float dummy_scale = 1.0f; //0.95f;
223         const float deltaPos = 0.05f;
224         glMatrixMode(GL_TEXTURE);
225             glLoadIdentity();
226             if( istexBackgroundRectangle ) {
227                 // coords go from 0.0 to n, not from 0.0 to 1.0
228                 glTranslatef( texBackgroundWidth * 0.5f, texBackgroundHeight * 0.5f, 0.0f );
229                 glScalef( texBackgroundWidth * 0.5f,
230                     texBackgroundHeight * 0.5f, 1.0f );
231             } else {
232                 glTranslatef( 0.5f, 0.5f, 0.0f );
233                 glScalef( float( screen_width ) / float( texBackgroundWidth ) * 0.5f,
234                     float( screen_height ) / float( texBackgroundHeight ) * 0.5f, 1.0f );
235             }
236             glMultMatrixf( (GLfloat *) CameraProjM );
237             glMultMatrixf( (GLfloat *) CameraViewM );
238             glTranslatef( deltaPos, deltaPos, deltaPos );
239         glMatrixMode(GL_MODELVIEW);
240
241         glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
242         glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
243         glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
244         glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
245         glTexGenfv( GL_S, GL_EYE_PLANE, shadIdentMatrix[0] );
246         glTexGenfv( GL_T, GL_EYE_PLANE, shadIdentMatrix[1] );
247         glTexGenfv( GL_R, GL_EYE_PLANE, shadIdentMatrix[2] );
248         glTexGenfv( GL_Q, GL_EYE_PLANE, shadIdentMatrix[3] );
249         glEnable( GL_TEXTURE_GEN_S );
250         glEnable( GL_TEXTURE_GEN_T );
251         glEnable( GL_TEXTURE_GEN_R );
252         glEnable( GL_TEXTURE_GEN_Q );
253
254         sgVec4 enviro = {1.00f, 1.00f, 1.00f, 0.85f};
255
256         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
257         glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE ); 
258         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE );
259         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR ); 
260         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT_ARB );
261         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); 
262                 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, enviro);
263
264         glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
265         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE0_ARB);
266         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
267         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PRIMARY_COLOR_ARB );
268         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA ); 
269
270         glCallList ( dlist ) ;
271         glMatrixMode(GL_TEXTURE);
272         glTranslatef( - deltaPos*2.0f, -deltaPos*2.5f, -deltaPos*2.0f );
273         glMatrixMode(GL_MODELVIEW);
274         glCallList ( dlist ) ;
275
276         // alter colors only on last rendering
277         // sgVec4 fLight = {0.93f, 0.93f, 1.00f, 0.85f};
278         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB );
279         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); 
280
281         glMatrixMode(GL_TEXTURE);
282         glTranslatef( deltaPos*0.7f, deltaPos*1.7f, deltaPos*0.7f );
283         glMatrixMode(GL_MODELVIEW);
284         glCallList ( dlist ) ;
285
286
287         glActiveTexturePtr( GL_TEXTURE1_ARB );
288         glDisable( GL_TEXTURE_GEN_S );
289         glDisable( GL_TEXTURE_GEN_T );
290         glDisable( GL_TEXTURE_GEN_R );
291         glDisable( GL_TEXTURE_GEN_Q );
292         glMatrixMode(GL_TEXTURE);
293             glLoadIdentity();
294         glMatrixMode(GL_MODELVIEW);
295         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
296         glDisable(texBackgroundTarget);
297         glActiveTexturePtr( GL_TEXTURE0_ARB );
298         glMatrixMode(GL_TEXTURE);
299             glLoadIdentity();
300         glMatrixMode(GL_MODELVIEW);
301         glEnable(GL_TEXTURE_2D);
302         glBindTexture(GL_TEXTURE_2D, 0);
303     }
304     // restore states
305     if( ! my_shader->_depth_test )
306         glEnable( GL_DEPTH_TEST );
307
308     glEnable( GL_LIGHTING );
309     glDepthMask( GL_TRUE );
310     if( sst )
311         sst->force();
312
313    // don't draw !
314     return false;
315 }
316
317 static int fresnel_shader_callback( ssgEntity *e ) {
318    if( ! ((SGShadowAnimation *)e->getUserData())->get_condition_value() )
319        return true;
320
321         GLuint dlist = 0;
322     ssgLeaf *leaf = (ssgLeaf *) e;
323 #ifdef _SSG_USE_DLIST
324     dlist = leaf->getDListIndex();
325     if( ! dlist ) {
326         leaf->makeDList();
327         dlist = leaf->getDListIndex();
328     }
329 #endif
330     if( ! dlist )
331         return true;
332     ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
333     if ( sst )
334         sst->apply();
335
336     sgVec4 sunColor, ambientColor;
337     ssgGetLight( 0 )->getColour(GL_DIFFUSE, sunColor );
338     ssgGetLight( 0 )->getColour(GL_AMBIENT, ambientColor );
339
340     // SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
341     glEnable(GL_BLEND);
342         glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
343         glEnable(GL_ALPHA_TEST);
344         glAlphaFunc(GL_GREATER, 0.0f);
345
346         if( true ) {
347 //        sgVec4 R = {0.5,0.0,0.0,0.0};
348         sgVec4 enviro = {1.0,0.0,0.0,1.0};
349 //        sgCopyVec4( enviro, sunColor );
350         glActiveTexturePtr( GL_TEXTURE0_ARB );
351         glEnable(GL_TEXTURE_2D);
352         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
353         glActiveTexturePtr( GL_TEXTURE1_ARB );
354         glDisable(GL_TEXTURE_2D);
355         glEnable(GL_TEXTURE_1D);
356         glBindTexture(GL_TEXTURE_1D, texFresnel);
357         // c = a0 * a2 + a1 * (1-a2)
358 //        glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
359 //        glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
360         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
361         glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB ); 
362         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_CONSTANT_ARB );
363         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR ); 
364         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB );
365         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); 
366         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE );
367         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR ); 
368                 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, enviro);
369         shFresnel->enable();
370             shFresnel->bind();
371             glCallList ( dlist ) ;
372         shFresnel->disable();
373         glActiveTexturePtr( GL_TEXTURE1_ARB );
374         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
375         glDisable(GL_TEXTURE_1D);
376         glActiveTexturePtr( GL_TEXTURE0_ARB );
377         glDisable(GL_TEXTURE_1D);
378         glEnable(GL_TEXTURE_2D);
379     }
380     // restore states
381 //    glBindTexture(GL_TEXTURE_2D, 0);
382 //    glDepthFunc(GL_LESS);
383 //    glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
384    if( sst )
385             sst->force();
386
387     // don't draw !
388     return false;
389 }
390
391
392
393 static int chrome_shader_callback( ssgEntity *e ) {
394    if( ! ((SGShadowAnimation *)e->getUserData())->get_condition_value() )
395        return true;
396
397         GLuint dlist = 0;
398     ssgLeaf *leaf = (ssgLeaf *) e;
399 #ifdef _SSG_USE_DLIST
400     dlist = leaf->getDListIndex();
401     if( ! dlist ) {
402         leaf->makeDList();
403         dlist = leaf->getDListIndex();
404     }
405 #endif
406     if( ! dlist )
407         return true;
408     ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
409     if ( sst )
410         sst->apply();
411
412     SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
413     if( ! my_shader->_depth_test )
414         glDisable( GL_DEPTH_TEST );
415
416     GLint maskTexComponent = 3;
417     glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_COMPONENTS, &maskTexComponent);
418
419     // The fake env chrome texture
420     glActiveTexturePtr( GL_TEXTURE1_ARB );
421     glEnable(GL_TEXTURE_2D);
422     {
423         // No lighting is computed in spherical mapping mode because the environment
424         // is supposed to be allready lighted. We must reshade our environment texture.
425         sgVec4 sunColor, ambientColor, envColor;
426         ssgGetLight( 0 )->getColour(GL_DIFFUSE, sunColor );
427         ssgGetLight( 0 )->getColour(GL_AMBIENT, ambientColor );
428         sgAddScaledVec3( envColor, ambientColor, sunColor, 0.4f);
429         glBindTexture(GL_TEXTURE_2D, my_shader->_effectTexture->getHandle());
430
431         sgVec3 delta_light;
432         sgSubVec3(delta_light, envColor, my_shader->_envColor);
433         if( (fabs(delta_light[0]) + fabs(delta_light[1]) + fabs(delta_light[2])) > 0.05f ) {
434                     sgCopyVec3( my_shader->_envColor, envColor );
435             // reload the texture data and let the driver reshade it for us
436             glPixelTransferf( GL_RED_SCALE, envColor[0] );
437             glPixelTransferf( GL_GREEN_SCALE, envColor[1] );
438             glPixelTransferf( GL_BLUE_SCALE, envColor[2] );
439             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, my_shader->_texWidth, my_shader->_texHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, my_shader->_textureData);
440             glPixelTransferf( GL_RED_SCALE, 1.0f );
441             glPixelTransferf( GL_GREEN_SCALE, 1.0f );
442             glPixelTransferf( GL_BLUE_SCALE, 1.0f );
443         }
444     }
445     if( maskTexComponent == 4 ) {
446         // c = lerp(model tex, chrome tex, model tex alpha)
447         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
448         glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB ); 
449         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB );
450         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR ); 
451         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE );
452         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); 
453         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_PREVIOUS_ARB );
454         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA ); 
455
456         glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
457         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
458         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
459     } else {
460         // c = chrome tex
461         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
462         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE );
463         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR ); 
464
465         glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
466         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
467         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
468     }
469     // automatic generation of texture coordinates
470     // from normals
471
472     glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
473     glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
474     glEnable( GL_TEXTURE_GEN_S );
475     glEnable( GL_TEXTURE_GEN_T );
476
477     glCallList ( dlist ) ;
478
479     glActiveTexturePtr( GL_TEXTURE1_ARB );
480     glDisable( GL_TEXTURE_GEN_S );
481     glDisable( GL_TEXTURE_GEN_T );
482
483     glMatrixMode(GL_TEXTURE);
484         glLoadIdentity();
485     glMatrixMode(GL_MODELVIEW);
486
487     glDisable(GL_TEXTURE_2D);
488     glBindTexture(GL_TEXTURE_2D, 0);
489     glActiveTexturePtr( GL_TEXTURE0_ARB );
490
491     // restore states
492     if( ! my_shader->_depth_test )
493         glEnable( GL_DEPTH_TEST );
494
495     if( sst )
496         sst->force();
497
498    // don't draw !
499     return false;
500 }
501
502 static void init_shaders(void) {
503         Shader::Init();
504     if( false && Shader::is_VP_supported() ) {
505             shFresnel = new Shader("/FlightGear/data/Textures/fresnel_vp.txt", "fresnel_vp");
506 //        shFresnel->bindNames("somedata", 0);
507     }
508         glActiveTexturePtr = (glActiveTextureProc) SGLookupFunction("glActiveTextureARB");
509     const int fresnelSize = 512;
510     unsigned char imageFresnel[ fresnelSize * 3 ];
511     for(int i = 0; i < fresnelSize; i++) {
512         const float R0 = 0.2f;
513         float NdotV = float( i ) / float( fresnelSize );
514         float f = R0 + (1.0f-R0)*pow(1.0f - NdotV, 5);
515         unsigned char ff = (unsigned char) (f * 255.0);
516         imageFresnel[i*3+0] = imageFresnel[i*3+1] = imageFresnel[i*3+2] = ff;
517     }
518     glGenTextures( 1, &texFresnel );
519         glBindTexture(GL_TEXTURE_1D, texFresnel );
520         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
521     glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
522     glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
523         glTexParameteri(GL_TEXTURE_1D, GL_GENERATE_MIPMAP_SGIS, true);
524         glTexImage1D(GL_TEXTURE_1D, 0, 3, fresnelSize, 0, GL_RGB, GL_UNSIGNED_BYTE, imageFresnel);
525         glBindTexture(GL_TEXTURE_1D, 0 );
526
527     sgMakeIdentMat4( shadIdentMatrix );
528
529         initDone = true;
530 }
531
532 ////////////////////////////////////////////////////////////////////////
533 // Implementation of SGShaderAnimation
534 ////////////////////////////////////////////////////////////////////////
535
536 SGShaderAnimation::SGShaderAnimation ( SGPropertyNode *prop_root,
537                    SGPropertyNode_ptr props )
538   : SGAnimation(props, new ssgBranch),
539     _condition(0),
540     _condition_value(true),
541     _shader_type(0),
542     _param_1(props->getFloatValue("param", 1.0f)),
543     _depth_test(props->getBoolValue("depth-test", true)),
544     _factor(props->getFloatValue("factor", 1.0f)),
545     _factor_prop(0),
546     _speed(props->getFloatValue("speed", 1.0f)),
547     _speed_prop(0),
548     _effectTexture(0),
549     _textureData(0),
550     _texWidth(0),
551     _texHeight(0)
552
553 {
554     SGPropertyNode_ptr node = props->getChild("condition");
555     if (node != 0) {
556         _condition = sgReadCondition(prop_root, node);
557         _condition_value = false;
558     }
559     node = props->getChild("factor-prop");
560     if( node )
561         _factor_prop = prop_root->getNode(node->getStringValue(), true);
562     node = props->getChild("speed-prop");
563     if( node )
564         _speed_prop = prop_root->getNode(node->getStringValue(), true);
565
566     sgSetVec4(_envColor, 0.0f, 0.0f, 0.0f, 1.0f);
567     node = props->getChild("texture");
568     if( node ) {
569         _effectTexture = ssgGetCurrentOptions()->createTexture( (char *) node->getStringValue(), 0, 0, 0);
570         glBindTexture(GL_TEXTURE_2D, _effectTexture->getHandle() );
571         glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &_texWidth);
572         glGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &_texHeight);
573
574         _textureData = new unsigned char[_texWidth * _texHeight * 3];
575         glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, _textureData);
576         glBindTexture(GL_TEXTURE_2D, 0 );
577     }
578     string shader_name = props->getStringValue("shader");
579     if( shader_name == "fresnel" || shader_name == "reflection" )
580         _shader_type = 1;
581     else if( shader_name == "heat-haze" )
582         _shader_type = 2;
583     else if( shader_name == "chrome" && _effectTexture)
584         _shader_type = 3;
585 }
586
587 static void setCallBack(ssgBranch *branch, ssgBase *user_data, ssgCallback cb) {
588     for (int i = 0; i < branch->getNumKids(); i++) {
589         ssgEntity *e = branch->getKid(i);
590         if( e->isAKindOf( ssgTypeBranch() ) )
591             setCallBack( (ssgBranch *) e, user_data, cb);
592         else if( e->isAKindOf( ssgTypeVtxTable() ) ) {
593                 e->setCallback( SSG_CALLBACK_PREDRAW, cb );
594             e->setUserData( user_data );
595         }
596     }
597 }
598
599 void SGShaderAnimation::init()
600 {
601     if( ! initDone )
602         init_shaders();
603     if( _shader_type == 1 && Shader::is_VP_supported() && shFresnel)
604         setCallBack( getBranch(), (ssgBase *) this, fresnel_shader_callback );
605     else if( _shader_type == 2 ) {
606         // this is the same extension with different names
607         isRectangleTextureSupported = SGIsOpenGLExtensionSupported("GL_EXT_texture_rectangle") ||
608             SGIsOpenGLExtensionSupported("GL_ARB_texture_rectangle") ||
609             SGIsOpenGLExtensionSupported("GL_NV_texture_rectangle");
610         setCallBack( getBranch(), (ssgBase *) this, heat_haze_shader_callback );
611     }
612     else if( _shader_type == 3 )
613         setCallBack( getBranch(), (ssgBase *) this, chrome_shader_callback );
614     else
615         setCallBack( getBranch(), (ssgBase *) this, null_shader_callback );
616 }
617
618 SGShaderAnimation::~SGShaderAnimation()
619 {
620     delete _condition;
621     delete _effectTexture;
622     delete _textureData;
623 }
624
625 int
626 SGShaderAnimation::update()
627 {
628     if (_condition)
629         _condition_value = _condition->test();
630     if( _factor_prop)
631         _factor = _factor_prop->getFloatValue();
632     if( _speed_prop)
633         _speed = _speed_prop->getFloatValue();
634     return 2;
635 }
636
637 void sgShaderFrameInit(double delta_time_sec) {
638     haveBackground = false;
639     totalTime += delta_time_sec;
640 }