diff --git a/src/Demos/osgprerender/Makefile b/src/Demos/osgprerender/Makefile index a53aa262c..e2efc2caa 100644 --- a/src/Demos/osgprerender/Makefile +++ b/src/Demos/osgprerender/Makefile @@ -10,6 +10,6 @@ INSTFILES = \ $(CXXFILES)\ Makefile.inst=Makefile -EXEC = osgreflect +EXEC = osgprerender include $(TOPDIR)/Make/makerules diff --git a/src/Demos/osgprerender/Makefile.inst b/src/Demos/osgprerender/Makefile.inst index 9fd7cfbff..86206155b 100644 --- a/src/Demos/osgprerender/Makefile.inst +++ b/src/Demos/osgprerender/Makefile.inst @@ -6,6 +6,6 @@ CXXFILES =\ LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) -EXEC = osgreflect +EXEC = osgprerender include $(TOPDIR)/Make/makerules diff --git a/src/Demos/osgprerender/osgprerender.cpp b/src/Demos/osgprerender/osgprerender.cpp index 8769cb70e..5a094841c 100644 --- a/src/Demos/osgprerender/osgprerender.cpp +++ b/src/Demos/osgprerender/osgprerender.cpp @@ -20,81 +20,11 @@ #include #include - - -// -// A simple demo demonstrating planer reflections using multiple renderings -// of a subgraph, overriding of state attribures and use of the stencil buffer. -// -// The multipass system implemented here is a variation if Mark Kilgard's -// paper "Improving Shadows and Reflections via the Stencil Buffer" which -// can be found on the developer parts of the NVidia web site. -// -// The variations comes from the fact that the mirrors stencil values -// are done on the first pass, rather than the second as in Mark's paper. -// The second pass is now Mark's first pass - drawing the unreflected scene, -// but also unsets the stencil buffer. This variation stops the unreflected -// world poking through the mirror to be seen in the final rendering and -// also obscures the world correctly when on the reverse side of the mirror. -// Although there is still some unresolved issue with the clip plane needing -// to be flipped when looking at the reverse side of the mirror. Niether -// of these issues are mentioned in the Mark's paper, but trip us up when -// we apply them. - - -osg::StateSet* createMirrorTexturedState(const std::string& filename) +osg::Node* createPreRenderSubGraph(osg::Node* subgraph) { - osg::StateSet* dstate = new osg::StateSet; - dstate->setMode(GL_CULL_FACE,osg::StateAttribute::OFF); - - // set up the texture. - osg::Image* image = osgDB::readImageFile(filename.c_str()); - if (image) - { - osg::Texture* texture = new osg::Texture; - texture->setImage(image); - dstate->setAttributeAndModes(texture,osg::StateAttribute::ON); - } - - return dstate; -} - - -osg::Drawable* createMirrorSurface(float xMin,float xMax,float yMin,float yMax,float z) -{ - - // set up the drawstate. - - // set up the Geometry. - osg::Geometry* geom = new osg::Geometry; - - osg::Vec3Array* coords = new osg::Vec3Array(4); - (*coords)[0].set(xMin,yMax,z); - (*coords)[1].set(xMin,yMin,z); - (*coords)[2].set(xMax,yMin,z); - (*coords)[3].set(xMax,yMax,z); - geom->setVertexArray(coords); - - osg::Vec3Array* norms = new osg::Vec3Array(1); - (*norms)[0].set(0.0f,0.0f,1.0f); - geom->setNormalArray(norms); - geom->setNormalBinding(osg::Geometry::BIND_OVERALL); - - osg::Vec2Array* tcoords = new osg::Vec2Array(4); - (*tcoords)[0].set(0.0f,1.0f); - (*tcoords)[1].set(0.0f,0.0f); - (*tcoords)[2].set(1.0f,0.0f); - (*tcoords)[3].set(1.0f,1.0f); - geom->setTexCoordArray(0,tcoords); - - osg::Vec4Array* colours = new osg::Vec4Array(1); - (*colours)[0].set(1.0f,1.0f,1.0,1.0f); - geom->setColorArray(colours); - geom->setColorBinding(osg::Geometry::BIND_OVERALL); - - geom->addPrimitive(osgNew osg::DrawArrays(osg::Primitive::QUADS,0,4)); - - return geom; + // ok we havn't done anything yet, but this is where the funky code + // will go :) + return NULL; } void write_usage(std::ostream& out,const std::string& name) @@ -167,207 +97,21 @@ int main( int argc, char **argv ) return 1; } + // create a transform to spin the model. osg::Transform* loadedModelTransform = new osg::Transform; loadedModelTransform->addChild(loadedModel); - // calculate where to place the mirror according to the - // loaded models bounding sphere. - const osg::BoundingSphere& bs = loadedModelTransform->getBound(); + osg::NodeCallback* nc = new osgUtil::TransformCallback(loadedModelTransform->getBound().center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(45.0f)); + loadedModelTransform->setAppCallback(nc); - float width_factor = 1.5; - float height_factor = 0.3; - - float xMin = bs.center().x()-bs.radius()*width_factor; - float xMax = bs.center().x()+bs.radius()*width_factor; - float yMin = bs.center().y()-bs.radius()*width_factor; - float yMax = bs.center().y()+bs.radius()*width_factor; - - float z = bs.center().z()-bs.radius()*height_factor; - - - // create a textured, transparent node at the appropriate place. - osg::Drawable* mirror = createMirrorSurface(xMin,xMax,yMin,yMax,z); - + osg::Group* rootNode = new osg::Group(); + rootNode->addChild(loadedModelTransform); + rootNode->addChild(createPreRenderSubGraph(loadedModelTransform)); - osg::Group* rootNode = new osg::Group; - - // make sure that the global color mask exists. - osg::ColorMask* rootColorMask = new osg::ColorMask; - rootColorMask->setMask(true,true,true,true); - - // set up depth to be inherited by the rest of the scene unless - // overrideen. this is overridden in bin 3. - osg::Depth* rootDepth = new osg::Depth; - rootDepth->setFunction(osg::Depth::LESS); - rootDepth->setRange(0.0,1.0); - - osg::StateSet* rootStateSet = new osg::StateSet(); - rootStateSet->setAttribute(rootColorMask); - rootStateSet->setAttribute(rootDepth); - - rootNode->setStateSet(rootStateSet); - - - // bin1 - set up the stencil values and depth for mirror. - { - - // set up the stencil ops so that the stencil buffer get set at - // the mirror plane - osg::Stencil* stencil = new osg::Stencil; - stencil->setFunction(osg::Stencil::ALWAYS,1,~0); - stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::REPLACE); - - // switch off the writing to the color bit planes. - osg::ColorMask* colorMask = new osg::ColorMask; - colorMask->setMask(false,false,false,false); - - osg::StateSet* statesetBin1 = new osg::StateSet(); - statesetBin1->setRenderBinDetails(1,"RenderBin"); - statesetBin1->setMode(GL_CULL_FACE,osg::StateAttribute::OFF); - statesetBin1->setAttributeAndModes(stencil,osg::StateAttribute::ON); - statesetBin1->setAttribute(colorMask); - - // set up the mirror geode. - osg::Geode* geode = new osg::Geode; - geode->addDrawable(mirror); - geode->setStateSet(statesetBin1); - - rootNode->addChild(geode); - - } - - // bin one - draw scene without mirror or reflection, unset - // stencil values where scene is infront of mirror and hence - // occludes the mirror. - { - osg::Stencil* stencil = new osg::Stencil; - stencil->setFunction(osg::Stencil::ALWAYS,0,~0); - stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::REPLACE); - - osg::StateSet* statesetBin2 = new osg::StateSet(); - statesetBin2->setRenderBinDetails(2,"RenderBin"); - statesetBin2->setAttributeAndModes(stencil,osg::StateAttribute::ON); - - - osg::Group* groupBin2 = new osg::Group(); - groupBin2->setStateSet(statesetBin2); - groupBin2->addChild(loadedModelTransform); - - rootNode->addChild(groupBin2); - } - - // bin3 - set up the depth to the furthest depth value - { - - // set up the stencil ops so that only operator on this mirrors stencil value. - osg::Stencil* stencil = new osg::Stencil; - stencil->setFunction(osg::Stencil::EQUAL,1,~0); - stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP); - - // switch off the writing to the color bit planes. - osg::ColorMask* colorMask = new osg::ColorMask; - colorMask->setMask(false,false,false,false); - - // set up depth so all writing to depth goes to maximum depth. - osg::Depth* depth = new osg::Depth; - depth->setFunction(osg::Depth::ALWAYS); - depth->setRange(1.0,1.0); - - osg::StateSet* statesetBin3 = new osg::StateSet(); - statesetBin3->setRenderBinDetails(3,"RenderBin"); - statesetBin3->setMode(GL_CULL_FACE,osg::StateAttribute::OFF); - statesetBin3->setAttributeAndModes(stencil,osg::StateAttribute::ON); - statesetBin3->setAttribute(colorMask); - statesetBin3->setAttribute(depth); - - // set up the mirror geode. - osg::Geode* geode = new osg::Geode; - geode->addDrawable(mirror); - geode->setStateSet(statesetBin3); - - rootNode->addChild(geode); - - } - - // bin4 - draw the reflection. - { - - // now create the 'reflection' of the loaded model by applying - // create a Transform which flips the loaded model about the z axis - // relative to the mirror node, the loadedModel is added to the - // Transform so now appears twice in the scene, but is shared so there - // is negligable memory overhead. Also use an osg::StateSet - // attached to the Transform to override the face culling on the subgraph - // to prevert an 'inside' out view of the reflected model. - // set up the stencil ops so that only operator on this mirrors stencil value. - - osg::Stencil* stencil = new osg::Stencil; - stencil->setFunction(osg::Stencil::EQUAL,1,~0); - stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP); - - // this clip plane removes any of the scene which when mirror would - // poke through the mirror. However, this clip plane should really - // flip sides once the eye point goes to the back of the mirror... - osg::ClipPlane* clipplane = new osg::ClipPlane; - clipplane->setClipPlane(osg::Vec4(0.0f,0.0f,-1.0f,z)); - clipplane->setClipPlaneNum(0); - - osg::StateSet* dstate = new osg::StateSet; - dstate->setRenderBinDetails(4,"RenderBin"); - dstate->setMode(GL_CULL_FACE,osg::StateAttribute::OVERRIDE_OFF); - dstate->setAttributeAndModes(stencil,osg::StateAttribute::ON); - dstate->setAttributeAndModes(clipplane,osg::StateAttribute::ON); - - osg::Transform* dcs = new osg::Transform; - dcs->setStateSet(dstate); - dcs->preMult(osg::Matrix::translate(0.0f,0.0f,-z)* - osg::Matrix::scale(1.0f,1.0f,-1.0f)* - osg::Matrix::translate(0.0f,0.0f,z)); - - dcs->addChild(loadedModelTransform); - - rootNode->addChild(dcs); - - } - - - // bin5 - draw the textured mirror and blend it with the reflection. - { - - // set up depth so all writing to depth goes to maximum depth. - osg::Depth* depth = new osg::Depth; - depth->setFunction(osg::Depth::ALWAYS); - - osg::Stencil* stencil = new osg::Stencil; - stencil->setFunction(osg::Stencil::EQUAL,1,~0); - stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::ZERO); - - // set up additive blending. - osg::Transparency* trans = new osg::Transparency; - trans->setFunction(osg::Transparency::ONE,osg::Transparency::ONE); - - osg::StateSet* statesetBin5 = createMirrorTexturedState("Images/tank.rgb"); - - statesetBin5->setRenderBinDetails(5,"RenderBin"); - statesetBin5->setMode(GL_CULL_FACE,osg::StateAttribute::OFF); - statesetBin5->setAttributeAndModes(stencil,osg::StateAttribute::ON); - statesetBin5->setAttributeAndModes(trans,osg::StateAttribute::ON); - statesetBin5->setAttribute(depth); - - // set up the mirror geode. - osg::Geode* geode = new osg::Geode; - geode->addDrawable(mirror); - geode->setStateSet(statesetBin5); - - rootNode->addChild(geode); - - } // add model to the viewer. viewer.addViewport( rootNode ); - osg::NodeCallback* nc = new osgUtil::TransformCallback(loadedModelTransform->getBound().center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(45.0f)); - loadedModelTransform->setAppCallback(nc); // register trackball, flight and drive. viewer.registerCameraManipulator(new osgGA::TrackballManipulator);