]> git.mxchange.org Git - flightgear.git/commitdiff
Begin to implement configurable rendering pipeline
authorFrederic Bouvier <fredfgfs01@free.fr>
Thu, 19 Apr 2012 18:31:53 +0000 (20:31 +0200)
committerFrederic Bouvier <fredfgfs01@free.fr>
Sat, 12 May 2012 11:45:31 +0000 (13:45 +0200)
CMakeLists.txt
src/Main/CMakeLists.txt
src/Viewer/CMakeLists.txt
src/Viewer/renderer.cxx
src/Viewer/renderer.hxx
src/Viewer/renderingpipeline.cxx [new file with mode: 0644]
src/Viewer/renderingpipeline.hxx [new file with mode: 0644]

index db3892ca136348dea6e877e1b62ac52603f6e680..c3d972aba9bbf1864842e40331a1fa60144fe355 100644 (file)
@@ -151,11 +151,13 @@ if (MSVC AND MSVC_3RDPARTY_ROOT)
     if (CMAKE_CL_64)
         set( OSG_MSVC ${OSG_MSVC}-64 )
         set( MSVC_3RDPARTY_DIR 3rdParty.x64 )
+               set( BOOST_LIB lib64 )
     else (CMAKE_CL_64)
         set( MSVC_3RDPARTY_DIR 3rdParty )
+               set( BOOST_LIB lib )
     endif (CMAKE_CL_64)
 
-    set (CMAKE_LIBRARY_PATH ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/lib ${MSVC_3RDPARTY_ROOT}/install/${OSG_MSVC}/OpenScenegraph/lib ${MSVC_3RDPARTY_ROOT}/install/${OSG_MSVC}/SimGear/lib )
+    set (CMAKE_LIBRARY_PATH ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/lib ${MSVC_3RDPARTY_ROOT}/install/${OSG_MSVC}/OpenScenegraph/lib ${MSVC_3RDPARTY_ROOT}/install/${OSG_MSVC}/SimGear/lib $(BOOST_ROOT)/$(BOOST_LIB) )
     set (CMAKE_INCLUDE_PATH ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/include ${MSVC_3RDPARTY_ROOT}/install/${OSG_MSVC}/OpenScenegraph/include ${MSVC_3RDPARTY_ROOT}/install/${OSG_MSVC}/SimGear/include)
     set (BOOST_ROOT         ${MSVC_3RDPARTY_ROOT}/boost_1_44_0)
     set (OPENAL_INCLUDE_DIR ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/include)
index 017a29c8a409f95b7d55f3f46549e2c4046c0a40..92dbb7ceb3347addfea6459d620dd2df5e137309 100644 (file)
@@ -39,6 +39,8 @@ set(HEADERS
 get_property(FG_SOURCES GLOBAL PROPERTY FG_SOURCES)
 get_property(FG_HEADERS GLOBAL PROPERTY FG_HEADERS)
 
+link_directories ( ${Boost_LIBRARY_DIRS} )
+
 add_executable(fgfs ${SOURCES} ${FG_SOURCES} ${FG_HEADERS} ${HEADERS})
 
 get_property(FG_LIBS GLOBAL PROPERTY FG_LIBS)
index 7b7bd0aa38375f03f383319b40c4d5d9aef8f993..d517c72012f1a1d2f09c13f969c1a944f77b0b63 100644 (file)
@@ -8,6 +8,7 @@ set(SOURCES
        fg_os_osgviewer.cxx
        fgviewer.cxx
        renderer.cxx
+       renderingpipeline.cxx
        splash.cxx
        viewer.cxx
        viewmgr.cxx
@@ -20,6 +21,7 @@ set(HEADERS
        WindowSystemAdapter.hxx
        fgviewer.hxx
        renderer.hxx
+       renderingpipeline.hxx
        splash.hxx
        viewer.hxx
        viewmgr.hxx
index 09a742e3baaec4320b8298be90afb21c7151ba03..97aec0d3c327435e5f8c39034fcd2259dc1da23c 100644 (file)
 #include "viewer.hxx"
 #include "viewmgr.hxx"
 #include "splash.hxx"
+#include "renderingpipeline.hxx"
 #include "renderer.hxx"
 #include "CameraGroup.hxx"
 #include "FGEventHandler.hxx"
@@ -522,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);
@@ -1223,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);
index 10ae668db8c58d0bfd446684bf243566fab91323..4c7d6636c06f463cd7c282852e6ad41192fa71db 100644 (file)
@@ -40,6 +40,7 @@ class CameraGroup;
 }
 
 class SGSky;
+class FGRenderingPipeline;
 
 class FGRenderer {
 
@@ -106,6 +107,11 @@ public:
        flightgear::CameraInfo* buildDeferredPipeline(flightgear::CameraGroup* cgroup, unsigned flags, osg::Camera* camera,
                                    const osg::Matrix& view, const osg::Matrix& projection, osg::GraphicsContext* gc);
 
+       /**
+        */
+       flightgear::CameraInfo* buildDefaultDeferredPipeline(flightgear::CameraGroup* cgroup, unsigned flags, osg::Camera* camera,
+                                   const osg::Matrix& view, const osg::Matrix& projection, osg::GraphicsContext* gc);
+
     void updateShadowCamera(const flightgear::CameraInfo* info, const osg::Vec3d& position);
     void updateShadowMapSize(int mapSize);
     void enableShadows(bool enabled);
@@ -134,6 +140,7 @@ protected:
     SGTimeStamp _splash_time;
     SGSky* _sky;
     bool _classicalRenderer;
+    std::string _renderer;
     int _shadowMapSize;
     size_t _numCascades;
     float _cascadeFar[4];
@@ -154,6 +161,8 @@ protected:
     osg::ref_ptr<osg::Uniform> _shadowNumber;
     osg::ref_ptr<osg::Uniform> _shadowDistances;
     osg::ref_ptr<osg::Uniform> _depthInColor;
+
+    osg::ref_ptr<FGRenderingPipeline> _pipeline;
 };
 
 bool fgDumpSceneGraphToFile(const char* filename);
diff --git a/src/Viewer/renderingpipeline.cxx b/src/Viewer/renderingpipeline.cxx
new file mode 100644 (file)
index 0000000..dfdcf33
--- /dev/null
@@ -0,0 +1,291 @@
+// renderingpipeline.cxx -- description of the cameras needed by the Rembrandt renderer
+//
+// Written by Curtis Olson, started May 1997.
+// This file contains parts of main.cxx prior to october 2004
+//
+// Copyright (C) 1997 - 2012  Curtis L. Olson  - http://www.flightgear.org/~curt
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#ifdef HAVE_WINDOWS_H
+#  include <windows.h>
+#endif
+
+#include <boost/lexical_cast.hpp>
+
+#include <osg/GL>
+#include <osg/FrameBufferObject> // For texture formats
+
+#include <simgear/debug/logstream.hxx>
+#include <simgear/scene/util/SGReaderWriterOptions.hxx>
+#include <simgear/scene/model/modellib.hxx>
+#include <simgear/scene/material/EffectBuilder.hxx>
+#include <simgear/scene/material/EffectCullVisitor.hxx>
+#include <simgear/props/props_io.hxx>
+#include <simgear/structure/exception.hxx>
+#include <simgear/math/SGMath.hxx>
+
+#include "renderingpipeline.hxx"
+#include "CameraGroup.hxx"
+#include <Main/globals.hxx>
+#include "renderer.hxx"
+
+namespace flightgear {
+
+FGRenderingPipeline* makeRenderingPipeline(const std::string& name,
+                   const simgear::SGReaderWriterOptions* options)
+{
+    std::string fileName(name);
+    fileName += ".xml";
+    std::string absFileName
+        = simgear::SGModelLib::findDataFile(fileName, options);
+    if (absFileName.empty()) {
+        SG_LOG(SG_INPUT, SG_ALERT, "can't find \"" << fileName << "\"");
+        return 0;
+    }
+    SGPropertyNode_ptr effectProps = new SGPropertyNode();
+    try {
+        readProperties(absFileName, effectProps.ptr(), 0, true);
+    }
+    catch (sg_io_exception& e) {
+        SG_LOG(SG_INPUT, SG_ALERT, "error reading \"" << absFileName << "\": "
+               << e.getFormattedMessage());
+        return 0;
+    }
+
+    osg::ref_ptr<FGRenderingPipeline> pipeline = new FGRenderingPipeline;
+    std::vector<SGPropertyNode_ptr> buffers = effectProps->getChildren("buffer");
+    for (int i = 0; i < (int)buffers.size(); ++i) {
+        pipeline->buffers.push_back(new FGRenderingPipeline::Buffer(buffers[i]));
+    }
+
+    std::vector<SGPropertyNode_ptr> stages = effectProps->getChildren("stage");
+    for (int i = 0; i < (int)stages.size(); ++i) {
+        pipeline->stages.push_back(new FGRenderingPipeline::Stage(stages[i]));
+    }
+
+    return pipeline.release();
+}
+
+}
+
+template<typename T>
+void findAttrOrHex(const simgear::effect::EffectPropertyMap<T>& pMap,
+              const SGPropertyNode* prop,
+              T& result)
+{
+    try {
+        simgear::findAttr(pMap, prop, result);
+    } catch (simgear::effect::BuilderException&) {
+        std::string val = prop->getStringValue();
+        try {
+            result = boost::lexical_cast<T>(val);
+        } catch (boost::bad_lexical_cast &) {
+            throw simgear::effect::BuilderException(string("findAttrOrHex: could not find attribute ")
+                                   + string(val));
+        }
+    }
+}
+
+simgear::effect::EffectNameValue<GLint> internalFormatInit[] =
+{
+    { "rgb8", GL_RGB8 },
+    { "rgba8", GL_RGBA8 },
+    { "rgb16", GL_RGB16 },
+    { "rgba16", GL_RGBA16 },
+    { "rg16", 0x822C },
+    { "depth-component24", GL_DEPTH_COMPONENT24 },
+    { "depth-component32", GL_DEPTH_COMPONENT32 }
+};
+simgear::effect::EffectPropertyMap<GLint> internalFormats(internalFormatInit);
+
+simgear::effect::EffectNameValue<GLenum> sourceFormatInit[] =
+{
+    { "rg", 0x8227 },
+    { "rgb", GL_RGB },
+    { "rgba", GL_RGBA },
+    { "depth-component", GL_DEPTH_COMPONENT }
+};
+simgear::effect::EffectPropertyMap<GLenum> sourceFormats(sourceFormatInit);
+
+simgear::effect::EffectNameValue<GLenum> sourceTypeInit[] =
+{
+    { "unsigned-byte", GL_UNSIGNED_BYTE },
+    { "unsigned-short", GL_UNSIGNED_SHORT },
+    { "unsigned-int", GL_UNSIGNED_INT },
+    { "float", GL_FLOAT }
+};
+simgear::effect::EffectPropertyMap<GLenum> sourceTypes(sourceTypeInit);
+
+simgear::effect::EffectNameValue<GLenum> wrapModesInit[] =
+{
+    {"clamp", GL_CLAMP},
+    {"clamp-to-border", GL_CLAMP_TO_BORDER_ARB},
+    {"clamp-to-edge", GL_CLAMP_TO_EDGE},
+    {"mirror", GL_MIRRORED_REPEAT_IBM},
+    {"repeat", GL_REPEAT}
+};
+simgear::effect::EffectPropertyMap<GLenum> wrapModes(wrapModesInit);
+
+FGRenderingPipeline::Buffer::Buffer(SGPropertyNode* prop)
+{
+    SGPropertyNode_ptr nameProp = prop->getChild("name");
+    if (!nameProp.valid()) {
+        throw sg_exception("Buffer name is mandatory");
+    }
+    name = nameProp->getStringValue();
+    findAttrOrHex(internalFormats, prop->getChild("internal-format"), internalFormat);
+    findAttrOrHex(sourceFormats, prop->getChild("source-format"), sourceFormat);
+    findAttrOrHex(sourceTypes, prop->getChild("source-type"), sourceType);
+    findAttrOrHex(sourceTypes, prop->getChild("wrap-mode"), wrapMode);
+    SGPropertyNode_ptr widthProp = prop->getChild("width");
+    if (!widthProp.valid())
+        width = -1;
+    else if (widthProp->getStringValue() == std::string("screen"))
+        width = -1;
+    else
+        width = widthProp->getIntValue();
+    SGPropertyNode_ptr heightProp = prop->getChild("height");
+    if (!heightProp.valid())
+        height = -1;
+    else if (heightProp->getStringValue() == std::string("screen"))
+        height = -1;
+    else
+        height = heightProp->getIntValue();
+
+    scaleFactor = prop->getFloatValue("scale-factor", 1.f);
+    shadowComparison = prop->getBoolValue("shadow-comparison", false);
+}
+
+FGRenderingPipeline::Stage::Stage(SGPropertyNode* prop)
+{
+    SGPropertyNode_ptr nameProp = prop->getChild("name");
+    if (!nameProp.valid()) {
+        throw sg_exception("Stage name is mandatory");
+    }
+    name = nameProp->getStringValue();
+    SGPropertyNode_ptr typeProp = prop->getChild("type");
+    if (!typeProp.valid()) {
+        throw sg_exception("Stage type is mandatory");
+    }
+    type = typeProp->getStringValue();
+}
+
+FGRenderingPipeline::FGRenderingPipeline()
+{
+}
+
+flightgear::CameraInfo* FGRenderingPipeline::buildCamera(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( info );
+    
+    for (size_t i = 0; i < stages.size(); ++i) {
+        osg::ref_ptr<Stage> stage = stages[i];
+        buildStage(info, stage, cgroup, camera, view, projection, gc);
+    }
+
+    return 0;
+}
+
+osg::Texture2D* buildDeferredBuffer(GLint internalFormat, GLenum sourceFormat, GLenum sourceType, GLenum wrapMode, bool shadowComparison)
+{
+    osg::Texture2D* tex = new osg::Texture2D;
+    tex->setResizeNonPowerOfTwoHint( false );
+    tex->setInternalFormat( internalFormat );
+    tex->setShadowComparison(shadowComparison);
+    if (shadowComparison) {
+        tex->setShadowTextureMode(osg::Texture2D::LUMINANCE);
+        tex->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
+    }
+    tex->setSourceFormat(sourceFormat);
+    tex->setSourceType(sourceType);
+    tex->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR );
+    tex->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR );
+    tex->setWrap( osg::Texture::WRAP_S, (osg::Texture::WrapMode)wrapMode );
+    tex->setWrap( osg::Texture::WRAP_T, (osg::Texture::WrapMode)wrapMode );
+       return tex;
+}
+
+void FGRenderingPipeline::buildBuffers( flightgear::CameraInfo* info )
+{
+    for (size_t i = 0; i < buffers.size(); ++i) {
+        osg::ref_ptr<Buffer> buffer = buffers[i];
+        info->addBuffer(buffer->name, buildDeferredBuffer( buffer->internalFormat,
+                                                            buffer->sourceFormat,
+                                                            buffer->sourceType,
+                                                            buffer->wrapMode,
+                                                            buffer->shadowComparison) );
+    }
+}
+
+class FGStageCameraCullCallback : public osg::NodeCallback {
+public:
+    FGStageCameraCullCallback(FGRenderingPipeline::Stage* s, flightgear::CameraInfo* i) : stage(s), 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();
+        for (flightgear::RenderBufferMap::iterator ii = info->buffers.begin(); ii != info->buffers.end(); ++ii) {
+            cv->addBuffer(ii->first, ii->second.texture );
+        }
+
+               if ( !info->getRenderStageInfo(stage->name).fullscreen )
+                       info->setMatrices( camera );
+
+        cv->traverse( *camera );
+    }
+
+private:
+    osg::ref_ptr<FGRenderingPipeline::Stage> stage;
+    flightgear::CameraInfo* info;
+};
+
+void FGRenderingPipeline::buildStage(flightgear::CameraInfo* info,
+                                        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 FGRenderingPipeline::buildMainCamera(flightgear::CameraInfo* info,
+                                        Stage* stage,
+                                        flightgear::CameraGroup* cgroup,
+                                        osg::Camera* camera,
+                                        const osg::Matrix& view,
+                                        const osg::Matrix& projection,
+                                        osg::GraphicsContext* gc)
+{
+}
diff --git a/src/Viewer/renderingpipeline.hxx b/src/Viewer/renderingpipeline.hxx
new file mode 100644 (file)
index 0000000..875294f
--- /dev/null
@@ -0,0 +1,90 @@
+
+#ifndef __FG_RENDERINGPIPELINE_HXX
+#define __FG_RENDERINGPIPELINE_HXX 1
+
+#include <osg/ref_ptr>
+#include <string>
+
+namespace simgear
+{
+class SGReaderWriterOptions;
+}
+namespace flightgear
+{
+struct CameraInfo;
+class CameraGroup;
+}
+
+class FGRenderingPipeline;
+namespace flightgear {
+    FGRenderingPipeline* makeRenderingPipeline(const std::string& name,
+                   const simgear::SGReaderWriterOptions* options);
+}
+
+class FGRenderingPipeline : public osg::Referenced {
+public:
+    struct Buffer : public osg::Referenced {
+        Buffer(SGPropertyNode* prop);
+
+        std::string name;
+        GLint internalFormat;
+        GLenum sourceFormat;
+        GLenum sourceType;
+        int width;
+        int height;
+        float scaleFactor;
+        GLenum wrapMode;
+               bool shadowComparison;
+               //GLenum shadowTextureMode;
+               //osg::Vec4 borderColor;
+    };
+
+    struct Pass : public osg::Referenced {
+        Pass(SGPropertyNode* prop);
+
+        std::string name;
+        std::string type;
+    };
+
+    struct Stage : public osg::Referenced {
+        Stage(SGPropertyNode* prop);
+
+        std::string name;
+        std::string type;
+
+        std::vector<osg::ref_ptr<Pass> > passes;
+    };
+    FGRenderingPipeline();
+
+    flightgear::CameraInfo* buildCamera(flightgear::CameraGroup* cgroup,
+                                        unsigned flags,
+                                        osg::Camera* camera,
+                                        const osg::Matrix& view,
+                                        const osg::Matrix& projection,
+                                        osg::GraphicsContext* gc);
+
+private:
+    std::vector<osg::ref_ptr<Buffer> > buffers;
+    std::vector<osg::ref_ptr<Stage> > stages;
+
+    void buildBuffers(flightgear::CameraInfo* info);
+    void buildStage(flightgear::CameraInfo* info,
+                    Stage* stage,
+                    flightgear::CameraGroup* cgroup,
+                    osg::Camera* camera,
+                    const osg::Matrix& view,
+                    const osg::Matrix& projection,
+                    osg::GraphicsContext* gc);
+    void buildMainCamera(flightgear::CameraInfo* info,
+                    Stage* stage,
+                    flightgear::CameraGroup* cgroup,
+                    osg::Camera* camera,
+                    const osg::Matrix& view,
+                    const osg::Matrix& projection,
+                    osg::GraphicsContext* gc);
+
+    friend FGRenderingPipeline* flightgear::makeRenderingPipeline(const std::string& name,
+                   const simgear::SGReaderWriterOptions* options);
+};
+
+#endif