[osg-users] How to handle cameras in the scene graph when rendering to framebuffer
Robert Osfield
robert.osfield at gmail.com
Mon Feb 27 03:02:03 PST 2017
HI Werner,
It's hard to work exactly what is going on with a quick read through
as it's rather complicated set up of various Camera's. My current
best guess Your Cl_3D_Wallpaper class is setting the RenderOrder to
POST_RENDER as this is make it render after the Camera you are adding
to do the screenshot has been done.
Perhaps the best way to work out what order things are being done in
is to add a Camera initiali, pre, post and a final DrawCallbacks to
each of the Camera's and have these debug callbacks just write to the
console when they are being called.
Robert.
On 27 February 2017 at 10:34, Werner Modenbach
<Werner.Modenbach at texion.eu> wrote:
> Hi Robert,
>
> sorry for the delayed answer. It's carnival time here and so everybody is
> out - except me ;-)
>
> I try to give an as compressed description as possible here.
>
> The scene looks like that:
> *
>
> * ---------------
>
> * | RootNode |
>
> * ---------------
>
> * / \
>
> * ---------------
> ---------------------
>
> * | ShadowScene | |evtl.
> PPU-Prozessor|
>
> * ---------------
> ---------------------
>
> * / \
>
> * --------------- ---------------
>
> * | Switchnode | | LightSource |
>
> * --------------- ---------------
>
> * / \\\
>
> * --------------- -----------------
>
> * | User scene | | evtl. further |
>
> * --------------- | Objects |
>
> * -----------------
>
> The further objects are the wallpaper, a magnifier etc.
>
>
> The main camera is a standard camera with perspective view and a trackball
> manipulator.
> The wallpaper class is like that:
> class Cl_3D_Wallpaper : public osg::Camera {
>
> public:
>
> Cl_3D_Wallpaper(Cl_3Dview_osg *_parent);
>
> /** This Method creates the background image. */
>
> void setWallpaper(const QString _path);
>
> protected:
> Cl_3Dview_osg *view;
> QString path;
> };
>
>
> Cl_3D_Wallpaper::Cl_3D_Wallpaper(Cl_3Dview_osg *_parent): view(_parent),
> path(QLatin1String("")) {
>
> setCullingActive( false );
>
> setClearMask( 0 );
>
> setAllowEventFocus( false );
>
> setReferenceFrame( osg::Transform::ABSOLUTE_RF );
>
> setRenderOrder( osg::Camera::POST_RENDER );
>
> setProjectionMatrix( osg::Matrix::ortho2D(0.0, 1.0, 0.0, 1.0) );
>
> setName(getNodeName().toStdString().c_str());
>
> osg::StateSet* ss = getOrCreateStateSet();
>
> ss->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
>
> ss->setAttributeAndModes( new osg::Depth(osg::Depth::LEQUAL, 1.0, 1.0)
> );
>
> view->installDefaultShader(ss); // In case we are on gl3
>
> }
>
> /** Diese Methode erzeugt eine Hintergrundbildanzeige,
>
> * falls der Pfad auf eine Bilddatei verweist.
>
> */
>
> void Cl_3D_Wallpaper::setWallpaper(const QString _path) {
>
> path = _path;
>
> if (!_path.isEmpty()) {
>
> // ================================================
>
> // Die Szene des Bildes erzeugen
>
> // ================================================
>
> osg::Geode* geode = new osg::Geode();
>
> osg::Geometry* geometry =
> osg::createTexturedQuadGeometry(osg::Vec3(0,0,0),osg::Vec3(1,0,0),osg::Vec3(0,1,0),0,
> 0, 1, 1);
>
> geode->addDrawable(geometry);
>
> osg::Texture2D* texture = view->loadTexture(_path, false);
>
>
> geode->getOrCreateStateSet()->setTextureAttributeAndModes(BASE_TEXTURE_UNIT,
> texture, osg::StateAttribute::ON);
>
> geode->getOrCreateStateSet()->setMode(GL_LIGHTING,
> osg::StateAttribute::OFF);
>
> addChild(geode);
>
> view->installDefaultShader(geode->getOrCreateStateSet()); //In case
> we are on gl3
>
> }
>
> }
>
> Now the part of getting a frame buffer screenshot:
>
> /** The screen image is rendered at a pregiven dpi */
>
> QImage Cl_3Dview_osg::getHighResQImage(const int _dpi) {
>
> double scale = (double)_dpi / (double)dpi;
>
> // Calculation of image size and tiles per row
>
> int width = (int) (view->getGraphicsWidth());
>
> int height = (int) (view->getGraphicsHeight());
>
> int imageWidth = (int)(width * scale);
>
> int imageHeight = (int)(height * scale);
>
> int tiles = (imageWidth - 1) / width + 1;
>
> osg::ref_ptr<osg::Image> image = new osg::Image;
>
> // Creating the new camera
> osg::ref_ptr<osg::Camera> camera = new osg::Camera;
>
> camera->getOrCreateStateSet()->setGlobalDefaults();
>
> camera->setClearColor(view->getCamera()->getClearColor());
>
> camera->setViewport(new osg::Viewport(0,0,width,height));
>
> camera->setClearMask( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
>
> camera->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
>
> camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
>
> camera->setRenderOrder( osg::Camera::POST_RENDER );
>
>
> camera->addChild(view->getCamera()->getChild(0)); // The root node
>
> osg::ref_ptr<osg::Image> fbImage = new osg::Image;
>
> fbImage->allocateImage(width,height,1,GL_RGBA,GL_UNSIGNED_BYTE, 1);
>
> camera->attach( osg::Camera::COLOR_BUFFER, fbImage.get(), 0, 0);
>
> // Setting the new camera a child of the main camera
>
> view->getCamera()->addChild(camera.get());
>
> // Loop over tiles
> osg::Matrixd viewMatrix = view->getCamera()->getViewMatrix();
>
> osg::Matrixd projectionMatrix =
> view->getCamera()->getProjectionMatrix();
>
> int y_out = imageHeight - 1;
>
> for (int row = 0; row < tiles; row++) {
>
> for (int col = 0; col < tiles; col++) {
>
> // Calculate projection matrix offset of each tile
>
> osg::Matrix offsetMatrix =
>
> osg::Matrix::scale(scale, scale, 1.0) *
>
> osg::Matrix::translate(scale-1-2*col, scale-1-2*row,
> 0.0);
>
> camera->setViewMatrix(viewMatrix);
>
> camera->setProjectionMatrix( projectionMatrix * offsetMatrix );
>
> view->frame();
> image = fbImage.get();
>
> // Transferring tile into final image
> .......
>
> }
>
> y_out -= height;
>
> if (y_out < 0) break;
>
> }
>
> view->getCamera()->removeChild(camera.get());
> }
>
>
> The rendered image is missing my wallpaper.
> If I add the camera as a slave camera to the main camera I just get an empty
> black image.
> Actually I also don't understand the difference between slave and child
> cameras here. I know you explained it recently :-)
> Why does the slave camera give an empty image but the child camera doesn't?
>
> BTW. I wrote my code here with the background of giving an example to others
> looking for functionality like that.
>
>
>
>
>
> Am 24.02.2017 um 17:56 schrieb Robert Osfield:
>
> Hi Werner,
>
> In principle what you are doing should be possible. What is going
> wrong in your instance is impossible to say without seeing how you are
> setting up the viewer Camera's and the in scene graph Camera's.
>
> Robert.
>
> On 24 February 2017 at 16:44, Werner Modenbach
> <Werner.Modenbach at texion.eu> wrote:
>
> Hi all,
> sorry for so many questions today.
>
> My scene graph has additional cameras as children somewhere in the scene
> graph.
> For example a hud camera for a background image.
>
> I do screenshots by adding a slave camera to the main camera which renders
> the scene to the FB.
> Unfortunately this rendering doesn't show the parts of the nested cameras,
> i.e. no
> background wallpaper.
> What is the recommended way to solve this?
>
> Thanks for any help.
>
> - Werner -
>
>
> _______________________________________________
> osg-users mailing list
> osg-users at lists.openscenegraph.org
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>
> _______________________________________________
> osg-users mailing list
> osg-users at lists.openscenegraph.org
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>
>
>
> _______________________________________________
> osg-users mailing list
> osg-users at lists.openscenegraph.org
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>
More information about the osg-users
mailing list