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