From fd45208196f824bf3536b24d25d8386e7cba302d Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 3 Apr 2012 14:23:23 +0200 Subject: [PATCH] re-added code for reflection & refraction rendering --- apps/openmw/mwrender/water.cpp | 68 +++++++++++++++++++++++++++++----- apps/openmw/mwrender/water.hpp | 9 ++++- files/settings-default.cfg | 8 ++++ 3 files changed, 74 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index cbf9c5b29..c19a487ab 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -1,4 +1,7 @@ #include "water.hpp" +#include + +using namespace Ogre; namespace MWRender { @@ -9,17 +12,17 @@ Water::Water (Ogre::Camera *camera, const ESM::Cell* cell) : { try { - Ogre::CompositorManager::getSingleton().addCompositor(mViewport, "Water", -1); - Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Water", false); + CompositorManager::getSingleton().addCompositor(mViewport, "Water", -1); + CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Water", false); } catch(...) {} mTop = cell->water; mIsUnderwater = false; - mWaterPlane = Ogre::Plane(Ogre::Vector3::UNIT_Y, 0); + mWaterPlane = Plane(Vector3::UNIT_Y, 0); - Ogre::MeshManager::getSingleton().createPlane("water", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, mWaterPlane, CELL_SIZE*5, CELL_SIZE * 5, 10, 10, true, 1, 3,5, Ogre::Vector3::UNIT_Z); + MeshManager::getSingleton().createPlane("water", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, mWaterPlane, CELL_SIZE*5, CELL_SIZE * 5, 10, 10, true, 1, 3,5, Vector3::UNIT_Z); mWater = mSceneManager->createEntity("water"); @@ -33,18 +36,41 @@ Water::Water (Ogre::Camera *camera, const ESM::Cell* cell) : mWaterNode->setPosition(getSceneNodeCoordinates(cell->data.gridX, cell->data.gridY)); } mWaterNode->attachObject(mWater); + + // Create rendertargets for reflection and refraction + int rttsize = Settings::Manager::getInt("rtt size", "Water"); + for (unsigned int i = 0; i < 2; ++i) + { + if (i==0 && !Settings::Manager::getBool("reflection", "Water")) continue; + if (i==1 && !Settings::Manager::getBool("refraction", "Water")) continue; + + TexturePtr tex = TextureManager::getSingleton().createManual(i == 0 ? "WaterReflection" : "WaterRefraction", + ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, rttsize, rttsize, 0, PF_R8G8B8, TU_RENDERTARGET); + + RenderTarget* rtt = tex->getBuffer()->getRenderTarget(); + Viewport* vp = rtt->addViewport(mCamera); + vp->setOverlaysEnabled(false); + vp->setBackgroundColour(ColourValue(0.8f, 0.9f, 1.0f)); + vp->setShadowsEnabled(false); + //vp->setVisibilityMask( ... ); + rtt->addListener(this); + rtt->setActive(true); + + if (i == 0) mReflectionTarget = rtt; + else mRefractionTarget = rtt; + } } Water::~Water() { - Ogre::MeshManager::getSingleton().remove("water"); + MeshManager::getSingleton().remove("water"); mWaterNode->detachObject(mWater); mSceneManager->destroyEntity(mWater); mSceneManager->destroySceneNode(mWaterNode); - Ogre::CompositorManager::getSingleton().removeCompositorChain(mViewport); + CompositorManager::getSingleton().removeCompositorChain(mViewport); } void Water::changeCell(const ESM::Cell* cell) @@ -73,7 +99,7 @@ void Water::checkUnderwater(float y) if ((mIsUnderwater && y > mTop) || !mWater->isVisible() || mCamera->getPolygonMode() != Ogre::PM_SOLID) { try { - Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Water", false); + CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Water", false); } catch(...) {} mIsUnderwater = false; } @@ -81,15 +107,37 @@ void Water::checkUnderwater(float y) if (!mIsUnderwater && y < mTop && mWater->isVisible() && mCamera->getPolygonMode() == Ogre::PM_SOLID) { try { - Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Water", true); + CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Water", true); } catch(...) {} mIsUnderwater = true; } } -Ogre::Vector3 Water::getSceneNodeCoordinates(int gridX, int gridY) +Vector3 Water::getSceneNodeCoordinates(int gridX, int gridY) +{ + return Vector3(gridX * CELL_SIZE + (CELL_SIZE / 2), mTop, -gridY * CELL_SIZE - (CELL_SIZE / 2)); +} + +void Water::preRenderTargetUpdate(const RenderTargetEvent& evt) { - return Ogre::Vector3(gridX * CELL_SIZE + (CELL_SIZE / 2), mTop, -gridY * CELL_SIZE - (CELL_SIZE / 2)); + mWater->setVisible(false); + + if (evt.source == mReflectionTarget) + { + mCamera->enableCustomNearClipPlane(mWaterPlane); + mCamera->enableReflection(Plane(Vector3::UNIT_Y, mWaterNode->_getDerivedPosition().y)); + } +} + +void Water::postRenderTargetUpdate(const RenderTargetEvent& evt) +{ + mWater->setVisible(true); + + if (evt.source == mReflectionTarget) + { + mCamera->disableReflection(); + mCamera->disableCustomNearClipPlane(); + } } } // namespace diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index 5a5d1cca0..6f3c4a6c3 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -7,7 +7,7 @@ namespace MWRender { /// Water rendering - class Water : Ogre::RenderTargetListener, Ogre::Camera::Listener + class Water : Ogre::RenderTargetListener { static const int CELL_SIZE = 8192; Ogre::Camera *mCamera; @@ -23,6 +23,13 @@ namespace MWRender { Ogre::Vector3 getSceneNodeCoordinates(int gridX, int gridY); + protected: + void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); + void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); + + Ogre::RenderTarget* mReflectionTarget; + Ogre::RenderTarget* mRefractionTarget; + public: Water (Ogre::Camera *camera, const ESM::Cell* cell); ~Water(); diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 6372a31c1..ec105c8f3 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -41,3 +41,11 @@ fog end factor = 1.0 # Max. number of lights that affect the terrain. Setting to 1 will only reflect sunlight num lights = 8 + +[Water] + +reflection = false + +refraction = false + +rtt size = 256