From: ehofman Date: Sun, 25 Sep 2005 07:44:50 +0000 (+0000) Subject: Vivian Meazza: X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=1577ab04e134b1cc57dc8d746b66b323843b7b4d;p=simgear.git Vivian Meazza: Correct the bug in the translate animation where the offset was part of the multiplication. It now behaves like all other animations: out = (prop * factor) + offset I feel strongly that the existing is wrong and must be corrected - it is non-op if the offset is zero as I have found to my cost! It is just a typo I expect. The diff also provides non-op default values for the scale animation. I've also included Harald's latest eye-candy animation which allows us to have a very smart heat-haze for exhausts. They have been tested by me and others on Linux and Cygwin. You might like to upload these - I have a revised Hunter ready to go as soon as they are uploaded. --- diff --git a/simgear/scene/model/Makefile.am b/simgear/scene/model/Makefile.am index d05744c1..8c82b161 100644 --- a/simgear/scene/model/Makefile.am +++ b/simgear/scene/model/Makefile.am @@ -24,6 +24,7 @@ libsgmodel_a_SOURCES = \ personality.cxx \ placement.cxx \ placementtrans.cxx \ - shadowvolume.cxx + shadowvolume.cxx \ + shadanim.cxx INCLUDES = -I$(top_srcdir) diff --git a/simgear/scene/model/animation.cxx b/simgear/scene/model/animation.cxx index 67ee8dd7..68428e4f 100644 --- a/simgear/scene/model/animation.cxx +++ b/simgear/scene/model/animation.cxx @@ -772,7 +772,7 @@ SGTranslateAnimation::update() { if (_condition == 0 || _condition->test()) { if (_table == 0) { - _position_m = (_prop->getDoubleValue() + _offset_m) * _factor; + _position_m = (_prop->getDoubleValue() * _factor) + _offset_m; if (_has_min && _position_m < _min_m) _position_m = _min_m; if (_has_max && _position_m > _max_m) @@ -796,9 +796,9 @@ SGScaleAnimation::SGScaleAnimation( SGPropertyNode *prop_root, SGPropertyNode_ptr props ) : SGAnimation(props, new ssgTransform), _prop((SGPropertyNode *)prop_root->getNode(props->getStringValue("property", "/null"), true)), - _x_factor(props->getDoubleValue("x-factor", 1.0)), - _y_factor(props->getDoubleValue("y-factor", 1.0)), - _z_factor(props->getDoubleValue("z-factor", 1.0)), + _x_factor(props->getDoubleValue("x-factor", 0)), + _y_factor(props->getDoubleValue("y-factor", 0)), + _z_factor(props->getDoubleValue("z-factor", 0)), _x_offset(props->getDoubleValue("x-offset", 1.0)), _y_offset(props->getDoubleValue("y-offset", 1.0)), _z_offset(props->getDoubleValue("z-offset", 1.0)), diff --git a/simgear/scene/model/animation.hxx b/simgear/scene/model/animation.hxx index 535cb276..d6fc2712 100644 --- a/simgear/scene/model/animation.hxx +++ b/simgear/scene/model/animation.hxx @@ -599,5 +599,31 @@ private: bool _condition_value; }; +/** ++ * An "animation" that replace fixed opengl pipeline by shaders ++ */ +class SGShaderAnimation : public SGAnimation +{ +public: + SGShaderAnimation ( SGPropertyNode *prop_root, + SGPropertyNode_ptr props ); + virtual ~SGShaderAnimation (); + virtual void init(); + virtual int update(); + bool get_condition_value(void); +private: + SGCondition * _condition; + bool _condition_value; + int _shader_type; + float _param_1; + sgVec4 _param_color; +public: + bool _depth_test; + float _factor; + SGPropertyNode_ptr _factor_prop; + float _speed; + SGPropertyNode_ptr _speed_prop; +}; + #endif // _SG_ANIMATION_HXX diff --git a/simgear/scene/model/model.cxx b/simgear/scene/model/model.cxx index 9d0ae8c5..c44509db 100644 --- a/simgear/scene/model/model.cxx +++ b/simgear/scene/model/model.cxx @@ -167,6 +167,8 @@ sgMakeAnimation( ssgBranch * model, animation = new SGDistScaleAnimation(node); } else if (!strcmp("noshadow", type)) { animation = new SGShadowAnimation(prop_root, node); + } else if (!strcmp("shader", type)) { + animation = new SGShaderAnimation(prop_root, node); } else { animation = new SGNullAnimation(node); SG_LOG(SG_INPUT, SG_WARN, "Unknown animation type " << type); diff --git a/simgear/scene/model/shadanim.cxx b/simgear/scene/model/shadanim.cxx new file mode 100644 index 00000000..3f4c002b --- /dev/null +++ b/simgear/scene/model/shadanim.cxx @@ -0,0 +1,462 @@ +// non fixed Opengl pipeline rendering +// +// Written by Harald JOHNSEN, started Jully 2005. +// +// Copyright (C) 2005 Harald JOHNSEN - hjohnsen@evc.net +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA +// +// + + +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#include "animation.hxx" +/* + + shader + fresnel + ... + + + + shader + heat-haze + ... + ... + ... + ... + ... + + + + shader + + ... + false + + +*/ +static Shader *shFresnel=NULL; +static GLuint texFresnel = 0; + +static GLuint texBackground = 0; +static const int texBackgroundWidth = 1024, texBackgroundHeight = 1024; +static bool initDone = false; +static bool haveBackground = false; + +static glActiveTextureProc glActiveTexturePtr = 0; +static double totalTime = 0.0; + +static int null_shader_callback( ssgEntity *e ) { + GLuint dlist = 0; + ssgLeaf *leaf = (ssgLeaf *) e; +#ifdef _SSG_USE_DLIST + dlist = leaf->getDListIndex(); + if( ! dlist ) { + leaf->makeDList(); + dlist = leaf->getDListIndex(); + } +#endif + if( ! dlist ) + return true; + ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState()); + if ( sst ) + sst->apply(); + + SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() ); + if( ! my_shader->_depth_test ) + glDisable( GL_DEPTH_TEST ); + glCallList ( dlist ) ; + // restore states + if( ! my_shader->_depth_test ) + glEnable( GL_DEPTH_TEST ); + + // don't draw ! + return false; +} + +static int heat_haze_shader_callback( ssgEntity *e ) { + GLuint dlist = 0; + ssgLeaf *leaf = (ssgLeaf *) e; +#ifdef _SSG_USE_DLIST + dlist = leaf->getDListIndex(); + if( ! dlist ) { + leaf->makeDList(); + dlist = leaf->getDListIndex(); + } +#endif + if( ! dlist ) + return true; + if( ! haveBackground ) { + // store the backbuffer in a texture + if( ! texBackground ) { + // allocate our texture here so we don't waste memory if no model use that effect + glGenTextures(1, &texBackground); + glBindTexture(GL_TEXTURE_2D, texBackground); + // trying to match the backbuffer pixel format + GLint internalFormat = GL_RGB8; + GLint colorBits = 0, alphaBits = 0; + glGetIntegerv( GL_BLUE_BITS, &colorBits ); + glGetIntegerv( GL_ALPHA_BITS, &alphaBits ); + if(colorBits == 5) { + if( alphaBits == 0 ) + internalFormat = GL_RGB5; + else + internalFormat = GL_RGB5_A1; + } else { + if( alphaBits != 0 ) + internalFormat = GL_RGBA8; + } + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, + texBackgroundWidth, texBackgroundHeight, 0, GL_RGB, GL_FLOAT, NULL); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); + } + GLint viewport[4]; + glGetIntegerv( GL_VIEWPORT, viewport ); + const int screen_width = viewport[2]; + const int screen_height = viewport[3]; + glBindTexture(GL_TEXTURE_2D, texBackground); + // center of texture = center of screen + // obviously we don't have the whole screen if screen_width > texBackgroundWidth + glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, + (screen_width - texBackgroundWidth) / 2, + (screen_height - texBackgroundHeight) / 2, + texBackgroundWidth, texBackgroundHeight ); + haveBackground = true; + glBindTexture(GL_TEXTURE_2D, 0); + } + ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState()); + if ( sst ) + sst->apply(); + + SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() ); + if( ! my_shader->_depth_test ) + glDisable( GL_DEPTH_TEST ); + glDepthMask( GL_FALSE ); + glDisable( GL_LIGHTING ); + if(1) { + // noise texture, tex coord from the model translated by a time factor + glActiveTexturePtr( GL_TEXTURE0_ARB ); + glEnable(GL_TEXTURE_2D); + const float noiseDist = fmodf(- totalTime * my_shader->_factor * my_shader->_speed, 4.0f); + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glTranslatef( noiseDist, 0.0f, 0.0f ); + glMatrixMode(GL_MODELVIEW); + + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + + // background texture + glActiveTexturePtr( GL_TEXTURE1_ARB ); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, texBackground); + + // automatic generation of texture coordinates + // map to screen space + sgMat4 CameraProjM, CameraViewM, textureMatrix; + GLint viewport[4]; + glGetIntegerv( GL_VIEWPORT, viewport ); + const int screen_width = viewport[2]; + const int screen_height = viewport[3]; + glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *) CameraProjM); + glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) CameraViewM); + const float dummy_scale = 1.0f; //0.95f; + const float deltaPos = 0.05f; + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glTranslatef( 0.5f, 0.5f, 0.0f ); + glScalef( float( screen_width ) / float( texBackgroundWidth ) * 0.5f * dummy_scale, + float( screen_height ) / float( texBackgroundHeight ) * 0.5f * dummy_scale, 1.0f ); + glMultMatrixf( (GLfloat *) CameraProjM ); + glMultMatrixf( (GLfloat *) CameraViewM ); + glTranslatef( deltaPos, deltaPos, deltaPos ); + glMatrixMode(GL_MODELVIEW); + + sgMakeIdentMat4( textureMatrix ); + glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); + glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); + glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); + glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ); + glTexGenfv( GL_S, GL_EYE_PLANE, textureMatrix[0] ); + glTexGenfv( GL_T, GL_EYE_PLANE, textureMatrix[1] ); + glTexGenfv( GL_R, GL_EYE_PLANE, textureMatrix[2] ); + glTexGenfv( GL_Q, GL_EYE_PLANE, textureMatrix[3] ); + glEnable( GL_TEXTURE_GEN_S ); + glEnable( GL_TEXTURE_GEN_T ); + glEnable( GL_TEXTURE_GEN_R ); + glEnable( GL_TEXTURE_GEN_Q ); + + sgVec4 enviro = {1.00f, 1.00f, 1.00f, 0.85f}; + + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB ); + glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE ); + glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE ); + glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR ); + glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT_ARB ); + glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, enviro); + + glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); + glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE0_ARB); + glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); +// glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_CONSTANT_ARB ); + glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PRIMARY_COLOR_ARB ); + glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA ); + + glCallList ( dlist ) ; + glMatrixMode(GL_TEXTURE); + glTranslatef( - deltaPos*2.0f, -deltaPos*2.5f, -deltaPos*2.0f ); + glMatrixMode(GL_MODELVIEW); + glCallList ( dlist ) ; + + // alter colors only on last rendering + sgVec4 fLight = {0.93f, 0.93f, 1.00f, 0.85f}; + glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB ); + glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); +// glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, fLight); + + glMatrixMode(GL_TEXTURE); + glTranslatef( deltaPos*0.7f, deltaPos*1.7f, deltaPos*0.7f ); + glMatrixMode(GL_MODELVIEW); + glCallList ( dlist ) ; + + + glActiveTexturePtr( GL_TEXTURE1_ARB ); + glDisable( GL_TEXTURE_GEN_S ); + glDisable( GL_TEXTURE_GEN_T ); + glDisable( GL_TEXTURE_GEN_R ); + glDisable( GL_TEXTURE_GEN_Q ); + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + glDisable(GL_TEXTURE_2D); + glActiveTexturePtr( GL_TEXTURE0_ARB ); + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); + } + // restore states + if( ! my_shader->_depth_test ) + glEnable( GL_DEPTH_TEST ); + + glEnable( GL_LIGHTING ); + glDepthMask( GL_TRUE ); + if( sst ) + sst->force(); + + // don't draw ! + return false; +} + +static int fresnel_shader_callback( ssgEntity *e ) { + GLuint dlist = 0; + ssgLeaf *leaf = (ssgLeaf *) e; +#ifdef _SSG_USE_DLIST + dlist = leaf->getDListIndex(); + if( ! dlist ) { + leaf->makeDList(); + dlist = leaf->getDListIndex(); + } +#endif + if( ! dlist ) + return true; + ssgSimpleState *sst = ((ssgSimpleState *)leaf->getState()); + if ( sst ) + sst->apply(); + + sgVec4 sunColor, ambientColor; + ssgGetLight( 0 )->getColour(GL_DIFFUSE, sunColor ); + ssgGetLight( 0 )->getColour(GL_AMBIENT, ambientColor ); + + SGShaderAnimation *my_shader = (SGShaderAnimation *) ( e->getUserData() ); + glEnable(GL_BLEND); + glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ; + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.0f); + + if( true ) { +// sgVec4 R = {0.5,0.0,0.0,0.0}; + sgVec4 enviro = {1.0,0.0,0.0,1.0}; +// sgCopyVec4( enviro, sunColor ); + glActiveTexturePtr( GL_TEXTURE0_ARB ); + glEnable(GL_TEXTURE_2D); + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + glActiveTexturePtr( GL_TEXTURE1_ARB ); + glDisable(GL_TEXTURE_2D); + glEnable(GL_TEXTURE_1D); + glBindTexture(GL_TEXTURE_1D, texFresnel); + // c = a0 * a2 + a1 * (1-a2) +// glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); +// glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB ); + glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB ); + glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_CONSTANT_ARB ); + glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR ); + glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB ); + glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); + glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE ); + glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR ); + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, enviro); + shFresnel->enable(); + shFresnel->bind(); + glCallList ( dlist ) ; + shFresnel->disable(); + glActiveTexturePtr( GL_TEXTURE1_ARB ); + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + glDisable(GL_TEXTURE_1D); + glActiveTexturePtr( GL_TEXTURE0_ARB ); + glDisable(GL_TEXTURE_1D); + glEnable(GL_TEXTURE_2D); + } + // restore states +// glBindTexture(GL_TEXTURE_2D, 0); +// glDepthFunc(GL_LESS); +// glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ; + if( sst ) + sst->force(); + + // don't draw ! + return false; +} + +static void init_shaders(void) { + Shader::Init(); + if( Shader::is_VP_supported() ) { + shFresnel = new Shader("/FlightGear/data/Textures/fresnel_vp.txt", "fresnel_vp"); +// shFresnel->bindNames("somedata", 0); + } + glActiveTexturePtr = (glActiveTextureProc) SGLookupFunction("glActiveTextureARB"); + const int fresnelSize = 512; + unsigned char imageFresnel[ fresnelSize * 3 ]; + for(int i = 0; i < fresnelSize; i++) { + const float R0 = 0.2f; + float NdotV = float( i ) / float( fresnelSize ); + float f = R0 + (1.0f-R0)*pow(1.0f - NdotV, 5); + unsigned char ff = (unsigned char) (f * 255.0); + imageFresnel[i*3+0] = imageFresnel[i*3+1] = imageFresnel[i*3+2] = ff; + } + glGenTextures( 1, &texFresnel ); + glBindTexture(GL_TEXTURE_1D, texFresnel ); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_1D, GL_GENERATE_MIPMAP_SGIS, true); + glTexImage1D(GL_TEXTURE_1D, 0, 3, fresnelSize, 0, GL_RGB, GL_UNSIGNED_BYTE, imageFresnel); + glBindTexture(GL_TEXTURE_1D, 0 ); + + initDone = true; +} + +//////////////////////////////////////////////////////////////////////// +// Implementation of SGShaderAnimation +//////////////////////////////////////////////////////////////////////// + +SGShaderAnimation::SGShaderAnimation ( SGPropertyNode *prop_root, + SGPropertyNode_ptr props ) + : SGAnimation(props, new ssgBranch), + _condition(0), + _condition_value(true), + _shader_type(0), + _param_1(props->getFloatValue("param", 1.0f)), + _depth_test(props->getBoolValue("depth-test", true)), + _factor(props->getFloatValue("factor", 1.0f)), + _factor_prop(0), + _speed(props->getFloatValue("speed", 1.0f)), + _speed_prop(0) + +{ + SGPropertyNode_ptr node = props->getChild("condition"); + if (node != 0) { + _condition = sgReadCondition(prop_root, node); + _condition_value = false; + } + node = props->getChild("factor-prop"); + if( node ) + _factor_prop = prop_root->getNode(node->getStringValue(), true); + node = props->getChild("speed-prop"); + if( node ) + _speed_prop = prop_root->getNode(node->getStringValue(), true); + + string shader_name = props->getStringValue("shader"); + if( shader_name == "fresnel" || shader_name == "reflection" ) + _shader_type = 1; + else if( shader_name == "heat-haze" ) + _shader_type = 2; +} + +static void setCallBack(ssgBranch *branch, ssgBase *user_data, ssgCallback cb) { + for (int i = 0; i < branch->getNumKids(); i++) { + ssgEntity *e = branch->getKid(i); + if( e->isAKindOf( ssgTypeBranch() ) ) + setCallBack( (ssgBranch *) e, user_data, cb); + else if( e->isAKindOf( ssgTypeVtxTable() ) ) { + e->setCallback( SSG_CALLBACK_PREDRAW, cb ); + e->setUserData( user_data ); + } + } +} + +void SGShaderAnimation::init() +{ + if( ! initDone ) + init_shaders(); + if( _shader_type == 1 && Shader::is_VP_supported() ) + setCallBack( getBranch(), (ssgBase *) this, fresnel_shader_callback ); + else if( _shader_type == 2 ) + setCallBack( getBranch(), (ssgBase *) this, heat_haze_shader_callback ); + else + setCallBack( getBranch(), (ssgBase *) this, null_shader_callback ); +} + +SGShaderAnimation::~SGShaderAnimation() +{ + delete _condition; +} + +int +SGShaderAnimation::update() +{ + if (_condition) + _condition_value = _condition->test(); + if( _factor_prop) + _factor = _factor_prop->getFloatValue(); + if( _speed_prop) + _speed = _speed_prop->getFloatValue(); + return 2; +} + +void sgShaderFrameInit(double delta_time_sec) { + haveBackground = false; + totalTime += delta_time_sec; +}