void WaterSurfaceShader::linkStateSet( osg::ref_ptr< osg::StateSet > stateSet ) { std::stringstream ss; // Vertex Textures for( unsigned int iLevel = 0; iLevel < NumHeightMapLevels; iLevel++ ) { int level = (int)iLevel; ss << VertexTextureLocation << level; std::string vertexTextureLocation = ss.str(); ss.str( "" ); int pixelSize = (int)pow( 2.0, (double)( level + 1 ) ); stateSet->setTextureAttributeAndModes( level, new NoiseTexture3D( pixelSize ), osg::StateAttribute::ON ); osg::Uniform* uniform = new osg::Uniform( vertexTextureLocation.c_str(), level ); stateSet->addUniform( uniform ); } // Time _timeUniform = new osg::Uniform( osg::Uniform::FLOAT, TimeLocation.c_str() ); _timeUniform->set( 0.0f ); _timeUniform->setUpdateCallback( new TimeUniformCallback() ); stateSet->addUniform( _timeUniform ); // Link stateSet->setAttributeAndModes( _shaderProgram, osg::StateAttribute::ON ); }
void ComputeNode::addComputationResultsRenderTree() { _computationResultsRenderProgram = new osg::Program; _vertexShader = osgDB::readRefShaderFile(osg::Shader::VERTEX, _vertexShaderSourcePath); _computationResultsRenderProgram->addShader(_vertexShader.get()); _geometryShader = osgDB::readRefShaderFile(osg::Shader::GEOMETRY, _geometryShaderSourcePath); _computationResultsRenderProgram->addShader(_geometryShader.get()); _fragmentShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, _fragmentShaderSourcePath); _computationResultsRenderProgram->addShader(_fragmentShader.get()); _computationResultsRenderProgram->addBindAttribLocation("tex_coords", 1); _computationResultsRenderGroup = new osg::Group; _computationResultsRenderGroup->setDataVariance(osg::Object::DYNAMIC); _computationResultsRenderStateSet = _computationResultsRenderGroup->getOrCreateStateSet(); _computationResultsRenderStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); osg::PointSprite *sprite = new osg::PointSprite; int texture_unit = 0; _computationResultsRenderStateSet->setTextureAttributeAndModes(texture_unit, sprite, osg::StateAttribute::ON); _computationResultsRenderStateSet->setAttributeAndModes(_computationResultsRenderProgram.get(), osg::StateAttribute::ON); _computationResultsRenderStateSet->addUniform(new osg::Uniform("particleTexture", texture_unit)); _computationResultsRenderStateSet->addUniform(new osg::Uniform("numRows", (int)NUM_ELEMENTS_X)); _computationResultsRenderStateSet->addUniform(new osg::Uniform("numCols", (int)NUM_ELEMENTS_Y)); _computationResultsRenderStateSet->setMode(GL_POINT_SMOOTH, osg::StateAttribute::ON); _computationResultsRenderStateSet->setMode(GL_VERTEX_PROGRAM_POINT_SIZE_ARB, osg::StateAttribute::ON); _computationResultsRenderStateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON); _computationResultsRenderStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF); osg::Texture2D *tex = new osg::Texture2D(); osg::Image* particleImage = createSpotLightImage(osg::Vec4(1, 0, 0, 1), osg::Vec4(0.5, 0, 0, 0.0), 32, 0.7); if (particleImage) { tex->setImage(particleImage); } _computationResultsRenderStateSet->setTextureAttributeAndModes(texture_unit, tex, osg::StateAttribute::ON); osg::BlendFunc *blend = new osg::BlendFunc; if (false) //emissive particles { blend->setFunction(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE); } else { blend->setFunction(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA); } _computationResultsRenderStateSet->setAttributeAndModes(blend, osg::StateAttribute::ON); osg::Depth* depth = new osg::Depth; depth->setRange(0.0f, 0.0f); depth->setFunction(osg::Depth::ALWAYS); depth->setWriteMask(false); depth->setFunction(osg::Depth::ALWAYS); _computationResultsRenderStateSet->setAttributeAndModes(depth, osg::StateAttribute::OFF); osg::Geode* particleGeode = new osg::Geode; unsigned int numVertices = NUM_ELEMENTS_X*NUM_ELEMENTS_Y; osg::Geometry* particleGeometry = new osg::Geometry; particleGeometry->setUseDisplayList(false); particleGeometry->setUseVertexBufferObjects(true); osg::Vec3Array* vertexarray = new osg::Vec3Array; osg::Vec2Array* tcoords = new osg::Vec2Array; osg::Vec2 bottom_texcoord(0.0f, 0.0f); osg::Vec2 dx_texcoord(1.0f / (float)(NUM_ELEMENTS_X), 0.0f); osg::Vec2 dy_texcoord(0.0f, 1.0f / (float)(NUM_ELEMENTS_Y)); for (int i = 0; i < NUM_ELEMENTS_X; i++) { osg::Vec2 texcoord = bottom_texcoord + dy_texcoord*(float)i; for (int j = 0; j < NUM_ELEMENTS_Y; j++) { vertexarray->push_back(osg::Vec3(texcoord.x(), texcoord.y(), 0.0)); tcoords->push_back(osg::Vec2(texcoord.x(), texcoord.y())); texcoord += dx_texcoord; } } particleGeometry->setVertexArray(vertexarray); particleGeometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, numVertices)); particleGeometry->setTexCoordArray(0, tcoords); //this glMemoryBarrier thing... not sure if we could better do instanced drawing? all the data is in Shader Storage Buffer.. particleGeometry->setVertexAttribArray(1, particleGeometry->getTexCoordArray(0), osg::Array::BIND_PER_VERTEX); _computationResultsRenderGroup->addChild(particleGeode); particleGeode->addDrawable(particleGeometry); addChild(_computationResultsRenderGroup.get()); }
osg::Node* CreateScene() { osg::Group* pGroup = new osg::Group; pGroup->addChild( createDebugText() ); ////////////////////////// // simple terrain part I ////////////////////////// osg::ref_ptr<CTerrain> rTerrain = new CTerrain; rTerrain->Init(); pGroup->addChild( rTerrain->getNodeWithShader() ); ////////////////////////// // RTT terrain ////////////////////////// osg::Group* pRenderMe = new osg::Group; osg::Geode* pGeodeShape = new osg::Geode; pGeodeShape->addDrawable( new osg::ShapeDrawable( new osg::Sphere(osg::Vec3(0.0f,0.0f,4.0f),1.0f) ) ); pGroup->addChild( pGeodeShape ); pRenderMe->addChild( rTerrain->getNode() ); pGroup->addChild( pGeodeShape ); pHeightRTT = new CHeightRTT; pHeightRTT->init( rViewer, rTextCam, rViewer->getCamera(), pGroup, pRenderMe ); ////////////////////////// // simple terrain part II ////////////////////////// rTerrain->setCam( pHeightRTT->getCamera() ); ////////////////////////// // grass billboard stuff ////////////////////////// pGeodeGrass = new osg::Geode(); geomGrass = createGrassGeom(); pGeodeGrass->addDrawable( geomGrass ); osg::ref_ptr< osg::Shader > vertexShader = new osg::Shader(); vertexShader->setType( osg::Shader::VERTEX ); vertexShader->loadShaderSourceFromFile( "grass.vert" ); osg::ref_ptr< osg::Shader > fragShader = new osg::Shader(); fragShader->setType( osg::Shader::FRAGMENT ); fragShader->loadShaderSourceFromFile( "grass.frag" ); osg::ref_ptr< osg::Program > program = new osg::Program(); program->addShader( vertexShader.get() ); program->addShader( fragShader.get() ); ss = pGeodeGrass->getOrCreateStateSet(); ss->setAttribute( program.get(), osg::StateAttribute::ON | osg::StateAttribute::PROTECTED ); uniformCC = new osg::Uniform("cc",(int)cc); ss->addUniform( uniformCC ); // camera lock uniformLock = new osg::Uniform( "bLock", false ); ss->addUniform( uniformLock ); // spacing uniformSpacing = new osg::Uniform( "spacing", (float)sp ); ss->addUniform( uniformSpacing ); // height map ss->setTextureAttributeAndModes( 1, pHeightRTT->getTexture(), osg::StateAttribute::ON ); osg::Uniform* uniformHeightMap = new osg::Uniform( "texHeightMap", 1 ); ss->addUniform( uniformHeightMap ); // height adjust uniformHeightAdjust = new osg::Uniform( "heightAdjust", heightAdjust ); ss->addUniform( uniformHeightAdjust ); // wind factor uniformWindFactor = new osg::Uniform( "windFactor", windFactor ); ss->addUniform( uniformWindFactor ); // grass stretch uniformGrassStretch = new osg::Uniform( "grassStretch", grassStretch ); ss->addUniform( uniformGrassStretch ); // ortho camera inverse view matrix osg::Uniform* uniformOrthoInverseViewMatrix = new osg::Uniform( "orthoInverseViewMatrix", pHeightRTT->getCamera()->getInverseViewMatrix() ); ss->addUniform( uniformOrthoInverseViewMatrix ); pGeodeGrass->setUpdateCallback( new CMyUpdateCallbackGrass( pHeightRTT->getCamera(), uniformOrthoInverseViewMatrix ) ); osg::Texture2D* pTex = new osg::Texture2D; osg::Image* pImage = osgDB::readImageFile( "grass2.tga" ); pTex->setImage( pImage ); ss->setTextureAttributeAndModes( 0, pTex, osg::StateAttribute::ON ); ss->setMode( GL_BLEND, osg::StateAttribute::ON ); ss->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); ss->setRenderBinDetails( 9, "DepthSortedBin" ); ss->setMode( GL_ALPHA_TEST, osg::StateAttribute::ON ); ss->setAttribute( new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.9f), osg::StateAttribute::ON ); pGroup->addChild( pGeodeGrass ); //////////////// // a grid //////////////// CSulGeomGrid* pGeomGrid = new CSulGeomGrid; pGeomGrid->Create( osg::Vec3(0,0,0), 10, 10, 1, 1, 5, 5 ); pGroup->addChild( pGeomGrid ); // what does this exactly do? (you would think it would disable culling,.. but it doesn't!) // think it culls when an object is a certain pixel size on the screen pGroup->setCullingActive( false ); return pGroup; }
bool ShaderGenerator::processGeometry( osg::StateSet* ss, osg::ref_ptr<osg::StateSet>& replacement ) { // do nothing if there's no GLSL support if ( !Registry::capabilities().supportsGLSL() ) return false; // State object with extra accessors: StateEx* state = static_cast<StateEx*>(_state.get()); // check for a real osg::Program in the whole state stack. If it exists, bail out // so that OSG can use the program already in the graph. We never override a // full Program. osg::StateAttribute* program = state->getAttribute(osg::StateAttribute::PROGRAM); if ( dynamic_cast<osg::Program*>(program) != 0L ) return false; // see if the current state set contains a VirtualProgram already. If so, // we will add to it if necessary. osg::ref_ptr<VirtualProgram> vp = dynamic_cast<VirtualProgram*>( ss->getAttribute(VirtualProgram::SA_TYPE) ); // Check whether the lighting state has changed and install a mode uniform. if ( ss->getMode(GL_LIGHTING) != osg::StateAttribute::INHERIT ) { if ( !replacement.valid() ) replacement = osg::clone(ss, osg::CopyOp::SHALLOW_COPY); //if ( !replacement.valid() ) // replacement = osg::clone(ss, osg::CopyOp::DEEP_COPY_ALL); osg::StateAttribute::GLModeValue value = state->getMode(GL_LIGHTING); // from the state, not the ss. replacement->addUniform( Registry::shaderFactory()->createUniformForGLMode(GL_LIGHTING, value) ); } // if the stateset changes any texture attributes, we need a new virtual program: if (ss->getTextureAttributeList().size() > 0) { if ( !replacement.valid() ) replacement = osg::clone(ss, osg::CopyOp::SHALLOW_COPY); //if ( !replacement.valid() ) // replacement = osg::clone(ss, osg::CopyOp::DEEP_COPY_ALL); // work off the state's accumulated texture attribute set: int texCount = state->getNumTextureAttributes(); if ( !vp ) { vp = osg::clone( _defaultVP.get() ); replacement->setAttributeAndModes( vp, osg::StateAttribute::ON ); } // start generating the shader source. std::stringstream vertHead, vertBody, fragHead, fragBody; // compatibility strings make it work in GL or GLES. vertHead << "#version " GLSL_VERSION_STR "\n" GLSL_PRECISION; fragHead << "#version " GLSL_VERSION_STR "\n" GLSL_PRECISION; // function declarations: vertBody << "void " VERTEX_FUNCTION "(inout vec4 vertex_view)\n{\n"; fragBody << "void " FRAGMENT_FUNCTION "(inout vec4 color)\n{\n"; for( int t = 0; t < texCount; ++t ) { if (t == 0) { fragBody << INDENT << MEDIUMP "vec4 texel; \n"; } osg::StateAttribute* tex = state->getTextureAttribute( t, osg::StateAttribute::TEXTURE ); if ( tex ) { // see if we have a texenv; if so get its blending mode. osg::TexEnv::Mode blendingMode = osg::TexEnv::MODULATE; osg::TexEnv* env = dynamic_cast<osg::TexEnv*>(state->getTextureAttribute(t, osg::StateAttribute::TEXENV) ); if ( env ) { blendingMode = env->getMode(); if ( blendingMode == osg::TexEnv::BLEND ) { replacement->getOrCreateUniform( Stringify() << TEXENV_COLOR << t, osg::Uniform::FLOAT_VEC4 )->set( env->getColor() ); } } osg::TexGen::Mode texGenMode = osg::TexGen::OBJECT_LINEAR; osg::TexGen* texGen = dynamic_cast<osg::TexGen*>(state->getTextureAttribute(t, osg::StateAttribute::TEXGEN)); if ( texGen ) { texGenMode = texGen->getMode(); } vertHead << "varying " MEDIUMP "vec4 " TEX_COORD << t << ";\n"; fragHead << "varying " MEDIUMP "vec4 " TEX_COORD << t << ";\n"; // handle different TexGen modes. switch(texGenMode) { case osg::TexGen::SPHERE_MAP: vertBody //todo: consolidate. << INDENT "{\n" // scope it in case there are > 1 << INDENT "vec3 v = normalize(vec3(vertex_view));\n" << INDENT "vec3 n = normalize(gl_NormalMatrix * gl_Normal);\n" << INDENT "vec3 r = reflect(v, n);\n" << INDENT "float m = 2.0 * sqrt(r.x*r.x + r.y*r.y + (r.z+1.0)*(r.z+1.0));\n" << INDENT TEX_COORD << t << ".s = r.x/m + 0.5;\n" << INDENT TEX_COORD << t << ".t = r.y/m + 0.5;\n" << INDENT "}\n"; break; default: vertBody << INDENT << TEX_COORD << t << " = gl_MultiTexCoord" << t << ";\n"; break; } if ( dynamic_cast<osg::Texture1D*>(tex) ) { fragHead << "uniform sampler1D " SAMPLER << t << ";\n"; fragBody << INDENT "texel = texture1D(" SAMPLER << t << ", " TEX_COORD << t << ".x);\n"; replacement->getOrCreateUniform( Stringify() << SAMPLER << t, osg::Uniform::SAMPLER_1D )->set( t ); } #if 1 else if ( dynamic_cast<osg::Texture2D*>(tex) ) { fragHead << "uniform sampler2D " SAMPLER << t << ";\n"; fragBody << INDENT "texel = texture2D(" SAMPLER << t << ", " TEX_COORD << t << ".xy);\n"; replacement->getOrCreateUniform( Stringify() << SAMPLER << t, osg::Uniform::SAMPLER_2D )->set( t ); } #else // embosser else if ( dynamic_cast<osg::Texture2D*>(tex) ) { fragHead << "uniform sampler2D " SAMPLER << t << ";\n"; fragBody << INDENT "{\n" << INDENT "float bs = 1.0/256.0;\n" << INDENT "vec4 bm = vec4(0.0);\n" << INDENT "float u = " TEX_COORD << t << ".x;\n" << INDENT "float v = " TEX_COORD << t << ".y;\n" << INDENT "texel = texture2D(" SAMPLER << t << ", vec2(u, v)); \n" << INDENT "bm = texture2D(" SAMPLER << t << ", vec2(u-bs, v-bs)) + \n" << INDENT " texture2D(" SAMPLER << t << ", vec2(u-bs, v-bs)) - \n" << INDENT " texel - \n" << INDENT " texture2D(" SAMPLER << t << ", vec2(u+bs, v+bs)); \n" << INDENT "texel *= vec4( 2.0*(bm.rgb+vec3(0.5,0.5,0.5)),1.0 );\n" << INDENT "}\n"; replacement->getOrCreateUniform( Stringify() << SAMPLER << t, osg::Uniform::SAMPLER_2D )->set( t ); } #endif #if 0 // works, but requires a higher version of GL? else if ( dynamic_cast<osg::TextureRectangle*>(tex) ) { fragHead << "uniform sampler2Drect " SAMPLER << t << ";\n"; fragBody << INDENT "texel = texture2Drect(" SAMPLER << t << ", " TEX_COORD << t << ".xy);\n"; replacement->getOrCreateUniform( Stringify() << SAMPLER << t, osg::Uniform::SAMPLER_2D_RECT )->set( t ); } #endif // doesn't work. why? else if ( dynamic_cast<osg::TextureRectangle*>(tex) ) { osg::Image* image = static_cast<osg::TextureRectangle*>(tex)->getImage(); vertBody << INDENT << TEX_COORD << t << ".x /= " << (image->s()-1) << ".0;\n" << INDENT << TEX_COORD << t << ".y /= " << (image->t()-1) << ".0;\n"; fragHead << "uniform sampler2D " SAMPLER << t << ";\n"; fragBody << INDENT "texel = texture2D(" SAMPLER << t << ", " TEX_COORD << t << ".xy);\n"; replacement->getOrCreateUniform( Stringify() << SAMPLER << t, osg::Uniform::SAMPLER_2D )->set( t ); } else if ( dynamic_cast<osg::Texture3D*>(tex) ) { fragHead << "uniform sampler3D " SAMPLER << t << ";\n"; fragBody << INDENT "texel = texture3D(" SAMPLER << t << ", " TEX_COORD << t << ".xyz);\n"; replacement->getOrCreateUniform( Stringify() << SAMPLER << t, osg::Uniform::SAMPLER_3D )->set( t ); } // See http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml switch( blendingMode ) { case osg::TexEnv::REPLACE: fragBody << INDENT "color = texel; \n"; break; case osg::TexEnv::MODULATE: fragBody << INDENT "color = color * texel; \n"; break; case osg::TexEnv::DECAL: fragBody << INDENT "color.rgb = color.rgb * (1.0 - texel.a) + (texel.rgb * texel.a); \n"; break; case osg::TexEnv::BLEND: fragHead << "uniform " MEDIUMP "vec4 " TEXENV_COLOR << t << "\n;"; fragBody << INDENT "color.rgb = color.rgb * (1.0 - texel.rgb) + (" << TEXENV_COLOR << t << ".rgb * texel.rgb); \n" << INDENT "color.a = color.a * texel.a; \n"; break; case osg::TexEnv::ADD: default: fragBody << INDENT "color.rgb = color.rgb + texel.rgb; \n" << INDENT "color.a = color.a * texel.a; \n"; } } } // close out functions: vertBody << "}\n"; fragBody << "}\n"; // Extract the shader source strings (win compat method) std::string vertBodySrc, vertSrc, fragBodySrc, fragSrc; vertBodySrc = vertBody.str(); vertHead << vertBodySrc; vertSrc = vertHead.str(); fragBodySrc = fragBody.str(); fragHead << fragBodySrc; fragSrc = fragHead.str(); // inject the shaders: vp->setFunction( VERTEX_FUNCTION, vertSrc, ShaderComp::LOCATION_VERTEX_VIEW ); vp->setFunction( FRAGMENT_FUNCTION, fragSrc, ShaderComp::LOCATION_FRAGMENT_COLORING ); } return replacement.valid(); }
bool ShaderGenerator::processGeometry( osg::StateSet* ss, osg::ref_ptr<osg::StateSet>& replacement ) { // do nothing if there's no GLSL support if ( !Registry::capabilities().supportsGLSL() ) return false; // State object with extra accessors: StateEx* state = static_cast<StateEx*>(_state.get()); // check for a real osg::Program in the whole state stack. If it exists, bail out // so that OSG can use the program already in the graph. We never override a // full Program. osg::StateAttribute* program = state->getAttribute(osg::StateAttribute::PROGRAM); if ( dynamic_cast<osg::Program*>(program) != 0L ) return false; // see if the current state set contains a VirtualProgram already. If so, // we will add to it if necessary. VirtualProgram* vp = dynamic_cast<VirtualProgram*>( ss->getAttribute(VirtualProgram::SA_TYPE) ); // Check whether the lighting state has changed and install a mode uniform. if ( ss->getMode(GL_LIGHTING) != osg::StateAttribute::INHERIT ) { if ( !replacement.valid() ) replacement = osg::clone(ss, osg::CopyOp::DEEP_COPY_ALL); ShaderFactory* sf = Registry::instance()->getShaderFactory(); osg::StateAttribute::GLModeValue value = state->getMode(GL_LIGHTING); // from the state, not the ss. replacement->addUniform( sf->createUniformForGLMode(GL_LIGHTING, value) ); } // if the stateset changes any texture attributes, we need a new virtual program: if (ss->getTextureAttributeList().size() > 0) { if ( !replacement.valid() ) replacement = osg::clone(ss, osg::CopyOp::DEEP_COPY_ALL); // work off the state's accumulated texture attribute set: int texCount = state->getNumTextureAttributes(); if ( !vp ) { vp = osg::clone( _defaultVP.get() ); replacement->setAttributeAndModes( vp, osg::StateAttribute::ON ); } // start generating the shader source. std::stringstream vertHead, vertBody, fragHead, fragBody; // compatibility strings make it work in GL or GLES. vertHead << "#version " GLSL_VERSION_STR "\n" GLSL_PRECISION; fragHead << "#version " GLSL_VERSION_STR "\n" GLSL_PRECISION; // function declarations: vertBody << "void " VERTEX_FUNCTION "()\n{\n"; fragBody << "void " FRAGMENT_FUNCTION "(inout vec4 color)\n{\n"; for( int t = 0; t < texCount; ++t ) { if (t == 0) { fragBody << INDENT << MEDIUMP "vec4 texel; \n"; } osg::StateAttribute* tex = state->getTextureAttribute( t, osg::StateAttribute::TEXTURE ); if ( tex ) { // see if we have a texenv; if so get its blending mode. osg::TexEnv::Mode blendingMode = osg::TexEnv::MODULATE; osg::TexEnv* env = dynamic_cast<osg::TexEnv*>(state->getTextureAttribute(t, osg::StateAttribute::TEXENV) ); if ( env ) { blendingMode = env->getMode(); if ( blendingMode == osg::TexEnv::BLEND ) { replacement->getOrCreateUniform( Stringify() << TEXENV_COLOR << t, osg::Uniform::FLOAT_VEC4 )->set( env->getColor() ); } } vertHead << "varying " MEDIUMP "vec4 " TEX_COORD << t << ";\n"; vertBody << INDENT << TEX_COORD << t << " = gl_MultiTexCoord" << t << ";\n"; fragHead << "varying " MEDIUMP "vec4 " TEX_COORD << t << ";\n"; if ( dynamic_cast<osg::Texture1D*>(tex) ) { fragHead << "uniform sampler1D " SAMPLER << t << ";\n"; fragBody << INDENT "texel = texture1D(" SAMPLER << t << ", " TEX_COORD << t << ".x);\n"; replacement->getOrCreateUniform( Stringify() << SAMPLER << t, osg::Uniform::SAMPLER_1D )->set( t ); } else if ( dynamic_cast<osg::Texture2D*>(tex) ) { fragHead << "uniform sampler2D " SAMPLER << t << ";\n"; fragBody << INDENT "texel = texture2D(" SAMPLER << t << ", " TEX_COORD << t << ".xy);\n"; replacement->getOrCreateUniform( Stringify() << SAMPLER << t, osg::Uniform::SAMPLER_2D )->set( t ); } else if ( dynamic_cast<osg::Texture3D*>(tex) ) { fragHead << "uniform sampler3D " SAMPLER << t << ";\n"; fragBody << INDENT "texel = texture3D(" SAMPLER << t << ", " TEX_COORD << t << ".xyz);\n"; replacement->getOrCreateUniform( Stringify() << SAMPLER << t, osg::Uniform::SAMPLER_3D )->set( t ); } // See http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml switch( blendingMode ) { case osg::TexEnv::REPLACE: fragBody << INDENT "color = texel; \n"; break; case osg::TexEnv::MODULATE: fragBody << INDENT "color = color * texel; \n"; break; case osg::TexEnv::DECAL: fragBody << INDENT "color.rgb = color.rgb * (1.0 - texel.a) + (texel.rgb * texel.a); \n"; break; case osg::TexEnv::BLEND: fragHead << "uniform " MEDIUMP "vec4 " TEXENV_COLOR << t << "\n;"; fragBody << INDENT "color.rgb = color.rgb * (1.0 - texel.rgb) + (" << TEXENV_COLOR << t << ".rgb * texel.rgb); \n" << INDENT "color.a = color.a * texel.a; \n"; break; case osg::TexEnv::ADD: default: fragBody << INDENT "color.rgb = color.rgb + texel.rgb; \n" << INDENT "color.a = color.a * texel.a; \n"; } } } // close out functions: vertBody << "}\n"; fragBody << "}\n"; // Extract the shader source strings (win compat method) std::string vertBodySrc, vertSrc, fragBodySrc, fragSrc; vertBodySrc = vertBody.str(); vertHead << vertBodySrc; vertSrc = vertHead.str(); fragBodySrc = fragBody.str(); fragHead << fragBodySrc; fragSrc = fragHead.str(); // inject the shaders: vp->setFunction( VERTEX_FUNCTION, vertSrc, ShaderComp::LOCATION_VERTEX_PRE_LIGHTING ); vp->setFunction( FRAGMENT_FUNCTION, fragSrc, ShaderComp::LOCATION_FRAGMENT_PRE_LIGHTING ); } return replacement.valid(); }