void VarianceShadowMapHandler::configureShadowMaps(void)
{
    ShadowStageData::ShadowMapStore &vShadowMaps = _pStageData->getShadowMaps();

    UInt32 uiSHMSize = vShadowMaps.size();

    UInt32 uiMapSize = _pStage-> getMapSize ();

    Real32 maximumAnistropy;

    glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maximumAnistropy);

    maximumAnistropy = osgMin(maximumAnistropy, Real32(8.0));

    for(UInt32 i = 0; i < uiSHMSize; ++i)
    {
        if(vShadowMaps[i].uiType == 
                                ShadowStageData::ShadowMapElem::DepthShadowMap)
        {
            vShadowMaps[i].pTexO->setCompareMode(GL_NONE);

            vShadowMaps[i].pTexO->setMinFilter     (GL_LINEAR_MIPMAP_LINEAR);
            vShadowMaps[i].pTexO->setMagFilter     (GL_LINEAR              );

            vShadowMaps[i].pTexO->setInternalFormat(GL_RGBA16F_ARB);
            vShadowMaps[i].pTexO->setExternalFormat(GL_RGBA);

            vShadowMaps[i].pTexO->setAnisotropy    (maximumAnistropy       );

            vShadowMaps[i].pTexO->setWrapS         (GL_REPEAT              );
            vShadowMaps[i].pTexO->setWrapT         (GL_REPEAT              );


            vShadowMaps[i].pImage->set(Image::OSG_RGBA_PF, 
                                uiMapSize, uiMapSize, 1,
                                1, 1, 0.f, 
                                NULL,
                                Image::OSG_FLOAT16_IMAGEDATA,
                                false);

            vShadowMaps[i].pFBO->setColorAttachment(
                vShadowMaps[i].pFBO->getDepthAttachment(), 0);


            RenderBufferUnrecPtr pDepthRB = RenderBuffer::createLocal();
            
            pDepthRB->setInternalFormat(GL_DEPTH_COMPONENT24);

            vShadowMaps[i].pFBO->setDepthAttachment(pDepthRB);

            vShadowMaps[i].pFBO->setSize(uiMapSize, uiMapSize);

            vShadowMaps[i].uiType = 
                                ShadowStageData::ShadowMapElem::ColorShadowMap;

        }
    }

    _bShadowMapsConfigured = true;
}
void VarianceShadowMapHandler::initShadowMaps(void)
{
    ShadowStageData::ShadowMapStore &vShadowMaps = _pStageData->getShadowMaps();

    const ShadowStageData::LightStore  &vLights  = _pStageData->getLights();


    if(vLights.size() < vShadowMaps.size())
    {
        vShadowMaps.resize(vLights.size());
    }
    else
    {
        Real32 maximumAnistropy;

        glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maximumAnistropy);

        maximumAnistropy = osgMin(maximumAnistropy, Real32(8.0));


        UInt32 uiLSize   =  vLights.size();
        UInt32 uiMapSize = _pStage-> getMapSize ();

        if(vShadowMaps.size() == 0) 
        {
            _uiMapSize = uiMapSize;
        }

        for(UInt32 i = vShadowMaps.size(); i < uiLSize; ++i)
        {
            ShadowStageData::ShadowMapElem tmpElem;

            tmpElem.uiType = ShadowStageData::ShadowMapElem::ColorShadowMap;

            tmpElem.pImage = Image            ::createLocal();
            tmpElem.pTexO  = TextureObjChunk  ::createLocal();
            tmpElem.pTexE  = TextureEnvChunk  ::createLocal();
            tmpElem.pFBO   = FrameBufferObject::createLocal();

            tmpElem.pImage->set(Image::OSG_RGBA_PF, 
                                uiMapSize, uiMapSize, 1,
                                1, 1, 0.f, 
                                NULL,
                                Image::OSG_FLOAT16_IMAGEDATA,
                                false);

            TextureBufferUnrecPtr pDepthTex = TextureBuffer::createLocal();

            pDepthTex->setTexture(tmpElem.pTexO);

            tmpElem.pFBO ->setColorAttachment(pDepthTex, 0);

            tmpElem.pTexO->setImage(tmpElem.pImage);

            tmpElem.pTexO->setInternalFormat(GL_RGBA16F_ARB);
            tmpElem.pTexO->setExternalFormat(GL_RGBA);

            tmpElem.pTexO->setMinFilter     (GL_LINEAR_MIPMAP_LINEAR);
            tmpElem.pTexO->setMagFilter     (GL_LINEAR              );

            tmpElem.pTexO->setAnisotropy    (maximumAnistropy       );

            tmpElem.pTexO->setWrapS         (GL_REPEAT              );
            tmpElem.pTexO->setWrapT         (GL_REPEAT              );

            tmpElem.pTexO->setTarget(GL_TEXTURE_2D);



            RenderBufferUnrecPtr pDepthRB = RenderBuffer::create();
            
            pDepthRB->setInternalFormat(GL_DEPTH_COMPONENT24);

            tmpElem.pFBO->setDepthAttachment(pDepthRB);

            tmpElem.pFBO->setSize(uiMapSize, uiMapSize);


            vShadowMaps.push_back(tmpElem);
        }
    }
}
示例#3
0
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);
}
HDRStageDataTransitPtr HDRStage::setupStageData(Int32 iPixelWidth,
                                                Int32 iPixelHeight)
{
    HDRStageDataTransitPtr returnValue = HDRStageData::createLocal();

    if(returnValue == NULL)
        return returnValue;

    OSG::Thread::setCurrentLocalFlags();

    // Scene Target

    FrameBufferObjectUnrecPtr pSceneFBO    = FrameBufferObject::createLocal();

    RenderBufferUnrecPtr      pDepthBuffer = RenderBuffer     ::createLocal();

    pDepthBuffer->setInternalFormat(GL_DEPTH_COMPONENT24   );

        
    TextureObjChunkUnrecPtr pSceneTex     = TextureObjChunk::createLocal();
    TextureEnvChunkUnrecPtr pSceneTexEnv  = TextureEnvChunk::createLocal();
    ImageUnrecPtr           pImg          = Image          ::createLocal();
    
    pImg->set(Image::OSG_RGB_PF, 
              iPixelWidth, 
              iPixelHeight,
              1,
              1,
              1,
              0.0,
              0,
              Image::OSG_FLOAT32_IMAGEDATA,
              false);
    
    pSceneTex   ->setImage         (pImg             ); 
    pSceneTex   ->setMinFilter     (GL_LINEAR        );
    pSceneTex   ->setMagFilter     (GL_LINEAR        );
    pSceneTex   ->setWrapS         (GL_CLAMP_TO_EDGE );
    pSceneTex   ->setWrapT         (GL_CLAMP_TO_EDGE );
    pSceneTex   ->setInternalFormat(getBufferFormat());

    pSceneTexEnv->setEnvMode       (GL_REPLACE       );
    
    TextureBufferUnrecPtr pSceneTexBuffer   = TextureBuffer::createLocal();
    
    pSceneTexBuffer->setTexture(pSceneTex);
    

    
    pSceneFBO->setSize(iPixelWidth, iPixelHeight);
    
    pSceneFBO->setColorAttachment(pSceneTexBuffer, 0);
    pSceneFBO->setDepthAttachment(pDepthBuffer      );
    
    pSceneFBO->editMFDrawBuffers()->push_back(GL_COLOR_ATTACHMENT0_EXT);
    
    setRenderTarget(pSceneFBO);
    



    // Shrink Target (w/2, h/2)

    FrameBufferObjectUnrecPtr pShrinkFBO     = FrameBufferObject::createLocal();

    TextureObjChunkUnrecPtr   pShrinkTex     = TextureObjChunk::createLocal();
    TextureEnvChunkUnrecPtr   pShrinkTexEnv  = TextureEnvChunk::createLocal();
                              pImg           = Image          ::createLocal();
    
    pImg->set(Image::OSG_RGB_PF, 
              iPixelWidth  / 2, 
              iPixelHeight / 2,
              1,
              1,
              1,
              0.0,
              0,
              Image::OSG_FLOAT32_IMAGEDATA,
              false);
    
    pShrinkTex   ->setImage         (pImg             ); 
    pShrinkTex   ->setMinFilter     (GL_LINEAR        );
    pShrinkTex   ->setMagFilter     (GL_LINEAR        );
    pShrinkTex   ->setWrapS         (GL_CLAMP_TO_EDGE );
    pShrinkTex   ->setWrapT         (GL_CLAMP_TO_EDGE );
    pShrinkTex   ->setInternalFormat(getBufferFormat());

    pShrinkTexEnv->setEnvMode       (GL_REPLACE       );
    
    TextureBufferUnrecPtr pShrinkTexBuffer   = TextureBuffer::createLocal();
    
    pShrinkTexBuffer->setTexture(pShrinkTex);
    

    
    pShrinkFBO->setSize(iPixelWidth / 2, iPixelHeight / 2);
    
    pShrinkFBO->setColorAttachment(pShrinkTexBuffer, 0);
    
    pShrinkFBO->editMFDrawBuffers()->push_back(GL_COLOR_ATTACHMENT0_EXT);
    
    returnValue->setShrinkRenderTarget(pShrinkFBO);





    // blur (w/4, h/4)


    FrameBufferObjectUnrecPtr pBlurFBO     = FrameBufferObject::createLocal();

    TextureObjChunkUnrecPtr   pBlurTex1    = TextureObjChunk  ::createLocal();
    TextureEnvChunkUnrecPtr   pBlurTex1Env = TextureEnvChunk  ::createLocal();
    
    
    pImg = Image::createLocal();
    
    pImg->set(Image::OSG_RGB_PF, 
              iPixelWidth  / 4,
              iPixelHeight / 4,
              1,
              1,
              1,
              0.0,
              0,
              Image::OSG_FLOAT32_IMAGEDATA,
              false);
    
    pBlurTex1   ->setImage         (pImg             ); 
    pBlurTex1   ->setMinFilter     (GL_LINEAR        );
    pBlurTex1   ->setMagFilter     (GL_LINEAR        );
    pBlurTex1   ->setWrapS         (GL_CLAMP_TO_EDGE );
    pBlurTex1   ->setWrapT         (GL_CLAMP_TO_EDGE );
    pBlurTex1   ->setInternalFormat(getBufferFormat());

    pBlurTex1Env->setEnvMode       (GL_REPLACE       );
    
    TextureBufferUnrecPtr pBlurTexBuffer1 = TextureBuffer::createLocal();
    
    pBlurTexBuffer1->setTexture(pBlurTex1);
    
    
    
    TextureObjChunkUnrecPtr pBlurTex2    = TextureObjChunk::createLocal();
    TextureEnvChunkUnrecPtr pBlurTex2Env = TextureEnvChunk::createLocal();
    
    
    pImg = Image::createLocal();

    pImg->set(Image::OSG_RGB_PF, 
              iPixelWidth  / 4,
              iPixelHeight / 4,
              1,
              1,
              1,
              0.0,
              0,
              Image::OSG_FLOAT32_IMAGEDATA,
              false);
    
    pBlurTex2   ->setImage         (pImg             ); 
    pBlurTex2   ->setMinFilter     (GL_LINEAR        );
    pBlurTex2   ->setMagFilter     (GL_LINEAR        );
    pBlurTex2   ->setWrapS         (GL_CLAMP_TO_EDGE );
    pBlurTex2   ->setWrapT         (GL_CLAMP_TO_EDGE );
    pBlurTex2   ->setInternalFormat(getBufferFormat());

    pBlurTex2Env->setEnvMode       (GL_REPLACE       );
    
    TextureBufferUnrecPtr pBlurTexBuffer2 = TextureBuffer::createLocal();

    pBlurTexBuffer2->setTexture(pBlurTex2);


    pBlurFBO->setSize(iPixelWidth  / 4,
                      iPixelHeight / 4);
    
    pBlurFBO->setColorAttachment(pBlurTexBuffer1,  0);
    pBlurFBO->setColorAttachment(pBlurTexBuffer2,  1);
    
    returnValue->setBlurRenderTarget(pBlurFBO);


    // general mat chunk


    MaterialChunkUnrecPtr pMatChunk = MaterialChunk::createLocal();
        
    pMatChunk->setLit(false);




    // tone map material

    ChunkMaterialUnrecPtr    pTonemapMat  = ChunkMaterial  ::createLocal();
    
    pTonemapMat->addChunk(pMatChunk         );
    pTonemapMat->addChunk(pSceneTex,       0);
    pTonemapMat->addChunk(pSceneTexEnv,    0);
    pTonemapMat->addChunk(pBlurTex1,       1);
    pTonemapMat->addChunk(pBlurTex1Env,    1);

    SimpleSHLChunkUnrecPtr pTonemapShader = generateHDRFragmentProgram();
    
    pTonemapShader->addUniformVariable("sceneTex",     0);
    pTonemapShader->addUniformVariable("blurTex",      1);
    pTonemapShader->addUniformVariable("blurAmount",   getBlurAmount  ());
    pTonemapShader->addUniformVariable("exposure",     getExposure    ());
    pTonemapShader->addUniformVariable("effectAmount", getEffectAmount());
    pTonemapShader->addUniformVariable("gamma",        getGamma       ());
    
    pTonemapMat->addChunk(pTonemapShader, 0);
    
    returnValue->setToneMappingMaterial(pTonemapMat);




    // Shrink material

    ChunkMaterialUnrecPtr pShrinkMat = ChunkMaterial::createLocal();
    
    pShrinkMat->addChunk(pMatChunk   );
    
    pShrinkMat->addChunk(pSceneTex,     0);
    pShrinkMat->addChunk(pSceneTexEnv,  0);

    SimpleSHLChunkUnrecPtr pShrinkShader = generate2DShrinkHalfFilterFP();
        
    pShrinkShader->addUniformVariable("inputTex", 0);
    
    pShrinkMat->addChunk(pShrinkShader, 0);
    
    returnValue->setShrinkMaterial(pShrinkMat);




    // Blur material

    ChunkMaterialUnrecPtr pBlurMat = ChunkMaterial::createLocal();
    
    pBlurMat->addChunk(pMatChunk   );
    
    pBlurMat->addChunk(pShrinkTex,    0);
    pBlurMat->addChunk(pShrinkTexEnv, 0);
    pBlurMat->addChunk(pBlurTex1,     1);
    pBlurMat->addChunk(pBlurTex1Env,  1);
    pBlurMat->addChunk(pBlurTex2,     2);
    pBlurMat->addChunk(pBlurTex2Env,  2);

    pBlurMat->addChunk(pShrinkShader, 0);
    
    returnValue->setBlurMaterial(pBlurMat);


    // generate blur fragment programs
    SimpleSHLChunkUnrecPtr pHBlurShader = 
        generate1DConvolutionFilterFP(getBlurWidth(), 
                                      false, 
                                      true, 
                                      iPixelWidth  / 2, 
                                      iPixelHeight / 2);
    
   
    pHBlurShader->addUniformVariable("inputTex", 0);

    returnValue->setHBlurShader(pHBlurShader);

    
    
    // VBlur Override


    SimpleSHLChunkUnrecPtr pVBlurShader = 
        generate1DConvolutionFilterFP(getBlurWidth(),  
                                      true, 
                                      true, 
                                      iPixelWidth  / 2, 
                                      iPixelHeight / 2);
    
    pVBlurShader->addUniformVariable("inputTex", 1);
    
    returnValue->setVBlurShader(pVBlurShader);

    OSG::Thread::resetCurrentLocalFlags();

    Thread::getCurrentChangeList()->commitChanges();

    return returnValue;
}
示例#5
0
//
// FBO solution
//
static void writeHiResScreenShotFBO(const char* name, UInt32 width, UInt32 height)
{
    size_t num_ports = win->getMFPort()->size();
    if (num_ports == 0)
        return;
    //
    // calc image dimensions
    //
    UInt32 winWidth  = win->getWidth();
    UInt32 winHeight = win->getHeight();

    if (width  < winWidth ) width  = winWidth;
    if (height < winHeight) height = winHeight;

    Real32 a = Real32(winWidth) / Real32(winHeight);
    width = UInt32(a*height);

    //
    // output stream for writing the final image
    //
    std::ofstream stream(name, std::ios::binary);
    if (stream.good() == false)
        return;

    //
    // Setup the FBO
    //
    FrameBufferObjectUnrecPtr fbo = FrameBufferObject::create();
    //
    // We use two render buffers. One for the color buffer and one for the depth and
    // stencil buffer. This example does not take credit of the stencil buffer. There-
    // fore a depth buffer would suffice. However, the use of the combined depth and
    // stencil buffer is useful in other contextes and hence used.
    //
    RenderBufferUnrecPtr colBuf = RenderBuffer::create();
    RenderBufferUnrecPtr  dsBuf = RenderBuffer::create();
    //
    // As we would like to read back the FBO color buffer, we must provide a fitting
    // image.
    //
    ImageUnrecPtr buffer_image = Image::create();
    buffer_image->set(Image::OSG_RGBA_PF, winWidth, winHeight);
    colBuf->setImage(buffer_image);
    //
    // We must setup the internal image formats of the two render buffers accordingly.
    //
    colBuf->setInternalFormat(GL_RGBA);
    dsBuf ->setInternalFormat(GL_DEPTH24_STENCIL8_EXT);
    //
    // we must inform the FBO about the actual used color render buffers.
    //
    fbo->editMFDrawBuffers()->push_back(GL_COLOR_ATTACHMENT0_EXT);
    //
    // The FBO takes responsibility of the render buffers. Notice, that the shared
    // depth/stencil buffer is provided twice. As the depth render buffer and as the
    // stencil render buffer.
    //
    fbo->setColorAttachment  (colBuf, 0);
    fbo->setDepthAttachment  (dsBuf);
    fbo->setStencilAttachment(dsBuf);
    //
    // Also the FBO must be sized correctly.
    //
    fbo->setWidth (winWidth );
    fbo->setHeight(winHeight);
    //
    // In order to read the color buffer back next two statements are necessary.
    //
    fbo->setPostProcessOnDeactivate(true);
    fbo->getColorAttachments(0)->setReadBack(true);

    //
    // We tile the final image and render each tile with the screen resolution
    // into the FBO. The more tiles we use the bigger the resolution of the
    // final image gets with respect to a provided measure of length.
    //
    typedef boost::tuple<TileCameraDecoratorUnrecPtr, bool, SimpleStageUnrecPtr, ViewportUnrecPtr> TupleT;
    std::vector<TupleT> decorators;
    decorators.resize(num_ports);

    //
    // Remember the stage viewports for later cleanup
    //
    std::stack<ViewportUnrecPtr> stage_viewports;

    //
    // Setup the tile camera decorators for each viewport of the window and
    // disable the tile property of tileable viewport backgrounds.
    //
    for (size_t i = 0; i < num_ports; ++i) {
        Viewport* vp = win->getPort(i);

        TileCameraDecoratorUnrecPtr decorator = TileCameraDecorator::create();

        decorator->setFullSize (width, height);
        decorator->setDecoratee(vp->getCamera());

        vp->setCamera(decorator);

        bool bTiled = false;
        TileableBackground* tbg = dynamic_cast<TileableBackground*>(vp->getBackground());
        if (tbg) {
            bTiled = tbg->getTile();
            tbg->setTile(false);
        }

        //
        // The scene manager root node does not provide the illumination of the
        // scene. This is governed internally by the manager. However, to take
        // credit of the illumination we scan to the final parent of the scene
        // graph.
        //
        Node* internalRoot = rootNode(mgr->getRoot());
        //
        // 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);
        //
        // We clone the camera of the first viewport and do not swap the buffer on later
        // rendering. This way the image generation process is not noticable in the
        // window.
        //
        CameraUnrecPtr camera = dynamic_pointer_cast<Camera>(vp->getCamera()->shallowCopy());
        //
        // 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(fbo);
        stage->setCamera      (decorator);
        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      (root);
        stage_viewport->setBackground(vp->getBackground());
        stage_viewport->setCamera    (camera);

        win->addPort(stage_viewport);

        //
        // remember the decorator, the background tile prop setting and the stage setup
        //
        decorators[i] = boost::make_tuple(decorator, bTiled, stage, stage_viewport);
    }

    //
    // We write the image in simple ppm format. This one starts with a description
    // header which we output once on first write.
    //
    bool write_header = true;

    //
    // Calc the max y start position (width). We process the tiles from bottom
    // up and from left tp right as determined by the image format.
    //
    UInt32 yPosLast = 0;
    for (; yPosLast < height-winHeight; yPosLast += winHeight);

    //
    // Process from bottom to top
    //
    for (Int32 yPos = yPosLast; yPos >= 0; yPos -= winHeight)
    {
        UInt32 ySize = std::min(winHeight, height - yPos);

        //
        // Collect the tile images for each row, i.e. we write the
        // image in row manner to disk. This way the main memory is
        // only moderately stressed.
        //
        std::vector<ImageUnrecPtr> vecColImages;

        //
        // Process from left to right
        //
        for (UInt32 xPos = 0; xPos < width; xPos += winWidth)
        {
            UInt32 xSize = std::min(winWidth, width - xPos);
            //
            // The current tile image
            //
            ImageUnrecPtr col_image = Image::create();
            col_image->set(Image::OSG_RGBA_PF, xSize, ySize);
            //
            // Adapt the tile camera decorator boxes to the current tile
            //
            for (size_t i = 0; i < num_ports; ++i)
            {
                //
                // this tile does not fill the whole FBO - adjust to only render
                // to a part of it
                //
                decorators[i].get<2>()->setLeft  (0.f);
                decorators[i].get<2>()->setRight (xSize / float(winWidth));
                decorators[i].get<2>()->setBottom(0.f);
                decorators[i].get<2>()->setTop   (ySize / float(winHeight));

                TileCameraDecorator* decorator = decorators[i].get<0>();

                decorator->setSize( xPos / float(width),
                                    yPos / float(height),
                          (xPos + xSize) / float(width),
                          (yPos + ySize) / float(height) );

            }
            //
            // render the tile
            //
            mgr->update();
            win->renderNoFinish(mgr->getRenderAction());
            win->frameExit();
            win->deactivate ();

            //
            // Copy the image into the tile image stored for later processing
            //
            if(fbo)
            {
                RenderBuffer* grabber = dynamic_cast<RenderBuffer*>(fbo->getColorAttachments(0));

                if(grabber)
                {
                    grabber->getImage()->subImage(0, 0, 0, xSize, ySize, 1, col_image);
                }
            }

            vecColImages.push_back(col_image);
        }

        //
        // Write the image format header once
        //
        if (write_header) {
            write_header = false;
            if (!writePNMImagesHeader(vecColImages, width, height, stream)) break;
        }
        //
        // Write the current column
        //
        if (!writePNMImagesData(vecColImages, stream)) break;
        //
        // Forget the current column images
        //
        vecColImages.clear();
    }

    //
    // restore window and cleanup
    //
    for (size_t i = 0; i < num_ports; ++i) {
        win->subPortByObj(decorators[i].get<3>());

        Viewport* vp = win->getPort(i);
        vp->setCamera(decorators[i].get<0>()->getDecoratee());
        vp->setSize(0, 0, 1, 1);

        TileableBackground* tbg = dynamic_cast<TileableBackground*>(vp->getBackground());
        if (tbg)
            tbg->setTile(decorators[i].get<1>());
    }
}
CubeMapGeneratorStageDataTransitPtr CubeMapGenerator::setupStageData(
    RenderActionBase *pAction)
{
    CubeMapGeneratorStageDataTransitPtr returnValue = 
        CubeMapGeneratorStageData::createLocal();
    
    if(returnValue == NULL)
        return returnValue;

    FrameBufferObjectUnrecPtr pCubeTarget  = NULL;
    RenderBufferUnrecPtr      pDepthBuffer = NULL;

    if(this->getRenderTarget() == NULL)
    {
        pCubeTarget  = FrameBufferObject::createLocal();
        pDepthBuffer = RenderBuffer     ::createLocal();

        pDepthBuffer->setInternalFormat (GL_DEPTH_COMPONENT24);

        pCubeTarget ->setDepthAttachment(pDepthBuffer        );

        returnValue ->setRenderTarget   (pCubeTarget         );
    }
    else
    {
        pCubeTarget = this->getRenderTarget();
    }

    TextureObjChunkUnrecPtr   pCubeTex     = NULL;

    if(0x0000 != (_sfSetupMode.getValue() & SetupTexture))
    {
        pCubeTex = TextureObjChunk::createLocal();

        ImageUnrecPtr pImg = Image::createLocal();
    
        pImg->set(Image::OSG_RGB_PF, 
                  getWidth (), 
                  getHeight(),
                  1,
                  1,
                  1,
                  0.0,
                  0,
                  Image::OSG_UINT8_IMAGEDATA,
                  false,
                  6);
        
        pCubeTex   ->setImage         (pImg              ); 
        pCubeTex   ->setMinFilter     (GL_LINEAR         );
        pCubeTex   ->setMagFilter     (GL_LINEAR         );
        pCubeTex   ->setWrapS         (GL_CLAMP_TO_EDGE  );
        pCubeTex   ->setWrapT         (GL_CLAMP_TO_EDGE  );
        pCubeTex   ->setWrapR         (GL_CLAMP_TO_EDGE  );
        pCubeTex   ->setInternalFormat(getTextureFormat());
    }
    else
    {
        pCubeTex = _sfTexture.getValue();
    }

    TextureEnvChunkUnrecPtr pCubeTexEnv  = NULL;

    if(0x0000 != (_sfSetupMode.getValue() & SetupTexEnv))
    {
        pCubeTexEnv = TextureEnvChunk::createLocal();
        
        pCubeTexEnv->setEnvMode       (GL_REPLACE       );
    }

    TexGenChunkUnrecPtr           pCubeTexGen   = NULL;
    TextureTransformChunkUnrecPtr pCubeTexTrans = NULL;

    if(0x0000 != (_sfSetupMode.getValue() & SetupTexGen))
    {
        pCubeTexGen = TexGenChunk::createLocal();

        pCubeTexGen->setGenFuncS(GL_REFLECTION_MAP);
        pCubeTexGen->setGenFuncT(GL_REFLECTION_MAP);
        pCubeTexGen->setGenFuncR(GL_REFLECTION_MAP);

        pCubeTexTrans = TextureTransformChunk::createLocal();

        pCubeTexTrans->setUseCameraBeacon(true);
    }


    static GLenum targets[6] = 
    {
        GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
        GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
        GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
        GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
        GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
        GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
    };

    for(UInt32 i = 0; i < 6; ++i)
    {
        TextureBufferUnrecPtr pCubeTexBuffer = TextureBuffer::createLocal();
    
        pCubeTexBuffer->setTexture  (pCubeTex  );
        pCubeTexBuffer->setTexTarget(targets[i]);

        pCubeTarget->setColorAttachment(pCubeTexBuffer,    i);
    }

    pCubeTarget->setSize(getWidth (),
                         getHeight());

    if(0x0000 != (_sfSetupMode.getValue() & OverrideTex))
    {
        returnValue->addChunk(pCubeTex,
                              getTexUnit());
    }

    if(0x0000 != (_sfSetupMode.getValue() & SetupTexEnv))
    {
        returnValue->addChunk(pCubeTexEnv,
                              getTexUnit());
    }

    if(0x0000 != (_sfSetupMode.getValue() & SetupTexGen))
    {
        returnValue->addChunk(pCubeTexGen,
                              getTexUnit());
        returnValue->addChunk(pCubeTexTrans,
                              getTexUnit());

        returnValue->setTexTransform(pCubeTexTrans);
    }

    if(this->getCamera() == NULL)
    {
        PerspectiveCameraUnrecPtr pCam = PerspectiveCamera::createLocal();

        pCam->setNear(pAction->getCamera()->getNear());
        pCam->setFar (pAction->getCamera()->getFar ());
        
        pCam->setFov (osgDegree2Rad(90.f));

        returnValue->setCamera(pCam);
    }

    return returnValue;
}
DisplayFilterStageDataTransitPtr 
    DisplayFilterStage::setupStageData(Int32 iPixelWidth,
                                       Int32 iPixelHeight)
{
    DisplayFilterStageDataTransitPtr returnValue = 
        DisplayFilterStageData::createLocal();

    if(returnValue == NULL)
        return returnValue;

    // Scene Buffer

    FrameBufferObjectUnrecPtr pFBO     = FrameBufferObject::createLocal();
    RenderBufferUnrecPtr      pDBuffer = RenderBuffer     ::createLocal();
    TextureBufferUnrecPtr     pTBuffer = TextureBuffer    ::createLocal();

    TextureObjChunkUnrecPtr   pTex     = TextureObjChunk  ::createLocal();
    ImageUnrecPtr             pImg     = Image            ::createLocal();

    pImg->set(Image::OSG_RGB_PF, 
              iPixelWidth, 
              iPixelHeight,
              1,
              1,
              1,
              0.0,
              0,
              Image::OSG_UINT8_IMAGEDATA,
              false);
    
    pTex    ->setImage         (pImg             ); 
    pTex    ->setMinFilter     (GL_NEAREST       );
    pTex    ->setMagFilter     (GL_NEAREST       );
    pTex    ->setWrapS         (GL_CLAMP_TO_EDGE );
    pTex    ->setWrapT         (GL_CLAMP_TO_EDGE );
    
    pTBuffer->setTexture(pTex);

    pDBuffer->setInternalFormat(GL_DEPTH_COMPONENT24);
 

    pFBO->setSize(iPixelWidth, iPixelHeight);
    
    pFBO->setColorAttachment(pTBuffer, 0);
    pFBO->setDepthAttachment(pDBuffer   );

    pFBO->editMFDrawBuffers()->push_back(GL_COLOR_ATTACHMENT0_EXT);


    pFBO->setEnableMultiSample  (this->getEnableMultiSample  ());
    pFBO->setColorSamples       (this->getColorSamples       ());
    pFBO->setCoverageSamples    (this->getCoverageSamples    ());
    pFBO->setFixedSampleLocation(this->getFixedSampleLocation());

    returnValue->setTarget(pFBO);


    ChunkMaterialUnrecPtr pCMat = ChunkMaterial::createLocal();

    pCMat->addChunk(pTex);

    returnValue->setBaseMaterial(pCMat);

    returnValue->setWidth (iPixelWidth );
    returnValue->setHeight(iPixelHeight);

    commitChanges();

    return returnValue;
}