]> git.mxchange.org Git - flightgear.git/blobdiff - src/Viewer/renderer.cxx
Prepare and implement reinit methods for instruments
[flightgear.git] / src / Viewer / renderer.cxx
index 4884e157e7de3dc52340f3ff629bcc508dd562b5..24f3f1d1894b0f12454c76745fee55df338b150c 100644 (file)
@@ -74,6 +74,7 @@
 #include <simgear/scene/model/animation.hxx>
 #include <simgear/scene/model/placement.hxx>
 #include <simgear/scene/sky/sky.hxx>
+#include <simgear/scene/util/DeletionManager.hxx>
 #include <simgear/scene/util/SGUpdateVisitor.hxx>
 #include <simgear/scene/util/RenderConstants.hxx>
 #include <simgear/scene/util/SGSceneUserData.hxx>
@@ -383,25 +384,6 @@ static osg::ref_ptr<osg::Group> mDeferredRealRoot = new osg::Group;
 
 static osg::ref_ptr<osg::Group> mRoot = new osg::Group;
 
-static osg::ref_ptr<osg::Switch> panelSwitch;
-                                    
-                                    
-// update callback for the switch node controlling the 2D panel
-class FGPanelSwitchCallback : public osg::NodeCallback {
-public:
-    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
-    {
-        assert(dynamic_cast<osg::Switch*>(node));
-        osg::Switch* sw = static_cast<osg::Switch*>(node);
-        
-        bool enabled = fgPanelVisible();
-        sw->setValue(0, enabled);
-        if (!enabled)
-            return;
-        traverse(node, nv);
-    }
-};
-
 #ifdef FG_JPEG_SERVER
 static void updateRenderer()
 {
@@ -528,8 +510,8 @@ FGRenderer::init( void )
     _useColorForDepth = fgGetBool( "/sim/rendering/rembrandt/use-color-for-depth", false );
     _depthInColor->set( _useColorForDepth );
 
-    _renderer         = fgGetString("/sim/rendering/rembrandt/renderer", "");
-    if (!_classicalRenderer && !_renderer.empty())
+    _renderer         = fgGetString("/sim/rendering/rembrandt/renderer", "default-pipeline");
+    if (!_classicalRenderer)
         _pipeline = makeRenderingPipeline(_renderer, 0);
     _scenery_loaded   = fgGetNode("/sim/sceneryloaded", true);
     _scenery_override = fgGetNode("/sim/sceneryloaded-override", true);
@@ -595,6 +577,7 @@ FGRenderer::init( void )
 
     if (!_classicalRenderer) {
         eventHandler->setChangeStatsCameraRenderOrder( true );
+        _sky->set_minimum_sky_visibility( 0.0 ); // A black sky appears for below that
     }
 }
 
@@ -687,7 +670,7 @@ FGRenderer::buildClassicalPipeline(CameraGroup* cgroup, unsigned flags, osg::Cam
     cgroup->getViewer()->addSlave(camera, projection, view, useMasterSceneData);
     installCullVisitor(camera);
     int slaveIndex = cgroup->getViewer()->getNumSlaves() - 1;
-       info->addCamera( MAIN_CAMERA, camera, slaveIndex );
+    info->addCamera( MAIN_CAMERA, camera, slaveIndex );
     camera->setRenderOrder(Camera::POST_RENDER, slaveIndex);
     cgroup->addCamera(info);
     return info;
@@ -720,12 +703,11 @@ public:
         cv->traverse( *camera );
 
         if ( kind == GEOMETRY_CAMERA ) {
-            // Save transparent bins to render later
+            // Remove transparent bins. They will be renderer in the additional light stage (side effect)
             osgUtil::RenderStage* renderStage = cv->getRenderStage();
             osgUtil::RenderBin::RenderBinList& rbl = renderStage->getRenderBinList();
             for (osgUtil::RenderBin::RenderBinList::iterator rbi = rbl.begin(); rbi != rbl.end(); ) {
                 if (rbi->second->getSortMode() == osgUtil::RenderBin::SORT_BACK_TO_FRONT) {
-                    info->savedTransparentBins.insert( std::make_pair( rbi->first, rbi->second ) );
                     rbl.erase( rbi++ );
                 } else {
                     ++rbi;
@@ -738,27 +720,17 @@ public:
                 for (int i = 0; i < 4; ++i ) {
                     if (!grp->getValue(i))
                         continue;
-                    osg::TexGen* shadowTexGen = info->shadowTexGen[i];
-                    shadowTexGen->setMode(osg::TexGen::EYE_LINEAR);
 
                     osg::Camera* cascadeCam = static_cast<osg::Camera*>( grp->getChild(i) );
-                    // compute the matrix which takes a vertex from view coords into tex coords
-                    shadowTexGen->setPlanesFromMatrix(  cascadeCam->getProjectionMatrix() *
-                                                        osg::Matrix::translate(1.0,1.0,1.0) *
-                                                        osg::Matrix::scale(0.5f,0.5f,0.5f) );
+                    osg::Matrixf shadowMatrix = camera->getInverseViewMatrix() *
+                                                cascadeCam->getViewMatrix() *
+                                                cascadeCam->getProjectionMatrix() *
+                                                osg::Matrix::translate(1.0, 1.0, 1.0) *
+                                                osg::Matrix::scale(0.5f, 0.5f, 0.5f);
 
-                    osg::RefMatrix * refMatrix = new osg::RefMatrix( cascadeCam->getInverseViewMatrix() * *cv->getModelViewMatrix() );
-
-                    cv->getRenderStage()->getPositionalStateContainer()->addPositionedTextureAttribute( i+1, refMatrix, shadowTexGen );
+                    info->shadowMatrix[i]->set( shadowMatrix );
                 }
             }
-            // Render saved transparent render bins
-            osgUtil::RenderStage* renderStage = cv->getRenderStage();
-            osgUtil::RenderBin::RenderBinList& rbl = renderStage->getRenderBinList();
-            for (osgUtil::RenderBin::RenderBinList::iterator rbi = info->savedTransparentBins.begin(); rbi != info->savedTransparentBins.end(); ++rbi ){
-                rbl.insert( std::make_pair( rbi->first + 10000, rbi->second ) );
-            }
-            info->savedTransparentBins.clear();
         }
     }
 
@@ -787,44 +759,12 @@ osg::Texture2D* buildDeferredBuffer(GLint internalFormat, GLenum sourceFormat, G
        return tex;
 }
 
-void buildDefaultDeferredBuffers( CameraInfo* info, int shadowMapSize, bool useColorForDepth )
-{
-    if (useColorForDepth) {
-        info->addBuffer("real-depth", buildDeferredBuffer( GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT, osg::Texture::CLAMP_TO_BORDER) );
-        info->addBuffer("depth", buildDeferredBuffer( GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, osg::Texture::CLAMP_TO_BORDER) );
-    }
-    else {
-        info->addBuffer("depth", buildDeferredBuffer( GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT, osg::Texture::CLAMP_TO_BORDER) );
-    }
-    info->addBuffer("normal", buildDeferredBuffer( GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, osg::Texture::CLAMP_TO_BORDER) );
-    info->addBuffer("diffuse", buildDeferredBuffer( GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, osg::Texture::CLAMP_TO_BORDER) );
-    info->addBuffer("spec-emis", buildDeferredBuffer( GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, osg::Texture::CLAMP_TO_BORDER) );
-    info->addBuffer("lighting", buildDeferredBuffer( GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, osg::Texture::CLAMP_TO_BORDER) );
-    info->addBuffer("shadow", buildDeferredBuffer( GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT, osg::Texture::CLAMP_TO_BORDER, true), 0.0f );
-    info->getBuffer("shadow")->setTextureSize(shadowMapSize,shadowMapSize);
-}
-
 void attachBufferToCamera( CameraInfo* info, osg::Camera* camera, osg::Camera::BufferComponent c, const std::string& ck, const std::string& bk )
 {
     camera->attach( c, info->getBuffer(bk) );
     info->getRenderStageInfo(ck).buffers.insert( std::make_pair( c, bk ) );
 }
 
-osg::Camera* FGRenderer::buildDefaultDeferredGeometryCamera( CameraInfo* info, osg::GraphicsContext* gc )
-{
-    std::vector<ref_ptr<FGRenderingPipeline::Attachment> > attachments;
-    if (_useColorForDepth) {
-        attachments.push_back(new FGRenderingPipeline::Attachment(osg::Camera::DEPTH_BUFFER, "real-depth") );
-        attachments.push_back(new FGRenderingPipeline::Attachment(osg::Camera::COLOR_BUFFER3, "depth") );
-    } else {
-        attachments.push_back(new FGRenderingPipeline::Attachment(osg::Camera::DEPTH_BUFFER, "depth") );
-    }
-    attachments.push_back(new FGRenderingPipeline::Attachment(osg::Camera::COLOR_BUFFER0, "normal") );
-    attachments.push_back(new FGRenderingPipeline::Attachment(osg::Camera::COLOR_BUFFER1, "diffuse") );
-    attachments.push_back(new FGRenderingPipeline::Attachment(osg::Camera::COLOR_BUFFER2, "spec-emis") );
-    return buildDeferredGeometryCamera(info, gc, GEOMETRY_CAMERA, attachments);
-}
-
 void buildAttachments(CameraInfo* info, osg::Camera* camera, const std::string& name, const std::vector<ref_ptr<FGRenderingPipeline::Attachment> > &attachments) {
     BOOST_FOREACH(ref_ptr<FGRenderingPipeline::Attachment> attachment, attachments) {
         if (attachment->valid())
@@ -839,11 +779,13 @@ osg::Camera* FGRenderer::buildDeferredGeometryCamera( CameraInfo* info, osg::Gra
 
     camera->setCullMask( ~simgear::MODELLIGHT_BIT );
     camera->setName( "GeometryC" );
+    camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
     camera->setGraphicsContext( gc );
     camera->setCullCallback( new FGDeferredRenderingCameraCullCallback( name, info ) );
     camera->setClearMask( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
     camera->setClearColor( osg::Vec4( 0., 0., 0., 0. ) );
     camera->setClearDepth( 1.0 );
+    camera->setColorMask(true, true, true, true);
     camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
     camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0);
     camera->setViewport( new osg::Viewport );
@@ -887,8 +829,8 @@ static osg::Camera* createShadowCascadeCamera( int no, int cascadeSize ) {
     oss << "CascadeCamera" << (no + 1);
     cascadeCam->setName( oss.str() );
     cascadeCam->setClearMask(0);
-    cascadeCam->setCullMask(~( simgear::MODELLIGHT_BIT /* | simgear::NO_SHADOW_BIT */ ) );
-    cascadeCam->setCullingMode( cascadeCam->getCullingMode() & ~osg::CullSettings::SMALL_FEATURE_CULLING );
+    cascadeCam->setCullMask( simgear::CASTSHADOW_BIT );
+    cascadeCam->setCullingMode( cascadeCam->getCullingMode() osg::CullSettings::SMALL_FEATURE_CULLING );
     cascadeCam->setAllowEventFocus(false);
     cascadeCam->setReferenceFrame(osg::Transform::ABSOLUTE_RF_INHERIT_VIEWPOINT);
     cascadeCam->setRenderOrder(osg::Camera::NESTED_RENDER);
@@ -897,13 +839,6 @@ static osg::Camera* createShadowCascadeCamera( int no, int cascadeSize ) {
     return cascadeCam;
 }
 
-osg::Camera* FGRenderer::buildDefaultDeferredShadowCamera( CameraInfo* info, osg::GraphicsContext* gc )
-{
-    std::vector<ref_ptr<FGRenderingPipeline::Attachment> > attachments;
-    attachments.push_back(new FGRenderingPipeline::Attachment(osg::Camera::DEPTH_BUFFER, "shadow") );
-    return buildDeferredShadowCamera(info, gc, SHADOW_CAMERA, attachments);
-}
-
 osg::Camera* FGRenderer::buildDeferredShadowCamera( CameraInfo* info, osg::GraphicsContext* gc, const std::string& name, const std::vector<ref_ptr<FGRenderingPipeline::Attachment> > &attachments )
 {
     osg::Camera* mainShadowCamera = new osg::Camera;
@@ -932,7 +867,6 @@ osg::Camera* FGRenderer::buildDeferredShadowCamera( CameraInfo* info, osg::Graph
         osg::Camera* cascadeCam = createShadowCascadeCamera( i, _shadowMapSize/2 );
         cascadeCam->addChild( mDeferredRealRoot.get() );
         shadowSwitch->addChild( cascadeCam );
-        info->shadowTexGen[i] = new osg::TexGen;
     }
     if (fgGetBool("/sim/rendering/shadows/enabled", true))
         shadowSwitch->setAllChildrenOn();
@@ -1111,152 +1045,54 @@ void FGRenderer::updateCascadeNumber(size_t num)
     _shadowNumber->set( (int)_numCascades );
 }
 
-osg::Camera* FGRenderer::buildDefaultDeferredLightingCamera( CameraInfo* info, osg::GraphicsContext* gc )
-{
-    std::vector<ref_ptr<FGRenderingPipeline::Attachment> > attachments;
-    if (_useColorForDepth) {
-        attachments.push_back(new FGRenderingPipeline::Attachment(osg::Camera::DEPTH_BUFFER, "real-depth") );
-    } else {
-        attachments.push_back(new FGRenderingPipeline::Attachment(osg::Camera::DEPTH_BUFFER, "depth") );
+class DebugPassListener : public SGPropertyChangeListener {
+public:
+    DebugPassListener(osg::Switch* sw, int i) : _switch(sw), _index(i) {}
+    virtual void valueChanged(SGPropertyNode* node) {
+        _switch->setValue(_index, node->getBoolValue());
     }
-    attachments.push_back(new FGRenderingPipeline::Attachment(osg::Camera::COLOR_BUFFER0, "lighting") );
-    return buildDeferredLightingCamera( info, gc, LIGHTING_CAMERA, attachments );
-}
 
-osg::Camera* FGRenderer::buildDeferredLightingCamera( CameraInfo* info, osg::GraphicsContext* gc, const std::string& name, const std::vector<ref_ptr<FGRenderingPipeline::Attachment> > &attachments )
+private:
+    osg::ref_ptr<osg::Switch> _switch;
+    int _index;
+};
+
+osg::Camera*
+FGRenderer::buildDeferredLightingCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc, const FGRenderingPipeline::Stage* stage )
 {
     osg::Camera* camera = new osg::Camera;
-    info->addCamera(name, camera );
+    info->addCamera(stage->name, camera );
 
-    camera->setCullCallback( new FGDeferredRenderingCameraCullCallback( name, info ) );
+    camera->setCullCallback( new FGDeferredRenderingCameraCullCallback( stage->name, info ) );
     camera->setAllowEventFocus(false);
     camera->setGraphicsContext(gc);
     camera->setViewport(new Viewport);
-    camera->setName("LightingC");
+    camera->setName(stage->name+"C");
     camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
-    camera->setRenderOrder(osg::Camera::NESTED_RENDER, 50);
+    camera->setRenderOrder(osg::Camera::NESTED_RENDER, stage->orderNum);
     camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
     camera->setViewport( new osg::Viewport );
-    buildAttachments(info, camera, name, attachments);
+    buildAttachments(info, camera, stage->name, stage->attachments);
     camera->setDrawBuffer(GL_FRONT);
     camera->setReadBuffer(GL_FRONT);
-    camera->setClearColor( osg::Vec4( 0., 0., 0., 1. ) );
+    camera->setClearColor( osg::Vec4( 0.5, 0.5, 0.5, 1. ) );
     camera->setClearMask( GL_COLOR_BUFFER_BIT );
     osg::StateSet* ss = camera->getOrCreateStateSet();
     ss->setAttribute( new osg::Depth(osg::Depth::LESS, 0.0, 1.0, false) );
     ss->addUniform( _depthInColor );
 
-    osg::Group* lightingGroup = new osg::Group;
-
-    osg::Camera* quadCam1 = new osg::Camera;
-    quadCam1->setName( "QuadCamera1" );
-    quadCam1->setClearMask(0);
-    quadCam1->setAllowEventFocus(false);
-    quadCam1->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
-    quadCam1->setRenderOrder(osg::Camera::NESTED_RENDER);
-    quadCam1->setViewMatrix(osg::Matrix::identity());
-    quadCam1->setProjectionMatrixAsOrtho2D(-1,1,-1,1);
-    quadCam1->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
-    ss = quadCam1->getOrCreateStateSet();
-    ss->addUniform( _ambientFactor );
-    ss->addUniform( info->projInverse );
-    ss->addUniform( info->viewInverse );
-    ss->addUniform( info->view );
-    ss->addUniform( _sunDiffuse );
-    ss->addUniform( _sunSpecular );
-    ss->addUniform( _sunDirection );
-    ss->addUniform( _planes );
-    ss->addUniform( _shadowNumber );
-    ss->addUniform( _shadowDistances );
-
-    osg::Geometry* g = osg::createTexturedQuadGeometry( osg::Vec3(-1.,-1.,0.), osg::Vec3(2.,0.,0.), osg::Vec3(0.,2.,0.) );
-    g->setUseDisplayList(false);
-    simgear::EffectGeode* eg = new simgear::EffectGeode;
-    simgear::Effect* effect = simgear::makeEffect("Effects/ambient", true);
-    if (!effect) {
-        SG_LOG(SG_VIEW, SG_ALERT, "Effects/ambient not found");
-        return 0;
-    }
-    eg->setEffect( effect );
-    g->setName( "AmbientQuad" );
-    eg->setName("AmbientQuad");
-    eg->setCullingActive(false);
-    eg->addDrawable(g);
-    quadCam1->addChild( eg );
-
-    g = osg::createTexturedQuadGeometry( osg::Vec3(-1.,-1.,0.), osg::Vec3(2.,0.,0.), osg::Vec3(0.,2.,0.) );
-    g->setUseDisplayList(false);
-    g->setName( "SunlightQuad" );
-    eg = new simgear::EffectGeode;
-    effect = simgear::makeEffect("Effects/sunlight", true);
-    if (!effect) {
-        SG_LOG(SG_VIEW, SG_ALERT, "Effects/sunlight not found");
-        return 0;
-    }
-    eg->setEffect( effect );
-    eg->setName("SunlightQuad");
-    eg->setCullingActive(false);
-    eg->addDrawable(g);
-    quadCam1->addChild( eg );
-
-    osg::Camera* lightCam = new osg::Camera;
-    ss = lightCam->getOrCreateStateSet();
-    ss->addUniform( _planes );
-    ss->addUniform( info->bufferSize );
-    lightCam->setName( "LightCamera" );
-    lightCam->setClearMask(0);
-    lightCam->setAllowEventFocus(false);
-    lightCam->setReferenceFrame(osg::Transform::RELATIVE_RF);
-    lightCam->setRenderOrder(osg::Camera::NESTED_RENDER,1);
-    lightCam->setViewMatrix(osg::Matrix::identity());
-    lightCam->setProjectionMatrix(osg::Matrix::identity());
-    lightCam->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
-    lightCam->setCullMask( simgear::MODELLIGHT_BIT );
-    lightCam->setInheritanceMask( osg::CullSettings::ALL_VARIABLES & ~osg::CullSettings::CULL_MASK );
-    lightCam->addChild( mDeferredRealRoot.get() );
-
+    osg::Switch* lightingGroup = new osg::Switch;
 
-    osg::Camera* quadCam2 = new osg::Camera;
-    quadCam2->setName( "QuadCamera1" );
-    quadCam2->setClearMask(0);
-    quadCam2->setAllowEventFocus(false);
-    quadCam2->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
-    quadCam2->setRenderOrder(osg::Camera::NESTED_RENDER,2);
-    quadCam2->setViewMatrix(osg::Matrix::identity());
-    quadCam2->setProjectionMatrixAsOrtho2D(-1,1,-1,1);
-    quadCam2->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
-    ss = quadCam2->getOrCreateStateSet();
-    ss->addUniform( _ambientFactor );
-    ss->addUniform( info->projInverse );
-    ss->addUniform( info->viewInverse );
-    ss->addUniform( info->view );
-    ss->addUniform( _sunDiffuse );
-    ss->addUniform( _sunSpecular );
-    ss->addUniform( _sunDirection );
-    ss->addUniform( _fogColor );
-    ss->addUniform( _fogDensity );
-    ss->addUniform( _planes );
-
-    g = osg::createTexturedQuadGeometry( osg::Vec3(-1.,-1.,0.), osg::Vec3(2.,0.,0.), osg::Vec3(0.,2.,0.) );
-    g->setUseDisplayList(false);
-    g->setName( "FogQuad" );
-    eg = new simgear::EffectGeode;
-    effect = simgear::makeEffect("Effects/fog", true);
-    if (!effect) {
-        SG_LOG(SG_VIEW, SG_ALERT, "Effects/fog not found");
-        return 0;
+    BOOST_FOREACH( osg::ref_ptr<FGRenderingPipeline::Pass> pass, stage->passes ) {
+        ref_ptr<Node> node = buildPass(info, pass);
+        if (node.valid()) {
+            lightingGroup->addChild(node);
+            if (!pass->debugProperty.empty()) {
+                lightingGroup->setValue(lightingGroup->getNumChildren()-1, fgGetBool(pass->debugProperty));
+                fgAddChangeListener(new DebugPassListener(lightingGroup, lightingGroup->getNumChildren()-1), pass->debugProperty);
+            }
+        }
     }
-    eg->setEffect( effect );
-    eg->setName("FogQuad");
-    eg->setCullingActive(false);
-    eg->addDrawable(g);
-    quadCam2->addChild( eg );
-
-    lightingGroup->addChild( _sky->getPreRoot() );
-    lightingGroup->addChild( _sky->getCloudRoot() );
-    lightingGroup->addChild( quadCam1 );
-    lightingGroup->addChild( lightCam );
-    lightingGroup->addChild( quadCam2 );
 
     camera->addChild( lightingGroup );
 
@@ -1269,30 +1105,20 @@ FGRenderer::buildDeferredPipeline(CameraGroup* cgroup, unsigned flags, osg::Came
                                     const osg::Matrix& projection,
                                     osg::GraphicsContext* gc)
 {
-    if (_renderer.empty() || !_pipeline.valid())
-        return buildDefaultDeferredPipeline(cgroup, flags, camera, view, projection, gc);
     return buildCameraFromRenderingPipeline(_pipeline, cgroup, flags, camera, view, projection, gc);
 }
 
 osg::Camera* 
-FGRenderer::buildDeferredFullscreenCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc, const FGRenderingPipeline::Stage* stage )
+FGRenderer::buildDeferredFullscreenCamera( flightgear::CameraInfo* info, const FGRenderingPipeline::Pass* pass )
 {
     osg::Camera* camera = new osg::Camera;
-    info->addCamera(stage->name, camera, stage->scaleFactor, true);
 
-    camera->setCullCallback( new FGDeferredRenderingCameraCullCallback(stage->name, info, stage->needsDuDv) );
+    camera->setClearMask( 0 );
     camera->setAllowEventFocus(false);
-    camera->setGraphicsContext(gc);
-    camera->setViewport(new Viewport);
-    camera->setName(stage->name+"C");
+    camera->setName(pass->name+"C");
     camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
-    camera->setRenderOrder(osg::Camera::NESTED_RENDER, stage->orderNum);
-    camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
-    buildAttachments(info, camera, stage->name, stage->attachments);
-    camera->setDrawBuffer(GL_FRONT);
-    camera->setReadBuffer(GL_FRONT);
-    camera->setClearColor( osg::Vec4( 1., 1., 1., 1. ) );
-    camera->setClearMask( GL_COLOR_BUFFER_BIT );
+    camera->setRenderOrder(osg::Camera::NESTED_RENDER, pass->orderNum);
+    camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
     camera->setViewMatrix(osg::Matrix::identity());
     camera->setProjectionMatrixAsOrtho2D(-1,1,-1,1);
 
@@ -1302,10 +1128,12 @@ FGRenderer::buildDeferredFullscreenCamera( flightgear::CameraInfo* info, osg::Gr
     ss->addUniform( info->viewInverse );
     ss->addUniform( info->view );
     ss->addUniform( info->bufferSize );
-    if (stage->needsDuDv) {
-        ss->addUniform( info->du );
-        ss->addUniform( info->dv );
-    }
+    ss->addUniform( info->worldPosCart );
+    ss->addUniform( info->worldPosGeod );
+    ss->addUniform( info->shadowMatrix[0] );
+    ss->addUniform( info->shadowMatrix[1] );
+    ss->addUniform( info->shadowMatrix[2] );
+    ss->addUniform( info->shadowMatrix[3] );
     ss->addUniform( _ambientFactor );
     ss->addUniform( _sunDiffuse );
     ss->addUniform( _sunSpecular );
@@ -1313,16 +1141,18 @@ FGRenderer::buildDeferredFullscreenCamera( flightgear::CameraInfo* info, osg::Gr
     ss->addUniform( _planes );
     ss->addUniform( _shadowNumber );
     ss->addUniform( _shadowDistances );
+    ss->addUniform( _fogColor );
+    ss->addUniform( _fogDensity );
 
     osg::Geometry* g = osg::createTexturedQuadGeometry( osg::Vec3(-1.,-1.,0.), osg::Vec3(2.,0.,0.), osg::Vec3(0.,2.,0.) );
     g->setUseDisplayList(false);
     simgear::EffectGeode* eg = new simgear::EffectGeode;
-    simgear::Effect* effect = simgear::makeEffect(stage->effect, true);
+    simgear::Effect* effect = simgear::makeEffect(pass->effect, true);
     if (effect) {
         eg->setEffect( effect );
     }
 
-    eg->setName(stage->name+"Quad");
+    eg->setName(pass->name+"Quad");
     eg->setCullingActive(false);
     eg->addDrawable(g);
     camera->addChild(eg);
@@ -1330,19 +1160,46 @@ FGRenderer::buildDeferredFullscreenCamera( flightgear::CameraInfo* info, osg::Gr
     return camera;
 }
 
+osg::Camera* 
+FGRenderer::buildDeferredFullscreenCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc, const FGRenderingPipeline::Stage* stage )
+{
+    osg::Camera* camera = buildDeferredFullscreenCamera(info, static_cast<const FGRenderingPipeline::Pass*>(stage));
+    info->addCamera(stage->name, camera, stage->scaleFactor, true);
+
+    camera->setCullCallback( new FGDeferredRenderingCameraCullCallback(stage->name, info, stage->needsDuDv) );
+    camera->setGraphicsContext(gc);
+    camera->setViewport(new Viewport);
+    camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
+    buildAttachments(info, camera, stage->name, stage->attachments);
+    camera->setDrawBuffer(GL_FRONT);
+    camera->setReadBuffer(GL_FRONT);
+    camera->setClearColor( osg::Vec4( 1., 1., 1., 1. ) );
+    camera->setClearMask( GL_COLOR_BUFFER_BIT );
+    camera->setViewMatrix(osg::Matrix::identity());
+    camera->setProjectionMatrixAsOrtho2D(-1,1,-1,1);
+
+    osg::StateSet* ss = camera->getOrCreateStateSet();
+    if (stage->needsDuDv) {
+        ss->addUniform( info->du );
+        ss->addUniform( info->dv );
+    }
+
+    return camera;
+}
+
 void
-FGRenderer::buildDeferredDisplayCamera( osg::Camera* camera, flightgear::CameraInfo* info, const std::string& name, osg::GraphicsContext* gc )
+FGRenderer::buildDeferredDisplayCamera( osg::Camera* camera, flightgear::CameraInfo* info, const FGRenderingPipeline::Stage* stage, osg::GraphicsContext* gc )
 {
     camera->setName( "DisplayC" );
-    camera->setCullCallback( new FGDeferredRenderingCameraCullCallback( name, info ) );
+    camera->setCullCallback( new FGDeferredRenderingCameraCullCallback( stage->name, info ) );
     camera->setReferenceFrame(Transform::ABSOLUTE_RF);
     camera->setAllowEventFocus(false);
     osg::Geometry* g = osg::createTexturedQuadGeometry( osg::Vec3(-1.,-1.,0.), osg::Vec3(2.,0.,0.), osg::Vec3(0.,2.,0.) );
     g->setUseDisplayList(false); //DEBUG
     simgear::EffectGeode* eg = new simgear::EffectGeode;
-    simgear::Effect* effect = simgear::makeEffect("Effects/display", true);
+    simgear::Effect* effect = simgear::makeEffect(stage->effect, true);
     if (!effect) {
-        SG_LOG(SG_VIEW, SG_ALERT, "Effects/display not found");
+        SG_LOG(SG_VIEW, SG_ALERT, stage->effect + " not found");
         return;
     }
     eg->setEffect(effect);
@@ -1354,73 +1211,59 @@ FGRenderer::buildDeferredDisplayCamera( osg::Camera* camera, flightgear::CameraI
 
     osg::StateSet* ss = camera->getOrCreateStateSet();
     ss->addUniform( _depthInColor );
+    ss->addUniform( info->projInverse );
+    ss->addUniform( info->viewInverse );
+    ss->addUniform( info->view );
+    ss->addUniform( info->bufferSize );
+    ss->addUniform( info->worldPosCart );
+    ss->addUniform( info->worldPosGeod );
+    ss->addUniform( info->shadowMatrix[0] );
+    ss->addUniform( info->shadowMatrix[1] );
+    ss->addUniform( info->shadowMatrix[2] );
+    ss->addUniform( info->shadowMatrix[3] );
+    ss->addUniform( _ambientFactor );
+    ss->addUniform( _sunDiffuse );
+    ss->addUniform( _sunSpecular );
+    ss->addUniform( _sunDirection );
+    ss->addUniform( _planes );
+    ss->addUniform( _shadowNumber );
+    ss->addUniform( _shadowDistances );
+    ss->addUniform( _fogColor );
+    ss->addUniform( _fogDensity );
 }
 
-CameraInfo*
-FGRenderer::buildDefaultDeferredPipeline(CameraGroup* cgroup, unsigned flags, osg::Camera* camera,
-                                    const osg::Matrix& view,
-                                    const osg::Matrix& projection,
-                                    osg::GraphicsContext* gc)
-{
-    CameraInfo* info = new CameraInfo(flags);
-    buildDefaultDeferredBuffers(info, _shadowMapSize, _useColorForDepth);
-
-    osg::Camera* geometryCamera = buildDefaultDeferredGeometryCamera( info, gc );
-    cgroup->getViewer()->addSlave(geometryCamera, false);
-    installCullVisitor(geometryCamera);
-    int slaveIndex = cgroup->getViewer()->getNumSlaves() - 1;
-    info->getRenderStageInfo(GEOMETRY_CAMERA).slaveIndex = slaveIndex;
-    
-    Camera* shadowCamera = buildDefaultDeferredShadowCamera( info, gc );
-    cgroup->getViewer()->addSlave(shadowCamera, false);
-    installCullVisitor(shadowCamera);
-    slaveIndex = cgroup->getViewer()->getNumSlaves() - 1;
-    info->getRenderStageInfo(SHADOW_CAMERA).slaveIndex = slaveIndex;
-
-    osg::Camera* lightingCamera = buildDefaultDeferredLightingCamera( info, gc );
-    cgroup->getViewer()->addSlave(lightingCamera, false);
-    installCullVisitor(lightingCamera);
-    slaveIndex = cgroup->getViewer()->getNumSlaves() - 1;
-    info->getRenderStageInfo(LIGHTING_CAMERA).slaveIndex = slaveIndex;
-
-    buildDeferredDisplayCamera( camera, info, DISPLAY_CAMERA, gc );
-
-    cgroup->getViewer()->addSlave(camera, false);
-    installCullVisitor(camera);
-    slaveIndex = cgroup->getViewer()->getNumSlaves() - 1;
-    info->addCamera( DISPLAY_CAMERA, camera, slaveIndex, true );
-    camera->setRenderOrder(Camera::POST_RENDER, 99); //FIXME
-    cgroup->addCamera(info);
-    return info;
-}
-
-void FGRenderer::buildStage(FGRenderingPipeline* rpipe, CameraInfo* info,
-                                        FGRenderingPipeline::Stage* stage,
-                                        CameraGroup* cgroup,
-                                        osg::Camera* mainCamera,
-                                        const osg::Matrix& view,
-                                        const osg::Matrix& projection,
-                                        osg::GraphicsContext* gc)
+void
+FGRenderer::buildStage(CameraInfo* info,
+                        FGRenderingPipeline::Stage* stage,
+                        CameraGroup* cgroup,
+                        osg::Camera* mainCamera,
+                        const osg::Matrix& view, const osg::Matrix& projection, osg::GraphicsContext* gc)
 {
     if (!stage->valid())
         return;
 
     ref_ptr<Camera> camera;
-    if (stage->type == "geometry")
+    bool needOffsets = false;
+    if (stage->type == "geometry") {
         camera = buildDeferredGeometryCamera(info, gc, stage->name, stage->attachments);
-    else if (stage->type == "lighting")
-        camera = buildDeferredLightingCamera(info, gc, stage->name, stage->attachments);
-    else if (stage->type == "shadow")
+        needOffsets = true;
+    } else if (stage->type == "lighting") {
+        camera = buildDeferredLightingCamera(info, gc, stage);
+        needOffsets = true;
+    } else if (stage->type == "shadow")
         camera = buildDeferredShadowCamera(info, gc, stage->name, stage->attachments);
     else if (stage->type == "fullscreen")
         camera = buildDeferredFullscreenCamera(info, gc, stage);
     else if (stage->type == "display") {
         camera = mainCamera;
-        buildDeferredDisplayCamera(camera, info, stage->name, gc);
+        buildDeferredDisplayCamera(camera, info, stage, gc);
     } else
         throw sg_exception("Stage type is not supported");
 
-    cgroup->getViewer()->addSlave(camera, false);
+    if (needOffsets)
+        cgroup->getViewer()->addSlave(camera, projection, view, false);
+    else
+        cgroup->getViewer()->addSlave(camera, false);
     installCullVisitor(camera);
     int slaveIndex = cgroup->getViewer()->getNumSlaves() - 1;
     if (stage->type == "display")
@@ -1428,7 +1271,62 @@ void FGRenderer::buildStage(FGRenderingPipeline* rpipe, CameraInfo* info,
     info->getRenderStageInfo(stage->name).slaveIndex = slaveIndex;
 }
 
-void FGRenderer::buildBuffers(FGRenderingPipeline* rpipe, CameraInfo* info)
+osg::Node*
+FGRenderer::buildLightingSkyCloudsPass(FGRenderingPipeline::Pass* pass)
+{
+    Group* group = new Group;
+    StateSet* ss = group->getOrCreateStateSet();
+    ss->setAttributeAndModes( new osg::ColorMask( true, true, true, false ), osg::StateAttribute::ON );
+    group->addChild( _sky->getPreRoot() );
+    group->addChild( _sky->getCloudRoot() );
+    return group;
+}
+
+osg::Node*
+FGRenderer::buildLightingLightsPass(CameraInfo* info, FGRenderingPipeline::Pass* pass)
+{
+    osg::Camera* lightCam = new osg::Camera;
+    StateSet* ss = lightCam->getOrCreateStateSet();
+    ss->addUniform( _planes );
+    ss->addUniform( info->bufferSize );
+    ss->addUniform( _fogColor );
+    ss->addUniform( _fogDensity );
+    lightCam->setName( "LightCamera" );
+    lightCam->setClearMask(0);
+    lightCam->setAllowEventFocus(false);
+    lightCam->setReferenceFrame(osg::Transform::RELATIVE_RF);
+    lightCam->setRenderOrder(osg::Camera::NESTED_RENDER,pass->orderNum);
+    lightCam->setViewMatrix(osg::Matrix::identity());
+    lightCam->setProjectionMatrix(osg::Matrix::identity());
+    lightCam->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+    lightCam->setCullMask( simgear::MODELLIGHT_BIT | simgear::PANEL2D_BIT | simgear::PERMANENTLIGHT_BIT);
+    lightCam->setInheritanceMask( osg::CullSettings::ALL_VARIABLES & ~osg::CullSettings::CULL_MASK );
+    lightCam->addChild( mDeferredRealRoot.get() );
+
+    return lightCam;
+}
+
+osg::Node*
+FGRenderer::buildPass(CameraInfo* info, FGRenderingPipeline::Pass* pass)
+{
+    if (!pass->valid())
+        return 0;
+
+    ref_ptr<Node> node;
+    if (pass->type == "sky-clouds")
+        node = buildLightingSkyCloudsPass(pass);
+    else if (pass->type == "fullscreen")
+        node = buildDeferredFullscreenCamera(info, pass);
+    else if (pass->type == "lights")
+        node = buildLightingLightsPass(info, pass);
+    else
+        throw sg_exception("Pass type is not supported");
+
+    return node.release();
+}
+
+void
+FGRenderer::buildBuffers(FGRenderingPipeline* rpipe, CameraInfo* info)
 {
     for (size_t i = 0; i < rpipe->buffers.size(); ++i) {
         osg::ref_ptr<FGRenderingPipeline::Buffer> buffer = rpipe->buffers[i];
@@ -1455,7 +1353,7 @@ CameraInfo* FGRenderer::buildCameraFromRenderingPipeline(FGRenderingPipeline* rp
     
     for (size_t i = 0; i < rpipe->stages.size(); ++i) {
         osg::ref_ptr<FGRenderingPipeline::Stage> stage = rpipe->stages[i];
-        buildStage(rpipe, info, stage, cgroup, camera, view, projection, gc);
+        buildStage(info, stage, cgroup, camera, view, projection, gc);
     }
 
     cgroup->addCamera(info);
@@ -1609,22 +1507,8 @@ FGRenderer::setupView( void )
         geode->addDrawable(new SGHUDDrawable);
         guiCamera->addChild(geode);
       
-        panelSwitch = new osg::Switch;
-        osg::StateSet* stateSet = panelSwitch->getOrCreateStateSet();
-        stateSet->setRenderBinDetails(1000, "RenderBin");
-        
-        // speed optimization?
-        stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
-        stateSet->setAttribute(new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA));
-        stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
-        stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
-        stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
         
-        
-        panelSwitch->setUpdateCallback(new FGPanelSwitchCallback);
-        panelChanged();
-        
-        guiCamera->addChild(panelSwitch.get());
+      guiCamera->addChild(FGPanelNode::create2DPanelNode());
     }
     
     osg::Switch* sw = new osg::Switch;
@@ -1643,21 +1527,9 @@ FGRenderer::setupView( void )
     stateSet = mRealRoot->getOrCreateStateSet();
     stateSet->setAttributeAndModes(new osg::Program, osg::StateAttribute::ON);
 
-       mDeferredRealRoot->addChild( mRealRoot.get() );
-}
+    mDeferredRealRoot->addChild( mRealRoot.get() );
 
-void FGRenderer::panelChanged()
-{
-    if (!panelSwitch) {
-        return;
-    }
-    
-    osg::Node* n = FGPanelNode::createNode(globals->get_current_panel());
-    if (panelSwitch->getNumChildren()) {
-        panelSwitch->setChild(0, n);
-    } else {
-        panelSwitch->addChild(n);
-    }
+    DeletionManager::install(mRealRoot.get());
 }
                                     
 // Update all Visuals (redraws anything graphics related)