Hi Martin, I have am only popping online briefly so a just a quick response. What makes you think that the pre render camera is not being drawn?
Robert. On 20 January 2017 at 22:12, Malcolm Pigott <[email protected]> wrote: > I have a scene in OpenSceneGraph which has a "normal" 3D content overlaid > with content in an Ortho2D projection. This works OK. > > I am now trying to render this scene to a texture (via a Frame Buffer Object) > and am working with the osgPreRender example. Below is some code derived from > that example which has a 2D overlay which is shown when the scene is drawn > normally, but not (seemingly) drawn when rendered to a texture using > setRenderOrder(osg::Camera::PRE_RENDER). > > This is using OpenSceneGraph 3.4.0 and VS2015 Update 2. > > > Code: > > /* OpenSceneGraph example, osgprerender. > * > * Permission is hereby granted, free of charge, to any person obtaining a > copy > * of this software and associated documentation files (the "Software"), to > deal > * in the Software without restriction, including without limitation the > rights > * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell > * copies of the Software, and to permit persons to whom the Software is > * furnished to do so, subject to the following conditions: > * > * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE > * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > FROM, > * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN > * THE SOFTWARE. > */ > > #include <osg/GLExtensions> > #include <osg/Node> > #include <osg/Geometry> > #include <osg/Notify> > #include <osg/MatrixTransform> > #include <osg/Texture2D> > #include <osg/TextureRectangle> > #include <osg/Stencil> > #include <osg/ColorMask> > #include <osg/Depth> > #include <osg/Billboard> > #include <osg/Material> > #include <osg/AnimationPath> > #include <osg/LineWidth> > > #include <osgGA/TrackballManipulator> > #include <osgGA/FlightManipulator> > #include <osgGA/DriveManipulator> > > #include <osgUtil/SmoothingVisitor> > > #include <osgDB/Registry> > #include <osgDB/ReadFile> > #include <osgDB/WriteFile> > > #include <osgViewer/Viewer> > #include <osgViewer/ViewerEventHandlers> > > #include <iostream> > > // call back which creates a deformation field to oscillate the model. > class MyGeometryCallback : > public osg::Drawable::UpdateCallback, > public osg::Drawable::AttributeFunctor > { > public: > > MyGeometryCallback(const osg::Vec3& o, > const osg::Vec3& x, const osg::Vec3& y, const osg::Vec3& z, > double period, double xphase, double amplitude) : > _firstCall(true), > _startTime(0.0), > _time(0.0), > _period(period), > _xphase(xphase), > _amplitude(amplitude), > _origin(o), > _xAxis(x), > _yAxis(y), > _zAxis(z) {} > > virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable) > { > // OpenThreads::Thread::microSleep( 1000 ); > > const osg::FrameStamp* fs = nv->getFrameStamp(); > double simulationTime = fs->getSimulationTime(); > if (_firstCall) > { > _firstCall = false; > _startTime = simulationTime; > } > > _time = simulationTime - _startTime; > > drawable->accept(*this); > drawable->dirtyBound(); > > osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(drawable); > if (geometry) > { > osgUtil::SmoothingVisitor::smooth(*geometry); > } > > } > > virtual void apply(osg::Drawable::AttributeType type, unsigned int count, > osg::Vec3* begin) > { > if (type == osg::Drawable::VERTICES) > { > const float TwoPI = 2.0f*osg::PI; > const float phase = -_time / _period; > > osg::Vec3* end = begin + count; > for (osg::Vec3* itr = begin; itr<end; ++itr) > { > osg::Vec3 dv(*itr - _origin); > osg::Vec3 local(dv*_xAxis, dv*_yAxis, dv*_zAxis); > > local.z() = local.x()*_amplitude* > sinf(TwoPI*(phase + local.x()*_xphase)); > > (*itr) = _origin + > _xAxis*local.x() + > _yAxis*local.y() + > _zAxis*local.z(); > } > } > } > > bool _firstCall; > > double _startTime; > double _time; > > double _period; > double _xphase; > float _amplitude; > > osg::Vec3 _origin; > osg::Vec3 _xAxis; > osg::Vec3 _yAxis; > osg::Vec3 _zAxis; > > }; > > osg::Node* createPreRenderSubGraph(osg::Node* subgraph, > unsigned tex_width, unsigned tex_height, > osg::Camera::RenderTargetImplementation renderImplementation, > bool useTextureRectangle, > unsigned int samples, unsigned int colorSamples) > { > if (!subgraph) return 0; > > // create a group to contain the flag and the pre rendering camera. > osg::Group* parent = new osg::Group; > > // texture to render to and to use for rendering of flag. > osg::Texture* texture = 0; > { > osg::TextureRectangle* textureRect = new osg::TextureRectangle; > textureRect->setTextureSize(tex_width, tex_height); > textureRect->setInternalFormat(GL_RGBA); > textureRect->setFilter(osg::Texture2D::MIN_FILTER, > osg::Texture2D::LINEAR); > textureRect->setFilter(osg::Texture2D::MAG_FILTER, > osg::Texture2D::LINEAR); > > texture = textureRect; > } > > // first create the geometry of the flag of which to view. > { > // create the to visualize. > osg::Geometry* polyGeom = new osg::Geometry(); > > polyGeom->setName("PolyGeom"); > > polyGeom->setDataVariance(osg::Object::DYNAMIC); > polyGeom->setSupportsDisplayList(false); > > osg::Vec3 origin(0.0f, 0.0f, 0.0f); > osg::Vec3 xAxis(1.0f, 0.0f, 0.0f); > osg::Vec3 yAxis(0.0f, 0.0f, 1.0f); > osg::Vec3 zAxis(0.0f, -1.0f, 0.0f); > float height = 100.0f; > float width = 200.0f; > int noSteps = 20; > > osg::Vec3Array* vertices = new osg::Vec3Array; > osg::Vec3 bottom = origin; > osg::Vec3 top = origin; top.z() += height; > osg::Vec3 dv = xAxis*(width / ((float)(noSteps - 1))); > > osg::Vec2Array* texcoords = new osg::Vec2Array; > > // note, when we use TextureRectangle we have to scale the tex coords > up to compensate. > osg::Vec2 bottom_texcoord(0.0f, 0.0f); > osg::Vec2 top_texcoord(0.0f, useTextureRectangle ? tex_height : 1.0f); > osg::Vec2 dv_texcoord((useTextureRectangle ? tex_width : 1.0f) / > (float)(noSteps - 1), 0.0f); > > for (int i = 0; i<noSteps; ++i) > { > vertices->push_back(top); > vertices->push_back(bottom); > top += dv; > bottom += dv; > > texcoords->push_back(top_texcoord); > texcoords->push_back(bottom_texcoord); > top_texcoord += dv_texcoord; > bottom_texcoord += dv_texcoord; > } > > > // pass the created vertex array to the points geometry object. > polyGeom->setVertexArray(vertices); > > polyGeom->setTexCoordArray(0, texcoords); > > osg::Vec4Array* colors = new osg::Vec4Array; > colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); > polyGeom->setColorArray(colors, osg::Array::BIND_OVERALL); > > polyGeom->addPrimitiveSet(new > osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP, 0, vertices->size())); > > // 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; > > stateset->setTextureAttributeAndModes(0, texture, > osg::StateAttribute::ON); > > polyGeom->setStateSet(stateset); > > polyGeom->setUpdateCallback(new MyGeometryCallback(origin, xAxis, > yAxis, zAxis, 1.0, 1.0 / width, 0.2f)); > > osg::Geode* geode = new osg::Geode(); > geode->addDrawable(polyGeom); > > parent->addChild(geode); > > } > > > // then create the camera node to do the render to texture > { > osg::Camera* camera = new osg::Camera; > > // set up the background color and clear mask. > camera->setClearColor(osg::Vec4(0.1f, 0.1f, 0.3f, 1.0f)); > camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); > > const osg::BoundingSphere& bs = subgraph->getBound(); > if (!bs.valid()) > { > return subgraph; > } > > float znear = 1.0f*bs.radius(); > float zfar = 3.0f*bs.radius(); > > // 2:1 aspect ratio as per flag geometry below. > float proj_top = 0.25f*znear; > float proj_right = 0.5f*znear; > > znear *= 0.9f; > zfar *= 1.1f; > > // set up projection. > camera->setProjectionMatrixAsFrustum(-proj_right, proj_right, > -proj_top, proj_top, znear, zfar); > > // 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)); > > // set viewport > camera->setViewport(0, 0, tex_width, tex_height); > > // set the camera to render before the main camera. > camera->setRenderOrder(osg::Camera::PRE_RENDER); > > // tell the camera to use OpenGL frame buffer object where supported. > camera->setRenderTargetImplementation(renderImplementation); > > // attach the texture and use it as the color buffer. > camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, 0, false, > samples, colorSamples); > > // add subgraph to render > camera->addChild(subgraph); > > parent->addChild(camera); > > } > > return parent; > } > > osg::Node *createNormalScene(osgViewer::Viewer &Viewer) > { > auto topNodeOfNormalScene = new osg::Group(); > { > auto normal3DScene = new osg::Group(); > { > normal3DScene->addChild(osgDB::readNodeFile("cessna.osgt")); // > 3D example > topNodeOfNormalScene->addChild(normal3DScene); > } > auto overlayLikeA2DHUD = new osg::Group(); > { > auto overlayCamera = new osg::Camera(); > overlayCamera->getOrCreateStateSet()->setGlobalDefaults(); > double _orthoLeft = 0.0; > double _orthoRight = 1280.0; > double _orthoBottom = 0.0; > double _orthoTop = 1024.0; > { > // Create the symbology camera > > overlayCamera->setName("OverlayViewCamera"); > overlayCamera->setProjectionMatrixAsOrtho2D(_orthoLeft, > _orthoRight, _orthoBottom, _orthoTop); > overlayCamera->setDataVariance(osg::Object::DYNAMIC); // gets > updated when the screen size changes. > //_symbologyCamera->setRenderOrder(osg::Camera::POST_RENDER); > overlayCamera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); > overlayCamera->setClearMask(GL_DEPTH_BUFFER_BIT); > overlayCamera->setViewport(new osg::Viewport(0.0, 0.0, > (_orthoRight - _orthoLeft), (_orthoTop - _orthoBottom))); > } > { > auto Geometry = new osg::Geometry(); > { > Geometry->setName("2DTie"); > double Left = 100.0; > double Bottom = 100.0; > double Right = 924.0; > double Top = 1180.0; > // tie > osg::Vec3Array *vertexArray = new osg::Vec3Array(); > vertexArray->push_back(osg::Vec3d(Left, Bottom, 0.0)); > vertexArray->push_back(osg::Vec3d(Right, Bottom, 0.0)); > vertexArray->push_back(osg::Vec3d(Left, Top, 0.0)); > vertexArray->push_back(osg::Vec3d(Right, Top, 0.0)); > Geometry->setVertexArray(vertexArray); > osg::Vec3 colors[] = { { 1.0f, 1.0f, 1.0f } }; > osg::Vec3Array *colorArray = new osg::Vec3Array(1, > colors); > Geometry->setColorArray(colorArray, > osg::Array::BIND_OVERALL); > Geometry->addPrimitiveSet(new > osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP, 0, vertexArray->size())); > Geometry->getOrCreateStateSet()->setAttributeAndModes(new > osg::LineWidth(2.0f), osg::StateAttribute::ON); > } > auto Geode = new osg::Geode(); > Geode->addDrawable(Geometry); > auto Group = new osg::Group(); > Group->addChild(Geode); > overlayCamera->addChild(Group); > } > overlayLikeA2DHUD->addChild(overlayCamera); > //Viewer.addSlave(_symbologyCamera, false); > topNodeOfNormalScene->addChild(overlayLikeA2DHUD); > } > } > return topNodeOfNormalScene; > } > > int main(int argc, char **argv) > { > // use an ArgumentParser object to manage the program arguments. > osg::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()->addCommandLineOption("--fbo", "Use Frame > Buffer Object for render to texture, where supported."); > arguments.getApplicationUsage()->addCommandLineOption("--fb", "Use > FrameBuffer for render to texture."); > arguments.getApplicationUsage()->addCommandLineOption("--pbuffer", "Use > Pixel Buffer for render to texture, where supported."); > arguments.getApplicationUsage()->addCommandLineOption("--window", "Use a > separate Window for render to texture."); > arguments.getApplicationUsage()->addCommandLineOption("--width", "Set the > width of the render to texture."); > arguments.getApplicationUsage()->addCommandLineOption("--height", "Set > the height of the render to texture."); > arguments.getApplicationUsage()->addCommandLineOption("--image", "Render > to an image, then apply a post draw callback to it, and use this image to > update a texture."); > > arguments.getApplicationUsage()->addCommandLineOption("--texture-rectangle", > "Use osg::TextureRectangle for doing the render to texture to."); > > // construct the viewer. > osgViewer::Viewer viewer(arguments); > > // add stats > viewer.addEventHandler(new osgViewer::StatsHandler()); > > // add the record camera path handler > viewer.addEventHandler(new osgViewer::RecordCameraPathHandler); > > // add the threading handler > viewer.addEventHandler(new osgViewer::ThreadingHandler()); > > // if user request help write it out to cout. > if (arguments.read("-h") || arguments.read("--help")) > { > arguments.getApplicationUsage()->write(std::cout); > return 1; > } > > unsigned int tex_width = 1280; > unsigned int tex_height = 1024; > unsigned int samples = 0; > unsigned int colorSamples = 0; > > while (arguments.read("--width", tex_width)) {} > while (arguments.read("--height", tex_height)) {} > > osg::Camera::RenderTargetImplementation renderImplementation = > osg::Camera::FRAME_BUFFER_OBJECT; > > while (arguments.read("--fbo")) { renderImplementation = > osg::Camera::FRAME_BUFFER_OBJECT; } > while (arguments.read("--pbuffer")) { renderImplementation = > osg::Camera::PIXEL_BUFFER; } > while (arguments.read("--pbuffer-rtt")) { renderImplementation = > osg::Camera::PIXEL_BUFFER_RTT; } > while (arguments.read("--fb")) { renderImplementation = > osg::Camera::FRAME_BUFFER; } > while (arguments.read("--window")) { renderImplementation = > osg::Camera::SEPARATE_WINDOW; } > while (arguments.read("--fbo-samples", samples)) {} > while (arguments.read("--color-samples", colorSamples)) {} > > bool useTextureRectangle = true; > while (arguments.read("--texture-rectangle")) { useTextureRectangle = > true; } > > // load the nodes from the commandline arguments. > osg::Node* loadedModel = osgDB::readNodeFiles(arguments); > > // if not loaded assume no arguments passed in, try use default mode > instead. > if (!loadedModel) loadedModel = createNormalScene(viewer); // > osgDB::readNodeFile("cessna.osgt"); > > if (!loadedModel) > { > return 1; > } > > bool PreRender = true; // alter via debugger > if (PreRender) > { > // create a transform to spin the model. > osg::MatrixTransform* loadedModelTransform = new osg::MatrixTransform; > loadedModelTransform->addChild(loadedModel); > > osg::NodeCallback* nc = new > osg::AnimationPathCallback(loadedModelTransform->getBound().center(), > osg::Vec3(0.0f, 0.0f, 1.0f), osg::inDegrees(45.0f)); > loadedModelTransform->setUpdateCallback(nc); > > osg::Group* rootNode = new osg::Group(); > rootNode->addChild(createPreRenderSubGraph(loadedModelTransform, > tex_width, tex_height, renderImplementation, useTextureRectangle, samples, > colorSamples)); > > bool WriteOutNodeFile = false; // alter via debugger > if (WriteOutNodeFile) > { > osgDB::writeNodeFile(*rootNode, "PreRenderExample.osgt"); // view > using Notepad++ and LUA language mode (for example). > } > > // add model to the viewer. > viewer.setSceneData(rootNode); > } > else > { > auto camera = viewer.getCamera(); > // set up the background color and clear mask. > camera->setClearColor(osg::Vec4(0.1f, 0.1f, 0.3f, 1.0f)); > camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); > > viewer.setSceneData(loadedModel); > } > > return viewer.run(); > } > > > > > Many thanks for any guidance. > > ------------------ > Read this topic online here: > http://forum.openscenegraph.org/viewtopic.php?p=70025#70025 > > > > > Attachments: > http://forum.openscenegraph.org//files/ortho2dinprerender_895.cpp > > > _______________________________________________ > osg-users mailing list > [email protected] > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org _______________________________________________ osg-users mailing list [email protected] http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

