diff --git a/apps/openmw/mwrender/refraction.cpp b/apps/openmw/mwrender/refraction.cpp index 85642bc08..05229da1d 100644 --- a/apps/openmw/mwrender/refraction.cpp +++ b/apps/openmw/mwrender/refraction.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "renderconst.hpp" @@ -14,9 +15,13 @@ namespace MWRender Refraction::Refraction(Ogre::Camera *parentCamera) : mParentCamera(parentCamera) + , mRenderActive(false) + , mIsUnderwater(false) { mCamera = mParentCamera->getSceneManager()->createCamera("RefractionCamera"); + mParentCamera->getSceneManager()->addRenderQueueListener(this); + Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().createManual("WaterRefraction", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, 512, 512, 0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET); @@ -24,7 +29,7 @@ namespace MWRender Ogre::Viewport* vp = mRenderTarget->addViewport(mCamera); vp->setOverlaysEnabled(false); vp->setShadowsEnabled(false); - vp->setVisibilityMask(RV_Actors + RV_Misc + RV_Statics + RV_StaticsSmall + RV_Terrain); + vp->setVisibilityMask(RV_Actors + RV_Misc + RV_Statics + RV_StaticsSmall + RV_Terrain + RV_Sky); vp->setMaterialScheme("water_reflection"); mRenderTarget->setAutoUpdated(true); mRenderTarget->addListener(this); @@ -47,17 +52,42 @@ namespace MWRender mCamera->setAspectRatio(mParentCamera->getAspectRatio()); mCamera->setFOVy(mParentCamera->getFOVy()); - mCamera->enableCustomNearClipPlane(mNearClipPlane); + mRenderActive = true; } void Refraction::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) { - + mRenderActive = false; } void Refraction::setHeight(float height) { mNearClipPlane = Ogre::Plane( -Ogre::Vector3(0,1,0), -(height + 5)); + mNearClipPlaneUnderwater = Ogre::Plane( Ogre::Vector3(0,1,0), height - 5); + } + + void Refraction::setViewportBackground (Ogre::ColourValue colour) + { + mRenderTarget->getViewport (0)->setBackgroundColour (colour); + } + + void Refraction::renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation) + { + // We don't want the sky to get clipped by custom near clip plane (the water plane) + if (queueGroupId < 20 && mRenderActive) + { + mCamera->disableCustomNearClipPlane(); + Ogre::Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS()); + } + } + + void Refraction::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation) + { + if (queueGroupId < 20 && mRenderActive) + { + mCamera->enableCustomNearClipPlane(mIsUnderwater ? mNearClipPlaneUnderwater : mNearClipPlane); + Ogre::Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS()); + } } } diff --git a/apps/openmw/mwrender/refraction.hpp b/apps/openmw/mwrender/refraction.hpp index e3777d9cf..6b3c487c1 100644 --- a/apps/openmw/mwrender/refraction.hpp +++ b/apps/openmw/mwrender/refraction.hpp @@ -3,6 +3,7 @@ #include #include +#include namespace Ogre { @@ -13,7 +14,7 @@ namespace Ogre namespace MWRender { - class Refraction : public Ogre::RenderTargetListener + class Refraction : public Ogre::RenderTargetListener, public Ogre::RenderQueueListener { public: @@ -23,12 +24,20 @@ namespace MWRender void setHeight (float height); void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); + void setViewportBackground(Ogre::ColourValue colour); + void setUnderwater(bool underwater) {mIsUnderwater = underwater;} + + void renderQueueStarted (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation); + void renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &repeatThisInvocation); private: Ogre::Camera* mParentCamera; Ogre::Camera* mCamera; Ogre::RenderTarget* mRenderTarget; Ogre::Plane mNearClipPlane; + Ogre::Plane mNearClipPlaneUnderwater; + bool mRenderActive; + bool mIsUnderwater; }; } diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 867829564..f31dca08c 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -124,8 +124,8 @@ void PlaneReflection::renderQueueEnded (Ogre::uint8 queueGroupId, const Ogre::St { if (queueGroupId < 20 && mRenderActive) { - if (!mIsUnderwater) - mCamera->enableCustomNearClipPlane(mErrorPlane); + // this trick does not seem to work well for extreme angles + mCamera->enableCustomNearClipPlane(mIsUnderwater ? mErrorPlaneUnderwater : mErrorPlane); Root::getSingleton().getRenderSystem()->_setProjectionMatrix(mCamera->getProjectionMatrixRS()); } } @@ -159,6 +159,7 @@ void PlaneReflection::setHeight (float height) { mWaterPlane = Plane(Ogre::Vector3(0,1,0), height); mErrorPlane = Plane(Ogre::Vector3(0,1,0), height - 5); + mErrorPlaneUnderwater = Plane(Ogre::Vector3(0,-1,0), -height - 5); } void PlaneReflection::setActive (bool active) @@ -348,6 +349,8 @@ Water::updateUnderwater(bool underwater) if (mReflection) mReflection->setUnderwater (mIsUnderwater); + if (mRefraction) + mRefraction->setUnderwater (mIsUnderwater); updateVisible(); } @@ -377,6 +380,8 @@ void Water::setViewportBackground(const ColourValue& bg) { if (mReflection) mReflection->setViewportBackground(bg); + if (mRefraction) + mRefraction->setViewportBackground(bg); } void Water::updateVisible() diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index cf181674a..9aa18f008 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -89,6 +89,7 @@ namespace MWRender { SkyManager* mSky; Ogre::Plane mWaterPlane; Ogre::Plane mErrorPlane; + Ogre::Plane mErrorPlaneUnderwater; bool mRenderActive; };