void ShaderGenerator::run(osg::Node* graph, StateSetCache* cache) { if ( graph ) { _texImageUnits.clear(); // generate shaders: graph->accept( *this ); // perform GL state sharing if ( cache ) cache->optimize( graph ); osg::StateSet* stateset = graph->getOrCreateStateSet(); // install a blank VP at the top as the default. VirtualProgram* vp = VirtualProgram::get(stateset); if ( !vp ) { vp = VirtualProgram::getOrCreate(stateset); vp->setInheritShaders( true ); vp->setName( _name ); } // apply a uniform for each sampler binding we found. for(std::set<int>::iterator i = _texImageUnits.begin(); i != _texImageUnits.end(); ++i) { std::string name = Stringify() << SAMPLER << *i; stateset->addUniform( new osg::Uniform(name.c_str(), *i) ); } _texImageUnits.clear(); } }
void ShaderGenerator::run(osg::Node* graph, const std::string& vpName, StateSetCache* cache) { if ( graph ) { // generate shaders: graph->accept( *this ); // perform GL state sharing optimizeStateSharing( graph, cache ); osg::StateSet* stateset = cloneOrCreateStateSet(graph); // install a blank VP at the top as the default. VirtualProgram* vp = VirtualProgram::get(stateset); if ( !vp ) { vp = VirtualProgram::getOrCreate(stateset); vp->setInheritShaders( true ); vp->setName( vpName ); } } }
VirtualProgram* VirtualProgram::cloneOrCreate(const osg::StateSet* src, osg::StateSet* dest) { if ( !dest ) return 0L; const VirtualProgram* vp = 0L; if ( src ) { vp = get( src ); } if ( !vp ) { return getOrCreate( dest ); } else { VirtualProgram* cloneVP = osg::clone( vp, osg::CopyOp::DEEP_COPY_ALL ); cloneVP->setInheritShaders(true); dest->setAttributeAndModes(cloneVP, osg::StateAttribute::ON); return cloneVP; } }
TileRasterizer::TileRasterizer() : osg::Camera() { // active an update traversal. setNumChildrenRequiringUpdateTraversal(1); setCullingActive(false); // set up the RTT camera. setClearColor(osg::Vec4(0,0,0,0)); setClearMask(GL_COLOR_BUFFER_BIT); setReferenceFrame(ABSOLUTE_RF); //setComputeNearFarMode( osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR ); setRenderOrder(PRE_RENDER); setRenderTargetImplementation(FRAME_BUFFER_OBJECT); setImplicitBufferAttachmentMask(0, 0); setSmallFeatureCullingPixelSize(0.0f); setViewMatrix(osg::Matrix::identity()); osg::StateSet* ss = getOrCreateStateSet(); ss->setMode(GL_BLEND, 1); ss->setMode(GL_CULL_FACE, 0); GLUtils::setLighting(ss, 0); this->setPreDrawCallback(new PreDrawRouter<TileRasterizer>(this)); this->setPostDrawCallback(new PostDrawRouter<TileRasterizer>(this)); #if 0 // works in OE, not in VRV :( osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits(); traits->sharedContext = 0L; traits->doubleBuffer = false; traits->x = 0, traits->y = 0, traits->width = 256, traits->height = 256; traits->format = GL_RGBA; traits->red = 8; traits->green = 8; traits->blue = 8; traits->alpha = 8; traits->depth = 0; osg::GraphicsContext* gc = osg::GraphicsContext::createGraphicsContext(traits); setGraphicsContext(gc); #endif setDrawBuffer(GL_FRONT); setReadBuffer(GL_FRONT); VirtualProgram* vp = VirtualProgram::getOrCreate(ss); vp->setInheritShaders(false); // Someday we might need this to undistort rasterizer cells. We'll see #if 0 vp->setFunction("oe_rasterizer_clip", distort, ShaderComp::LOCATION_VERTEX_CLIP); _distortionU = new osg::Uniform("oe_rasterizer_f", 1.0f); ss->addUniform(_distortionU.get()); #endif }
VirtualProgram* VirtualProgram::getOrCreate(osg::StateSet* stateset) { if ( !stateset ) return 0L; VirtualProgram* vp = dynamic_cast<VirtualProgram*>( stateset->getAttribute(SA_TYPE) ); if ( !vp ) { vp = new VirtualProgram(); vp->setInheritShaders(true); stateset->setAttributeAndModes( vp, osg::StateAttribute::ON ); } return vp; }
void DrapingTechnique::setUpCamera(OverlayDecorator::TechRTTParams& params) { // create the projected texture: osg::Texture2D* projTexture = new osg::Texture2D(); projTexture->setTextureSize( *_textureSize, *_textureSize ); projTexture->setInternalFormat( GL_RGBA ); projTexture->setSourceFormat( GL_RGBA ); projTexture->setSourceType( GL_UNSIGNED_BYTE ); projTexture->setFilter( osg::Texture::MIN_FILTER, _mipmapping? osg::Texture::LINEAR_MIPMAP_LINEAR: osg::Texture::LINEAR ); projTexture->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR ); projTexture->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_BORDER ); projTexture->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_BORDER ); //projTexture->setWrap( osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE ); projTexture->setBorderColor( osg::Vec4(0,0,0,0) ); // set up the RTT camera: params._rttCamera = new osg::Camera(); params._rttCamera->setClearColor( osg::Vec4f(0,0,0,0) ); // this ref frame causes the RTT to inherit its viewpoint from above (in order to properly // process PagedLOD's etc. -- it doesn't affect the perspective of the RTT camera though) params._rttCamera->setReferenceFrame( osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT ); params._rttCamera->setViewport( 0, 0, *_textureSize, *_textureSize ); params._rttCamera->setComputeNearFarMode( osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR ); params._rttCamera->setRenderOrder( osg::Camera::PRE_RENDER ); params._rttCamera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT ); params._rttCamera->attach( osg::Camera::COLOR_BUFFER, projTexture, 0, 0, _mipmapping ); if ( _attachStencil ) { // try a depth-packed buffer. failing that, try a normal one.. if the FBO doesn't support // that (which is doesn't on some GPUs like Intel), it will automatically fall back on // a PBUFFER_RTT impl if ( Registry::capabilities().supportsDepthPackedStencilBuffer() ) { #ifdef OSG_GLES2_AVAILABLE params._rttCamera->attach( osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, GL_DEPTH24_STENCIL8_EXT ); #else params._rttCamera->attach( osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, GL_DEPTH_STENCIL_EXT ); #endif } else { params._rttCamera->attach( osg::Camera::STENCIL_BUFFER, GL_STENCIL_INDEX ); } params._rttCamera->setClearStencil( 0 ); params._rttCamera->setClearMask( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); } else { params._rttCamera->setClearMask( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); } // set up a StateSet for the RTT camera. osg::StateSet* rttStateSet = params._rttCamera->getOrCreateStateSet(); // lighting is off. We don't want draped items to be lit. rttStateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED ); // install a new default shader program that replaces anything from above. if ( _useShaders ) { VirtualProgram* vp = VirtualProgram::getOrCreate(rttStateSet); vp->setName( "DrapingTechnique RTT" ); vp->setInheritShaders( false ); //rttStateSet->setAttributeAndModes( vp, osg::StateAttribute::ON ); } // active blending within the RTT camera's FBO if ( _rttBlending ) { //Setup a separate blend function for the alpha components and the RGB components. //Because the destination alpha is initialized to 0 instead of 1 osg::BlendFunc* blendFunc = 0; if (Registry::capabilities().supportsGLSL(1.4f)) { //Blend Func Separate is only available on OpenGL 1.4 and above blendFunc = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } else { blendFunc = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } rttStateSet->setAttributeAndModes(blendFunc, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); } else { rttStateSet->setMode(GL_BLEND, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); } // attach the overlay group to the camera. // TODO: we should probably lock this since other cull traversals might be accessing the group // while we are changing its children. params._rttCamera->addChild( params._group ); // overlay geometry is rendered with no depth testing, and in the order it's found in the // scene graph... until further notice. rttStateSet->setMode(GL_DEPTH_TEST, 0); rttStateSet->setBinName( "TraversalOrderBin" ); // add to the terrain stateset, i.e. the stateset that the OverlayDecorator will // apply to the terrain before cull-traversing it. This will activate the projective // texturing on the terrain. params._terrainStateSet->setTextureAttributeAndModes( *_textureUnit, projTexture, osg::StateAttribute::ON ); // fire up the local per-view data: LocalPerViewData* local = new LocalPerViewData(); params._techniqueData = local; if ( _useShaders ) { // GPU path VirtualProgram* vp = VirtualProgram::getOrCreate(params._terrainStateSet); vp->setName( "DrapingTechnique terrain shaders"); //params._terrainStateSet->setAttributeAndModes( vp, osg::StateAttribute::ON ); // sampler for projected texture: params._terrainStateSet->getOrCreateUniform( "oe_overlay_tex", osg::Uniform::SAMPLER_2D )->set( *_textureUnit ); // the texture projection matrix uniform. local->_texGenUniform = params._terrainStateSet->getOrCreateUniform( "oe_overlay_texmatrix", osg::Uniform::FLOAT_MAT4 ); // vertex shader - subgraph std::string vs = "#version " GLSL_VERSION_STR "\n" GLSL_DEFAULT_PRECISION_FLOAT "\n" "uniform mat4 oe_overlay_texmatrix; \n" "varying vec4 oe_overlay_texcoord; \n" "void oe_overlay_vertex(inout vec4 VertexVIEW) \n" "{ \n" " oe_overlay_texcoord = oe_overlay_texmatrix * VertexVIEW; \n" "} \n"; vp->setFunction( "oe_overlay_vertex", vs, ShaderComp::LOCATION_VERTEX_VIEW ); // fragment shader - subgraph std::string fs = "#version " GLSL_VERSION_STR "\n" GLSL_DEFAULT_PRECISION_FLOAT "\n" "uniform sampler2D oe_overlay_tex; \n" "varying vec4 oe_overlay_texcoord; \n" "void oe_overlay_fragment( inout vec4 color ) \n" "{ \n" " vec4 texel = texture2DProj(oe_overlay_tex, oe_overlay_texcoord); \n" " color = vec4( mix( color.rgb, texel.rgb, texel.a ), color.a); \n" "} \n"; vp->setFunction( "oe_overlay_fragment", fs, ShaderComp::LOCATION_FRAGMENT_COLORING ); } else { // FFP path local->_texGen = new osg::TexGen(); local->_texGen->setMode( osg::TexGen::EYE_LINEAR ); params._terrainStateSet->setTextureAttributeAndModes( *_textureUnit, local->_texGen.get(), 1 ); osg::TexEnv* env = new osg::TexEnv(); env->setMode( osg::TexEnv::DECAL ); params._terrainStateSet->setTextureAttributeAndModes( *_textureUnit, env, 1 ); } }
/** * Creates a complete set of positioned label nodes from a feature list. */ osg::Node* createNode( const FeatureList& input, const Style& style, const FilterContext& context ) { if ( style.get<TextSymbol>() == 0L && style.get<IconSymbol>() == 0L ) return 0L; // copy the style so we can (potentially) modify the text symbol. Style styleCopy = style; TextSymbol* text = styleCopy.get<TextSymbol>(); IconSymbol* icon = styleCopy.get<IconSymbol>(); osg::Group* group = new osg::Group(); StringExpression textContentExpr ( text ? *text->content() : StringExpression() ); NumericExpression textPriorityExpr( text ? *text->priority() : NumericExpression() ); NumericExpression textSizeExpr ( text ? *text->size() : NumericExpression() ); StringExpression iconUrlExpr ( icon ? *icon->url() : StringExpression() ); NumericExpression iconScaleExpr ( icon ? *icon->scale() : NumericExpression() ); NumericExpression iconHeadingExpr ( icon ? *icon->heading() : NumericExpression() ); for( FeatureList::const_iterator i = input.begin(); i != input.end(); ++i ) { const Feature* feature = i->get(); if ( !feature ) continue; const Geometry* geom = feature->getGeometry(); if ( !geom ) continue; Style tempStyle = styleCopy; // evaluate expressions into literals. // TODO: Later we could replace this with a generate "expression evaluator" type // that we could pass to PlaceNode in the DB options. -gw if ( text ) { if ( text->content().isSet() ) tempStyle.get<TextSymbol>()->content()->setLiteral( feature->eval( textContentExpr, &context ) ); if ( text->size().isSet() ) tempStyle.get<TextSymbol>()->size()->setLiteral( feature->eval(textSizeExpr, &context) ); } if ( icon ) { if ( icon->url().isSet() ) tempStyle.get<IconSymbol>()->url()->setLiteral( feature->eval(iconUrlExpr, &context) ); if ( icon->scale().isSet() ) tempStyle.get<IconSymbol>()->scale()->setLiteral( feature->eval(iconScaleExpr, &context) ); if ( icon->heading().isSet() ) tempStyle.get<IconSymbol>()->heading()->setLiteral( feature->eval(iconHeadingExpr, &context) ); } osg::Node* node = makePlaceNode( context, feature, tempStyle, textPriorityExpr); if ( node ) { if ( context.featureIndex() ) { context.featureIndex()->tagNode(node, const_cast<Feature*>(feature)); } group->addChild( node ); } } VirtualProgram* vp = VirtualProgram::getOrCreate(group->getOrCreateStateSet()); vp->setInheritShaders( false ); return group; }
void ClampingTechnique::setUpCamera(OverlayDecorator::TechRTTParams& params) { // To store technique-specific per-view info: LocalPerViewData* local = new LocalPerViewData(); params._techniqueData = local; // create the projected texture: local->_rttTexture = new osg::Texture2D(); local->_rttTexture->setTextureSize( *_textureSize, *_textureSize ); local->_rttTexture->setInternalFormat( GL_DEPTH_COMPONENT ); local->_rttTexture->setFilter( osg::Texture::MIN_FILTER, osg::Texture::NEAREST ); local->_rttTexture->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR ); // this is important. geometry that is outside the depth texture will clamp to the // closest edge value in the texture -- this is good when you are rendering a // primitive that has one or more of its verts off-screen. local->_rttTexture->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE ); local->_rttTexture->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE ); //local->_rttTexture->setBorderColor( osg::Vec4(0,0,0,1) ); // set up the RTT camera: params._rttCamera = new osg::Camera(); params._rttCamera->setName("GPU Clamping"); params._rttCamera->setReferenceFrame( osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT ); params._rttCamera->setClearDepth( 1.0 ); params._rttCamera->setClearMask( GL_DEPTH_BUFFER_BIT ); params._rttCamera->setComputeNearFarMode( osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR ); params._rttCamera->setViewport( 0, 0, *_textureSize, *_textureSize ); params._rttCamera->setRenderOrder( osg::Camera::PRE_RENDER ); params._rttCamera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT ); params._rttCamera->setImplicitBufferAttachmentMask(0, 0); params._rttCamera->attach( osg::Camera::DEPTH_BUFFER, local->_rttTexture.get() ); #ifdef DUMP_RTT_IMAGE local->_rttDebugImage = new osg::Image(); local->_rttDebugImage->allocateImage(4096, 4096, 1, GL_RGB, GL_UNSIGNED_BYTE); memset( (void*)local->_rttDebugImage->getDataPointer(), 0xff, local->_rttDebugImage->getTotalSizeInBytes() ); params._rttCamera->attach( osg::Camera::COLOR_BUFFER, local->_rttDebugImage.get() ); params._rttCamera->setFinalDrawCallback( new DumpTex(local->_rttDebugImage.get()) ); #endif #ifdef TIME_RTT_CAMERA params._rttCamera->setInitialDrawCallback( new RttIn() ); params._rttCamera->setFinalDrawCallback( new RttOut() ); #endif // set up a StateSet for the RTT camera. osg::StateSet* rttStateSet = params._rttCamera->getOrCreateStateSet(); rttStateSet->setMode( GL_BLEND, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); // prevents wireframe mode in the depth camera. rttStateSet->setAttributeAndModes( new osg::PolygonMode( osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::FILL ), osg::StateAttribute::ON | osg::StateAttribute::PROTECTED ); // install a VP on the stateset that cancels out any higher-up VP code. // This will prevent things like VPs on the main camera (e.g., log depth buffer) // from interfering with the depth camera VirtualProgram* rttVP = VirtualProgram::getOrCreate(rttStateSet); rttVP->setInheritShaders(false); // attach the terrain to the camera. // todo: should probably protect this with a mutex..... params._rttCamera->addChild( _engine ); // the terrain itself. // assemble the overlay graph stateset. local->_groupStateSet = new osg::StateSet(); // Required for now, otherwise GPU-clamped geometry will jitter sometimes. // TODO: figure out why and fix it. This is a workaround for now. local->_groupStateSet->setDataVariance( osg::Object::DYNAMIC ); local->_groupStateSet->setTextureAttributeAndModes( _textureUnit, local->_rttTexture.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE ); // set up depth test/write parameters for the overlay geometry: local->_groupStateSet->setAttributeAndModes( new osg::Depth( osg::Depth::LEQUAL, 0.0, 1.0, true ), osg::StateAttribute::ON ); local->_groupStateSet->setRenderingHint( osg::StateSet::TRANSPARENT_BIN ); // uniform for the horizon distance (== max clamping distance) local->_horizonDistance2Uniform = local->_groupStateSet->getOrCreateUniform( "oe_clamp_horizonDistance2", osg::Uniform::FLOAT ); // sampler for depth map texture: local->_groupStateSet->getOrCreateUniform( "oe_clamp_depthTex", osg::Uniform::SAMPLER_2D )->set( _textureUnit ); // matrix that transforms a vert from EYE coords to the depth camera's CLIP coord. local->_camViewToDepthClipUniform = local->_groupStateSet->getOrCreateUniform( "oe_clamp_cameraView2depthClip", osg::Uniform::FLOAT_MAT4 ); #ifdef SUPPORT_Z // matrix that transforms a vert from depth clip coords to depth view coords. local->_depthClipToDepthViewUniform = local->_groupStateSet->getOrCreateUniform( "oe_clamp_depthClip2depthView", osg::Uniform::FLOAT_MAT4 ); // matrix that transforms a vert from depth view coords to camera view coords. local->_depthViewToCamViewUniform = local->_groupStateSet->getOrCreateUniform( "oe_clamp_depthView2cameraView", osg::Uniform::FLOAT_MAT4 ); #else // matrix that transforms a vert from depth-cam CLIP coords to EYE coords. local->_depthClipToCamViewUniform = local->_groupStateSet->getOrCreateUniform( "oe_clamp_depthClip2cameraView", osg::Uniform::FLOAT_MAT4 ); #endif // default value for altitude offset; can be overriden by geometry. local->_groupStateSet->addUniform( new osg::Uniform(Clamping::AltitudeOffsetUniformName, 0.0f) ); // make the shader that will do clamping and depth offsetting. VirtualProgram* vp = VirtualProgram::getOrCreate(local->_groupStateSet.get()); vp->setName( "GPUClamping" ); // Bind clamping attribute location, and a default uniform indicating whether // they are available (default is false). vp->addBindAttribLocation( Clamping::AnchorAttrName, Clamping::AnchorAttrLocation ); local->_groupStateSet->addUniform( new osg::Uniform(Clamping::HasAttrsUniformName, false) ); // Bind clamping heights location. vp->addBindAttribLocation( Clamping::HeightsAttrName, Clamping::HeightsAttrLocation ); osgEarth::Shaders pkg; pkg.load(vp, pkg.GPUClampingVertex); pkg.load(vp, pkg.GPUClampingFragment); }
void OverlayDecorator::initializePerViewData( PerViewData& pvd ) { if ( !_textureUnit.isSet() || !_overlayGraph.valid() ) return; // create the projected texture: osg::Texture2D* projTexture = new osg::Texture2D(); projTexture->setTextureSize( *_textureSize, *_textureSize ); projTexture->setInternalFormat( GL_RGBA ); projTexture->setSourceFormat( GL_RGBA ); projTexture->setSourceType( GL_UNSIGNED_BYTE ); projTexture->setFilter( osg::Texture::MIN_FILTER, _mipmapping? osg::Texture::LINEAR_MIPMAP_LINEAR: osg::Texture::LINEAR ); projTexture->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR ); projTexture->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); //CLAMP_TO_BORDER ); projTexture->setWrap( osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE ); projTexture->setWrap( osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE ); projTexture->setBorderColor( osg::Vec4(0,0,0,0) ); // set up the RTT camera: pvd._rttCamera = new osg::Camera(); pvd._rttCamera->setClearColor( osg::Vec4f(0,0,0,0) ); pvd._rttCamera->setClearStencil( 0 ); pvd._rttCamera->setClearMask( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); // this ref frame causes the RTT to inherit its viewpoint from above (in order to properly // process PagedLOD's etc. -- it doesn't affect the perspective of the RTT camera though) pvd._rttCamera->setReferenceFrame( osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT ); pvd._rttCamera->setViewport( 0, 0, *_textureSize, *_textureSize ); pvd._rttCamera->setComputeNearFarMode( osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR ); pvd._rttCamera->setRenderOrder( osg::Camera::PRE_RENDER ); pvd._rttCamera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT ); pvd._rttCamera->attach( osg::Camera::COLOR_BUFFER, projTexture, 0, 0, _mipmapping ); if (_attachStencil) { // try a depth-packed buffer. failing that, try a normal one.. if the FBO doesn't support // that (which is doesn't on some GPUs like Intel), it will automatically fall back on // a PBUFFER_RTT impl if ( Registry::instance()->getCapabilities().supportsDepthPackedStencilBuffer() ) { #ifdef OSG_GLES2_AVAILABLE pvd._rttCamera->attach( osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, GL_DEPTH24_STENCIL8_EXT ); #else pvd._rttCamera->attach( osg::Camera::PACKED_DEPTH_STENCIL_BUFFER, GL_DEPTH_STENCIL_EXT ); #endif } else { pvd._rttCamera->attach( osg::Camera::STENCIL_BUFFER, GL_STENCIL_INDEX ); } } osg::StateSet* rttStateSet = pvd._rttCamera->getOrCreateStateSet(); rttStateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED ); // install a new default shader program that replaces anything from above. if ( _useShaders ) { VirtualProgram* vp = new VirtualProgram(); vp->setName( "overlay rtt" ); vp->installDefaultColoringAndLightingShaders(); vp->setInheritShaders( false ); rttStateSet->setAttributeAndModes( vp, osg::StateAttribute::ON ); } if ( _rttBlending ) { //Setup a separate blend function for the alpha components and the RGB components. //Because the destination alpha is initialized to 0 instead of 1 osg::BlendFunc* blendFunc = 0; if (Registry::instance()->getCapabilities().supportsGLSL(1.4f)) { //Blend Func Separate is only available on OpenGL 1.4 and above blendFunc = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } else { blendFunc = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } rttStateSet->setAttributeAndModes(blendFunc, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); } else { rttStateSet->setMode(GL_BLEND, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); } // attach the overlay graph to the RTT camera. if ( _overlayGraph.valid() && ( _overlayGraph->getNumParents() == 0 || _overlayGraph->getParent(0) != pvd._rttCamera.get() )) { if ( pvd._rttCamera->getNumChildren() > 0 ) pvd._rttCamera->replaceChild( 0, _overlayGraph.get() ); else pvd._rttCamera->addChild( _overlayGraph.get() ); } // overlay geometry is rendered with no depth testing, and in the order it's found in the // scene graph... until further notice... rttStateSet->setMode(GL_DEPTH_TEST, 0); rttStateSet->setBinName( "TraversalOrderBin" ); // assemble the subgraph stateset: pvd._subgraphStateSet = new osg::StateSet(); pvd._subgraphStateSet->setTextureAttributeAndModes( *_textureUnit, projTexture, osg::StateAttribute::ON ); if ( _useShaders ) { // GPU path initSubgraphShaders( pvd ); } else { // FFP path pvd._texGen = new osg::TexGen(); pvd._texGen->setMode( osg::TexGen::EYE_LINEAR ); pvd._subgraphStateSet->setTextureAttributeAndModes( *_textureUnit, pvd._texGen.get(), 1 ); osg::TexEnv* env = new osg::TexEnv(); env->setMode( osg::TexEnv::DECAL ); pvd._subgraphStateSet->setTextureAttributeAndModes( *_textureUnit, env, 1 ); } }