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