]> git.mxchange.org Git - simgear.git/blob - simgear/scene/model/shadanim.cxx
Vivian Meazza:
[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></shader>
57         <object-name>...</object-name>
58         <depth-test>false</depth-test>
59     </animation>
60
61 */
62 static Shader *shFresnel=NULL;
63 static GLuint texFresnel = 0;
64
65 static GLuint texBackground = 0;
66 static const int texBackgroundWidth = 1024, texBackgroundHeight = 1024;
67 static bool initDone = false;
68 static bool haveBackground = false;
69
70 static glActiveTextureProc glActiveTexturePtr = 0;
71 static double totalTime = 0.0;
72
73 static int null_shader_callback( ssgEntity *e ) {
74         GLuint dlist = 0;
75     ssgLeaf *leaf = (ssgLeaf *) e;
76 #ifdef _SSG_USE_DLIST
77     dlist = leaf->getDListIndex();
78     if( ! dlist ) {
79         leaf->makeDList();
80         dlist = leaf->getDListIndex();
81     }
82 #endif
83     if( ! dlist )
84         return true;
85     ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
86     if ( sst )
87         sst->apply();
88
89     SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
90     if( ! my_shader->_depth_test )
91         glDisable( GL_DEPTH_TEST );
92     glCallList ( dlist ) ;
93     // restore states
94     if( ! my_shader->_depth_test )
95         glEnable( GL_DEPTH_TEST );
96
97     // don't draw !
98     return false;
99 }
100
101 static int heat_haze_shader_callback( ssgEntity *e ) {
102         GLuint dlist = 0;
103     ssgLeaf *leaf = (ssgLeaf *) e;
104 #ifdef _SSG_USE_DLIST
105     dlist = leaf->getDListIndex();
106     if( ! dlist ) {
107         leaf->makeDList();
108         dlist = leaf->getDListIndex();
109     }
110 #endif
111     if( ! dlist )
112         return true;
113     if( ! haveBackground ) {
114         // store the backbuffer in a texture
115         if( ! texBackground ) {
116             // allocate our texture here so we don't waste memory if no model use that effect
117             glGenTextures(1, &texBackground);
118             glBindTexture(GL_TEXTURE_2D, texBackground);
119             // trying to match the backbuffer pixel format
120             GLint internalFormat = GL_RGB8;
121             GLint colorBits = 0, alphaBits = 0;
122             glGetIntegerv( GL_BLUE_BITS, &colorBits );
123             glGetIntegerv( GL_ALPHA_BITS, &alphaBits );
124             if(colorBits == 5) {
125                 if( alphaBits == 0 )
126                     internalFormat = GL_RGB5;
127                 else
128                     internalFormat = GL_RGB5_A1;
129             } else {
130                 if( alphaBits != 0 )
131                     internalFormat = GL_RGBA8;
132             }
133             glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 
134                             texBackgroundWidth, texBackgroundHeight, 0, GL_RGB, GL_FLOAT, NULL);
135
136             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
137             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
138             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
139             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
140             glBindTexture(GL_TEXTURE_2D, 0);
141         }
142         GLint viewport[4];
143         glGetIntegerv( GL_VIEWPORT, viewport );
144         const int screen_width = viewport[2];
145         const int screen_height = viewport[3];
146         glBindTexture(GL_TEXTURE_2D, texBackground);
147         // center of texture = center of screen
148         // obviously we don't have the whole screen if screen_width > texBackgroundWidth
149         glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 
150             (screen_width - texBackgroundWidth) / 2, 
151             (screen_height - texBackgroundHeight) / 2, 
152             texBackgroundWidth, texBackgroundHeight );
153         haveBackground = true;
154         glBindTexture(GL_TEXTURE_2D, 0);
155     }
156     ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
157     if ( sst )
158         sst->apply();
159
160     SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
161     if( ! my_shader->_depth_test )
162         glDisable( GL_DEPTH_TEST );
163     glDepthMask( GL_FALSE );
164     glDisable( GL_LIGHTING );
165     if(1) {
166         // noise texture, tex coord from the model translated by a time factor
167         glActiveTexturePtr( GL_TEXTURE0_ARB );
168         glEnable(GL_TEXTURE_2D);
169         const float noiseDist = fmodf(- totalTime * my_shader->_factor * my_shader->_speed, 4.0f);
170         glMatrixMode(GL_TEXTURE);
171             glLoadIdentity();
172             glTranslatef( noiseDist, 0.0f, 0.0f );
173         glMatrixMode(GL_MODELVIEW);
174
175         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
176
177         // background texture
178         glActiveTexturePtr( GL_TEXTURE1_ARB );
179         glEnable(GL_TEXTURE_2D);
180         glBindTexture(GL_TEXTURE_2D, texBackground);
181
182         // automatic generation of texture coordinates
183         // map to screen space
184         sgMat4 CameraProjM, CameraViewM, textureMatrix;
185         GLint viewport[4];
186         glGetIntegerv( GL_VIEWPORT, viewport );
187         const int screen_width = viewport[2];
188         const int screen_height = viewport[3];
189         glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *) CameraProjM);
190         glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) CameraViewM);
191         const float dummy_scale = 1.0f; //0.95f;
192         const float deltaPos = 0.05f;
193         glMatrixMode(GL_TEXTURE);
194             glLoadIdentity();
195             glTranslatef( 0.5f, 0.5f, 0.0f );
196             glScalef( float( screen_width ) / float( texBackgroundWidth ) * 0.5f * dummy_scale,
197                 float( screen_height ) / float( texBackgroundHeight ) * 0.5f * dummy_scale, 1.0f );
198             glMultMatrixf( (GLfloat *) CameraProjM );
199             glMultMatrixf( (GLfloat *) CameraViewM );
200             glTranslatef( deltaPos, deltaPos, deltaPos );
201         glMatrixMode(GL_MODELVIEW);
202
203         sgMakeIdentMat4( textureMatrix );
204         glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
205         glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
206         glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
207         glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
208         glTexGenfv( GL_S, GL_EYE_PLANE, textureMatrix[0] );
209         glTexGenfv( GL_T, GL_EYE_PLANE, textureMatrix[1] );
210         glTexGenfv( GL_R, GL_EYE_PLANE, textureMatrix[2] );
211         glTexGenfv( GL_Q, GL_EYE_PLANE, textureMatrix[3] );
212         glEnable( GL_TEXTURE_GEN_S );
213         glEnable( GL_TEXTURE_GEN_T );
214         glEnable( GL_TEXTURE_GEN_R );
215         glEnable( GL_TEXTURE_GEN_Q );
216
217         sgVec4 enviro = {1.00f, 1.00f, 1.00f, 0.85f};
218
219         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
220         glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE ); 
221         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE );
222         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR ); 
223         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT_ARB );
224         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); 
225                 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, enviro);
226
227         glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
228         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE0_ARB);
229         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
230 //        glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_CONSTANT_ARB );
231         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PRIMARY_COLOR_ARB );
232         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA ); 
233
234         glCallList ( dlist ) ;
235         glMatrixMode(GL_TEXTURE);
236         glTranslatef( - deltaPos*2.0f, -deltaPos*2.5f, -deltaPos*2.0f );
237         glMatrixMode(GL_MODELVIEW);
238         glCallList ( dlist ) ;
239
240         // alter colors only on last rendering
241         sgVec4 fLight = {0.93f, 0.93f, 1.00f, 0.85f};
242         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB );
243         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); 
244 //              glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, fLight);
245
246         glMatrixMode(GL_TEXTURE);
247         glTranslatef( deltaPos*0.7f, deltaPos*1.7f, deltaPos*0.7f );
248         glMatrixMode(GL_MODELVIEW);
249         glCallList ( dlist ) ;
250
251
252         glActiveTexturePtr( GL_TEXTURE1_ARB );
253         glDisable( GL_TEXTURE_GEN_S );
254         glDisable( GL_TEXTURE_GEN_T );
255         glDisable( GL_TEXTURE_GEN_R );
256         glDisable( GL_TEXTURE_GEN_Q );
257         glMatrixMode(GL_TEXTURE);
258             glLoadIdentity();
259         glMatrixMode(GL_MODELVIEW);
260         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
261         glDisable(GL_TEXTURE_2D);
262         glActiveTexturePtr( GL_TEXTURE0_ARB );
263         glMatrixMode(GL_TEXTURE);
264             glLoadIdentity();
265         glMatrixMode(GL_MODELVIEW);
266         glEnable(GL_TEXTURE_2D);
267         glBindTexture(GL_TEXTURE_2D, 0);
268     }
269     // restore states
270     if( ! my_shader->_depth_test )
271         glEnable( GL_DEPTH_TEST );
272
273     glEnable( GL_LIGHTING );
274     glDepthMask( GL_TRUE );
275     if( sst )
276         sst->force();
277
278    // don't draw !
279     return false;
280 }
281
282 static int fresnel_shader_callback( ssgEntity *e ) {
283         GLuint dlist = 0;
284     ssgLeaf *leaf = (ssgLeaf *) e;
285 #ifdef _SSG_USE_DLIST
286     dlist = leaf->getDListIndex();
287     if( ! dlist ) {
288         leaf->makeDList();
289         dlist = leaf->getDListIndex();
290     }
291 #endif
292     if( ! dlist )
293         return true;
294     ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState());
295     if ( sst )
296         sst->apply();
297
298     sgVec4 sunColor, ambientColor;
299     ssgGetLight( 0 )->getColour(GL_DIFFUSE, sunColor );
300     ssgGetLight( 0 )->getColour(GL_AMBIENT, ambientColor );
301
302     SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() );
303     glEnable(GL_BLEND);
304         glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
305         glEnable(GL_ALPHA_TEST);
306         glAlphaFunc(GL_GREATER, 0.0f);
307
308         if( true ) {
309 //        sgVec4 R = {0.5,0.0,0.0,0.0};
310         sgVec4 enviro = {1.0,0.0,0.0,1.0};
311 //        sgCopyVec4( enviro, sunColor );
312         glActiveTexturePtr( GL_TEXTURE0_ARB );
313         glEnable(GL_TEXTURE_2D);
314         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
315         glActiveTexturePtr( GL_TEXTURE1_ARB );
316         glDisable(GL_TEXTURE_2D);
317         glEnable(GL_TEXTURE_1D);
318         glBindTexture(GL_TEXTURE_1D, texFresnel);
319         // c = a0 * a2 + a1 * (1-a2)
320 //        glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
321 //        glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
322         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
323         glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB ); 
324         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_CONSTANT_ARB );
325         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR ); 
326         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB );
327         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); 
328         glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE );
329         glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR ); 
330                 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, enviro);
331         shFresnel->enable();
332             shFresnel->bind();
333             glCallList ( dlist ) ;
334         shFresnel->disable();
335         glActiveTexturePtr( GL_TEXTURE1_ARB );
336         glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
337         glDisable(GL_TEXTURE_1D);
338         glActiveTexturePtr( GL_TEXTURE0_ARB );
339         glDisable(GL_TEXTURE_1D);
340         glEnable(GL_TEXTURE_2D);
341     }
342     // restore states
343 //    glBindTexture(GL_TEXTURE_2D, 0);
344 //    glDepthFunc(GL_LESS);
345 //    glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
346    if( sst )
347             sst->force();
348
349     // don't draw !
350     return false;
351 }
352
353 static void init_shaders(void) {
354         Shader::Init();
355     if( Shader::is_VP_supported() ) {
356             shFresnel = new Shader("/FlightGear/data/Textures/fresnel_vp.txt", "fresnel_vp");
357 //        shFresnel->bindNames("somedata", 0);
358     }
359         glActiveTexturePtr = (glActiveTextureProc) SGLookupFunction("glActiveTextureARB");
360     const int fresnelSize = 512;
361     unsigned char imageFresnel[ fresnelSize * 3 ];
362     for(int i = 0; i < fresnelSize; i++) {
363         const float R0 = 0.2f;
364         float NdotV = float( i ) / float( fresnelSize );
365         float f = R0 + (1.0f-R0)*pow(1.0f - NdotV, 5);
366         unsigned char ff = (unsigned char) (f * 255.0);
367         imageFresnel[i*3+0] = imageFresnel[i*3+1] = imageFresnel[i*3+2] = ff;
368     }
369     glGenTextures( 1, &texFresnel );
370         glBindTexture(GL_TEXTURE_1D, texFresnel );
371         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
372     glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
373     glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
374         glTexParameteri(GL_TEXTURE_1D, GL_GENERATE_MIPMAP_SGIS, true);
375         glTexImage1D(GL_TEXTURE_1D, 0, 3, fresnelSize, 0, GL_RGB, GL_UNSIGNED_BYTE, imageFresnel);
376         glBindTexture(GL_TEXTURE_1D, 0 );
377
378         initDone = true;
379 }
380
381 ////////////////////////////////////////////////////////////////////////
382 // Implementation of SGShaderAnimation
383 ////////////////////////////////////////////////////////////////////////
384
385 SGShaderAnimation::SGShaderAnimation ( SGPropertyNode *prop_root,
386                    SGPropertyNode_ptr props )
387   : SGAnimation(props, new ssgBranch),
388     _condition(0),
389     _condition_value(true),
390     _shader_type(0),
391     _param_1(props->getFloatValue("param", 1.0f)),
392     _depth_test(props->getBoolValue("depth-test", true)),
393     _factor(props->getFloatValue("factor", 1.0f)),
394     _factor_prop(0),
395     _speed(props->getFloatValue("speed", 1.0f)),
396     _speed_prop(0)
397
398 {
399     SGPropertyNode_ptr node = props->getChild("condition");
400     if (node != 0) {
401         _condition = sgReadCondition(prop_root, node);
402         _condition_value = false;
403     }
404     node = props->getChild("factor-prop");
405     if( node )
406         _factor_prop = prop_root->getNode(node->getStringValue(), true);
407     node = props->getChild("speed-prop");
408     if( node )
409         _speed_prop = prop_root->getNode(node->getStringValue(), true);
410
411     string shader_name = props->getStringValue("shader");
412     if( shader_name == "fresnel" || shader_name == "reflection" )
413         _shader_type = 1;
414     else if( shader_name == "heat-haze" )
415         _shader_type = 2;
416 }
417
418 static void setCallBack(ssgBranch *branch, ssgBase *user_data, ssgCallback cb) {
419     for (int i = 0; i < branch->getNumKids(); i++) {
420         ssgEntity *e = branch->getKid(i);
421         if( e->isAKindOf( ssgTypeBranch() ) )
422             setCallBack( (ssgBranch *) e, user_data, cb);
423         else if( e->isAKindOf( ssgTypeVtxTable() ) ) {
424                 e->setCallback( SSG_CALLBACK_PREDRAW, cb );
425             e->setUserData( user_data );
426         }
427     }
428 }
429
430 void SGShaderAnimation::init()
431 {
432     if( ! initDone )
433         init_shaders();
434     if( _shader_type == 1 && Shader::is_VP_supported() )
435         setCallBack( getBranch(), (ssgBase *) this, fresnel_shader_callback );
436     else if( _shader_type == 2 )
437         setCallBack( getBranch(), (ssgBase *) this, heat_haze_shader_callback );
438     else
439         setCallBack( getBranch(), (ssgBase *) this, null_shader_callback );
440 }
441
442 SGShaderAnimation::~SGShaderAnimation()
443 {
444     delete _condition;
445 }
446
447 int
448 SGShaderAnimation::update()
449 {
450     if (_condition)
451         _condition_value = _condition->test();
452     if( _factor_prop)
453         _factor = _factor_prop->getFloatValue();
454     if( _speed_prop)
455         _speed = _speed_prop->getFloatValue();
456     return 2;
457 }
458
459 void sgShaderFrameInit(double delta_time_sec) {
460     haveBackground = false;
461     totalTime += delta_time_sec;
462 }