Hello Gerrit, below you can find my simple not finished example with the FBOBackground. It works reasonably with a standard render context but fails with a multisampling context.
I have currently not figured out what exactly is going wrong, so. Best, Johannes // User interface: // a) mouse => standard navigator // b) keyboard => // '1': toggle between static and dynamic mode // #include <stdlib.h> #include <stdio.h> #include <string> #include <sstream> #include <fstream> #include <vector> #include <boost/tuple/tuple.hpp> #include <boost/scoped_ptr.hpp> #include <boost/random.hpp> #include <boost/random/lagged_fibonacci.hpp> #ifdef OSG_BUILD_ACTIVE // Headers #include <OSGGLUT.h> #include <OSGConfig.h> #include <OSGSimpleGeometry.h> #include <OSGGLUTWindow.h> #include <OSGGradientBackground.h> #include <OSGSimpleSceneManager.h> #include <OSGSceneFileHandler.h> #include <OSGAction.h> #include <OSGFrameBufferObject.h> #include <OSGRenderBuffer.h> #include <OSGTextureBuffer.h> #include <OSGSimpleStage.h> #include <OSGPassiveViewport.h> #include <OSGVisitSubTree.h> #include <OSGImage.h> #include <OSGTextureObjChunk.h> #include <OSGFBOBackground.h> #else // Headers #include <OpenSG/OSGGLUT.h> #include <OpenSG/OSGConfig.h> #include <OpenSG/OSGSimpleGeometry.h> #include <OpenSG/OSGGLUTWindow.h> #include <OpenSG/OSGGradientBackground.h> #include <OpenSG/OSGSimpleSceneManager.h> #include <OpenSG/OSGSceneFileHandler.h> #include <OpenSG/OSGAction.h> #include <OpenSG/OSGFrameBufferObject.h> #include <OpenSG/OSGRenderBuffer.h> #include <OpenSG/OSGTextureBuffer.h> #include <OpenSG/OSGSimpleStage.h> #include <OpenSG/OSGPassiveViewport.h> #include <OpenSG/OSGVisitSubTree.h> #include <OpenSG/OSGImage.h> #include <OpenSG/OSGTextureObjChunk.h> #include <OpenSG/OSGFBOBackground.h> #endif OSG_USING_NAMESPACE; // just for convenience but not recommended #define USE_MULTISAMPLING #ifdef _DEBUG const int max_tori = 500; #else const int max_tori = 10000; #endif // // Helper class for building FBO // class FBOBuilder { public: struct TextureData { TextureData() : enable(true) , pixel_format(Image::OSG_RGBA_PF) , type(Image::OSG_UINT8_IMAGEDATA) , main_memory(true) , texObj(nullptr) , image(nullptr) {} ~TextureData() {texObj = nullptr; image = nullptr; } bool enable; UInt32 pixel_format; Int32 type; bool main_memory; TextureObjChunkUnrecPtr texObj; ImageUnrecPtr image; }; typedef std::vector<TextureData> VecTextureDataT; public: FBOBuilder(const VecTextureDataT& buffers, bool depth, bool stencil, const TextureData& ds_buffer) : _buffers(buffers) , _depth(depth) , _stencil(stencil) , _ds_buffer(ds_buffer) {} ~FBOBuilder() {} public: FrameBufferObjectTransitPtr operator()(UInt32 width, UInt32 height) const; private: VecTextureDataT _buffers; bool _depth; bool _stencil; TextureData _ds_buffer; }; FrameBufferObjectTransitPtr FBOBuilder::operator()( UInt32 width, UInt32 height) const { // // Setup the FBO // FrameBufferObjectUnrecPtr fbo = FrameBufferObject::create(); // // multiple color buffers // for (UINT32 idx = 0; idx < _buffers.size(); ++idx) { // // use textures? // if (_buffers[idx].enable) { ImageUnrecPtr texImg = (_buffers[idx].image == nullptr ? Image::create() : _buffers[idx].image); TextureObjChunkUnrecPtr texObj = (_buffers[idx].texObj == nullptr ? TextureObjChunk::create() : _buffers[idx].texObj); TextureBufferUnrecPtr texBuf = TextureBuffer::create(); if (_buffers[idx].image == nullptr) texImg->set(_buffers[idx].pixel_format, width, height, 1, 1, 1, 0.f, nullptr, _buffers[idx].type, _buffers[idx].main_memory); texObj->setImage(texImg); texBuf->setTexture(texObj); fbo->setColorAttachment(texBuf, idx); } else // // no, then use simple render buffer // { RenderBufferUnrecPtr renBuf = RenderBuffer::create(); renBuf->setInternalFormat(_buffers[idx].pixel_format); fbo->setColorAttachment(renBuf, idx); } fbo->editMFDrawBuffers()->push_back(GL_COLOR_ATTACHMENT0_EXT + idx); } // // a sole depth buffer // if (_depth && !_stencil) { // // use textures? // if (_ds_buffer.enable) { ImageUnrecPtr texImg = (_ds_buffer.image == nullptr ? Image::create() : _ds_buffer.image); TextureObjChunkUnrecPtr texObj = (_ds_buffer.texObj == nullptr ? TextureObjChunk::create() : _ds_buffer.texObj); TextureBufferUnrecPtr texBuf = TextureBuffer::create(); if (_ds_buffer.image == nullptr) texImg->set(_ds_buffer.pixel_format, width, height, 1, 1, 1, 0.f, nullptr, _ds_buffer.type, _ds_buffer.main_memory); texObj->setImage(texImg); if (_ds_buffer.texObj == nullptr) { texObj->setInternalFormat(GL_DEPTH_COMPONENT24); texObj->setExternalFormat(GL_DEPTH_COMPONENT24); } texBuf->setTexture(texObj); fbo->setDepthAttachment(texBuf); } else // // no, then use simple render buffer // { RenderBufferUnrecPtr renBuf = RenderBuffer::create(); renBuf->setInternalFormat(GL_DEPTH_COMPONENT24); fbo->setDepthAttachment(renBuf); } } else // // or a combined depth/stencil buffer // if (_depth && _stencil) { // // use textures? // if (_ds_buffer.enable) { ImageUnrecPtr texImg = (_ds_buffer.image == nullptr ? Image::create() : _ds_buffer.image); TextureObjChunkUnrecPtr texObj = (_ds_buffer.texObj == nullptr ? TextureObjChunk::create() : _ds_buffer.texObj); TextureBufferUnrecPtr texBuf = TextureBuffer::create(); if (_ds_buffer.image == nullptr) texImg->set(GL_DEPTH_STENCIL_EXT, width, height, 1, 1, 1, 0.f, nullptr, GL_UNSIGNED_INT_24_8, _ds_buffer.main_memory); texObj->setImage(texImg); texObj->setInternalFormat(GL_DEPTH24_STENCIL8_EXT); texObj->setExternalFormat(GL_DEPTH_STENCIL_EXT); texBuf->setTexture(texObj); fbo->setDepthAttachment(texBuf); fbo->setStencilAttachment(texBuf); } else // // no, then use simple render buffer // { RenderBufferUnrecPtr renBuf = RenderBuffer::create(); renBuf->setInternalFormat(GL_DEPTH24_STENCIL8); fbo->setDepthAttachment(renBuf); fbo->setStencilAttachment(renBuf); } } fbo->setWidth (width ); fbo->setHeight(height); return FrameBufferObjectTransitPtr(fbo); } class SimpleFBO { public: SimpleFBO(UInt32 width, UInt32 height, bool color_textured, bool depth_stencil_textured, bool read_back_color = true, bool read_back_depth_stencil = false); SimpleFBO(UInt32 width, UInt32 height, const std::vector<FBOBuilder::TextureData>& buffers, bool depth, bool stencil, const FBOBuilder::TextureData& ds_buffer); ~SimpleFBO() { _fbo = nullptr; } public: FrameBufferObject* fbo () const { return _fbo; } FrameBufferAttachment* colorBuffer (UInt32 idx = 0) const { return _fbo ? _fbo->getColorAttachments(idx) : nullptr; } FrameBufferAttachment* depthBuffer () const { return _fbo ? _fbo->getDepthAttachment() : nullptr; } FrameBufferAttachment* stencilBuffer () const { return _fbo ? _fbo->getStencilAttachment() : nullptr;} TextureObjChunk* colorTexObj (UInt32 idx = 0) const; TextureObjChunk* depthTexObj () const; TextureObjChunk* stencilTexObj () const; private: FrameBufferObjectRecPtr _fbo; }; // // Convenience class for building and wrapping a FBO. // SimpleFBO::SimpleFBO( UInt32 width, UInt32 height, bool color_textured, bool depth_stencil_textured, bool read_back_color, bool read_back_depth_stencil) : _fbo(nullptr) { FBOBuilder::TextureData color_data; color_data.enable = color_textured; color_data.main_memory = read_back_color; FBOBuilder::TextureData depth_stencil_data; depth_stencil_data.enable = depth_stencil_textured; depth_stencil_data.main_memory = read_back_depth_stencil; FBOBuilder::VecTextureDataT color_vec; color_vec.push_back(color_data); FBOBuilder fbo_builder(color_vec, true, true, depth_stencil_data); _fbo = fbo_builder(width, height); } SimpleFBO::SimpleFBO( UInt32 width, UInt32 height, const std::vector<FBOBuilder::TextureData>& buffers, bool depth, bool stencil, const FBOBuilder::TextureData& ds_buffer) : _fbo(nullptr) { FBOBuilder fbo_builder(buffers, depth, stencil, ds_buffer); _fbo = fbo_builder(width, height); } TextureObjChunk* SimpleFBO::colorTexObj(UInt32 idx) const { TextureBuffer* texBuf = dynamic_cast<TextureBuffer*>(colorBuffer(idx)); if (texBuf) return texBuf->getTexture(); return nullptr; } TextureObjChunk* SimpleFBO::depthTexObj() const { TextureBuffer* texBuf = dynamic_cast<TextureBuffer*>(depthBuffer()); if (texBuf) return texBuf->getTexture(); return nullptr; } TextureObjChunk* SimpleFBO::stencilTexObj() const { TextureBuffer* texBuf = dynamic_cast<TextureBuffer*>(stencilBuffer()); if (texBuf) return texBuf->getTexture(); return nullptr; } // // function forward declarations // static void cleanup(void); static void display(void); static void reshape(int w, int h); static void mouse(int button, int state, int x, int y); static void motion(int x, int y); static void keyboard(unsigned char k, int, int); static int setupGLUT(int *argc, char *argv[]); static int doMain(int argc, char *argv[]); static NodeTransitPtr createStaticScene(); static NodeTransitPtr createDynamicScene(); static void createAcquisitionStage(); static void createDynamicViewport(); static void enableStaticScene(); static Node* rootNode(Node* node); // // global state of example // SimpleSceneManagerRefPtr mgr; NodeRefPtr staticScene; NodeRefPtr dynamicScene; GLUTWindowRefPtr win; ViewportRefPtr staticVp; ViewportRefPtr dynamicVp; CameraRefPtr camera; boost::scoped_ptr<SimpleFBO> spSimpleFBO; static void cleanup(void) { mgr = nullptr; staticScene = nullptr; dynamicScene = nullptr; win = nullptr; dynamicVp = nullptr; spSimpleFBO.reset(); } static void display(void) { commitChanges(); mgr->redraw(); } static void reshape(int w, int h) { mgr->resize(w,h); glutPostRedisplay(); } static void mouse(int button, int state, int x, int y) { if (state) mgr->mouseButtonRelease(button, x, y); else mgr->mouseButtonPress(button, x, y); glutPostRedisplay(); } static void motion(int x, int y) { mgr->mouseMove(x, y); glutPostRedisplay(); } static void keyboard(unsigned char k, int, int) { switch(k) { case 27: case 'q': case 'Q': { cleanup(); osgExit(); std::exit(EXIT_SUCCESS); } break; case '1': { UInt32 width = win->getWidth(); UInt32 height = win->getHeight(); std::cout << "Creating acquisition stage " << width << "x" << height << std::endl; if (!dynamicVp) { createAcquisitionStage(); createDynamicViewport(); } else { enableStaticScene(); } } break; } glutPostRedisplay(); } // // initialize GLUT // static int setupGLUT(int *argc, char *argv[]) { glutInit(argc, argv); glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH | GLUT_STENCIL | GLUT_DOUBLE #ifdef USE_MULTISAMPLING | GLUT_MULTISAMPLE #endif ); int winid = glutCreateWindow("OpenSG"); glutReshapeFunc(reshape); glutDisplayFunc(display); glutIdleFunc(display); glutMouseFunc(mouse); glutMotionFunc(motion); glutKeyboardFunc(keyboard); return winid; } // // setup scene // static int doMain(int argc, char *argv[]) { preloadSharedObject("OSGFileIO"); preloadSharedObject("OSGImageFileIO"); osgInit(argc,argv); int winid = setupGLUT(&argc, argv); win = GLUTWindow::create(); win->setGlutId(winid); win->init(); if(argc < 2) { FWARNING(("No file given!\n")); FWARNING(("Supported file formats:\n")); std::list<const char*> suffixes; SceneFileHandler::the()->getSuffixList(suffixes); for(std::list<const char*>::iterator it = suffixes.begin(); it != suffixes.end(); ++it) { FWARNING(("%s\n", *it)); } staticScene = createStaticScene(); } else { staticScene = SceneFileHandler::the()->read(argv[1]); } dynamicScene = createDynamicScene(); commitChanges(); mgr = SimpleSceneManager::create(); NodeUnrecPtr root = makeCoredNode<Group>(); root->addChild(staticScene); mgr->setWindow(win); mgr->setRoot (root); GradientBackgroundUnrecPtr background = GradientBackground::create(); background->addLine(Color3f(0,0,0), 0); background->addLine(Color3f(1,1,1), 1); staticVp = win->getPort(0); staticVp->setBackground(background); camera = staticVp->getCamera(); mgr->showAll(); return 0; } // // create an arbitrarly complex render scene // static NodeTransitPtr createStaticScene() { NodeUnrecPtr root = makeCoredNode<Group>(); typedef boost::mt19937 base_generator_type; static base_generator_type generator(0); static boost::uniform_01<float> value; static boost::variate_generator< base_generator_type, boost::uniform_01<float> > die(generator, value); for (int i = 0; i < max_tori; ++i) { NodeUnrecPtr scene = makeTorus(.5, 2, 32, 32); TransformUnrecPtr transformCore = Transform::create(); Matrix mat; mat.setIdentity(); float x = 500.f * die(); float y = 500.f * die(); float z = 500.f * die(); float e1 = die(); float e2 = die(); float e3 = die(); Vec3f v(e1,e2,e3); v.normalize(); float a = TwoPi * die(); Quaternion q(v, a); mat.setTranslate(x,y,z); mat.setRotate(q); transformCore->setMatrix(mat); NodeUnrecPtr trafo = makeNodeFor(transformCore); trafo->addChild(scene); root->addChild(trafo); } return NodeTransitPtr(root); } static NodeTransitPtr createDynamicScene() { NodeUnrecPtr scene = makeCylinder(30, 100, 16, true, true, true); return NodeTransitPtr(scene); } // // setup of the image generation stage // static void createAcquisitionStage() { size_t num_ports = win->getMFPort()->size(); if (num_ports == 0) return; UInt32 width = win->getWidth(); UInt32 height = win->getHeight(); Real32 a = Real32(width) / Real32(height); width = UInt32(a*height); Viewport* vp = staticVp; Node* internalRoot = rootNode(mgr->getRoot()); // // Setup the FBO // spSimpleFBO.reset(new SimpleFBO(width, height, true, true, true, false)); //spSimpleFBO->fbo()->setPostProcessOnDeactivate(true); //spSimpleFBO->colorBuffer(0)->setReadBack(true); // // We would like to render the scene but won't detach it from its parent. // The VisitSubTree allows just that. // VisitSubTreeUnrecPtr visitor = VisitSubTree::create(); visitor->setSubTreeRoot(internalRoot); NodeUnrecPtr visit_node = makeNodeFor(visitor); // // The stage object does provide a render target for the frame buffer attachment. // SimpleStage has a camera, a background and the left, right, top, bottom // fields to let you restrict rendering to a sub-rectangle of your FBO, i.e. // they give you a viewport. // SimpleStageUnrecPtr stage = SimpleStage::create(); stage->setRenderTarget(spSimpleFBO->fbo()); stage->setCamera (vp->getCamera()); stage->setBackground (vp->getBackground()); // // Give the stage core a place to live // NodeUnrecPtr stage_node = makeNodeFor(stage); stage_node->addChild(visit_node); // // root // | // +- SimpleStage // | // +- VisitSubTree -> ApplicationScene // NodeUnrecPtr root = makeCoredNode<Group>(); root->addChild(stage_node); // // Give the root node a place to live, i.e. create a passive // viewport and add it to the window. // ViewportUnrecPtr stage_viewport = PassiveViewport::create(); stage_viewport->setRoot (stage_node); stage_viewport->setBackground(vp->getBackground()); stage_viewport->setCamera (vp->getCamera()); win->addPort(stage_viewport); mgr->update(); win->renderNoFinish(mgr->getRenderAction()); win->frameExit(); win->deactivate (); //ImageUnrecPtr col_image = Image::create(); //col_image->set(Image::OSG_RGBA_PF, width, height); //TextureObjChunk* texObj = spSimpleFBO->colorTexObj(0); //texObj->getImage()->subImage(0, 0, 0, width, height, 1, col_image); //col_image->write("d:/my_Test_opensg.png"); win->subPortByObj(stage_viewport); } static void createDynamicViewport() { win->subPortByObj(staticVp); FBOBackgroundUnrecPtr fboBckgnd = FBOBackground::create(); fboBckgnd->setFrameBufferObject(spSimpleFBO->fbo()); NodeUnrecPtr root = makeCoredNode<Group>(); root->addChild(dynamicScene); mgr->setRoot(root); dynamicVp = Viewport::create(); dynamicVp->setRoot (rootNode(root)); dynamicVp->setBackground(fboBckgnd); dynamicVp->setCamera (camera); dynamicVp->setSize (0,0, 1,1); mgr->getNavigator()->setViewport(dynamicVp); win->addPort(dynamicVp); mgr->update(); } static void enableStaticScene() { win->subPortByObj(dynamicVp); dynamicVp = nullptr; NodeUnrecPtr root = makeCoredNode<Group>(); root->addChild(staticScene); mgr->setRoot(root); mgr->getNavigator()->setViewport(staticVp); staticVp->setCamera(camera); win->addPort(staticVp); } static Node* rootNode(Node* node) { Node* root = nullptr; while (node) { root = node; node = node->getParent(); } return root; } // // main entry point // int main(int argc, char *argv[]) { int ret = doMain(argc, argv); glutMainLoop(); cleanup(); osgExit(); return ret; } ------------------------------------------------------------------------------ _______________________________________________ Opensg-users mailing list Opensg-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensg-users