diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 875d6d5bb..f9cba2b55 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -232,8 +232,8 @@ osg::ref_ptr readPngImage (const std::string& file) class Refraction : public SceneUtil::RTTNode { public: - Refraction() - : RTTNode(false) + Refraction(uint32_t rttSize) + : RTTNode(rttSize, rttSize, false) { mClipCullNode = new ClipCullNode; } @@ -296,8 +296,8 @@ private: class Reflection : public SceneUtil::RTTNode { public: - Reflection(bool isInterior) - : RTTNode(false) + Reflection(uint32_t rttSize, bool isInterior) + : RTTNode(rttSize, rttSize, false) { setInterior(isInterior); mClipCullNode = new ClipCullNode; @@ -477,7 +477,9 @@ void Water::updateWaterMaterial() if (Settings::Manager::getBool("shader", "Water")) { - mReflection = new Reflection(mInterior); + unsigned int rttSize = Settings::Manager::getInt("rtt size", "Water"); + + mReflection = new Reflection(rttSize, mInterior); mReflection->setWaterLevel(mTop); mReflection->setScene(mSceneRoot); if (mCullCallback) @@ -486,7 +488,7 @@ void Water::updateWaterMaterial() if (Settings::Manager::getBool("refraction", "Water")) { - mRefraction = new Refraction; + mRefraction = new Refraction(rttSize); mRefraction->setWaterLevel(mTop); mRefraction->setScene(mSceneRoot); if (mCullCallback) diff --git a/components/sceneutil/rtt.cpp b/components/sceneutil/rtt.cpp index e6a744900..c1478ce5e 100644 --- a/components/sceneutil/rtt.cpp +++ b/components/sceneutil/rtt.cpp @@ -24,46 +24,10 @@ namespace SceneUtil RTTNode* mGroup; }; - // RTT camera - class RTTCamera : public osg::Camera - { - public: - RTTCamera() - { - setRenderOrder(osg::Camera::PRE_RENDER, 1); - setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); - - unsigned int rttSize = Settings::Manager::getInt("rtt size", "Water"); - setViewport(0, 0, rttSize, rttSize); - - mColorBuffer = new osg::Texture2D; - mColorBuffer->setTextureSize(rttSize, rttSize); - mColorBuffer->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); - mColorBuffer->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); - mColorBuffer->setInternalFormat(GL_RGB); - mColorBuffer->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); - mColorBuffer->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); - attach(osg::Camera::COLOR_BUFFER, mColorBuffer); - - mDepthBuffer = new osg::Texture2D; - mDepthBuffer->setTextureSize(rttSize, rttSize); - mDepthBuffer->setSourceFormat(GL_DEPTH_COMPONENT); - mDepthBuffer->setInternalFormat(GL_DEPTH_COMPONENT24); - mDepthBuffer->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); - mDepthBuffer->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); - mDepthBuffer->setSourceType(GL_UNSIGNED_INT); - mDepthBuffer->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); - mDepthBuffer->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); - attach(osg::Camera::DEPTH_BUFFER, mDepthBuffer); - } - - osg::ref_ptr mColorBuffer; - osg::ref_ptr mDepthBuffer; - }; - - RTTNode::RTTNode(bool doPerViewMapping) - : mDoPerViewMapping(doPerViewMapping) + RTTNode::RTTNode(uint32_t textureWidth, uint32_t textureHeight, bool doPerViewMapping) + : mTextureWidth(textureWidth) + , mTextureHeight(textureHeight) + , mDoPerViewMapping(doPerViewMapping) { addCullCallback(new CullCallback(this)); } @@ -79,14 +43,14 @@ namespace SceneUtil vdd->mCamera->accept(*cv); } - osg::Texture2D* RTTNode::getColorTexture(osgUtil::CullVisitor* cv) + osg::Texture* RTTNode::getColorTexture(osgUtil::CullVisitor* cv) { - return getViewDependentData(cv)->mCamera->mColorBuffer.get(); + return getViewDependentData(cv)->mCamera->getBufferAttachmentMap()[osg::Camera::COLOR_BUFFER]._texture; } - osg::Texture2D* RTTNode::getDepthTexture(osgUtil::CullVisitor* cv) + osg::Texture* RTTNode::getDepthTexture(osgUtil::CullVisitor* cv) { - return getViewDependentData(cv)->mCamera->mDepthBuffer.get(); + return getViewDependentData(cv)->mCamera->getBufferAttachmentMap()[osg::Camera::DEPTH_BUFFER]._texture; } RTTNode::ViewDependentData* RTTNode::getViewDependentData(osgUtil::CullVisitor* cv) @@ -98,9 +62,43 @@ namespace SceneUtil if (mViewDependentDataMap.count(cv) == 0) { + auto camera = new osg::Camera(); mViewDependentDataMap[cv].reset(new ViewDependentData); - mViewDependentDataMap[cv]->mCamera = new RTTCamera(); + mViewDependentDataMap[cv]->mCamera = camera; + + camera->setRenderOrder(osg::Camera::PRE_RENDER); + camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); + camera->setViewport(0, 0, mTextureWidth, mTextureHeight); + setDefaults(mViewDependentDataMap[cv]->mCamera.get()); + + // Create any buffer attachments not added in setDefaults + if (camera->getBufferAttachmentMap().count(osg::Camera::COLOR_BUFFER) == 0) + { + auto colorBuffer = new osg::Texture2D; + colorBuffer->setTextureSize(mTextureWidth, mTextureHeight); + colorBuffer->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + colorBuffer->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + colorBuffer->setInternalFormat(GL_RGB); + colorBuffer->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); + colorBuffer->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); + camera->attach(osg::Camera::COLOR_BUFFER, colorBuffer); + } + + if (camera->getBufferAttachmentMap().count(osg::Camera::DEPTH_BUFFER) == 0) + { + auto depthBuffer = new osg::Texture2D; + depthBuffer->setTextureSize(mTextureWidth, mTextureHeight); + depthBuffer->setSourceFormat(GL_DEPTH_COMPONENT); + depthBuffer->setInternalFormat(GL_DEPTH_COMPONENT24); + depthBuffer->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + depthBuffer->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + depthBuffer->setSourceType(GL_UNSIGNED_INT); + depthBuffer->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); + depthBuffer->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); + camera->attach(osg::Camera::DEPTH_BUFFER, depthBuffer); + } } return mViewDependentDataMap[cv].get(); diff --git a/components/sceneutil/rtt.hpp b/components/sceneutil/rtt.hpp index 7863828f9..159e14790 100644 --- a/components/sceneutil/rtt.hpp +++ b/components/sceneutil/rtt.hpp @@ -9,6 +9,7 @@ namespace osg { class Texture2D; + class Camera; } namespace osgUtil @@ -18,8 +19,6 @@ namespace osgUtil namespace SceneUtil { - class RTTCamera; - /// @brief Implements per-view RTT operations. /// @par With a naive RTT implementation, subsequent views of multiple views will overwrite the results of the previous views, leading to /// the results of the last view being broadcast to all views. An error in all cases where the RTT result depends on the view. @@ -28,15 +27,17 @@ namespace SceneUtil /// @par Camera settings should be effectuated by overriding the setDefaults() and apply() methods, following a pattern similar to SceneUtil::StateSetUpdater /// @par When using the RTT texture in your statesets, it is recommended to use SceneUtil::StateSetUpdater as a cull callback to handle this as the appropriate /// textures can be retrieved during SceneUtil::StateSetUpdater::Apply() + /// @par For any of COLOR_BUFFER or DEPTH_BUFFER not added during setDefaults(), RTTNode will attach a default buffer. The default color buffer has an internal format of GL_RGB. + /// The default depth buffer has internal format GL_DEPTH_COMPONENT24, source format GL_DEPTH_COMPONENT, and source type GL_UNSIGNED_INT. Default wrap is CLAMP_TO_EDGE and filter LINEAR. class RTTNode : public osg::Node { public: - RTTNode(bool doPerViewMapping); + RTTNode(uint32_t textureWidth, uint32_t textureHeight, bool doPerViewMapping); ~RTTNode(); - osg::Texture2D* getColorTexture(osgUtil::CullVisitor* cv); + osg::Texture* getColorTexture(osgUtil::CullVisitor* cv); - osg::Texture2D* getDepthTexture(osgUtil::CullVisitor* cv); + osg::Texture* getDepthTexture(osgUtil::CullVisitor* cv); /// Apply state - to override in derived classes @@ -51,13 +52,15 @@ namespace SceneUtil private: struct ViewDependentData { - osg::ref_ptr mCamera; + osg::ref_ptr mCamera; }; ViewDependentData* getViewDependentData(osgUtil::CullVisitor* cv); typedef std::map< osgUtil::CullVisitor*, std::unique_ptr > ViewDependentDataMap; ViewDependentDataMap mViewDependentDataMap; + uint32_t mTextureWidth; + uint32_t mTextureHeight; bool mDoPerViewMapping; }; }