diff --git a/examples/osgdepthshadow/osgdepthshadow.cpp b/examples/osgdepthshadow/osgdepthshadow.cpp index cc2ff79c4..8c6d8cc90 100644 --- a/examples/osgdepthshadow/osgdepthshadow.cpp +++ b/examples/osgdepthshadow/osgdepthshadow.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include @@ -17,18 +17,12 @@ #include #include -#include + +#include +#include using namespace osg; -const int depth_texture_height = 512; -const int depth_texture_width = 512; - -ref_ptr bias = new RefMatrix(0.5f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.5f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.5f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f); - class LightTransformCallback: public osg::NodeCallback { @@ -91,152 +85,8 @@ LightTransformCallback::operator()(Node* node, NodeVisitor* nv) } -class RenderToTextureCallback: public NodeCallback -{ -public: - RenderToTextureCallback(Node* subgraph, - Texture2D* texture, - MatrixTransform* light_transform, - TexGen* tex_gen): - _subgraph(subgraph), - _texture(texture), - _local_stateset(new StateSet), - _viewport(new Viewport), - _light_projection(new RefMatrix), - _light_transform(light_transform), - _tex_gen(tex_gen) - { - _local_stateset->setAttribute(_viewport.get()); - _local_stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); - - ref_ptr polygon_offset = new PolygonOffset; - polygon_offset->setFactor(1.1f); - polygon_offset->setUnits(4.0f); - _local_stateset->setAttribute(polygon_offset.get(), StateAttribute::ON | StateAttribute::OVERRIDE); - _local_stateset->setMode(GL_POLYGON_OFFSET_FILL, StateAttribute::ON | StateAttribute::OVERRIDE); - ref_ptr cull_face = new CullFace; - cull_face->setMode(CullFace::FRONT); - _local_stateset->setAttribute(cull_face.get(), StateAttribute::ON | StateAttribute::OVERRIDE); - _local_stateset->setMode(GL_CULL_FACE, StateAttribute::ON | StateAttribute::OVERRIDE); - - _viewport->setViewport(0, 0, depth_texture_width, depth_texture_height); - - float znear = 1.0f * _subgraph->getBound().radius(); - float zfar = 3.0f * _subgraph->getBound().radius(); - float top = 0.5f * _subgraph->getBound().radius(); - float right = 0.5f * _subgraph->getBound().radius(); - znear *= 0.8f; - zfar *= 1.2f; - _light_projection->makeFrustum(-right, right, -top, top, znear, zfar); - } - - virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) - { - - osgUtil::CullVisitor* cullVisitor = dynamic_cast(nv); - if (cullVisitor && _texture.valid() && _subgraph.valid()) - { - _request_render_to_depth_texture(*node, *cullVisitor); - } - - // must traverse the subgraph - traverse(node,nv); - } - - void _request_render_to_depth_texture(osg::Node& node, osgUtil::CullVisitor& cv); - - ref_ptr _subgraph; - ref_ptr _texture; - ref_ptr _local_stateset; - ref_ptr _viewport; - ref_ptr _light_projection; - ref_ptr _light_transform; - ref_ptr _tex_gen; -}; - -void RenderToTextureCallback::_request_render_to_depth_texture(osg::Node&, osgUtil::CullVisitor& cv) -{ - // create the render to texture stage. - osg::ref_ptr rtts = new osgUtil::RenderToTextureStage; - - // set up lighting. - // currently ignore lights in the scene graph itself.. - // will do later. - osgUtil::RenderStage* previous_stage = cv.getCurrentRenderBin()->getStage(); - - // set up the background color and clear mask. - rtts->setClearMask(GL_DEPTH_BUFFER_BIT); - rtts->setColorMask(new ColorMask(false, false, false, false)); - - // set up to charge the same RenderStageLighting is the parent previous stage. - rtts->setRenderStageLighting(previous_stage->getRenderStageLighting()); - - - // record the render bin, to be restored after creation - // of the render to text - osgUtil::RenderBin* previousRenderBin = cv.getCurrentRenderBin(); - - osgUtil::CullVisitor::ComputeNearFarMode saved_compute_near_far_mode = cv.getComputeNearFarMode(); - cv.setComputeNearFarMode(osgUtil::CullVisitor::DO_NOT_COMPUTE_NEAR_FAR); - - // set the current renderbin to be the newly created stage. - cv.setCurrentRenderBin(rtts.get()); - - ref_ptr light_view = new RefMatrix; - light_view->makeLookAt(_light_transform->getMatrix().getTrans(), Vec3(0, 0, 0), Z_AXIS); - Matrix texture_matrix = (*light_view.get()) * (*_light_projection.get()) * (*bias.get()); - _tex_gen->setPlane(TexGen::S, Vec4(texture_matrix(0, 0), - texture_matrix(1, 0), - texture_matrix(2, 0), - texture_matrix(3, 0))); - _tex_gen->setPlane(TexGen::T, Vec4(texture_matrix(0, 1), - texture_matrix(1, 1), - texture_matrix(2, 1), - texture_matrix(3, 1))); - _tex_gen->setPlane(TexGen::R, Vec4(texture_matrix(0, 2), - texture_matrix(1, 2), - texture_matrix(2, 2), - texture_matrix(3, 2))); - _tex_gen->setPlane(TexGen::Q, Vec4(texture_matrix(0, 3), - texture_matrix(1, 3), - texture_matrix(2, 3), - texture_matrix(3, 3))); - - cv.pushProjectionMatrix(_light_projection.get()); - cv.pushModelViewMatrix(light_view.get()); - cv.pushStateSet(_local_stateset.get()); - - // traverse the subgraph - _subgraph->accept(cv); - - cv.popStateSet(); - cv.popModelViewMatrix(); - cv.popProjectionMatrix(); - - cv.setComputeNearFarMode(saved_compute_near_far_mode); - - // restore the previous renderbin. - cv.setCurrentRenderBin(previousRenderBin); - - if (rtts->getRenderGraphList().size()==0 && rtts->getRenderBinList().size()==0) - { - // getting to this point means that all the subgraph has been - // culled by small feature culling or is beyond LOD ranges. - return; - } - - rtts->setViewport(_viewport.get()); - - // and the render to texture stage to the current stages - // dependancy list. - cv.getCurrentRenderBin()->getStage()->addToDependencyList(rtts.get()); - - // if one exist attach texture to the RenderToTextureStage. - rtts->setTexture(_texture.get()); -} - -ref_ptr _create_lights(ref_ptr root_stateset) +ref_ptr _create_lights() { ref_ptr transform_0 = new MatrixTransform; @@ -256,6 +106,7 @@ ref_ptr _create_lights(ref_ptr root_stateset) transform_0->addChild(light_source_0.get()); ref_ptr geode = new Geode; + ref_ptr shape; ref_ptr hints = new TessellationHints; hints->setDetailRatio(0.3f); @@ -265,11 +116,11 @@ ref_ptr _create_lights(ref_ptr root_stateset) shape = new ShapeDrawable(new Cylinder(Vec3(0.0f, 0.0f, -0.4f), 0.05f, 0.8f), hints.get()); shape->setColor(Vec4(1.0f, 0.5f, 0.5f, 1.0f)); geode->addDrawable(shape.get()); + + geode->getOrCreateStateSet()->setMode(GL_LIGHTING, StateAttribute::OFF); transform_0->addChild(geode.get()); - light_source_0->setStateSetModes(*root_stateset.get(), StateAttribute::ON); - return transform_0; } @@ -336,72 +187,220 @@ ref_ptr _create_scene() return scene; } + +class UpdateCameraAndTexGenCallback : public osg::NodeCallback +{ + public: + + UpdateCameraAndTexGenCallback(osg::MatrixTransform* light_transform, osg::CameraNode* cameraNode, osg::TexGenNode* texgenNode): + _light_transform(light_transform), + _cameraNode(cameraNode), + _texgenNode(texgenNode) + { + } + + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + { + // first update subgraph to make sure objects are all moved into postion + traverse(node,nv); + + // now compute the camera's view and projection matrix to point at the shadower (the camera's children) + osg::BoundingSphere bs; + for(unsigned int i=0; i<_cameraNode->getNumChildren(); ++i) + { + bs.expandBy(_cameraNode->getChild(i)->getBound()); + } + + if (!bs.valid()) + { + osg::notify(osg::WARN) << "bb invalid"<<_cameraNode.get()<getMatrix().getTrans(); + + float centerDistance = (position-bs.center()).length(); + + float znear = centerDistance-bs.radius(); + float zfar = centerDistance+bs.radius(); + float zNearRatio = 0.001f; + if (znearsetReferenceFrame(osg::CameraNode::ABSOLUTE_RF); + _cameraNode->setProjectionMatrixAsFrustum(-right,right,-top,top,znear,zfar); + _cameraNode->setViewMatrixAsLookAt(position,bs.center(),osg::Vec3(0.0f,1.0f,0.0f)); + + // compute the matrix which takes a vertex from local coords into tex coords + // will use this later to specify osg::TexGen.. + osg::Matrix MVPT = _cameraNode->getViewMatrix() * + _cameraNode->getProjectionMatrix() * + osg::Matrix::translate(1.0,1.0,1.0) * + osg::Matrix::scale(0.5f,0.5f,0.5f); + + _texgenNode->getTexGen()->setMode(osg::TexGen::EYE_LINEAR); + _texgenNode->getTexGen()->setPlanesFromMatrix(MVPT); + + } + + protected: + + virtual ~UpdateCameraAndTexGenCallback() {} + + osg::ref_ptr _light_transform; + osg::ref_ptr _cameraNode; + osg::ref_ptr _texgenNode; + +}; + + +osg::Group* createShadowedScene(osg::Node* shadowed,osg::MatrixTransform* light_transform, unsigned int unit) +{ + osg::Group* group = new osg::Group; + + unsigned int tex_width = 1024; + unsigned int tex_height = 1024; + + osg::Texture2D* texture = new osg::Texture2D; + texture->setTextureSize(tex_width, tex_height); + + texture->setInternalFormat(GL_DEPTH_COMPONENT); + texture->setShadowComparison(true); + texture->setShadowTextureMode(Texture::LUMINANCE); + texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); + texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); + + // set up the render to texture camera. + { + + // create the camera + osg::CameraNode* camera = new osg::CameraNode; + + camera->setClearMask(GL_DEPTH_BUFFER_BIT); + camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); + camera->setComputeNearFarMode(osg::CameraNode::DO_NOT_COMPUTE_NEAR_FAR); + + // set viewport + camera->setViewport(0,0,tex_width,tex_height); + + osg::StateSet* _local_stateset = camera->getOrCreateStateSet(); + + _local_stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + + ref_ptr polygon_offset = new PolygonOffset; + polygon_offset->setFactor(1.1f); + polygon_offset->setUnits(4.0f); + _local_stateset->setAttribute(polygon_offset.get(), StateAttribute::ON | StateAttribute::OVERRIDE); + _local_stateset->setMode(GL_POLYGON_OFFSET_FILL, StateAttribute::ON | StateAttribute::OVERRIDE); + + ref_ptr cull_face = new CullFace; + cull_face->setMode(CullFace::FRONT); + _local_stateset->setAttribute(cull_face.get(), StateAttribute::ON | StateAttribute::OVERRIDE); + _local_stateset->setMode(GL_CULL_FACE, StateAttribute::ON | StateAttribute::OVERRIDE); + + + // set the camera to render before the main camera. + camera->setRenderOrder(osg::CameraNode::PRE_RENDER); + + // tell the camera to use OpenGL frame buffer object where supported. + camera->setRenderTargetImplmentation(osg::CameraNode::FRAME_BUFFER_OBJECT); + + // attach the texture and use it as the color buffer. + camera->attach(osg::CameraNode::DEPTH_BUFFER, texture); + + // add subgraph to render + camera->addChild(shadowed); + + group->addChild(camera); + + // create the texgen node to project the tex coords onto the subgraph + osg::TexGenNode* texgenNode = new osg::TexGenNode; + texgenNode->setTextureUnit(unit); + group->addChild(texgenNode); + + // set an update callback to keep moving the camera and tex gen in the right direction. + group->setUpdateCallback(new UpdateCameraAndTexGenCallback(light_transform, camera, texgenNode)); + } + + + // set the shadowed subgraph so that it uses the texture and tex gen settings. + { + osg::Group* shadowedGroup = new osg::Group; + shadowedGroup->addChild(shadowed); + group->addChild(shadowedGroup); + + osg::StateSet* stateset = shadowedGroup->getOrCreateStateSet(); + stateset->setTextureAttributeAndModes(unit,texture,osg::StateAttribute::ON); + stateset->setTextureMode(unit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); + stateset->setTextureMode(unit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON); + stateset->setTextureMode(unit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON); + stateset->setTextureMode(unit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON); + } + + // add the shadower and shadowed. + group->addChild(light_transform); + + return group; +} + + int main(int argc, char** argv) { - // use an ArgumentParser object to manage the program arguments. - ArgumentParser arguments(&argc, argv); + // use an ArgumentParser object to manage the program arguments. + ArgumentParser arguments(&argc, argv); - // set up the usage document, in case we need to print out how to use this program. - arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() + " is the example which demonstrates using of GL_ARB_shadow extension implemented in osg::Texture class"); - arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()); - arguments.getApplicationUsage()->addCommandLineOption("-h or --help", "Display this information"); - - // construct the viewer. - osgProducer::Viewer viewer(arguments); + // set up the usage document, in case we need to print out how to use this program. + arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() + " is the example which demonstrates using of GL_ARB_shadow extension implemented in osg::Texture class"); + arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()); + arguments.getApplicationUsage()->addCommandLineOption("-h or --help", "Display this information"); - // set up the value with sensible default event handlers. - viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS); - - // get details on keyboard and mouse bindings used by the viewer. - viewer.getUsage(*arguments. getApplicationUsage()); + // construct the viewer. + osgProducer::Viewer viewer(arguments); - // if user request help write it out to cout. - if (arguments.read("-h") || arguments.read("--help")) + // set up the value with sensible default event handlers. + viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS); + + // get details on keyboard and mouse bindings used by the viewer. + viewer.getUsage(*arguments. getApplicationUsage()); + + // if user request help write it out to cout. + if (arguments.read("-h") || arguments.read("--help")) { - arguments.getApplicationUsage()->write(std::cout); - return 1; + arguments.getApplicationUsage()->write(std::cout); + return 1; } - // any option left unread are converted into errors to write out later. - arguments.reportRemainingOptionsAsUnrecognized(); + // any option left unread are converted into errors to write out later. + arguments.reportRemainingOptionsAsUnrecognized(); - // report any errors if they have occured when parsing the program aguments. - if (arguments.errors()) + // report any errors if they have occured when parsing the program aguments. + if (arguments.errors()) { arguments.writeErrorMessages(std::cout); return 1; } - ref_ptr scene = new MatrixTransform; - scene->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(125.0),1.0,0.0,0.0)); - - ref_ptr shadowed_scene = _create_scene(); - if (!shadowed_scene.valid()) return 1; - scene->addChild(shadowed_scene.get()); + ref_ptr scene = new MatrixTransform; + scene->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(125.0),1.0,0.0,0.0)); - ref_ptr light_transform = _create_lights(scene->getOrCreateStateSet()); - if (!scene.valid()) return 1; - scene->addChild(light_transform.get()); + ref_ptr shadowed_scene = _create_scene(); + if (!shadowed_scene.valid()) return 1; - ref_ptr texture = new Texture2D; - texture->setInternalFormat(GL_DEPTH_COMPONENT); - texture->setShadowComparison(true); - texture->setShadowTextureMode(Texture::LUMINANCE); + ref_ptr light_transform = _create_lights(); + if (!light_transform.valid()) return 1; - ref_ptr tex_gen = new TexGen; - tex_gen->setMode(TexGen::EYE_LINEAR); - shadowed_scene->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture.get(), StateAttribute::ON); - shadowed_scene->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex_gen.get(), StateAttribute::ON); + ref_ptr shadowedScene = createShadowedScene(shadowed_scene.get(),light_transform.get(),0); - scene->setCullCallback(new RenderToTextureCallback(shadowed_scene.get(), texture.get(), light_transform.get(), tex_gen.get())); + scene->addChild(shadowedScene.get()); - // add model to viewer. - viewer.setSceneData(scene.get()); + viewer.setSceneData(scene.get()); - // create the windows and run the threads. - viewer.realize(); + // create the windows and run the threads. + viewer.realize(); - while (!viewer.done()) + while (!viewer.done()) { // wait for all cull and draw threads to complete. viewer.sync(); @@ -414,8 +413,8 @@ int main(int argc, char** argv) viewer.frame(); } - // wait for all cull and draw threads to complete before exit. - viewer.sync(); + // wait for all cull and draw threads to complete before exit. + viewer.sync(); - return 0; + return 0; } diff --git a/examples/osgdistortion/osgdistortion.cpp b/examples/osgdistortion/osgdistortion.cpp index 213d62da2..761e3d41b 100644 --- a/examples/osgdistortion/osgdistortion.cpp +++ b/examples/osgdistortion/osgdistortion.cpp @@ -25,7 +25,7 @@ using namespace osg; -osg::Node* createDistortionSubgraph(osg::Node* subgraph) +osg::Node* createDistortionSubgraph(osg::Node* subgraph, const osg::Vec4& clearColour) { osg::Group* distortionNode = new osg::Group; @@ -42,6 +42,10 @@ osg::Node* createDistortionSubgraph(osg::Node* subgraph) { osg::CameraNode* camera = new osg::CameraNode; + // set clear the color and depth buffer + camera->setClearColor(clearColour); + camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + // just inherit the main cameras view camera->setReferenceFrame(osg::Transform::RELATIVE_RF); camera->setProjectionMatrix(osg::Matrixd::identity()); @@ -49,7 +53,6 @@ osg::Node* createDistortionSubgraph(osg::Node* subgraph) // set viewport camera->setViewport(0,0,tex_width,tex_height); - camera->getOrCreateStateSet()->setAttribute(camera->getViewport()); // set the camera to render before the main camera. camera->setRenderOrder(osg::CameraNode::PRE_RENDER); @@ -219,7 +222,7 @@ int main( int argc, char **argv ) return 1; } - osg::Node* distortionNode = createDistortionSubgraph(loadedModel); + osg::Node* distortionNode = createDistortionSubgraph(loadedModel, viewer.getClearColor()); // add model to the viewer. viewer.setSceneData( distortionNode ); diff --git a/examples/osgfbo/osgfbo.cpp b/examples/osgfbo/osgfbo.cpp index 082f22825..6e0b2adf3 100644 --- a/examples/osgfbo/osgfbo.cpp +++ b/examples/osgfbo/osgfbo.cpp @@ -76,7 +76,6 @@ void build_world(osg::Group *root) camera->setClearColor(osg::Vec4(0.1f,0.1f,0.3f,1.0f)); camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); camera->setViewport(0, 0, width, height); - camera->getOrCreateStateSet()->setAttribute(camera->getViewport()); // set the camera to render before the main camera. camera->setRenderOrder(osg::CameraNode::PRE_RENDER); diff --git a/examples/osgforest/osgforest.cpp b/examples/osgforest/osgforest.cpp index 6363e7a8d..c3b4597fd 100644 --- a/examples/osgforest/osgforest.cpp +++ b/examples/osgforest/osgforest.cpp @@ -1028,8 +1028,8 @@ osg::Node* ForestTechniqueManager::createScene(unsigned int numTreesToCreates) osg::Program* program = new osg::Program; stateset->setAttribute(program); - osg::Shader* vertex_shader = new osg::Shader(osg::Shader::VERTEX, vertexShaderSource); - program->addShader(vertex_shader); + //osg::Shader* vertex_shader = new osg::Shader(osg::Shader::VERTEX, vertexShaderSource); + //program->addShader(vertex_shader); osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource); program->addShader(fragment_shader); diff --git a/examples/osgmultiplecameras/osgmultiplecameras.cpp b/examples/osgmultiplecameras/osgmultiplecameras.cpp index 43ae222df..5ea9d16b1 100644 --- a/examples/osgmultiplecameras/osgmultiplecameras.cpp +++ b/examples/osgmultiplecameras/osgmultiplecameras.cpp @@ -23,38 +23,43 @@ #include #include #include +#include #include -osg::Node* createRearView(osg::Node* subgraph) +osg::Node* createRearView(osg::Node* subgraph, const osg::Vec4& clearColour) { - osg::CameraNode* camera = new osg::CameraNode; - // set the projection matrix - camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1280,0,1024)); - + // set the viewport camera->setViewport(420,800,400,200); - - camera->getOrCreateStateSet()->setAttribute(camera->getViewport()); - // set the view matrix camera->setCullingActive(false); camera->setReferenceFrame(osg::Transform::RELATIVE_RF); camera->setTransformOrder(osg::CameraNode::POST_MULTIPLE); - camera->setProjectionMatrix(osg::Matrixd::identity()); + + camera->setProjectionMatrix(osg::Matrixd::scale(-1.0f,1.0f,1.0f)); camera->setViewMatrix(osg::Matrixd::rotate(osg::inDegrees(180.0f),0.0f,1.0f,0.0f)); - // only clear the depth buffer + // set clear the color and depth buffer + camera->setClearColor(clearColour); camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // draw subgraph after main camera view. camera->setRenderOrder(osg::CameraNode::POST_RENDER); + // add the subgraph to draw. camera->addChild(subgraph); + // switch of back face culling as we've swapped over the projection matrix making back faces become front faces. +#if 1 + camera->getOrCreateStateSet()->setAttribute(new osg::FrontFace(osg::FrontFace::CLOCKWISE)); +#else + camera->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); +#endif + return camera; } @@ -103,7 +108,7 @@ int main( int argc, char **argv ) // add the HUD subgraph. if (scene.valid()) group->addChild(scene.get()); - group->addChild(createRearView(scene.get())); + group->addChild(createRearView(scene.get(), viewer.getClearColor())); // set the scene to render viewer.setSceneData(group.get()); diff --git a/examples/osgpoints/osgpoints.cpp b/examples/osgpoints/osgpoints.cpp index 29094e653..151518d9d 100644 --- a/examples/osgpoints/osgpoints.cpp +++ b/examples/osgpoints/osgpoints.cpp @@ -122,6 +122,9 @@ int main( int argc, char **argv ) // get details on keyboard and mouse bindings used by the viewer. viewer.getUsage(*arguments.getApplicationUsage()); + bool shader = false; + while (arguments.read("--shader")) shader = true; + // if user request help write it out to cout. if (arguments.read("-h") || arguments.read("--help")) { @@ -196,6 +199,42 @@ int main( int argc, char **argv ) // register the handler for modifying the point size viewer.getEventHandlerList().push_front(new KeyboardEventHandler(viewer.getGlobalStateSet())); + + if (shader) + { + osg::StateSet* stateset = loadedModel->getOrCreateStateSet(); + + /////////////////////////////////////////////////////////////////// + // vertex shader using just Vec4 coefficients + char vertexShaderSource[] = + "void main(void) \n" + "{ \n" + "\n" + " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" + "}\n"; + + ////////////////////////////////////////////////////////////////// + // fragment shader + // + char fragmentShaderSource[] = + "void main(void) \n" + "{ \n" + " gl_FragColor = gl_Color; \n" + "}\n"; + + + osg::Program* program = new osg::Program; + stateset->setAttribute(program); + + osg::Shader* vertex_shader = new osg::Shader(osg::Shader::VERTEX, vertexShaderSource); + program->addShader(vertex_shader); + + //osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource); + //program->addShader(fragment_shader); + } + + + // create the windows and run the threads. viewer.realize(); diff --git a/examples/osgprerender/osgprerender.cpp b/examples/osgprerender/osgprerender.cpp index 76de1a5ab..d57941127 100644 --- a/examples/osgprerender/osgprerender.cpp +++ b/examples/osgprerender/osgprerender.cpp @@ -213,13 +213,11 @@ osg::Node* createPreRenderSubGraph(osg::Node* subgraph) // set view camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); - camera->setViewMatrixAsLookAt(bs.center()+osg::Vec3(0.0f,2.0f,0.0f)*bs.radius(),bs.center(),osg::Vec3(0.0f,0.0f,1.0f)); + camera->setViewMatrixAsLookAt(bs.center()-osg::Vec3(0.0f,2.0f,0.0f)*bs.radius(),bs.center(),osg::Vec3(0.0f,0.0f,1.0f)); // set viewport camera->setViewport(0,0,tex_width,tex_height); - camera->getOrCreateStateSet()->setAttribute(camera->getViewport()); - // set the camera to render before the main camera. camera->setRenderOrder(osg::CameraNode::PRE_RENDER); diff --git a/examples/osgprerendercubemap/osgprerendercubemap.cpp b/examples/osgprerendercubemap/osgprerendercubemap.cpp index da81f09ff..2cf2f47d3 100644 --- a/examples/osgprerendercubemap/osgprerendercubemap.cpp +++ b/examples/osgprerendercubemap/osgprerendercubemap.cpp @@ -1,420 +1,282 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include - #include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#define UPDATE_ONE_IMAGE_PER_FRAME 1 +#include + +#include +#include + +using namespace osg; -class PrerenderAppCallback : public osg::NodeCallback +ref_ptr _create_scene() +{ + ref_ptr scene = new Group; + ref_ptr geode_1 = new Geode; + scene->addChild(geode_1.get()); + + ref_ptr geode_2 = new Geode; + ref_ptr transform_2 = new MatrixTransform; + transform_2->addChild(geode_2.get()); + transform_2->setUpdateCallback(new osgUtil::TransformCallback(Vec3(0, 0, 0), Y_AXIS, inDegrees(45.0f))); + scene->addChild(transform_2.get()); + + ref_ptr geode_3 = new Geode; + ref_ptr transform_3 = new MatrixTransform; + transform_3->addChild(geode_3.get()); + transform_3->setUpdateCallback(new osgUtil::TransformCallback(Vec3(0, 0, 0), Y_AXIS, inDegrees(-22.5f))); + scene->addChild(transform_3.get()); + + const float radius = 0.8f; + const float height = 1.0f; + ref_ptr hints = new TessellationHints; + hints->setDetailRatio(2.0f); + ref_ptr shape; + + shape = new ShapeDrawable(new Box(Vec3(0.0f, -2.0f, 0.0f), 10, 0.1f, 10), hints.get()); + shape->setColor(Vec4(0.5f, 0.5f, 0.7f, 1.0f)); + geode_1->addDrawable(shape.get()); + + + shape = new ShapeDrawable(new Sphere(Vec3(-3.0f, 0.0f, 0.0f), radius), hints.get()); + shape->setColor(Vec4(0.6f, 0.8f, 0.8f, 1.0f)); + geode_2->addDrawable(shape.get()); + + shape = new ShapeDrawable(new Box(Vec3(3.0f, 0.0f, 0.0f), 2 * radius), hints.get()); + shape->setColor(Vec4(0.4f, 0.9f, 0.3f, 1.0f)); + geode_2->addDrawable(shape.get()); + + shape = new ShapeDrawable(new Cone(Vec3(0.0f, 0.0f, -3.0f), radius, height), hints.get()); + shape->setColor(Vec4(0.2f, 0.5f, 0.7f, 1.0f)); + geode_2->addDrawable(shape.get()); + + shape = new ShapeDrawable(new Cylinder(Vec3(0.0f, 0.0f, 3.0f), radius, height), hints.get()); + shape->setColor(Vec4(1.0f, 0.3f, 0.3f, 1.0f)); + geode_2->addDrawable(shape.get()); + + shape = new ShapeDrawable(new Box(Vec3(0.0f, 3.0f, 0.0f), 2, 0.1f, 2), hints.get()); + shape->setColor(Vec4(0.8f, 0.8f, 0.4f, 1.0f)); + geode_3->addDrawable(shape.get()); + + // material + ref_ptr matirial = new Material; + matirial->setColorMode(Material::DIFFUSE); + matirial->setAmbient(Material::FRONT_AND_BACK, Vec4(0, 0, 0, 1)); + matirial->setSpecular(Material::FRONT_AND_BACK, Vec4(1, 1, 1, 1)); + matirial->setShininess(Material::FRONT_AND_BACK, 64.0f); + scene->getOrCreateStateSet()->setAttributeAndModes(matirial.get(), StateAttribute::ON); + + return scene; +} + +osg::RefNodePath createReflector() +{ + ref_ptr scene = new Group; + ref_ptr geode_1 = new Geode; + scene->addChild(geode_1.get()); + + const float radius = 0.8f; + ref_ptr hints = new TessellationHints; + hints->setDetailRatio(2.0f); + ref_ptr shape = new ShapeDrawable(new Sphere(Vec3(0.0f, 0.0f, 0.0f), radius * 1.5f), hints.get()); + shape->setColor(Vec4(0.8f, 0.8f, 0.8f, 1.0f)); + geode_1->addDrawable(shape.get()); + + osg::RefNodePath refNodeList; + refNodeList.push_back(scene.get()); + refNodeList.push_back(geode_1.get()); + + return refNodeList; +} + +class UpdateCameraAndTexGenCallback : public osg::NodeCallback { public: - PrerenderAppCallback(osg::Node* subgraph): - _subgraph(subgraph) {} + typedef std::vector< osg::ref_ptr > CameraList; + UpdateCameraAndTexGenCallback(osg::RefNodePath& reflectorNodePath, CameraList& cameraNodes): + _reflectorNodePath(reflectorNodePath), + _cameraNodes(cameraNodes) + { + } + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) { - // traverse the subgraph to update any nodes. - if (_subgraph.valid()) _subgraph->accept(*nv); - - // must traverse the Node's subgraph + // first update subgraph to make sure objects are all moved into postion traverse(node,nv); + + // compute the position of the center of the reflector subgraph + osg::Matrixd matrix = osg::computeLocalToWorld(_reflectorNodePath); + osg::BoundingSphere bs = _reflectorNodePath.back()->getBound(); + osg::Vec3 position = bs.center() * matrix; + + typedef std::pair ImageData; + const ImageData id[] = + { + ImageData( osg::Vec3( 1, 0, 0), osg::Vec3( 0, -1, 0) ), // +X + ImageData( osg::Vec3(-1, 0, 0), osg::Vec3( 0, -1, 0) ), // -X + ImageData( osg::Vec3( 0, 1, 0), osg::Vec3( 0, 0, 1) ), // +Y + ImageData( osg::Vec3( 0, -1, 0), osg::Vec3( 0, 0, -1) ), // -Y + ImageData( osg::Vec3( 0, 0, 1), osg::Vec3( 0, -1, 0) ), // +Z + ImageData( osg::Vec3( 0, 0, -1), osg::Vec3( 0, -1, 0) ) // -Z + }; + + for(unsigned int i=0; + i<6 && i<_cameraNodes.size(); + ++i) + { + _cameraNodes[i]->setReferenceFrame(osg::CameraNode::ABSOLUTE_RF); + _cameraNodes[i]->setProjectionMatrixAsFrustum(-1.0,1.0,-1.0,1.0,1.0,10000.0); + _cameraNodes[i]->setViewMatrixAsLookAt(position,position+id[i].first,id[i].second); + } + } - osg::ref_ptr _subgraph; + protected: + + virtual ~UpdateCameraAndTexGenCallback() {} + + osg::RefNodePath _reflectorNodePath; + CameraList _cameraNodes; }; - -class PrerenderCullCallback : public osg::NodeCallback +class TexMatCullCallback : public osg::NodeCallback { public: - PrerenderCullCallback(osg::Node* subgraph, osg::TextureCubeMap* cubemap, osg::TexMat* texmat): - _subgraph(subgraph), - _cubemap(cubemap), + TexMatCullCallback(osg::TexMat* texmat): _texmat(texmat) - { - _updateCubemapFace = 0; - _clearColor = osg::Vec4(1,1,1,1); - _localState[0] = new osg::StateSet; - _localState[1] = new osg::StateSet; - _localState[2] = new osg::StateSet; - _localState[3] = new osg::StateSet; - _localState[4] = new osg::StateSet; - _localState[5] = new osg::StateSet; - } - + { + } + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) { - // Reset this counter to zero, otherwise it wont do the while loop down below. - // And the cubemap will never update the newer frames. - if (_updateCubemapFace > 5) - _updateCubemapFace = 0; - - osgUtil::CullVisitor* cv = dynamic_cast(nv); - if (cv && _cubemap.valid() && _subgraph.valid()) - { - const osg::Vec4 clearColArray[] = - { - osg::Vec4(0, 0, 1, 1), // +X - osg::Vec4(1, 0.7f, 0, 1), // -X - osg::Vec4(0, 1, 1, 1), // +Y - osg::Vec4(1, 1, 0, 1), // -Y - osg::Vec4(1, 0, 0, 1), // +Z - osg::Vec4(0, 1, 0, 1) // -Z - }; - - osg::Quat q; - cv->getModelViewMatrix().get(q); - const osg::Matrix C = osg::Matrix::rotate( q.inverse() ); - _texmat->setMatrix(C); - -#if UPDATE_ONE_IMAGE_PER_FRAME - if ((_updateCubemapFace >= 0) && (_updateCubemapFace <= 5)) - { - _clearColor = clearColArray[_updateCubemapFace]; - doPreRender(*node, *cv, _updateCubemapFace++); - } -#else - while (_updateCubemapFace<6) - { - _clearColor = clearColArray[_updateCubemapFace]; - doPreRender(*node, *cv, _updateCubemapFace++); - } -#endif - } - - // must traverse the subgraph + // first update subgraph to make sure objects are all moved into postion traverse(node,nv); + + osgUtil::CullVisitor* cv = dynamic_cast(nv); + if (cv) + { + osg::Quat quat; + cv->getModelViewMatrix().get(quat); + _texmat->setMatrix(osg::Matrix::rotate(quat.inverse())); + } } - - void doPreRender(osg::Node& node, osgUtil::CullVisitor& cv, const int nFace); - struct ImageData - { - ImageData(const osg::Vec3& dir, const osg::Vec3& up) : _dir(dir), _up(up) {} - osg::Vec3 _dir; - osg::Vec3 _up; - }; - - osg::ref_ptr _subgraph; - osg::ref_ptr _cubemap; - osg::ref_ptr _localState[6]; - osg::ref_ptr _texmat; - osg::Vec4 _clearColor; - int _updateCubemapFace; + protected: + + osg::ref_ptr _texmat; }; -void PrerenderCullCallback::doPreRender(osg::Node& /*node*/, osgUtil::CullVisitor& cv, const int nFace) +osg::Group* createShadowedScene(osg::Node* reflectedSubgraph, osg::RefNodePath reflectorNodePath, unsigned int unit, const osg::Vec4& clearColor) { - const ImageData id[] = + + osg::Group* group = new osg::Group; + + unsigned int tex_width = 512; + unsigned int tex_height = 512; + + osg::TextureCubeMap* texture = new osg::TextureCubeMap; + texture->setTextureSize(tex_width, tex_height); + + texture->setInternalFormat(GL_RGB); + texture->setFilter(osg::TextureCubeMap::MIN_FILTER,osg::TextureCubeMap::LINEAR); + texture->setFilter(osg::TextureCubeMap::MAG_FILTER,osg::TextureCubeMap::LINEAR); + + // set up the render to texture cameras. + UpdateCameraAndTexGenCallback::CameraList cameraNodes; + for(unsigned int i=0; i<6; ++i) { - ImageData( osg::Vec3( 1, 0, 0), osg::Vec3( 0, -1, 0) ), // +X - ImageData( osg::Vec3(-1, 0, 0), osg::Vec3( 0, -1, 0) ), // -X - ImageData( osg::Vec3( 0, 1, 0), osg::Vec3( 0, 0, 1) ), // +Y - ImageData( osg::Vec3( 0, -1, 0), osg::Vec3( 0, 0, -1) ), // -Y - ImageData( osg::Vec3( 0, 0, 1), osg::Vec3( 0, -1, 0) ), // +Z - ImageData( osg::Vec3( 0, 0, -1), osg::Vec3( 0, -1, 0) ) // -Z - }; - osg::Image* image = _cubemap->getImage((osg::TextureCubeMap::Face)nFace); - osg::Vec3 dir = id[nFace]._dir; - osg::Vec3 up = id[nFace]._up; + // create the camera + osg::CameraNode* camera = new osg::CameraNode; - const osg::BoundingSphere& bs = _subgraph->getBound(); - if (!bs.valid()) - { - osg::notify(osg::WARN) << "bb invalid"<<_subgraph.get()<setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + camera->setClearColor(clearColor); - // create the render to texture stage. - osg::ref_ptr rtts = new osgUtil::RenderToTextureStage; + // set viewport + camera->setViewport(0,0,tex_width,tex_height); - // set up lighting. - // currently ignore lights in the scene graph itself.. - // will do later. - osgUtil::RenderStage* previous_stage = cv.getCurrentRenderBin()->getStage(); + // set the camera to render before the main camera. + camera->setRenderOrder(osg::CameraNode::PRE_RENDER); - // set up the background color and clear mask. - rtts->setClearColor(_clearColor); + // tell the camera to use OpenGL frame buffer object where supported. + camera->setRenderTargetImplmentation(osg::CameraNode::FRAME_BUFFER_OBJECT); - // ABJ: use default (color+depth) - rtts->setClearMask(previous_stage->getClearMask()); + // attach the texture and use it as the color buffer. + camera->attach(osg::CameraNode::COLOR_BUFFER, texture, 0, i); - // set up to charge the same RenderStageLighting is the parent previous stage. - rtts->setRenderStageLighting(previous_stage->getRenderStageLighting()); - - // record the render bin, to be restored after creation - // of the render to text - osgUtil::RenderBin* previousRenderBin = cv.getCurrentRenderBin(); - - // set the current renderbin to be the newly created stage. - cv.setCurrentRenderBin(rtts.get()); - - - float znear = 1.0f*bs.radius(); - float zfar = 3.0f*bs.radius(); + // add subgraph to render + camera->addChild(reflectedSubgraph); - znear *= 0.9f; - zfar *= 1.1f; - - // set up projection. - const double fovy = 90.0; - const double aspectRatio = 1.0; - osg::RefMatrix* projection = new osg::RefMatrix; - projection->makePerspective(fovy, aspectRatio, znear, zfar); - - cv.pushProjectionMatrix(projection); - - osg::RefMatrix* matrix = new osg::RefMatrix; - osg::Vec3 eye = bs.center(); eye.z() = 0.0f; - osg::Vec3 center = eye + dir; - matrix->makeLookAt(eye, center, up); - - cv.pushModelViewMatrix(matrix); - - cv.pushStateSet(_localState[nFace].get()); - - { - // traverse the subgraph - _subgraph->accept(cv); + group->addChild(camera); + + cameraNodes.push_back(camera); } + + // create the texgen node to project the tex coords onto the subgraph + osg::TexGenNode* texgenNode = new osg::TexGenNode; + texgenNode->getTexGen()->setMode(osg::TexGen::REFLECTION_MAP); + texgenNode->setTextureUnit(unit); + group->addChild(texgenNode); - cv.popStateSet(); - - // restore the previous model view matrix. - cv.popModelViewMatrix(); - - // restore the previous model view matrix. - cv.popProjectionMatrix(); - - // restore the previous renderbin. - cv.setCurrentRenderBin(previousRenderBin); - - if (rtts->getRenderGraphList().size()==0 && rtts->getRenderBinList().size()==0) + // set the reflected subgraph so that it uses the texture and tex gen settings. { - // getting to this point means that all the subgraph has been - // culled by small feature culling or is beyond LOD ranges. - return; + osg::Node* reflectorNode = reflectorNodePath.front().get(); + group->addChild(reflectorNode); + + osg::StateSet* stateset = reflectorNode->getOrCreateStateSet(); + stateset->setTextureAttributeAndModes(unit,texture,osg::StateAttribute::ON); + stateset->setTextureMode(unit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); + stateset->setTextureMode(unit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON); + stateset->setTextureMode(unit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON); + stateset->setTextureMode(unit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON); + + osg::TexMat* texmat = new osg::TexMat; + stateset->setTextureAttributeAndModes(unit,texmat,osg::StateAttribute::ON); + + reflectorNode->setCullCallback(new TexMatCullCallback(texmat)); } - - int height = 512; - int width = 512; - - const osg::Viewport& viewport = *cv.getViewport(); - - // offset the impostor viewport from the center of the main window - // viewport as often the edges of the viewport might be obscured by - // other windows, which can cause image/reading writing problems. - int center_x = viewport.x()+viewport.width()/2; - int center_y = viewport.y()+viewport.height()/2; - - osg::Viewport* new_viewport = new osg::Viewport; - new_viewport->setViewport(center_x-width/2,center_y-height/2,width,height); - rtts->setViewport(new_viewport); - _localState[nFace]->setAttribute(new_viewport); + // add the reflector scene to draw just as normal + group->addChild(reflectedSubgraph); + + // set an update callback to keep moving the camera and tex gen in the right direction. + group->setUpdateCallback(new UpdateCameraAndTexGenCallback(reflectorNodePath, cameraNodes)); - // and the render to texture stage to the current stages - // dependancy list. - cv.getCurrentRenderBin()->getStage()->addToDependencyList(rtts.get()); - - // if one exist attach image to the RenderToTextureStage. - // if (image.valid()) rtts->setImage(_image.get()); - if (image) rtts->setImage(image); + return group; } -osg::Drawable* makeGeometry() -{ - const float radius = 20; - return new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f),radius)); -} - -osg::Node* createPreRenderSubGraph(osg::Node* subgraph) -{ - if (!subgraph) return 0; - - // create the quad to visualize. - osg::Drawable* geom = makeGeometry(); - geom->setSupportsDisplayList(false); - - // new we need to add the texture to the Drawable, we do so by creating a - // StateSet to contain the Texture StateAttribute. - osg::StateSet* stateset = new osg::StateSet; - - osg::TextureCubeMap* cubemap = new osg::TextureCubeMap; - - // set up the textures - osg::Image* imagePosX = new osg::Image; - osg::Image* imageNegX = new osg::Image; - osg::Image* imagePosY = new osg::Image; - osg::Image* imageNegY = new osg::Image; - osg::Image* imagePosZ = new osg::Image; - osg::Image* imageNegZ = new osg::Image; - - imagePosX->setInternalTextureFormat(GL_RGB); - imageNegX->setInternalTextureFormat(GL_RGB); - imagePosY->setInternalTextureFormat(GL_RGB); - imageNegY->setInternalTextureFormat(GL_RGB); - imagePosZ->setInternalTextureFormat(GL_RGB); - imageNegZ->setInternalTextureFormat(GL_RGB); - - cubemap->setImage(osg::TextureCubeMap::POSITIVE_X, imagePosX); - cubemap->setImage(osg::TextureCubeMap::NEGATIVE_X, imageNegX); - cubemap->setImage(osg::TextureCubeMap::POSITIVE_Y, imagePosY); - cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Y, imageNegY); - cubemap->setImage(osg::TextureCubeMap::POSITIVE_Z, imagePosZ); - cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Z, imageNegZ); - - cubemap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); - cubemap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); - cubemap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE); - cubemap->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); - cubemap->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); - stateset->setTextureAttributeAndModes(0, cubemap, osg::StateAttribute::ON); - - osg::TexGen *texgen = new osg::TexGen; - texgen->setMode(osg::TexGen::REFLECTION_MAP); - stateset->setTextureAttributeAndModes(0, texgen, osg::StateAttribute::ON); - - osg::TexMat* texmat = new osg::TexMat; - stateset->setTextureAttribute(0, texmat); - - stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); - - geom->setStateSet(stateset); - - osg::Geode* geode = new osg::Geode; - geode->addDrawable(geom); - - // Geodes can't have cull callback so create extra Group to attach cullcallback. - osg::Group* parent = new osg::Group; - - parent->setUpdateCallback(new PrerenderAppCallback(subgraph)); - - parent->setCullCallback(new PrerenderCullCallback(subgraph, cubemap, texmat)); - - parent->addChild(geode); - - return parent; -} - - -struct DrawableCullCallback : public osg::Drawable::CullCallback -{ - DrawableCullCallback(osg::TexMat* texmat) : _texmat(texmat) - {} - - virtual bool cull(osg::NodeVisitor* nv, osg::Drawable* /*drawable*/, osg::State* /*state*/) const - { - osgUtil::CullVisitor* cv = dynamic_cast(nv); - if (cv) - { - osg::Quat q; - cv->getModelViewMatrix().get(q); - const osg::Matrix C = osg::Matrix::rotate( q.inverse() ); - _texmat->setMatrix(C); - } - return false; - } - - mutable osg::ref_ptr _texmat; -}; - -osg::Node* createReferenceSphere() -{ - const float radius = 10; - osg::Drawable* sphere = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f),radius)); - - osg::StateSet* stateset = new osg::StateSet; - sphere->setStateSet(stateset); - - osg::TextureCubeMap* cubemap = new osg::TextureCubeMap; - #define CUBEMAP_FILENAME(face) "Cubemap_axis/" #face ".png" - - osg::Image* imagePosX = osgDB::readImageFile(CUBEMAP_FILENAME(posx)); - osg::Image* imageNegX = osgDB::readImageFile(CUBEMAP_FILENAME(negx)); - osg::Image* imagePosY = osgDB::readImageFile(CUBEMAP_FILENAME(posy)); - osg::Image* imageNegY = osgDB::readImageFile(CUBEMAP_FILENAME(negy)); - osg::Image* imagePosZ = osgDB::readImageFile(CUBEMAP_FILENAME(posz)); - osg::Image* imageNegZ = osgDB::readImageFile(CUBEMAP_FILENAME(negz)); - - if (imagePosX && imageNegX && imagePosY && imageNegY && imagePosZ && imageNegZ) - { - cubemap->setImage(osg::TextureCubeMap::POSITIVE_X, imagePosX); - cubemap->setImage(osg::TextureCubeMap::NEGATIVE_X, imageNegX); - cubemap->setImage(osg::TextureCubeMap::POSITIVE_Y, imagePosY); - cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Y, imageNegY); - cubemap->setImage(osg::TextureCubeMap::POSITIVE_Z, imagePosZ); - cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Z, imageNegZ); - - cubemap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); - cubemap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); - cubemap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE); - cubemap->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); - cubemap->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); - stateset->setTextureAttributeAndModes(0, cubemap, osg::StateAttribute::ON); - } - - osg::TexGen *texgen = new osg::TexGen; - texgen->setMode(osg::TexGen::REFLECTION_MAP); - stateset->setTextureAttributeAndModes(0, texgen, osg::StateAttribute::ON); - - osg::TexMat* texmat = new osg::TexMat; - stateset->setTextureAttribute(0, texmat); - - stateset->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); - - - sphere->setCullCallback(new DrawableCullCallback(texmat)); - - osg::Geode* geode = new osg::Geode(); - geode->addDrawable(sphere); - - return geode; -} - -int main( int argc, char **argv ) +int main(int argc, char** argv) { // use an ArgumentParser object to manage the program arguments. - osg::ArgumentParser arguments(&argc,argv); + ArgumentParser arguments(&argc, argv); // set up the usage document, in case we need to print out how to use this program. - arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates pre rendering of scene to a texture, and then apply this texture to geometry."); - arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ..."); - arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information"); - + arguments.getApplicationUsage()->setDescription(arguments.getApplicationName() + " is the example which demonstrates using of GL_ARB_shadow extension implemented in osg::Texture class"); + arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()); + arguments.getApplicationUsage()->addCommandLineOption("-h or --help", "Display this information"); + // construct the viewer. osgProducer::Viewer viewer(arguments); @@ -422,7 +284,7 @@ int main( int argc, char **argv ) viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS); // get details on keyboard and mouse bindings used by the viewer. - viewer.getUsage(*arguments.getApplicationUsage()); + viewer.getUsage(*arguments. getApplicationUsage()); // if user request help write it out to cout. if (arguments.read("-h") || arguments.read("--help")) @@ -437,72 +299,36 @@ int main( int argc, char **argv ) // report any errors if they have occured when parsing the program aguments. if (arguments.errors()) { - arguments.writeErrorMessages(std::cout); - return 1; + arguments.writeErrorMessages(std::cout); + return 1; } -/* - if (arguments.argc()<=1) - { - arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION); - return 1; - } -*/ - - osg::Group* rootNode = new osg::Group(); -#if 1 - osg::Node* sky = osgDB::readNodeFile("skydome.osg"); + ref_ptr scene = new MatrixTransform; + scene->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(125.0),1.0,0.0,0.0)); - // Proof of concept to see if the skydome really rotates and that the cubemap gets updated. - // create a transform to spin the model. - - osg::MatrixTransform* loadedModelTransform = new osg::MatrixTransform; - loadedModelTransform->addChild(sky); + ref_ptr reflectedSubgraph = _create_scene(); + if (!reflectedSubgraph.valid()) return 1; - osg::NodeCallback* nc = new osgUtil::TransformCallback(loadedModelTransform->getBound().center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(5.0f)); - loadedModelTransform->setUpdateCallback(nc); + ref_ptr reflectedScene = createShadowedScene(reflectedSubgraph.get(),createReflector(),0, viewer.getClearColor()); - // osg::Group* rootNode = new osg::Group(); - // rootNode->addChild(loadedModelTransform); - // rootNode->addChild(createPreRenderSubGraph(loadedModelTransform)); + scene->addChild(reflectedScene.get()); - - if (loadedModelTransform) - { - rootNode->addChild(createPreRenderSubGraph(loadedModelTransform)); - } -#endif - -#if 1 - osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform; - pat->setPosition(osg::Vec3(0,0,50)); - pat->addChild(createReferenceSphere()); - rootNode->addChild(pat); -#endif - - // load the nodes from the commandline arguments. - osg::Node* loadedModel = osgDB::readNodeFiles(arguments); - if (loadedModel) - rootNode->addChild(loadedModel); - - // add model to the viewer. - viewer.setSceneData( rootNode ); + viewer.setSceneData(scene.get()); // create the windows and run the threads. viewer.realize(); - while( !viewer.done() ) + while (!viewer.done()) { - // wait for all cull and draw threads to complete. - viewer.sync(); + // wait for all cull and draw threads to complete. + viewer.sync(); - // update the scene by traversing it with the the update visitor which will - // call all node update callbacks and animations. - viewer.update(); + // update the scene by traversing it with the the update visitor which will + // call all node update callbacks and animations. + viewer.update(); - // fire off the cull and draw traversals of the scene. - viewer.frame(); - + // fire off the cull and draw traversals of the scene. + viewer.frame(); } // wait for all cull and draw threads to complete before exit. @@ -510,4 +336,3 @@ int main( int argc, char **argv ) return 0; } - diff --git a/examples/osgshadowtexture/CreateShadowedScene.cpp b/examples/osgshadowtexture/CreateShadowedScene.cpp index f2c827c1b..53d09c7ae 100644 --- a/examples/osgshadowtexture/CreateShadowedScene.cpp +++ b/examples/osgshadowtexture/CreateShadowedScene.cpp @@ -126,7 +126,6 @@ osg::Group* createShadowedScene(osg::Node* shadower,osg::Node* shadowed,const os // set viewport camera->setViewport(0,0,tex_width,tex_height); - camera->getOrCreateStateSet()->setAttribute(camera->getViewport()); // set the camera to render before the main camera. camera->setRenderOrder(osg::CameraNode::PRE_RENDER); @@ -190,7 +189,6 @@ osg::Group* createShadowedScene(osg::Node* shadower,osg::Node* shadowed,const os camera->setViewMatrix(osg::Matrix::identity()); camera->setViewport(50,50,100,100); - camera->getOrCreateStateSet()->setAttribute(camera->getViewport()); // only clear the depth buffer camera->setClearMask(GL_DEPTH_BUFFER_BIT); diff --git a/include/osg/CameraNode b/include/osg/CameraNode index e1e4eac66..7a6c2fd67 100644 --- a/include/osg/CameraNode +++ b/include/osg/CameraNode @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -37,32 +38,45 @@ class OSG_EXPORT CameraNode : public Transform, public CullSettings META_Node(osg, CameraNode); + /** Sets the clear color. */ + inline void setClearColor(const Vec4& color) { _clearColor = color; } - /** Set the viewport of the scene view to use specified osg::Viewport. */ - void setViewport(osg::Viewport* viewport) - { - _viewport = viewport; - } + /** Returns the clear color. */ + inline const Vec4& getClearColor() const { return _clearColor; } + + /** Set the clear mask used in glClear(..). + * Defaults to GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT. */ + inline void setClearMask(GLbitfield mask) { _clearMask = mask; } - /** Set the viewport of the scene view to specified dimensions. */ - void setViewport(int x,int y,int width,int height) - { - if (!_viewport) _viewport = new osg::Viewport; - _viewport->setViewport(x,y,width,height); - } + /** Get the clear mask.*/ + inline GLbitfield getClearMask() const { return _clearMask; } + + /** Set the color mask of the camera to use specified osg::ColorMask. */ + void setColorMask(osg::ColorMask* colorMask); + + /** Set the color mask of the camera to specified values. */ + void setColorMask(bool red, bool green, bool blue, bool alpha); + + /** Get the const ColorMask. */ + const ColorMask* getColorMask() const { return _colorMask.get(); } + + /** Get the ColorMask. */ + ColorMask* getColorMask() { return _colorMask.get(); } + + + /** Set the viewport of the camera to use specified osg::Viewport. */ + void setViewport(osg::Viewport* viewport); + + /** Set the viewport of the camera to specified dimensions. */ + void setViewport(int x,int y,int width,int height); + /** Get the const viewport. */ const Viewport* getViewport() const { return _viewport.get(); } /** Get the viewport. */ Viewport* getViewport() { return _viewport.get(); } - /** Get the viewport of the scene view. */ - void getViewport(int& x,int& y,int& width,int& height) const - { - if (_viewport.valid()) _viewport->getViewport(x,y,width,height); - } - enum TransformOrder { @@ -149,22 +163,6 @@ class OSG_EXPORT CameraNode : public Transform, public CullSettings /** Get the inverse view matrix.*/ Matrixd getInverseViewMatrix() const; - - - /** Sets the clear color. */ - inline void setClearColor(const Vec4& color) { _clearColor = color; } - - /** Returns the clear color. */ - inline const Vec4& getClearColor() const { return _clearColor; } - - /** Set the clear mask used in glClear(..). - * Defaults to GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT. */ - inline void setClearMask(GLbitfield mask) { _clearMask = mask; } - - /** Get the clear mask.*/ - inline GLbitfield getClearMask() const { return _clearMask; } - - enum RenderOrder { @@ -276,6 +274,7 @@ class OSG_EXPORT CameraNode : public Transform, public CullSettings Vec4 _clearColor; GLbitfield _clearMask; + ref_ptr _colorMask; ref_ptr _viewport; TransformOrder _transformOrder; diff --git a/include/osg/FrameBufferObject b/include/osg/FrameBufferObject index 48ace5dba..e3132560a 100644 --- a/include/osg/FrameBufferObject +++ b/include/osg/FrameBufferObject @@ -19,6 +19,7 @@ #include #include #include +#include #ifndef GL_EXT_framebuffer_object #define GL_EXT_framebuffer_object 1 @@ -256,6 +257,7 @@ namespace osg explicit FrameBufferAttachment(Texture3D* target, int zoffset, int level = 0); explicit FrameBufferAttachment(TextureCubeMap* target, int face, int level = 0); explicit FrameBufferAttachment(TextureRectangle* target); + explicit FrameBufferAttachment(CameraNode::Attachment& attachment); ~FrameBufferAttachment(); diff --git a/include/osg/FrontFace b/include/osg/FrontFace index eaf7600a5..fa36e08d9 100644 --- a/include/osg/FrontFace +++ b/include/osg/FrontFace @@ -25,7 +25,12 @@ class OSG_EXPORT FrontFace : public StateAttribute { public : - FrontFace(); + enum Mode { + CLOCKWISE = GL_CW, + COUNTER_CLOCKWISE = GL_CCW + }; + + FrontFace(Mode face=COUNTER_CLOCKWISE); /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ FrontFace(const FrontFace& ff,const CopyOp& copyop=CopyOp::SHALLOW_COPY): @@ -46,11 +51,6 @@ class OSG_EXPORT FrontFace : public StateAttribute return 0; // passed all the above comparison macro's, must be equal. } - - enum Mode { - CLOCKWISE = GL_CW, - COUNTER_CLOCKWISE = GL_CCW - }; inline void setMode(Mode mode) { _mode = mode; } inline Mode getMode() const { return _mode; } diff --git a/include/osgUtil/RenderStage b/include/osgUtil/RenderStage index 3328dd241..f67912d9b 100644 --- a/include/osgUtil/RenderStage +++ b/include/osgUtil/RenderStage @@ -105,6 +105,12 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin /** Get the clear color.*/ int getClearStencil() const { return _clearStencil; } + void setInheritedRenderStageLightingMatrix(const osg::Matrix& matrix) { _inheritedRenderStageLightingMatrix = matrix; } + const osg::Matrix& getInheritedRenderStageLightingMatrix() const { return _inheritedRenderStageLightingMatrix; } + + void setInheritedRenderStageLighting(RenderStageLighting* rsl) { _inheritedRenderStageLighting = rsl; } + RenderStageLighting* getInheritedRenderStageLighting() { return _inheritedRenderStageLighting.get(); } + void setRenderStageLighting(RenderStageLighting* rsl) { _renderStageLighting = rsl; } RenderStageLighting* getRenderStageLighting() const @@ -159,6 +165,8 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin double _clearDepth; int _clearStencil; + mutable osg::Matrix _inheritedRenderStageLightingMatrix; + mutable osg::ref_ptr _inheritedRenderStageLighting; mutable osg::ref_ptr _renderStageLighting; diff --git a/include/osgUtil/RenderStageLighting b/include/osgUtil/RenderStageLighting index df10fcfbc..e707ba98a 100644 --- a/include/osgUtil/RenderStageLighting +++ b/include/osgUtil/RenderStageLighting @@ -54,7 +54,7 @@ class OSGUTIL_EXPORT RenderStageLighting : public osg::Object _texAttrListMap[textureUnit].push_back(AttrMatrixPair(attr,matrix)); } - virtual void draw(osg::State& state,RenderLeaf*& previous); + virtual void draw(osg::State& state,RenderLeaf*& previous, const osg::Matrix* postMultMatrix = 0); public: diff --git a/src/osg/CameraNode.cpp b/src/osg/CameraNode.cpp index 21b6288a6..ab687408b 100644 --- a/src/osg/CameraNode.cpp +++ b/src/osg/CameraNode.cpp @@ -23,6 +23,7 @@ CameraNode::CameraNode(): _renderOrder(POST_RENDER), _renderTargetImplementation(FRAME_BUFFER) { + setStateSet(new StateSet); } CameraNode::CameraNode(const CameraNode& camera,const CopyOp& copyop): @@ -30,6 +31,7 @@ CameraNode::CameraNode(const CameraNode& camera,const CopyOp& copyop): CullSettings(camera), _clearColor(camera._clearColor), _clearMask(camera._clearMask), + _colorMask(camera._colorMask), _viewport(camera._viewport), _transformOrder(camera._transformOrder), _projectionMatrix(camera._projectionMatrix), @@ -37,8 +39,7 @@ CameraNode::CameraNode(const CameraNode& camera,const CopyOp& copyop): _renderOrder(camera._renderOrder), _renderTargetImplementation(camera._renderTargetImplementation), _bufferAttachmentMap(camera._bufferAttachmentMap) - -{ +{ } @@ -46,6 +47,54 @@ CameraNode::~CameraNode() { } +void CameraNode::setColorMask(osg::ColorMask* colorMask) +{ + if (_colorMask == colorMask) return; + + osg::StateSet* stateset = getOrCreateStateSet(); + if (_colorMask.valid() && stateset) + { + stateset->removeAttribute(_colorMask.get()); + } + + _colorMask = colorMask; + + if (_colorMask.valid() && stateset) + { + stateset->setAttribute(_colorMask.get()); + } +} + +void CameraNode::setColorMask(bool red, bool green, bool blue, bool alpha) +{ + if (!_colorMask) setColorMask(new osg::ColorMask); + if (_colorMask.valid()) _colorMask->setMask(red,green,blue,alpha); +} + +void CameraNode::setViewport(osg::Viewport* viewport) +{ + if (_viewport == viewport) return; + + osg::StateSet* stateset = getOrCreateStateSet(); + if (_viewport.valid() && stateset) + { + stateset->removeAttribute(_viewport.get()); + } + + _viewport = viewport; + + if (_viewport.valid() && stateset) + { + stateset->setAttribute(_viewport.get()); + } +} + +void CameraNode::setViewport(int x,int y,int width,int height) +{ + if (!_viewport) setViewport(new osg::Viewport); + if (_viewport.valid()) _viewport->setViewport(x,y,width,height); +} + Matrixd CameraNode::getInverseViewMatrix() const { Matrixd inverse; diff --git a/src/osg/FrameBufferObject.cpp b/src/osg/FrameBufferObject.cpp index 114441067..c436b53cc 100644 --- a/src/osg/FrameBufferObject.cpp +++ b/src/osg/FrameBufferObject.cpp @@ -211,6 +211,55 @@ FrameBufferAttachment::FrameBufferAttachment(TextureRectangle* target) _ximpl->textureTarget = target; } +FrameBufferAttachment::FrameBufferAttachment(CameraNode::Attachment& attachment) +{ + osg::Texture* texture = attachment._texture.get(); + osg::Texture1D* texture1D = dynamic_cast(texture); + if (texture1D) + { + _ximpl = new Pimpl(Pimpl::TEXTURE1D, attachment._level); + _ximpl->textureTarget = texture1D; + return; + } + + osg::Texture2D* texture2D = dynamic_cast(texture); + if (texture2D) + { + _ximpl = new Pimpl(Pimpl::TEXTURE2D, attachment._level); + _ximpl->textureTarget = texture2D; + return; + } + + osg::Texture3D* texture3D = dynamic_cast(texture); + if (texture3D) + { + _ximpl = new Pimpl(Pimpl::TEXTURE3D, attachment._level); + _ximpl->textureTarget = texture3D; + _ximpl->zoffset = attachment._face; + return; + } + + osg::TextureCubeMap* textureCubeMap = dynamic_cast(texture); + if (textureCubeMap) + { + _ximpl = new Pimpl(Pimpl::TEXTURECUBE, attachment._level); + _ximpl->textureTarget = textureCubeMap; + _ximpl->cubeMapFace = attachment._face; + return; + } + + osg::TextureRectangle* textureRectangle = dynamic_cast(texture); + if (textureRectangle) + { + _ximpl = new Pimpl(Pimpl::TEXTURERECT); + _ximpl->textureTarget = textureRectangle; + return; + } + + osg::notify(osg::WARN)<<"Error: FrameBufferAttachment::FrameBufferAttachment(CameraNode::Attachment&) passed an unrecognised Texture type."< #include #include +#include #include @@ -302,6 +303,26 @@ void TextureCubeMap::apply(State& state) const } } + } + else if ( (_textureWidth!=0) && (_textureHeight!=0) && (_internalFormat!=0) ) + { + _textureObjectBuffer[contextID] = textureObject = generateTextureObject( + contextID,GL_TEXTURE_CUBE_MAP,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,0); + + textureObject->bind(); + + applyTexParameters(GL_TEXTURE_CUBE_MAP,state); + + for (int n=0; n<6; n++) + { + // no image present, but dimensions at set so less create the texture + glTexImage2D( faceTarget[n], 0, _internalFormat, + _textureWidth, _textureHeight, _borderWidth, + _internalFormat, + GL_UNSIGNED_BYTE, + 0); + } + } else { diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index 247b678e6..f92feb4f9 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -1036,6 +1036,7 @@ void CullVisitor::apply(osg::CameraNode& camera) StateSet* node_state = camera.getStateSet(); if (node_state) pushStateSet(node_state); + osg::RefMatrix& originalModelView = getModelViewMatrix(); if (camera.getReferenceFrame()==osg::Transform::ABSOLUTE_RF) { @@ -1078,17 +1079,28 @@ void CullVisitor::apply(osg::CameraNode& camera) // will do later. osgUtil::RenderStage* previous_stage = getCurrentRenderBin()->getStage(); + // set the compute near far mode. + ComputeNearFarMode saved_compute_near_far_mode = getComputeNearFarMode(); + setComputeNearFarMode( camera.getComputeNearFarMode()); + // set up the background color and clear mask. rtts->setClearColor(camera.getClearColor()); rtts->setClearMask(camera.getClearMask()); - - osg::Viewport* viewport = camera.getViewport()!=0 ? camera.getViewport() : previous_stage->getViewport(); + + // set the color mask. + osg::ColorMask* colorMask = camera.getColorMask()!=0 ? camera.getColorMask() : previous_stage->getColorMask(); + rtts->setColorMask(colorMask); // set up the viewport. + osg::Viewport* viewport = camera.getViewport()!=0 ? camera.getViewport() : previous_stage->getViewport(); rtts->setViewport( viewport ); // set up to charge the same RenderStageLighting is the parent previous stage. - //rtts->setRenderStageLighting(previous_stage->getRenderStageLighting()); + osg::Matrix inhertiedMVtolocalMV; + inhertiedMVtolocalMV.invert(originalModelView); + inhertiedMVtolocalMV.postMult(getModelViewMatrix()); + rtts->setInheritedRenderStageLightingMatrix(inhertiedMVtolocalMV); + rtts->setInheritedRenderStageLighting(previous_stage->getRenderStageLighting()); // record the render bin, to be restored after creation // of the render to text @@ -1106,6 +1118,10 @@ void CullVisitor::apply(osg::CameraNode& camera) // restore the previous renderbin. setCurrentRenderBin(previousRenderBin); + + // restore the previous compute near far mode + setComputeNearFarMode(saved_compute_near_far_mode); + if (rtts->getRenderGraphList().size()==0 && rtts->getRenderBinList().size()==0) { @@ -1156,9 +1172,49 @@ void CullVisitor::apply(osg::CameraNode& camera) fbo = new osg::FrameBufferObject; rtts->setFrameBufferObject(fbo.get()); - fbo->setAttachment(GL_COLOR_ATTACHMENT0_EXT, osg::FrameBufferAttachment(tex)); - fbo->setAttachment(GL_DEPTH_ATTACHMENT_EXT, osg::FrameBufferAttachment(new osg::RenderBuffer(viewport->width(), viewport->height(), GL_DEPTH_COMPONENT24))); + bool colorAttached = false; + bool depthAttached = false; + bool stencilAttached = false; + for(osg::CameraNode::BufferAttachmentMap::iterator itr = bufferAttachements.begin(); + itr != bufferAttachements.end(); + ++itr) + { + + osg::CameraNode::BufferComponent buffer = itr->first; + osg::CameraNode::Attachment& attachment = itr->second; + switch(buffer) + { + case(osg::CameraNode::DEPTH_BUFFER): + { + fbo->setAttachment(GL_DEPTH_ATTACHMENT_EXT, osg::FrameBufferAttachment(attachment)); + depthAttached = true; + break; + } + case(osg::CameraNode::STENCIL_BUFFER): + { + fbo->setAttachment(GL_STENCIL_ATTACHMENT_EXT, osg::FrameBufferAttachment(attachment)); + stencilAttached = true; + break; + } + default: + { + fbo->setAttachment(GL_COLOR_ATTACHMENT0_EXT, osg::FrameBufferAttachment(attachment)); + colorAttached = true; + break; + } + + } + } + + if (!depthAttached) + { + fbo->setAttachment(GL_DEPTH_ATTACHMENT_EXT, osg::FrameBufferAttachment(new osg::RenderBuffer(viewport->width(), viewport->height(), GL_DEPTH_COMPONENT24))); + } + if (!colorAttached) + { + fbo->setAttachment(GL_COLOR_ATTACHMENT0_EXT, osg::FrameBufferAttachment(new osg::RenderBuffer(viewport->width(), viewport->height(), GL_RGB))); + } } } diff --git a/src/osgUtil/RenderStage.cpp b/src/osgUtil/RenderStage.cpp index f1ee902c3..12b1885e6 100644 --- a/src/osgUtil/RenderStage.cpp +++ b/src/osgUtil/RenderStage.cpp @@ -177,8 +177,17 @@ void RenderStage::drawImplementation(osg::State& state,RenderLeaf*& previous) glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); - // apply the lights. - if (_renderStageLighting.valid()) _renderStageLighting->draw(state,previous); + // apply the positional state. + if (_inheritedRenderStageLighting.valid()) + { + _inheritedRenderStageLighting->draw(state, previous, &_inheritedRenderStageLightingMatrix); + } + + // apply the positional state. + if (_renderStageLighting.valid()) + { + _renderStageLighting->draw(state, previous, 0); + } // draw the children and local. RenderBin::drawImplementation(state,previous); diff --git a/src/osgUtil/RenderStageLighting.cpp b/src/osgUtil/RenderStageLighting.cpp index 815b295fc..4a429dd07 100644 --- a/src/osgUtil/RenderStageLighting.cpp +++ b/src/osgUtil/RenderStageLighting.cpp @@ -32,7 +32,7 @@ void RenderStageLighting::reset() _texAttrListMap.clear(); } -void RenderStageLighting::draw(osg::State& state,RenderLeaf*& previous) +void RenderStageLighting::draw(osg::State& state,RenderLeaf*& previous, const osg::Matrix* postMultMatrix) { if (previous) @@ -47,7 +47,18 @@ void RenderStageLighting::draw(osg::State& state,RenderLeaf*& previous) litr!=_attrList.end(); ++litr) { - state.applyModelViewMatrix((*litr).second.get()); + if (postMultMatrix) + { + if ((*litr).second.valid()) + state.applyModelViewMatrix(new osg::RefMatrix( (*((*litr).second)) * (*postMultMatrix))); + else + state.applyModelViewMatrix(new osg::RefMatrix( *postMultMatrix)); + } + + else + { + state.applyModelViewMatrix((*litr).second.get()); + } // apply the light source. litr->first->apply(state); @@ -71,7 +82,17 @@ void RenderStageLighting::draw(osg::State& state,RenderLeaf*& previous) litr!=attrList.end(); ++litr) { - state.applyModelViewMatrix((*litr).second.get()); + if (postMultMatrix) + { + if ((*litr).second.valid()) + state.applyModelViewMatrix(new osg::RefMatrix( (*((*litr).second)) * (*postMultMatrix))); + else + state.applyModelViewMatrix(new osg::RefMatrix( *postMultMatrix)); + } + else + { + state.applyModelViewMatrix((*litr).second.get()); + } // apply the light source. litr->first->apply(state); diff --git a/src/osgUtil/RenderToTextureStage.cpp b/src/osgUtil/RenderToTextureStage.cpp index 5da128190..7b2df4560 100644 --- a/src/osgUtil/RenderToTextureStage.cpp +++ b/src/osgUtil/RenderToTextureStage.cpp @@ -60,8 +60,11 @@ void RenderToTextureStage::draw(osg::State& state,RenderLeaf*& previous) } if (_image.valid()) + { _image->readPixels(_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height(),_imageReadPixelFormat,_imageReadPixelDataType); - + + } + if (fbo_supported) { fbo_ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);