From 6b008126b5fd99c38778c6293c15f9721a4fa509 Mon Sep 17 00:00:00 2001 From: Frederic Bouvier Date: Thu, 19 Apr 2012 20:31:53 +0200 Subject: [PATCH] Begin to implement configurable rendering pipeline --- CMakeLists.txt | 4 +- src/Main/CMakeLists.txt | 2 + src/Viewer/CMakeLists.txt | 2 + src/Viewer/renderer.cxx | 15 ++ src/Viewer/renderer.hxx | 9 + src/Viewer/renderingpipeline.cxx | 291 +++++++++++++++++++++++++++++++ src/Viewer/renderingpipeline.hxx | 90 ++++++++++ 7 files changed, 412 insertions(+), 1 deletion(-) create mode 100644 src/Viewer/renderingpipeline.cxx create mode 100644 src/Viewer/renderingpipeline.hxx diff --git a/CMakeLists.txt b/CMakeLists.txt index db3892ca1..c3d972aba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/src/Main/CMakeLists.txt b/src/Main/CMakeLists.txt index 017a29c8a..92dbb7ceb 100644 --- a/src/Main/CMakeLists.txt +++ b/src/Main/CMakeLists.txt @@ -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) diff --git a/src/Viewer/CMakeLists.txt b/src/Viewer/CMakeLists.txt index 7b7bd0aa3..d517c7201 100644 --- a/src/Viewer/CMakeLists.txt +++ b/src/Viewer/CMakeLists.txt @@ -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 diff --git a/src/Viewer/renderer.cxx b/src/Viewer/renderer.cxx index 09a742e3b..97aec0d3c 100644 --- a/src/Viewer/renderer.cxx +++ b/src/Viewer/renderer.cxx @@ -103,6 +103,7 @@ #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); diff --git a/src/Viewer/renderer.hxx b/src/Viewer/renderer.hxx index 10ae668db..4c7d6636c 100644 --- a/src/Viewer/renderer.hxx +++ b/src/Viewer/renderer.hxx @@ -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 _shadowNumber; osg::ref_ptr _shadowDistances; osg::ref_ptr _depthInColor; + + osg::ref_ptr _pipeline; }; bool fgDumpSceneGraphToFile(const char* filename); diff --git a/src/Viewer/renderingpipeline.cxx b/src/Viewer/renderingpipeline.cxx new file mode 100644 index 000000000..dfdcf3388 --- /dev/null +++ b/src/Viewer/renderingpipeline.cxx @@ -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 +#endif + +#ifdef HAVE_WINDOWS_H +# include +#endif + +#include + +#include +#include // For texture formats + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "renderingpipeline.hxx" +#include "CameraGroup.hxx" +#include
+#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 pipeline = new FGRenderingPipeline; + std::vector buffers = effectProps->getChildren("buffer"); + for (int i = 0; i < (int)buffers.size(); ++i) { + pipeline->buffers.push_back(new FGRenderingPipeline::Buffer(buffers[i])); + } + + std::vector 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 +void findAttrOrHex(const simgear::effect::EffectPropertyMap& 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(val); + } catch (boost::bad_lexical_cast &) { + throw simgear::effect::BuilderException(string("findAttrOrHex: could not find attribute ") + + string(val)); + } + } +} + +simgear::effect::EffectNameValue 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 internalFormats(internalFormatInit); + +simgear::effect::EffectNameValue sourceFormatInit[] = +{ + { "rg", 0x8227 }, + { "rgb", GL_RGB }, + { "rgba", GL_RGBA }, + { "depth-component", GL_DEPTH_COMPONENT } +}; +simgear::effect::EffectPropertyMap sourceFormats(sourceFormatInit); + +simgear::effect::EffectNameValue sourceTypeInit[] = +{ + { "unsigned-byte", GL_UNSIGNED_BYTE }, + { "unsigned-short", GL_UNSIGNED_SHORT }, + { "unsigned-int", GL_UNSIGNED_INT }, + { "float", GL_FLOAT } +}; +simgear::effect::EffectPropertyMap sourceTypes(sourceTypeInit); + +simgear::effect::EffectNameValue 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 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 = 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 = 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(nv); + osg::Camera* camera = static_cast(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 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 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 index 000000000..875294faf --- /dev/null +++ b/src/Viewer/renderingpipeline.hxx @@ -0,0 +1,90 @@ + +#ifndef __FG_RENDERINGPIPELINE_HXX +#define __FG_RENDERINGPIPELINE_HXX 1 + +#include +#include + +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 > 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 > buffers; + std::vector > 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