]> git.mxchange.org Git - flightgear.git/blobdiff - src/Viewer/renderer.cxx
Begin to implement configurable rendering pipeline
[flightgear.git] / src / Viewer / renderer.cxx
index 4e11982c1ba449afc6b1e8285a3e98303c939715..97aec0d3c327435e5f8c39034fcd2259dc1da23c 100644 (file)
@@ -64,7 +64,6 @@
 #include <osgDB/WriteFile>
 #include <osgViewer/Renderer>
 
-#include <simgear/math/SGMath.hxx>
 #include <simgear/scene/material/matlib.hxx>
 #include <simgear/scene/material/EffectCullVisitor.hxx>
 #include <simgear/scene/material/Effect.hxx>
 #include "viewer.hxx"
 #include "viewmgr.hxx"
 #include "splash.hxx"
+#include "renderingpipeline.hxx"
 #include "renderer.hxx"
 #include "CameraGroup.hxx"
 #include "FGEventHandler.hxx"
@@ -523,6 +523,9 @@ FGRenderer::init( void )
     _useColorForDepth = fgGetBool( "/sim/rendering/use-color-for-depth", false );
     _depthInColor->set( _useColorForDepth );
 
+    _renderer         = fgGetString("/sim/rendering/renderer", "");
+    if (!_classicalRenderer && !_renderer.empty())
+        _pipeline = makeRenderingPipeline(_renderer, 0);
     _scenery_loaded   = fgGetNode("/sim/sceneryloaded", true);
     _scenery_override = fgGetNode("/sim/sceneryloaded-override", true);
     _panel_hotspots   = fgGetNode("/sim/panel-hotspots", true);
@@ -687,39 +690,39 @@ FGRenderer::buildClassicalPipeline(flightgear::CameraGroup* cgroup, unsigned fla
 
 class FGDeferredRenderingCameraCullCallback : public osg::NodeCallback {
 public:
-    FGDeferredRenderingCameraCullCallback( flightgear::CameraKind k, CameraInfo* i ) : kind( k ), info( i ) {}
+    FGDeferredRenderingCameraCullCallback( const std::string& k, CameraInfo* i ) : kind( k ), info( i ) {}
     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(simgear::Effect::DEPTH_BUFFER, info->getBuffer( flightgear::RenderBufferInfo::DEPTH_BUFFER ) );
-    cv->addBuffer(simgear::Effect::NORMAL_BUFFER, info->getBuffer( flightgear::RenderBufferInfo::NORMAL_BUFFER ) );
-    cv->addBuffer(simgear::Effect::DIFFUSE_BUFFER, info->getBuffer( flightgear::RenderBufferInfo::DIFFUSE_BUFFER ) );
-    cv->addBuffer(simgear::Effect::SPEC_EMIS_BUFFER, info->getBuffer( flightgear::RenderBufferInfo::SPEC_EMIS_BUFFER ) );
-    cv->addBuffer(simgear::Effect::LIGHTING_BUFFER, info->getBuffer( flightgear::RenderBufferInfo::LIGHTING_BUFFER ) );
-    cv->addBuffer(simgear::Effect::SHADOW_BUFFER, info->getBuffer( flightgear::RenderBufferInfo::SHADOW_BUFFER ) );
-    // cv->addBuffer(simgear::Effect::AO_BUFFER, info->gBuffer->aoBuffer[2]);
-
-    if ( !info->getRenderStageInfo(kind).fullscreen )
-        info->setMatrices( camera );
-
-    cv->traverse( *camera );
-
-    if ( kind == flightgear::GEOMETRY_CAMERA ) {
-        // Save transparent bins to render later
-        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;
+        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]);
+
+        if ( !info->getRenderStageInfo(kind).fullscreen )
+            info->setMatrices( camera );
+
+        cv->traverse( *camera );
+
+        if ( kind == flightgear::GEOMETRY_CAMERA ) {
+            // Save transparent bins to render later
+            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;
+                }
             }
-        }
-    } else if ( kind == flightgear::LIGHTING_CAMERA ) {
-        osg::ref_ptr<osg::Camera> mainShadowCamera = info->getCamera( SHADOW_CAMERA );
+        } else if ( kind == flightgear::LIGHTING_CAMERA ) {
+            osg::ref_ptr<osg::Camera> mainShadowCamera = info->getCamera( SHADOW_CAMERA );
             if (mainShadowCamera.valid()) {
                 osg::Switch* grp = mainShadowCamera->getChild(0)->asSwitch();
                 for (int i = 0; i < 4; ++i ) {
@@ -750,7 +753,7 @@ public:
     }
 
 private:
-    flightgear::CameraKind kind;
+    std::string kind;
     CameraInfo* info;
 };
 
@@ -776,21 +779,21 @@ osg::Texture2D* buildDeferredBuffer(GLint internalFormat, GLenum sourceFormat, G
 void buildDeferredBuffers( flightgear::CameraInfo* info, int shadowMapSize, bool useColorForDepth )
 {
     if (useColorForDepth) {
-        info->addBuffer(flightgear::RenderBufferInfo::REAL_DEPTH_BUFFER, buildDeferredBuffer( GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT, osg::Texture::CLAMP_TO_BORDER) );
-        info->addBuffer(flightgear::RenderBufferInfo::DEPTH_BUFFER, buildDeferredBuffer( GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, osg::Texture::CLAMP_TO_BORDER) );
+        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(flightgear::RenderBufferInfo::DEPTH_BUFFER, buildDeferredBuffer( GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT, osg::Texture::CLAMP_TO_BORDER) );
+        info->addBuffer("depth", buildDeferredBuffer( GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT, osg::Texture::CLAMP_TO_BORDER) );
     }
-    info->addBuffer(flightgear::RenderBufferInfo::NORMAL_BUFFER, buildDeferredBuffer( GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, osg::Texture::CLAMP_TO_BORDER) );
-    info->addBuffer(flightgear::RenderBufferInfo::DIFFUSE_BUFFER, buildDeferredBuffer( GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, osg::Texture::CLAMP_TO_BORDER) );
-    info->addBuffer(flightgear::RenderBufferInfo::SPEC_EMIS_BUFFER, buildDeferredBuffer( GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, osg::Texture::CLAMP_TO_BORDER) );
-    info->addBuffer(flightgear::RenderBufferInfo::LIGHTING_BUFFER, buildDeferredBuffer( GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, osg::Texture::CLAMP_TO_BORDER) );
-    info->addBuffer(flightgear::RenderBufferInfo::SHADOW_BUFFER, buildDeferredBuffer( GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT, osg::Texture::CLAMP_TO_BORDER, true), 0.0f );
-    info->getBuffer(RenderBufferInfo::SHADOW_BUFFER)->setTextureSize(shadowMapSize,shadowMapSize);
+    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, flightgear::CameraKind ck, flightgear::RenderBufferInfo::Kind bk )
+void attachBufferToCamera( flightgear::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 ) );
@@ -810,14 +813,14 @@ osg::Camera* FGRenderer::buildDeferredGeometryCamera( flightgear::CameraInfo* in
     camera->setClearDepth( 1.0 );
     camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
     camera->setViewport( new osg::Viewport );
-    attachBufferToCamera( info, camera, osg::Camera::COLOR_BUFFER0, flightgear::GEOMETRY_CAMERA, flightgear::RenderBufferInfo::NORMAL_BUFFER );
-    attachBufferToCamera( info, camera, osg::Camera::COLOR_BUFFER1, flightgear::GEOMETRY_CAMERA, flightgear::RenderBufferInfo::DIFFUSE_BUFFER );
-    attachBufferToCamera( info, camera, osg::Camera::COLOR_BUFFER2, flightgear::GEOMETRY_CAMERA, flightgear::RenderBufferInfo::SPEC_EMIS_BUFFER );
+    attachBufferToCamera( info, camera, osg::Camera::COLOR_BUFFER0, flightgear::GEOMETRY_CAMERA, "normal" );
+    attachBufferToCamera( info, camera, osg::Camera::COLOR_BUFFER1, flightgear::GEOMETRY_CAMERA, "diffuse" );
+    attachBufferToCamera( info, camera, osg::Camera::COLOR_BUFFER2, flightgear::GEOMETRY_CAMERA, "spec-emis" );
     if (_useColorForDepth) {
-        attachBufferToCamera( info, camera, osg::Camera::DEPTH_BUFFER, flightgear::GEOMETRY_CAMERA, flightgear::RenderBufferInfo::REAL_DEPTH_BUFFER );
-        attachBufferToCamera( info, camera, osg::Camera::COLOR_BUFFER3, flightgear::GEOMETRY_CAMERA, flightgear::RenderBufferInfo::DEPTH_BUFFER );
+        attachBufferToCamera( info, camera, osg::Camera::DEPTH_BUFFER, flightgear::GEOMETRY_CAMERA, "real-depth" );
+        attachBufferToCamera( info, camera, osg::Camera::COLOR_BUFFER3, flightgear::GEOMETRY_CAMERA, "depth" );
     } else {
-        attachBufferToCamera( info, camera, osg::Camera::DEPTH_BUFFER, flightgear::GEOMETRY_CAMERA, flightgear::RenderBufferInfo::DEPTH_BUFFER );
+        attachBufferToCamera( info, camera, osg::Camera::DEPTH_BUFFER, flightgear::GEOMETRY_CAMERA, "depth" );
     }
     camera->setDrawBuffer(GL_FRONT);
     camera->setReadBuffer(GL_FRONT);
@@ -879,7 +882,7 @@ osg::Camera* FGRenderer::buildDeferredShadowCamera( flightgear::CameraInfo* info
     mainShadowCamera->setAllowEventFocus(false);
     mainShadowCamera->setGraphicsContext(gc);
     mainShadowCamera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
-    attachBufferToCamera( info, mainShadowCamera, osg::Camera::DEPTH_BUFFER, flightgear::SHADOW_CAMERA, flightgear::RenderBufferInfo::SHADOW_BUFFER );
+    attachBufferToCamera( info, mainShadowCamera, osg::Camera::DEPTH_BUFFER, flightgear::SHADOW_CAMERA, "shadow" );
     mainShadowCamera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
     mainShadowCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
     mainShadowCamera->setProjectionMatrix(osg::Matrix::identity());
@@ -1003,7 +1006,7 @@ void FGRenderer::updateShadowMapSize(int mapSize)
         Camera* camera = info->getCamera(SHADOW_CAMERA);
         if (camera == 0) continue;
 
-        Texture2D* tex = info->getBuffer(RenderBufferInfo::SHADOW_BUFFER);
+        Texture2D* tex = info->getBuffer("shadow");
         if (tex == 0) continue;
 
         tex->setTextureSize( mapSize, mapSize );
@@ -1074,183 +1077,6 @@ void FGRenderer::updateCascadeNumber(size_t num)
     _shadowNumber->set( (int)_numCascades );
 }
 
-
-#define STRINGIFY(x) #x
-#define TOSTRING(x) STRINGIFY(x)
-
-const char *ambient_vert_src = ""
-    "#line " TOSTRING(__LINE__) " 1\n"
-    "void main() {\n"
-    "    gl_Position = gl_Vertex;\n"
-    "    gl_TexCoord[0] = gl_MultiTexCoord0;\n"
-    "}\n";
-
-const char *ambient_frag_src = ""
-    "#line " TOSTRING(__LINE__) " 1\n"
-    "uniform sampler2D color_tex;\n"
-//    "uniform sampler2D ao_tex;\n"
-    "uniform sampler2D normal_tex;\n"
-    "uniform sampler2D spec_emis_tex;\n"
-    "uniform vec4 fg_SunAmbientColor;\n"
-    "void main() {\n"
-    "    vec2 coords = gl_TexCoord[0].xy;\n"
-    "    float initialized = texture2D( spec_emis_tex, coords ).a;\n"
-    "    if ( initialized < 0.1 )\n"
-    "        discard;\n"
-    "    vec3 tcolor = texture2D( color_tex, coords ).rgb;\n"
-//    "    float ao = texture2D( ao_tex, coords ).r;\n"
-//    "    gl_FragColor = vec4(tcolor*fg_SunAmbientColor.rgb*ao, 1.0);\n"
-    "    gl_FragColor = vec4(tcolor*fg_SunAmbientColor.rgb, 1.0);\n"
-    "}\n";
-
-const char *sunlight_vert_src = ""
-    "#line " TOSTRING(__LINE__) " 1\n"
-//  "uniform mat4 fg_ViewMatrixInverse;\n"
-    "uniform mat4 fg_ProjectionMatrixInverse;\n"
-    "varying vec3 ray;\n"
-    "void main() {\n"
-    "    gl_Position = gl_Vertex;\n"
-    "    gl_TexCoord[0] = gl_MultiTexCoord0;\n"
-//  "    ray = (fg_ViewMatrixInverse * vec4((fg_ProjectionMatrixInverse * gl_Vertex).xyz, 0.0)).xyz;\n"
-    "    ray = (fg_ProjectionMatrixInverse * gl_Vertex).xyz;\n"
-    "}\n";
-
-const char *sunlight_frag_src = ""
-#if 0
-    "#version 130\n"
-#endif
-    "#line " TOSTRING(__LINE__) " 1\n"
-    "uniform mat4 fg_ViewMatrix;\n"
-    "uniform sampler2D depth_tex;\n"
-    "uniform sampler2D normal_tex;\n"
-    "uniform sampler2D color_tex;\n"
-    "uniform sampler2D spec_emis_tex;\n"
-    "uniform sampler2DShadow shadow_tex;\n"
-    "uniform vec4 fg_SunDiffuseColor;\n"
-    "uniform vec4 fg_SunSpecularColor;\n"
-    "uniform vec3 fg_SunDirection;\n"
-    "uniform vec3 fg_Planes;\n"
-    "varying vec3 ray;\n"
-    "vec4 DynamicShadow( in vec4 ecPosition, out vec4 tint )\n"
-    "{\n"
-    "    vec4 coords;\n"
-    "    vec2 shift = vec2( 0.0 );\n"
-    "    int index = 4;\n"
-    "    if (ecPosition.z > -5.0) {\n"
-    "        index = 1;\n"
-    "        tint = vec4(0.0,1.0,0.0,1.0);\n"
-    "    } else if (ecPosition.z > -50.0) {\n"
-    "        index = 2;\n"
-    "        shift = vec2( 0.0, 0.5 );\n"
-    "        tint = vec4(0.0,0.0,1.0,1.0);\n"
-    "    } else if (ecPosition.z > -512.0) {\n"
-    "        index = 3;\n"
-    "        shift = vec2( 0.5, 0.0 );\n"
-    "        tint = vec4(1.0,1.0,0.0,1.0);\n"
-    "    } else if (ecPosition.z > -10000.0) {\n"
-    "        shift = vec2( 0.5, 0.5 );\n"
-    "        tint = vec4(1.0,0.0,0.0,1.0);\n"
-    "    } else {\n"
-    "        return vec4(1.1,1.1,0.0,1.0);\n" // outside, clamp to border
-    "    }\n"
-    "    coords.s = dot( ecPosition, gl_EyePlaneS[index] );\n"
-    "    coords.t = dot( ecPosition, gl_EyePlaneT[index] );\n"
-    "    coords.p = dot( ecPosition, gl_EyePlaneR[index] );\n"
-    "    coords.q = dot( ecPosition, gl_EyePlaneQ[index] );\n"
-    "    coords.st *= .5;\n"
-    "    coords.st += shift;\n"
-    "    return coords;\n"
-    "}\n"
-    "void main() {\n"
-    "    vec2 coords = gl_TexCoord[0].xy;\n"
-    "    vec4 spec_emis = texture2D( spec_emis_tex, coords );\n"
-    "    if ( spec_emis.a < 0.1 )\n"
-    "        discard;\n"
-    "    vec3 normal;\n"
-    "    normal.xy = texture2D( normal_tex, coords ).rg * 2.0 - vec2(1.0,1.0);\n"
-    "    normal.z = sqrt( 1.0 - dot( normal.xy, normal.xy ) );\n"
-    "    float len = length(normal);\n"
-    "    normal /= len;\n"
-    "    vec3 viewDir = normalize(ray);\n"
-    "    float depth = texture2D( depth_tex, coords ).r;\n"
-    "    vec3 pos;\n"
-    "    pos.z = - fg_Planes.y / (fg_Planes.x + depth * fg_Planes.z);\n"
-    "    pos.xy = viewDir.xy / viewDir.z * pos.z;\n"
-
-    "    vec4 tint;\n"
-#if 0
-    "    float shadow = 1.0;\n"
-#elif 1
-    "    float shadow = shadow2DProj( shadow_tex, DynamicShadow( vec4( pos, 1.0 ), tint ) ).r;\n"
-#else
-    "    float kernel[9] = float[]( 36/256.0, 24/256.0, 6/256.0,\n"
-    "                           24/256.0, 16/256.0, 4/256.0,\n"
-    "                           6/256.0,  4/256.0, 1/256.0 );\n"
-    "    float shadow = 0;\n"
-    "    for( int x = -2; x <= 2; ++x )\n"
-    "      for( int y = -2; y <= 2; ++y )\n"
-    "        shadow += kernel[abs(x)*3 + abs(y)] * shadow2DProj( shadow_tex, DynamicShadow( vec4(pos + vec3(0.05 * x, 0.05 * y, 0), 1.0), tint ) ).r;\n"
-#endif
-    "    vec3 lightDir = (fg_ViewMatrix * vec4( fg_SunDirection, 0.0 )).xyz;\n"
-    "    lightDir = normalize( lightDir );\n"
-    "    vec3 color = texture2D( color_tex, coords ).rgb;\n"
-    "    vec3 Idiff = clamp( dot( lightDir, normal ), 0.0, 1.0 ) * color * fg_SunDiffuseColor.rgb;\n"
-    "    vec3 halfDir = lightDir - viewDir;\n"
-    "    len = length( halfDir );\n"
-    "    vec3 Ispec = vec3(0.0);\n"
-    "    vec3 Iemis = spec_emis.z * color;\n"
-    "    if (len > 0.0001) {\n"
-    "        halfDir /= len;\n"
-    "        Ispec = pow( clamp( dot( halfDir, normal ), 0.0, 1.0 ), spec_emis.y * 255.0 ) * spec_emis.x * fg_SunSpecularColor.rgb;\n"
-    "    }\n"
-    "    gl_FragColor = vec4(mix(vec3(0.0), Idiff + Ispec, shadow) + Iemis, 1.0);\n"
-//    "    gl_FragColor = mix(tint, vec4(mix(vec3(0.0), Idiff + Ispec, shadow) + Iemis, 1.0), 0.92);\n"
-    "}\n";
-
-const char *fog_vert_src = ""
-    "#line " TOSTRING(__LINE__) " 1\n"
-    "uniform mat4 fg_ProjectionMatrixInverse;\n"
-    "varying vec3 ray;\n"
-    "void main() {\n"
-    "    gl_Position = gl_Vertex;\n"
-    "    gl_TexCoord[0] = gl_MultiTexCoord0;\n"
-    "    ray = (fg_ProjectionMatrixInverse * gl_Vertex).xyz;\n"
-    "}\n";
-
-const char *fog_frag_src = ""
-    "#line " TOSTRING(__LINE__) " 1\n"
-    "uniform sampler2D depth_tex;\n"
-    "uniform sampler2D normal_tex;\n"
-    "uniform sampler2D color_tex;\n"
-    "uniform sampler2D spec_emis_tex;\n"
-    "uniform vec4 fg_FogColor;\n"
-    "uniform float fg_FogDensity;\n"
-    "uniform vec3 fg_Planes;\n"
-    "varying vec3 ray;\n"
-    "void main() {\n"
-    "    vec2 coords = gl_TexCoord[0].xy;\n"
-    "    float initialized = texture2D( spec_emis_tex, coords ).a;\n"
-    "    if ( initialized < 0.1 )\n"
-    "        discard;\n"
-    "    vec3 normal;\n"
-    "    normal.xy = texture2D( normal_tex, coords ).rg * 2.0 - vec2(1.0,1.0);\n"
-    "    normal.z = sqrt( 1.0 - dot( normal.xy, normal.xy ) );\n"
-    "    float len = length(normal);\n"
-    "    normal /= len;\n"
-    "    vec3 viewDir = normalize(ray);\n"
-    "    float depth = texture2D( depth_tex, coords ).r;\n"
-    "    vec3 pos;\n"
-    "    pos.z = - fg_Planes.y / (fg_Planes.x + depth * fg_Planes.z);\n"
-    "    pos.xy = viewDir.xy / viewDir.z * pos.z;\n"
-
-    "    float fogFactor = 0.0;\n"
-    "    const float LOG2 = 1.442695;\n"
-    "    fogFactor = exp2(-fg_FogDensity * fg_FogDensity * pos.z * pos.z * LOG2);\n"
-    "    fogFactor = clamp(fogFactor, 0.0, 1.0);\n"
-
-    "    gl_FragColor = vec4(fg_FogColor.rgb, 1.0 - fogFactor);\n"
-    "}\n";
-
 osg::Camera* FGRenderer::buildDeferredLightingCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc )
 {
     osg::Camera* camera = new osg::Camera;
@@ -1265,11 +1091,11 @@ osg::Camera* FGRenderer::buildDeferredLightingCamera( flightgear::CameraInfo* in
     camera->setRenderOrder(osg::Camera::POST_RENDER, 50);
     camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT );
     camera->setViewport( new osg::Viewport );
-    attachBufferToCamera( info, camera, osg::Camera::COLOR_BUFFER, flightgear::LIGHTING_CAMERA, flightgear::RenderBufferInfo::LIGHTING_BUFFER );
+    attachBufferToCamera( info, camera, osg::Camera::COLOR_BUFFER, flightgear::LIGHTING_CAMERA, "lighting" );
     if (_useColorForDepth) {
-        attachBufferToCamera( info, camera, osg::Camera::DEPTH_BUFFER, flightgear::GEOMETRY_CAMERA, flightgear::RenderBufferInfo::REAL_DEPTH_BUFFER );
+        attachBufferToCamera( info, camera, osg::Camera::DEPTH_BUFFER, flightgear::GEOMETRY_CAMERA, "real-depth" );
     } else {
-        attachBufferToCamera( info, camera, osg::Camera::DEPTH_BUFFER, flightgear::GEOMETRY_CAMERA, flightgear::RenderBufferInfo::DEPTH_BUFFER );
+        attachBufferToCamera( info, camera, osg::Camera::DEPTH_BUFFER, flightgear::GEOMETRY_CAMERA, "depth" );
     }
     camera->setDrawBuffer(GL_FRONT);
     camera->setReadBuffer(GL_FRONT);
@@ -1306,30 +1132,11 @@ osg::Camera* FGRenderer::buildDeferredLightingCamera( flightgear::CameraInfo* in
     g->setUseDisplayList(false);
     simgear::EffectGeode* eg = new simgear::EffectGeode;
     simgear::Effect* effect = simgear::makeEffect("Effects/ambient", true);
-    if (effect) {
-        eg->setEffect( effect );
-    } else {
-        SG_LOG( SG_VIEW, SG_ALERT, "=> Using default, builtin, Effects/ambient" );
-        ss = eg->getOrCreateStateSet();
-        ss->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
-        ss->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
-        ss->setTextureAttributeAndModes( 0, info->getBuffer( flightgear::RenderBufferInfo::DEPTH_BUFFER ) );
-        ss->setTextureAttributeAndModes( 1, info->getBuffer( flightgear::RenderBufferInfo::NORMAL_BUFFER ) );
-        ss->setTextureAttributeAndModes( 2, info->getBuffer( flightgear::RenderBufferInfo::DIFFUSE_BUFFER ) );
-        ss->setTextureAttributeAndModes( 3, info->getBuffer( flightgear::RenderBufferInfo::SPEC_EMIS_BUFFER ) );
-        //ss->setTextureAttributeAndModes( 4, info->gBuffer->aoBuffer[2] );
-        ss->addUniform( new osg::Uniform( "depth_tex", 0 ) );
-        ss->addUniform( new osg::Uniform( "normal_tex", 1 ) );
-        ss->addUniform( new osg::Uniform( "color_tex", 2 ) );
-        ss->addUniform( new osg::Uniform( "spec_emis_tex", 3 ) );
-        //ss->addUniform( new osg::Uniform( "ao_tex", 4 ) );
-        ss->setRenderBinDetails( 0, "RenderBin" );
-        osg::Program* program = new osg::Program;
-        program->addShader( new osg::Shader( osg::Shader::VERTEX, ambient_vert_src ) );
-        program->addShader( new osg::Shader( osg::Shader::FRAGMENT, ambient_frag_src ) );
-        ss->setAttributeAndModes( program );
+    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);
@@ -1341,30 +1148,11 @@ osg::Camera* FGRenderer::buildDeferredLightingCamera( flightgear::CameraInfo* in
     g->setName( "SunlightQuad" );
     eg = new simgear::EffectGeode;
     effect = simgear::makeEffect("Effects/sunlight", true);
-    if (effect) {
-        eg->setEffect( effect );
-    } else {
-        SG_LOG( SG_VIEW, SG_ALERT, "=> Using default, builtin, Effects/sunlight" );
-        ss = eg->getOrCreateStateSet();
-        ss->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
-        ss->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
-        ss->setAttributeAndModes( new osg::BlendFunc( osg::BlendFunc::ONE, osg::BlendFunc::ONE ) );
-        ss->setTextureAttribute( 0, info->getBuffer( flightgear::RenderBufferInfo::DEPTH_BUFFER ) );
-        ss->setTextureAttribute( 1, info->getBuffer( flightgear::RenderBufferInfo::NORMAL_BUFFER ) );
-        ss->setTextureAttribute( 2, info->getBuffer( flightgear::RenderBufferInfo::DIFFUSE_BUFFER ) );
-        ss->setTextureAttribute( 3, info->getBuffer( flightgear::RenderBufferInfo::SPEC_EMIS_BUFFER ) );
-        ss->setTextureAttribute( 4, info->getBuffer( flightgear::RenderBufferInfo::SHADOW_BUFFER ) );
-        ss->addUniform( new osg::Uniform( "depth_tex", 0 ) );
-        ss->addUniform( new osg::Uniform( "normal_tex", 1 ) );
-        ss->addUniform( new osg::Uniform( "color_tex", 2 ) );
-        ss->addUniform( new osg::Uniform( "spec_emis_tex", 3 ) );
-        ss->addUniform( new osg::Uniform( "shadow_tex", 4 ) );
-        ss->setRenderBinDetails( 1, "RenderBin" );
-        osg::Program* program = new osg::Program;
-        program->addShader( new osg::Shader( osg::Shader::VERTEX, sunlight_vert_src ) );
-        program->addShader( new osg::Shader( osg::Shader::FRAGMENT, sunlight_frag_src ) );
-        ss->setAttributeAndModes( program );
+    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);
@@ -1413,28 +1201,11 @@ osg::Camera* FGRenderer::buildDeferredLightingCamera( flightgear::CameraInfo* in
     g->setName( "FogQuad" );
     eg = new simgear::EffectGeode;
     effect = simgear::makeEffect("Effects/fog", true);
-    if (effect) {
-        eg->setEffect( effect );
-    } else {
-        SG_LOG( SG_VIEW, SG_ALERT, "=> Using default, builtin, Effects/fog" );
-        ss = eg->getOrCreateStateSet();
-        ss->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
-        ss->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
-        ss->setAttributeAndModes( new osg::BlendFunc( osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA ) );
-        ss->setTextureAttributeAndModes( 0, info->getBuffer( flightgear::RenderBufferInfo::DEPTH_BUFFER ) );
-        ss->setTextureAttributeAndModes( 1, info->getBuffer( flightgear::RenderBufferInfo::NORMAL_BUFFER ) );
-        ss->setTextureAttributeAndModes( 2, info->getBuffer( flightgear::RenderBufferInfo::DIFFUSE_BUFFER ) );
-        ss->setTextureAttributeAndModes( 3, info->getBuffer( flightgear::RenderBufferInfo::SPEC_EMIS_BUFFER ) );
-        ss->addUniform( new osg::Uniform( "depth_tex", 0 ) );
-        ss->addUniform( new osg::Uniform( "normal_tex", 1 ) );
-        ss->addUniform( new osg::Uniform( "color_tex", 2 ) );
-        ss->addUniform( new osg::Uniform( "spec_emis_tex", 3 ) );
-        ss->setRenderBinDetails( 10000, "RenderBin" );
-        osg::Program* program = new osg::Program;
-        program->addShader( new osg::Shader( osg::Shader::VERTEX, fog_vert_src ) );
-        program->addShader( new osg::Shader( osg::Shader::FRAGMENT, fog_frag_src ) );
-        ss->setAttributeAndModes( program );
+    if (!effect) {
+        SG_LOG(SG_VIEW, SG_ALERT, "Effects/fog not found");
+        return 0;
     }
+    eg->setEffect( effect );
     eg->setName("FogQuad");
     eg->setCullingActive(false);
     eg->addDrawable(g);
@@ -1456,6 +1227,17 @@ FGRenderer::buildDeferredPipeline(flightgear::CameraGroup* cgroup, unsigned flag
                                     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 _pipeline->buildCamera(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)
 {
     CameraInfo* info = new CameraInfo(flags);
     buildDeferredBuffers(info, _shadowMapSize, _useColorForDepth);