]> git.mxchange.org Git - flightgear.git/blobdiff - src/Viewer/renderer.cxx
Rely entirely on the configurable renderer and add more configuration options in...
[flightgear.git] / src / Viewer / renderer.cxx
index 158fb40663008448e66d32c015482578ca0b9e3d..ac156c820e0745cda755f31ec97621b078b226ac 100644 (file)
@@ -70,6 +70,7 @@
 #include <simgear/scene/material/EffectCullVisitor.hxx>
 #include <simgear/scene/material/Effect.hxx>
 #include <simgear/scene/material/EffectGeode.hxx>
+#include <simgear/scene/material/EffectBuilder.hxx>
 #include <simgear/scene/model/animation.hxx>
 #include <simgear/scene/model/placement.hxx>
 #include <simgear/scene/sky/sky.hxx>
@@ -78,6 +79,7 @@
 #include <simgear/scene/util/SGSceneUserData.hxx>
 #include <simgear/scene/tgdb/GroundLightManager.hxx>
 #include <simgear/scene/tgdb/pt_lights.hxx>
+#include <simgear/scene/tgdb/userdata.hxx>
 #include <simgear/structure/OSGUtils.hxx>
 #include <simgear/props/props.hxx>
 #include <simgear/timing/sg_time.hxx>
@@ -501,7 +503,9 @@ public:
 void
 FGRenderer::init( void )
 {
-    _classicalRenderer = !fgGetBool("/sim/rendering/rembrandt", false);
+    sgUserDataInit( globals->get_props() );
+
+    _classicalRenderer = !fgGetBool("/sim/rendering/rembrandt/enabled", false);
     _shadowMapSize    = fgGetInt( "/sim/rendering/shadows/map-size", 4096 );
     fgAddChangeListener( new ShadowMapSizeListener, "/sim/rendering/shadows/map-size" );
     fgAddChangeListener( new ShadowEnabledListener, "/sim/rendering/shadows/enabled" );
@@ -521,11 +525,11 @@ FGRenderer::init( void )
     updateCascadeFar(1, _cascadeFar[1]);
     updateCascadeFar(2, _cascadeFar[2]);
     updateCascadeFar(3, _cascadeFar[3]);
-    _useColorForDepth = fgGetBool( "/sim/rendering/use-color-for-depth", false );
+    _useColorForDepth = fgGetBool( "/sim/rendering/rembrandt/use-color-for-depth", false );
     _depthInColor->set( _useColorForDepth );
 
-    _renderer         = fgGetString("/sim/rendering/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);
@@ -619,14 +623,14 @@ void installCullVisitor(Camera* camera)
     }
 }
 
-flightgear::CameraInfo*
-FGRenderer::buildRenderingPipeline(flightgear::CameraGroup* cgroup, unsigned flags, Camera* camera,
+CameraInfo*
+FGRenderer::buildRenderingPipeline(CameraGroup* cgroup, unsigned flags, Camera* camera,
                                    const Matrix& view,
                                    const Matrix& projection,
                                                                   osg::GraphicsContext* gc,
                                    bool useMasterSceneData)
 {
-       flightgear::CameraInfo* info = 0;
+       CameraInfo* info = 0;
        if (!_classicalRenderer && (flags & (CameraGroup::GUI | CameraGroup::ORTHO)) == 0)
                info = buildDeferredPipeline( cgroup, flags, camera, view, projection, gc );
 
@@ -639,8 +643,8 @@ FGRenderer::buildRenderingPipeline(flightgear::CameraGroup* cgroup, unsigned fla
        }
 }
 
-flightgear::CameraInfo*
-FGRenderer::buildClassicalPipeline(flightgear::CameraGroup* cgroup, unsigned flags, osg::Camera* camera,
+CameraInfo*
+FGRenderer::buildClassicalPipeline(CameraGroup* cgroup, unsigned flags, osg::Camera* camera,
                                 const osg::Matrix& view,
                                 const osg::Matrix& projection,
                                 bool useMasterSceneData)
@@ -691,26 +695,31 @@ FGRenderer::buildClassicalPipeline(flightgear::CameraGroup* cgroup, unsigned fla
 
 class FGDeferredRenderingCameraCullCallback : public osg::NodeCallback {
 public:
-    FGDeferredRenderingCameraCullCallback( const std::string& k, CameraInfo* i ) : kind( k ), info( i ) {}
+    FGDeferredRenderingCameraCullCallback( const std::string& k, CameraInfo* i, bool nd = false ) : kind( k ), info( i ), needsDuDv(nd) {}
     virtual void operator()( osg::Node *n, osg::NodeVisitor *nv) {
         simgear::EffectCullVisitor* cv = dynamic_cast<simgear::EffectCullVisitor*>(nv);
         osg::Camera* camera = static_cast<osg::Camera*>(n);
 
         cv->clearBufferList();
-        cv->addBuffer("depth", info->getBuffer( "depth" ) );
-        cv->addBuffer("normal", info->getBuffer( "normal" ) );
-        cv->addBuffer("diffuse", info->getBuffer( "diffuse" ) );
-        cv->addBuffer("spec-emis", info->getBuffer( "spec-emis" ) );
-        cv->addBuffer("lighting", info->getBuffer( "lighting" ) );
-        cv->addBuffer("shadow", info->getBuffer( "shadow" ) );
-        // cv->addBuffer(simgear::Effect::AO_BUFFER, info->gBuffer->aoBuffer[2]);
+        for (RenderBufferMap::iterator ii = info->buffers.begin(); ii != info->buffers.end(); ++ii) {
+            cv->addBuffer(ii->first, ii->second.texture);
+        }
 
         if ( !info->getRenderStageInfo(kind).fullscreen )
             info->setMatrices( camera );
 
+        if (needsDuDv) {
+            osg::Matrix projInverse;
+            info->projInverse->get( projInverse );
+
+            osg::Vec4 p0 = osg::Vec4( -1.0, -1.0, 0.0, 1.0 ) * projInverse;
+            info->du->set( osg::Vec4(  1.0, -1.0, 0.0, 1.0 ) * projInverse - p0 );
+            info->dv->set( osg::Vec4( -1.0,  1.0, 0.0, 1.0 ) * projInverse - p0 );
+        }
+
         cv->traverse( *camera );
 
-        if ( kind == flightgear::GEOMETRY_CAMERA ) {
+        if ( kind == GEOMETRY_CAMERA ) {
             // Save transparent bins to render later
             osgUtil::RenderStage* renderStage = cv->getRenderStage();
             osgUtil::RenderBin::RenderBinList& rbl = renderStage->getRenderBinList();
@@ -722,7 +731,7 @@ public:
                     ++rbi;
                 }
             }
-        } else if ( kind == flightgear::LIGHTING_CAMERA ) {
+        } else if ( kind == LIGHTING_CAMERA ) {
             osg::ref_ptr<osg::Camera> mainShadowCamera = info->getCamera( SHADOW_CAMERA );
             if (mainShadowCamera.valid()) {
                 osg::Switch* grp = mainShadowCamera->getChild(0)->asSwitch();
@@ -756,6 +765,7 @@ public:
 private:
     std::string kind;
     CameraInfo* info;
+    bool needsDuDv;
 };
 
 osg::Texture2D* buildDeferredBuffer(GLint internalFormat, GLenum sourceFormat, GLenum sourceType, GLenum wrapMode, bool shadowComparison = false)
@@ -777,61 +787,35 @@ osg::Texture2D* buildDeferredBuffer(GLint internalFormat, GLenum sourceFormat, G
        return tex;
 }
 
-void buildDeferredBuffers( flightgear::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( flightgear::CameraInfo* info, osg::Camera* camera, osg::Camera::BufferComponent c, const std::string& ck, const std::string& bk )
+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( flightgear::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") );
+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())
+            attachBufferToCamera( info, camera, attachment->component, name, attachment->buffer );
     }
-    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, attachments);
 }
 
-osg::Camera* FGRenderer::buildDeferredGeometryCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc, const std::vector<ref_ptr<FGRenderingPipeline::Attachment> > &attachments )
+osg::Camera* FGRenderer::buildDeferredGeometryCamera( CameraInfo* info, osg::GraphicsContext* gc, const std::string& name, const std::vector<ref_ptr<FGRenderingPipeline::Attachment> > &attachments )
 {
     osg::Camera* camera = new osg::Camera;
-    info->addCamera(flightgear::GEOMETRY_CAMERA, camera );
+    info->addCamera(name, camera );
 
     camera->setCullMask( ~simgear::MODELLIGHT_BIT );
     camera->setName( "GeometryC" );
     camera->setGraphicsContext( gc );
-    camera->setCullCallback( new FGDeferredRenderingCameraCullCallback( flightgear::GEOMETRY_CAMERA, info ) );
+    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->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
+    camera->setRenderOrder(osg::Camera::NESTED_RENDER, 0);
     camera->setViewport( new osg::Viewport );
-    BOOST_FOREACH(ref_ptr<FGRenderingPipeline::Attachment> attachment, attachments) {
-        attachBufferToCamera( info, camera, attachment->component, flightgear::GEOMETRY_CAMERA, attachment->buffer );
-    }
+    buildAttachments(info, camera, name, attachments);
     camera->setDrawBuffer(GL_FRONT);
     camera->setReadBuffer(GL_FRONT);
 
@@ -881,17 +865,10 @@ static osg::Camera* createShadowCascadeCamera( int no, int cascadeSize ) {
     return cascadeCam;
 }
 
-osg::Camera* FGRenderer::buildDefaultDeferredShadowCamera( flightgear::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, attachments);
-}
-
-osg::Camera* FGRenderer::buildDeferredShadowCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc, const std::vector<ref_ptr<FGRenderingPipeline::Attachment> > &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;
-    info->addCamera(flightgear::SHADOW_CAMERA, mainShadowCamera, 0.0f );
+    info->addCamera(name, mainShadowCamera, 0.0f );
 
     mainShadowCamera->setName( "ShadowC" );
     mainShadowCamera->setClearMask( GL_DEPTH_BUFFER_BIT );
@@ -899,9 +876,7 @@ osg::Camera* FGRenderer::buildDeferredShadowCamera( flightgear::CameraInfo* info
     mainShadowCamera->setAllowEventFocus(false);
     mainShadowCamera->setGraphicsContext(gc);
     mainShadowCamera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
-    BOOST_FOREACH(ref_ptr<FGRenderingPipeline::Attachment> attachment, attachments) {
-        attachBufferToCamera( info, mainShadowCamera, attachment->component, flightgear::SHADOW_CAMERA, attachment->buffer );
-    }
+    buildAttachments(info, mainShadowCamera, name, attachments);
     mainShadowCamera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
     mainShadowCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
     mainShadowCamera->setProjectionMatrix(osg::Matrix::identity());
@@ -909,6 +884,7 @@ osg::Camera* FGRenderer::buildDeferredShadowCamera( flightgear::CameraInfo* info
     mainShadowCamera->setViewport( 0, 0, _shadowMapSize, _shadowMapSize );
     mainShadowCamera->setDrawBuffer(GL_FRONT);
     mainShadowCamera->setReadBuffer(GL_FRONT);
+    mainShadowCamera->setRenderOrder(Camera::NESTED_RENDER, 1);
 
     osg::Switch* shadowSwitch = new osg::Switch;
     mainShadowCamera->addChild( shadowSwitch );
@@ -953,7 +929,7 @@ osg::Vec3 FGRenderer::getSunDirection() const
     return val;
 }
 
-void FGRenderer::updateShadowCamera(const flightgear::CameraInfo* info, const osg::Vec3d& position)
+void FGRenderer::updateShadowCamera(const CameraInfo* info, const osg::Vec3d& position)
 {
     ref_ptr<Camera> mainShadowCamera = info->getCamera( SHADOW_CAMERA );
     if (mainShadowCamera.valid()) {
@@ -1096,35 +1072,21 @@ void FGRenderer::updateCascadeNumber(size_t num)
     _shadowNumber->set( (int)_numCascades );
 }
 
-osg::Camera* FGRenderer::buildDefaultDeferredLightingCamera( flightgear::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") );
-    }
-    attachments.push_back(new FGRenderingPipeline::Attachment(osg::Camera::COLOR_BUFFER0, "lighting") );
-    return buildDeferredLightingCamera( info, gc, attachments );
-}
-
-osg::Camera* FGRenderer::buildDeferredLightingCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc, const std::vector<ref_ptr<FGRenderingPipeline::Attachment> > &attachments )
+osg::Camera* FGRenderer::buildDeferredLightingCamera( CameraInfo* info, osg::GraphicsContext* gc, const std::string& name, const std::vector<ref_ptr<FGRenderingPipeline::Attachment> > &attachments )
 {
     osg::Camera* camera = new osg::Camera;
-    info->addCamera(flightgear::LIGHTING_CAMERA, camera );
+    info->addCamera(name, camera );
 
-    camera->setCullCallback( new FGDeferredRenderingCameraCullCallback( flightgear::LIGHTING_CAMERA, info ) );
+    camera->setCullCallback( new FGDeferredRenderingCameraCullCallback( name, info ) );
     camera->setAllowEventFocus(false);
     camera->setGraphicsContext(gc);
     camera->setViewport(new Viewport);
     camera->setName("LightingC");
     camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
-    camera->setRenderOrder(osg::Camera::POST_RENDER, 50);
+    camera->setRenderOrder(osg::Camera::NESTED_RENDER, 50);
     camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
     camera->setViewport( new osg::Viewport );
-    BOOST_FOREACH(ref_ptr<FGRenderingPipeline::Attachment> attachment, attachments) {
-        attachBufferToCamera( info, camera, attachment->component, flightgear::LIGHTING_CAMERA, attachment->buffer );
-    }
+    buildAttachments(info, camera, name, attachments);
     camera->setDrawBuffer(GL_FRONT);
     camera->setReadBuffer(GL_FRONT);
     camera->setClearColor( osg::Vec4( 0., 0., 0., 1. ) );
@@ -1250,51 +1212,131 @@ osg::Camera* FGRenderer::buildDeferredLightingCamera( flightgear::CameraInfo* in
     return camera;
 }
 
-namespace flightgear {
-flightgear::CameraInfo* buildCameraFromRenderingPipeline(FGRenderingPipeline* rpipe, CameraGroup* cgroup, unsigned flags, osg::Camera* camera,
-                                    const osg::Matrix& view, const osg::Matrix& projection, osg::GraphicsContext* gc);
+osg::Camera*
+FGRenderer::buildDeferredLightingCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc, const FGRenderingPipeline::Stage* stage )
+{
+    osg::Camera* camera = new osg::Camera;
+    info->addCamera(stage->name, camera );
+
+    camera->setCullCallback( new FGDeferredRenderingCameraCullCallback( stage->name, info ) );
+    camera->setAllowEventFocus(false);
+    camera->setGraphicsContext(gc);
+    camera->setViewport(new Viewport);
+    camera->setName(stage->name+"C");
+    camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
+    camera->setRenderOrder(osg::Camera::NESTED_RENDER, stage->orderNum);
+    camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
+    camera->setViewport( new osg::Viewport );
+    buildAttachments(info, camera, stage->name, stage->attachments);
+    camera->setDrawBuffer(GL_FRONT);
+    camera->setReadBuffer(GL_FRONT);
+    camera->setClearColor( osg::Vec4( 0., 0., 0., 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;
+
+    BOOST_FOREACH( osg::ref_ptr<FGRenderingPipeline::Pass> pass, stage->passes ) {
+        ref_ptr<Node> node = buildPass(info, pass);
+        if (node.valid())
+            lightingGroup->addChild(node);
+    }
+
+    camera->addChild( lightingGroup );
+
+    return camera;
 }
 
-flightgear::CameraInfo*
+CameraInfo*
 FGRenderer::buildDeferredPipeline(CameraGroup* cgroup, unsigned flags, osg::Camera* camera,
                                     const osg::Matrix& view,
                                     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);
 }
 
-flightgear::CameraInfo*
-FGRenderer::buildDefaultDeferredPipeline(flightgear::CameraGroup* cgroup, unsigned flags, osg::Camera* camera,
-                                    const osg::Matrix& view,
-                                    const osg::Matrix& projection,
-                                    osg::GraphicsContext* gc)
+osg::Camera* 
+FGRenderer::buildDeferredFullscreenCamera( flightgear::CameraInfo* info, const FGRenderingPipeline::Pass* pass )
 {
-    CameraInfo* info = new CameraInfo(flags);
-    buildDeferredBuffers(info, _shadowMapSize, _useColorForDepth);
+    osg::Camera* camera = new osg::Camera;
 
-    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;
+    camera->setClearMask( 0 );
+    camera->setAllowEventFocus(false);
+    camera->setName(pass->name+"C");
+    camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
+    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);
+
+    osg::StateSet* ss = camera->getOrCreateStateSet();
+    ss->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
+    ss->addUniform( info->projInverse );
+    ss->addUniform( info->viewInverse );
+    ss->addUniform( info->view );
+    ss->addUniform( info->bufferSize );
+    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 );
+    ss->addUniform( _planes );
+
+    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(pass->effect, true);
+    if (effect) {
+        eg->setEffect( effect );
+    }
+
+    eg->setName(pass->name+"Quad");
+    eg->setCullingActive(false);
+    eg->addDrawable(g);
+    camera->addChild(eg);
+
+    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 )
+{
     camera->setName( "DisplayC" );
-    camera->setCullCallback( new FGDeferredRenderingCameraCullCallback( flightgear::DISPLAY_CAMERA, info ) );
+    camera->setCullCallback( new FGDeferredRenderingCameraCullCallback( 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.) );
@@ -1303,7 +1345,7 @@ FGRenderer::buildDefaultDeferredPipeline(flightgear::CameraGroup* cgroup, unsign
     simgear::Effect* effect = simgear::makeEffect("Effects/display", true);
     if (!effect) {
         SG_LOG(SG_VIEW, SG_ALERT, "Effects/display not found");
-        return 0;
+        return;
     }
     eg->setEffect(effect);
     eg->setCullingActive(false);
@@ -1314,17 +1356,129 @@ FGRenderer::buildDefaultDeferredPipeline(flightgear::CameraGroup* cgroup, unsign
 
     osg::StateSet* ss = camera->getOrCreateStateSet();
     ss->addUniform( _depthInColor );
+}
+
+void
+FGRenderer::buildStage(CameraInfo* info,
+                        FGRenderingPipeline::Stage* stage,
+                        CameraGroup* cgroup,
+                        osg::Camera* mainCamera,
+                        osg::GraphicsContext* gc)
+{
+    if (!stage->valid())
+        return;
+
+    ref_ptr<Camera> camera;
+    if (stage->type == "geometry")
+        camera = buildDeferredGeometryCamera(info, gc, stage->name, stage->attachments);
+    else if (stage->type == "lighting-builtin")
+        camera = buildDeferredLightingCamera(info, gc, stage->name, stage->attachments);
+    else if (stage->type == "lighting")
+        camera = buildDeferredLightingCamera(info, gc, stage);
+    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);
+    } else
+        throw sg_exception("Stage type is not supported");
 
     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+slaveIndex); //FIXME
+    int slaveIndex = cgroup->getViewer()->getNumSlaves() - 1;
+    if (stage->type == "display")
+        info->addCamera( stage->type, camera, slaveIndex, true );
+    info->getRenderStageInfo(stage->name).slaveIndex = slaveIndex;
+}
+
+osg::Node*
+FGRenderer::buildLightingSkyCloudsPass(FGRenderingPipeline::Pass* pass)
+{
+    Group* group = new Group;
+    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 );
+    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 );
+    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];
+        if (buffer->valid()) {
+            bool fullscreen = buffer->width == -1 && buffer->height == -1;
+            info->addBuffer(buffer->name, buildDeferredBuffer( buffer->internalFormat,
+                                                                buffer->sourceFormat,
+                                                                buffer->sourceType,
+                                                                buffer->wrapMode,
+                                                                buffer->shadowComparison),
+                            fullscreen ? buffer->scaleFactor : 0.0f);
+            if (!fullscreen) {
+                info->getBuffer(buffer->name)->setTextureSize(buffer->width, buffer->height);
+            }
+        }
+    }
+}
+
+CameraInfo* FGRenderer::buildCameraFromRenderingPipeline(FGRenderingPipeline* rpipe, CameraGroup* cgroup, unsigned flags, osg::Camera* camera,
+                                    const osg::Matrix& view, const osg::Matrix& projection, osg::GraphicsContext* gc)
+{
+    CameraInfo* info = new CameraInfo(flags);
+    buildBuffers(rpipe, info);
+    
+    for (size_t i = 0; i < rpipe->stages.size(); ++i) {
+        osg::ref_ptr<FGRenderingPipeline::Stage> stage = rpipe->stages[i];
+        buildStage(info, stage, cgroup, camera, gc);
+    }
+
     cgroup->addCamera(info);
+
     return info;
 }
 
-
 void
 FGRenderer::setupView( void )
 {
@@ -1991,63 +2145,6 @@ bool printVisibleSceneInfo(FGRenderer* renderer)
     return true;
 }
 
-void buildBuffers(FGRenderingPipeline* rpipe, flightgear::CameraInfo* info)
-{
-    for (size_t i = 0; i < rpipe->buffers.size(); ++i) {
-        osg::ref_ptr<FGRenderingPipeline::Buffer> buffer = rpipe->buffers[i];
-        info->addBuffer(buffer->name, buildDeferredBuffer( buffer->internalFormat,
-                                                            buffer->sourceFormat,
-                                                            buffer->sourceType,
-                                                            buffer->wrapMode,
-                                                            buffer->shadowComparison) );
-    }
-}
-
-void buildStage(FGRenderingPipeline* rpipe, flightgear::CameraInfo* info,
-                                        FGRenderingPipeline::Stage* stage,
-                                        flightgear::CameraGroup* cgroup,
-                                        osg::Camera* camera,
-                                        const osg::Matrix& view,
-                                        const osg::Matrix& projection,
-                                        osg::GraphicsContext* gc)
-{
-    osg::ref_ptr<osg::Camera> stageCamera;
-    if (stage->type == "main-camera")
-        stageCamera = camera;
-    else
-        stageCamera = new osg::Camera;
-
-    stageCamera->setName(stage->name);
-    stageCamera->setGraphicsContext(gc);
-    //stageCamera->setCullCallback(new FGStageCameraCullCallback(stage, info));
-    if (stage->type != "main-camera")
-        stageCamera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
-}
-
-void buildMainCamera(FGRenderingPipeline* rpipe, flightgear::CameraInfo* info,
-                                        FGRenderingPipeline::Stage* stage,
-                                        flightgear::CameraGroup* cgroup,
-                                        osg::Camera* camera,
-                                        const osg::Matrix& view,
-                                        const osg::Matrix& projection,
-                                        osg::GraphicsContext* gc)
-{
-}
-
-flightgear::CameraInfo* buildCameraFromRenderingPipeline(FGRenderingPipeline* rpipe, flightgear::CameraGroup* cgroup, unsigned flags, osg::Camera* camera,
-                                    const osg::Matrix& view, const osg::Matrix& projection, osg::GraphicsContext* gc)
-{
-    flightgear::CameraInfo* info = new flightgear::CameraInfo(flags);
-    buildBuffers(rpipe, info);
-    
-    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);
-    }
-
-    return 0;
-}
-
 }
 // end of renderer.cxx