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

Reply via email to