From c60388afb68afa22d433f7d9dfaa4ea3e0a95a0f Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 2 Nov 2015 00:30:18 +0100 Subject: [PATCH] Add fudge factor to move the water mesh away from camera when the camera gets too close --- apps/openmw/mwrender/water.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 20710ab7e..c44f480f8 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -205,6 +205,36 @@ public: } }; +/// Moves water mesh away from the camera slightly if the camera gets to close on the Z axis. +/// The offset works around graphics artifacts that occured with the GL_DEPTH_CLAMP when the camera gets extremely close to the mesh (seen on NVIDIA at least). +/// Must be added as a Cull callback. +class FudgeCallback : public osg::NodeCallback +{ +public: + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + { + osgUtil::CullVisitor* cv = static_cast(nv); + + const float fudge = 0.1; + if (std::abs(cv->getEyeLocal().z()) < fudge) + { + float diff = fudge - cv->getEyeLocal().z(); + osg::RefMatrix* modelViewMatrix = new osg::RefMatrix(*cv->getModelViewMatrix()); + + if (cv->getEyeLocal().z() > 0) + modelViewMatrix->preMultTranslate(osg::Vec3f(0,0,-diff)); + else + modelViewMatrix->preMultTranslate(osg::Vec3f(0,0,diff)); + + cv->pushModelViewMatrix(modelViewMatrix, osg::Transform::RELATIVE_RF); + traverse(node, nv); + cv->popModelViewMatrix(); + } + else + traverse(node, nv); + } +}; + osg::ref_ptr readShader (osg::Shader::Type type, const std::string& file, const std::map& defineMap = std::map()) { osg::ref_ptr shader (new osg::Shader(type)); @@ -432,6 +462,7 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem mWaterNode = new osg::PositionAttitudeTransform; mWaterNode->addChild(mWaterGeode); + mWaterNode->addCullCallback(new FudgeCallback); // simple water fallback for the local map osg::ref_ptr geode2 (osg::clone(mWaterGeode.get(), osg::CopyOp::DEEP_COPY_NODES));