diff --git a/apps/openmw/mwrender/refraction.cpp b/apps/openmw/mwrender/refraction.cpp index a924be7d7..67fe9e340 100644 --- a/apps/openmw/mwrender/refraction.cpp +++ b/apps/openmw/mwrender/refraction.cpp @@ -8,6 +8,8 @@ #include #include +#include + #include "renderconst.hpp" namespace MWRender @@ -30,7 +32,7 @@ namespace MWRender vp->setOverlaysEnabled(false); vp->setShadowsEnabled(false); vp->setVisibilityMask(RV_Actors + RV_Misc + RV_Statics + RV_StaticsSmall + RV_Terrain + RV_Sky); - vp->setMaterialScheme("water_reflection"); + vp->setMaterialScheme("water_refraction"); vp->setBackgroundColour (Ogre::ColourValue(0.0078, 0.0576, 0.150)); mRenderTarget->setAutoUpdated(true); mRenderTarget->addListener(this); @@ -54,6 +56,12 @@ namespace MWRender mCamera->setAspectRatio(mParentCamera->getAspectRatio()); mCamera->setFOVy(mParentCamera->getFOVy()); + // for depth calculation, we want the original viewproj matrix _without_ the custom near clip plane. + // since all we are interested in is depth, we only need the third row of the matrix. + Ogre::Matrix4 projMatrix = mCamera->getProjectionMatrixWithRSDepth () * mCamera->getViewMatrix (); + sh::Vector4* row3 = new sh::Vector4(projMatrix[2][0], projMatrix[2][1], projMatrix[2][2], projMatrix[2][3]); + sh::Factory::getInstance ().setSharedParameter ("vpRow2Fix", sh::makeProperty (row3)); + // enable clip plane here to take advantage of CPU culling for overwater or underwater objects mCamera->enableCustomNearClipPlane(mIsUnderwater ? mNearClipPlaneUnderwater : mNearClipPlane); @@ -62,6 +70,7 @@ namespace MWRender void Refraction::postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) { + mCamera->disableCustomNearClipPlane (); mRenderActive = false; } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 6c6c47417..c4f2d99cb 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -140,6 +140,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const sh::Factory::getInstance ().setSharedParameter ("windDir_windSpeed", sh::makeProperty(new sh::Vector3(0.5, -0.8, 0.2))); sh::Factory::getInstance ().setSharedParameter ("waterSunFade_sunHeight", sh::makeProperty(new sh::Vector2(1, 0.6))); sh::Factory::getInstance ().setGlobalSetting ("refraction", Settings::Manager::getBool("refraction", "Water") ? "true" : "false"); + sh::Factory::getInstance ().setGlobalSetting ("viewproj_fix", "false"); + sh::Factory::getInstance ().setSharedParameter ("vpRow2Fix", sh::makeProperty (new sh::Vector4(0,0,0,0))); applyCompositors(); diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index f71431a27..a76b0d1d3 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -144,6 +144,12 @@ void PlaneReflection::preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt) mSky->setSkyPosition(pos); mCamera->enableReflection(mWaterPlane); + // for depth calculation, we want the original viewproj matrix _without_ the custom near clip plane. + // since all we are interested in is depth, we only need the third row of the matrix. + Ogre::Matrix4 projMatrix = mCamera->getProjectionMatrixWithRSDepth () * mCamera->getViewMatrix (); + sh::Vector4* row3 = new sh::Vector4(projMatrix[2][0], projMatrix[2][1], projMatrix[2][2], projMatrix[2][3]); + sh::Factory::getInstance ().setSharedParameter ("vpRow2Fix", sh::makeProperty (row3)); + // enable clip plane here to take advantage of CPU culling for overwater or underwater objects mCamera->enableCustomNearClipPlane(mIsUnderwater ? mErrorPlaneUnderwater : mErrorPlane); } diff --git a/files/materials/objects.shader b/files/materials/objects.shader index 3f5aa418f..fad8c1ac8 100644 --- a/files/materials/objects.shader +++ b/files/materials/objects.shader @@ -23,12 +23,21 @@ #define VERTEX_LIGHTING 1 +#define VIEWPROJ_FIX @shGlobalSettingBool(viewproj_fix) + #ifdef SH_VERTEX_SHADER // ------------------------------------- VERTEX --------------------------------------- SH_BEGIN_PROGRAM shUniform(float4x4, wvp) @shAutoConstant(wvp, worldviewproj_matrix) + +#if VIEWPROJ_FIX + shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) + shUniform(float4, vpRow2Fix) @shSharedParameter(vpRow2Fix, vpRow2Fix) + shUniform(float4x4, vpMatrix) @shAutoConstant(vpMatrix, viewproj_matrix) +#endif + shVertexInput(float2, uv0) shOutput(float2, UV) shNormalInput(float4) @@ -65,7 +74,6 @@ #if SHADOWS shOutput(float4, lightSpacePos0) shUniform(float4x4, texViewProjMatrix0) @shAutoConstant(texViewProjMatrix0, texture_viewproj_matrix) - shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) #endif #if SHADOWS_PSSM @@ -73,7 +81,9 @@ shOutput(float4, lightSpacePos@shIterator) shUniform(float4x4, texViewProjMatrix@shIterator) @shAutoConstant(texViewProjMatrix@shIterator, texture_viewproj_matrix, @shIterator) @shEndForeach - shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) +#if !VIEWPROJ_FIX + shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) +#endif #endif #if VERTEX_LIGHTING @@ -89,9 +99,28 @@ #endif #ifdef NEED_DEPTH + + +#if VIEWPROJ_FIX + float4x4 vpFixed = vpMatrix; +#if !SH_GLSL + vpFixed[2] = vpRow2Fix; +#else + vpFixed[0][2] = vpRow2Fix.x; + vpFixed[1][2] = vpRow2Fix.y; + vpFixed[2][2] = vpRow2Fix.z; + vpFixed[3][2] = vpRow2Fix.w; +#endif + + float4x4 fixedWVP = shMatrixMult(vpFixed, worldMatrix); + + depthPassthrough = shMatrixMult(fixedWVP, shInputPosition).z; +#else depthPassthrough = shOutputPosition.z; #endif +#endif + #if LIGHTING objSpacePositionPassthrough = shInputPosition.xyz; #endif diff --git a/files/materials/openmw.configuration b/files/materials/openmw.configuration index 870c96728..21ac9416b 100644 --- a/files/materials/openmw.configuration +++ b/files/materials/openmw.configuration @@ -1,8 +1,13 @@ configuration water_reflection { - fog false shadows false shadows_pssm false + viewproj_fix true +} + +configuration water_refraction +{ + viewproj_fix true } configuration local_map diff --git a/files/materials/terrain.shader b/files/materials/terrain.shader index 497463f8e..b7ee15e8d 100644 --- a/files/materials/terrain.shader +++ b/files/materials/terrain.shader @@ -23,6 +23,8 @@ #define UNDERWATER @shGlobalSettingBool(underwater_effects) && LIGHTING +#define VIEWPROJ_FIX @shGlobalSettingBool(viewproj_fix) + #if NEED_DEPTH @shAllocatePassthrough(1, depth) @@ -51,6 +53,10 @@ shUniform(float4x4, worldMatrix) @shAutoConstant(worldMatrix, world_matrix) shUniform(float4x4, viewProjMatrix) @shAutoConstant(viewProjMatrix, viewproj_matrix) +#if VIEWPROJ_FIX + shUniform(float4, vpRow2Fix) @shSharedParameter(vpRow2Fix, vpRow2Fix) +#endif + shUniform(float2, lodMorph) @shAutoConstant(lodMorph, custom, 1001) shVertexInput(float2, uv0) @@ -94,7 +100,25 @@ shOutputPosition = shMatrixMult(viewProjMatrix, worldPos); #if NEED_DEPTH +#if VIEWPROJ_FIX + float4x4 vpFixed = viewProjMatrix; +#if !SH_GLSL + vpFixed[2] = vpRow2Fix; +#else + vpFixed[0][2] = vpRow2Fix.x; + vpFixed[1][2] = vpRow2Fix.y; + vpFixed[2][2] = vpRow2Fix.z; + vpFixed[3][2] = vpRow2Fix.w; +#endif + + float4x4 fixedWVP = shMatrixMult(vpFixed, worldMatrix); + + float depth = shMatrixMult(fixedWVP, shInputPosition).z; + @shPassthroughAssign(depth, depth); +#else @shPassthroughAssign(depth, shOutputPosition.z); +#endif + #endif @shPassthroughAssign(UV, uv0);