enable shaders path and dehardcode depth formats

pull/3097/head
glassmancody.info 3 years ago
parent b457dfd8b8
commit cad0b151cb

@ -38,6 +38,7 @@
Feature #5489: MCP: Telekinesis fix for activators
Feature #5996: Support Lua scripts in OpenMW
Feature #6017: Separate persistent and temporary cell references when saving
Feature #6032: Reverse-z depth buffer
Feature #6162: Refactor GUI to use shaders and to be GLES and GL3+ friendly
0.47.0

@ -8,14 +8,12 @@
#include "MyGUI_FactoryManager.h"
#include <components/misc/utf8stream.hpp>
#include <components/sceneutil/util.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwrender/util.hpp"
namespace MWGui
{
struct TypesetBookImpl;
@ -1221,7 +1219,7 @@ public:
RenderXform renderXform (mCroppedParent, textFormat.mRenderItem->getRenderTarget()->getInfo());
float z = MWBase::Environment::get().getResourceSystem()->getSceneManager()->getReverseZ() ? 1.0 : -1.0;
float z = MWRender::getReverseZ() ? 1.f : -1.f;
GlyphStream glyphStream(textFormat.mFont, static_cast<float>(mCoord.left), static_cast<float>(mCoord.top - mViewTop),
z /*mNode->getNodeDepth()*/, vertices, renderXform);

@ -741,7 +741,7 @@ namespace MWGui
}
// ------------------------------------------------------------------------------------------
MapWindow::MapWindow(CustomMarkerCollection &customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender, SceneUtil::WorkQueue* workQueue, bool reverseZ)
MapWindow::MapWindow(CustomMarkerCollection &customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender, SceneUtil::WorkQueue* workQueue)
: WindowPinnableBase("openmw_map_window.layout")
, LocalMapBase(customMarkers, localMapRender)
, NoDrop(drag, mMainWidget)
@ -751,7 +751,7 @@ namespace MWGui
, mGlobal(Settings::Manager::getBool("global", "Map"))
, mEventBoxGlobal(nullptr)
, mEventBoxLocal(nullptr)
, mGlobalMapRender(new MWRender::GlobalMap(localMapRender->getRoot(), workQueue, reverseZ))
, mGlobalMapRender(new MWRender::GlobalMap(localMapRender->getRoot(), workQueue))
, mEditNoteDialog()
{
static bool registered = false;

@ -222,7 +222,7 @@ namespace MWGui
class MapWindow : public MWGui::WindowPinnableBase, public LocalMapBase, public NoDrop
{
public:
MapWindow(CustomMarkerCollection& customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender, SceneUtil::WorkQueue* workQueue, bool reverseZ);
MapWindow(CustomMarkerCollection& customMarkers, DragAndDrop* drag, MWRender::LocalMap* localMapRender, SceneUtil::WorkQueue* workQueue);
virtual ~MapWindow();
void setCellName(const std::string& cellName);

@ -35,7 +35,6 @@
#include <components/resource/resourcesystem.hpp>
#include <components/resource/imagemanager.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/sceneutil/workqueue.hpp>
@ -305,9 +304,8 @@ namespace MWGui
mGuiModeStates[GM_MainMenu] = GuiModeState(menu);
mWindows.push_back(menu);
bool reverseZ = mResourceSystem->getSceneManager()->getReverseZ();
mLocalMapRender = new MWRender::LocalMap(mViewer->getSceneData()->asGroup(), reverseZ);
mMap = new MapWindow(mCustomMarkers, mDragAndDrop, mLocalMapRender, mWorkQueue, reverseZ);
mLocalMapRender = new MWRender::LocalMap(mViewer->getSceneData()->asGroup());
mMap = new MapWindow(mCustomMarkers, mDragAndDrop, mLocalMapRender, mWorkQueue);
mWindows.push_back(mMap);
mMap->renderGlobalMap();
trackWindow(mMap, "map");

@ -2,9 +2,13 @@
#include "vismask.hpp"
#include <components/sceneutil/agentpath.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
#include <osg/PositionAttitudeTransform>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
namespace MWRender
{
ActorsPaths::ActorsPaths(const osg::ref_ptr<osg::Group>& root, bool enabled)
@ -43,6 +47,7 @@ namespace MWRender
const auto newGroup = SceneUtil::createAgentPathGroup(path, halfExtents, start, end, settings);
if (newGroup)
{
MWBase::Environment::get().getResourceSystem()->getSceneManager()->recreateShaders(newGroup, "debug");
newGroup->setNodeMask(Mask_Debug);
mRootNode->addChild(newGroup);
mGroups[actor] = newGroup;

@ -10,10 +10,19 @@
#include <osg/PolygonMode>
#include <osg/ShapeDrawable>
#include <osg/StateSet>
#include <osg/Fog>
#include "bulletdebugdraw.hpp"
#include "vismask.hpp"
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/sceneutil/util.hpp>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
namespace MWRender
{
@ -30,7 +39,6 @@ void DebugDrawer::createGeometry()
{
mGeometry = new osg::Geometry;
mGeometry->setNodeMask(Mask_Debug);
mVertices = new osg::Vec3Array;
mColors = new osg::Vec4Array;
@ -42,6 +50,8 @@ void DebugDrawer::createGeometry()
mGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
mGeometry->setDataVariance(osg::Object::DYNAMIC);
mGeometry->addPrimitiveSet(mDrawArrays);
// make this friendly to recreateShaders()
mGeometry->setStateSet(new osg::StateSet);
mParentNode->addChild(mGeometry);
@ -52,6 +62,8 @@ void DebugDrawer::createGeometry()
mShapesRoot->setDataVariance(osg::Object::DYNAMIC);
mShapesRoot->setNodeMask(Mask_Debug);
mParentNode->addChild(mShapesRoot);
MWBase::Environment::get().getResourceSystem()->getSceneManager()->recreateShaders(mGeometry, "debug");
}
}

@ -168,7 +168,7 @@ namespace MWRender
mCamera->setRenderOrder(osg::Camera::PRE_RENDER);
mCamera->attach(osg::Camera::COLOR_BUFFER, mTexture, 0, 0, false, Settings::Manager::getInt("antialiasing", "Video"));
mCamera->setName("CharacterPreview");
mCamera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
mCamera->setComputeNearFarMode(osg::Camera::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES);
mCamera->setCullMask(~(Mask_UpdateVisitor));
mCamera->setNodeMask(Mask_RenderToTexture);
@ -187,6 +187,7 @@ namespace MWRender
defaultMat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1));
defaultMat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 0.f));
stateset->setAttribute(defaultMat);
stateset->addUniform(new osg::Uniform("projectionMatrix", static_cast<osg::Matrixf>(mCamera->getProjectionMatrix())));
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
stateset->setAttributeAndModes(depth, osg::StateAttribute::ON);

@ -25,6 +25,7 @@
#include "../mwworld/esmstore.hpp"
#include "vismask.hpp"
#include "util.hpp"
namespace
{
@ -220,14 +221,13 @@ namespace MWRender
osg::ref_ptr<osg::Texture2D> mOverlayTexture;
};
GlobalMap::GlobalMap(osg::Group* root, SceneUtil::WorkQueue* workQueue, bool reverseZ)
GlobalMap::GlobalMap(osg::Group* root, SceneUtil::WorkQueue* workQueue)
: mRoot(root)
, mWorkQueue(workQueue)
, mWidth(0)
, mHeight(0)
, mMinX(0), mMaxX(0)
, mMinY(0), mMaxY(0)
, mReverseZ(reverseZ)
{
mCellSize = Settings::Manager::getInt("global map cell size", "Map");
@ -325,7 +325,7 @@ namespace MWRender
if (texture)
{
osg::ref_ptr<osg::Geometry> geom = createTexturedQuad(srcLeft, srcTop, srcRight, srcBottom);
auto depth = SceneUtil::createDepth(mReverseZ);
auto depth = SceneUtil::createDepth(getReverseZ());
depth->setWriteMask(0);
osg::StateSet* stateset = geom->getOrCreateStateSet();
stateset->setAttribute(depth);

@ -33,7 +33,7 @@ namespace MWRender
class GlobalMap
{
public:
GlobalMap(osg::Group* root, SceneUtil::WorkQueue* workQueue, bool reverseZ);
GlobalMap(osg::Group* root, SceneUtil::WorkQueue* workQueue);
~GlobalMap();
void render();
@ -126,8 +126,6 @@ namespace MWRender
int mHeight;
int mMinX, mMaxX, mMinY, mMaxY;
bool mReverseZ;
};
}

@ -30,6 +30,7 @@
#include "../mwworld/cellstore.hpp"
#include "vismask.hpp"
#include "util.hpp"
namespace
{
@ -83,14 +84,13 @@ namespace
namespace MWRender
{
LocalMap::LocalMap(osg::Group* root, bool reverseZ)
LocalMap::LocalMap(osg::Group* root)
: mRoot(root)
, mMapResolution(Settings::Manager::getInt("local map resolution", "Map"))
, mMapWorldSize(Constants::CellSizeInUnits)
, mCellDistance(Constants::CellGridRadius)
, mAngle(0.f)
, mInterior(false)
, mReverseZ(reverseZ)
{
// Increase map resolution, if use UI scaling
float uiScale = MWBase::Environment::get().getWindowManager()->getScalingFactor();
@ -178,7 +178,7 @@ osg::ref_ptr<osg::Camera> LocalMap::createOrthographicCamera(float x, float y, f
{
osg::ref_ptr<osg::Camera> camera (new osg::Camera);
if (mReverseZ)
if (getReverseZ())
camera->setProjectionMatrix(SceneUtil::getReversedZProjectionMatrixAsOrtho(-width/2, width/2, -height/2, height/2, 5, (zmax-zmin) + 10));
else
camera->setProjectionMatrixAsOrtho(-width/2, width/2, -height/2, height/2, 5, (zmax-zmin) + 10);
@ -201,13 +201,15 @@ osg::ref_ptr<osg::Camera> LocalMap::createOrthographicCamera(float x, float y, f
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
stateset->setAttribute(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::FILL), osg::StateAttribute::OVERRIDE);
if (mReverseZ)
if (getReverseZ())
{
camera->setClearDepth(0.0);
auto depth = SceneUtil::createDepth(mReverseZ);
auto depth = SceneUtil::createDepth(true);
stateset->setAttributeAndModes(depth, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
}
stateset->addUniform(new osg::Uniform("projectionMatrix", static_cast<osg::Matrixf>(camera->getProjectionMatrix())), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
// assign large value to effectively turn off fog
// shaders don't respect glDisable(GL_FOG)
osg::ref_ptr<osg::Fog> fog (new osg::Fog);

@ -36,7 +36,7 @@ namespace MWRender
class LocalMap
{
public:
LocalMap(osg::Group* root, bool reverseZ);
LocalMap(osg::Group* root);
~LocalMap();
/**
@ -156,7 +156,6 @@ namespace MWRender
void setupRenderToTexture(osg::ref_ptr<osg::Camera> camera, int x, int y);
bool mInterior;
bool mReverseZ;
osg::BoundingBox mBounds;
};

@ -2,9 +2,14 @@
#include "vismask.hpp"
#include <components/sceneutil/navmesh.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
#include <osg/PositionAttitudeTransform>
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
namespace MWRender
{
NavMesh::NavMesh(const osg::ref_ptr<osg::Group>& root, bool enabled)
@ -45,6 +50,7 @@ namespace MWRender
mGroup = SceneUtil::createNavMeshGroup(navMesh, settings);
if (mGroup)
{
MWBase::Environment::get().getResourceSystem()->getSceneManager()->recreateShaders(mGroup, "debug");
mGroup->setNodeMask(Mask_Debug);
mRootNode->addChild(mGroup);
}

@ -43,6 +43,7 @@
#include "rotatecontroller.hpp"
#include "renderbin.hpp"
#include "vismask.hpp"
#include "util.hpp"
namespace
{
@ -370,9 +371,9 @@ void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode)
class DepthClearCallback : public osgUtil::RenderBin::DrawCallback
{
public:
DepthClearCallback(bool reverseZ)
DepthClearCallback()
{
mDepth = SceneUtil::createDepth(reverseZ);
mDepth = SceneUtil::createDepth(getReverseZ());
mDepth->setWriteMask(true);
}
@ -432,7 +433,7 @@ void NpcAnimation::setRenderBin()
if (!prototypeAdded)
{
osg::ref_ptr<osgUtil::RenderBin> depthClearBin (new osgUtil::RenderBin);
depthClearBin->setDrawCallback(new DepthClearCallback(mResourceSystem->getSceneManager()->getReverseZ()));
depthClearBin->setDrawCallback(new DepthClearCallback);
osgUtil::RenderBin::addRenderBinPrototype("DepthClear", depthClearBin);
prototypeAdded = true;
}

@ -8,7 +8,10 @@
#include <components/esm/loadpgrd.hpp>
#include <components/sceneutil/pathgridutil.hpp>
#include <components/sceneutil/util.hpp>
#include <components/misc/coordinateconverter.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
#include "../mwbase/world.hpp" // these includes can be removed once the static-hack is gone
#include "../mwbase/environment.hpp"
@ -112,6 +115,8 @@ void Pathgrid::enableCellPathgrid(const MWWorld::CellStore *store)
osg::ref_ptr<osg::Geometry> geometry = SceneUtil::createPathgridGeometry(*pathgrid);
MWBase::Environment::get().getResourceSystem()->getSceneManager()->recreateShaders(geometry, "debug");
cellPathGrid->addChild(geometry);
mPathGridRoot->addChild(cellPathGrid);

@ -9,6 +9,11 @@
#include <osgViewer/Viewer>
#include <components/settings/settings.hpp>
#include <components/sceneutil/util.hpp>
#include <components/debug/debuglog.hpp>
#include "vismask.hpp"
#include "renderingmanager.hpp"
namespace
{
@ -57,6 +62,8 @@ namespace
traverse(node, nv);
}
private:
MWRender::PostProcessor* mPostProcessor;
unsigned int mLastFrameNumber;
};
@ -70,6 +77,7 @@ namespace
void resizedImplementation(osg::GraphicsContext* gc, int x, int y, int width, int height) override
{
gc->resizedImplementation(x, y, width, height);
mPostProcessor->resize(width, height);
}
@ -79,22 +87,55 @@ namespace
namespace MWRender
{
PostProcessor::PostProcessor(osgViewer::Viewer* viewer, osg::Group* rootNode)
PostProcessor::PostProcessor(RenderingManager& rendering, osgViewer::Viewer* viewer, osg::Group* rootNode)
: mViewer(viewer)
, mRootNode(new osg::Group)
, mRendering(rendering)
{
osg::GraphicsContext* gc = viewer->getCamera()->getGraphicsContext();
unsigned int contextID = gc->getState()->getContextID();
osg::GLExtensions* ext = gc->getState()->get<osg::GLExtensions>();
constexpr char errPreamble[] = "Postprocessing and floating point depth buffers disabled: ";
if (!ext->isFrameBufferObjectSupported)
{
Log(Debug::Warning) << errPreamble << "FrameBufferObject unsupported.";
return;
}
if (Settings::Manager::getInt("antialiasing", "Video") > 1 && !ext->isRenderbufferMultisampleSupported())
{
Log(Debug::Warning) << errPreamble << "RenderBufferMultiSample unsupported. Disabling antialiasing will resolve this issue.";
return;
}
if (osg::isGLExtensionSupported(contextID, "GL_ARB_depth_buffer_float"))
mDepthFormat = GL_DEPTH_COMPONENT32F;
else if (osg::isGLExtensionSupported(contextID, "GL_NV_depth_buffer_float"))
mDepthFormat = GL_DEPTH_COMPONENT32F_NV;
else
{
// TODO: Once we have post-processing implemented we want to skip this return and continue with setup.
// Rendering to a FBO to fullscreen geometry has overhead (especially when MSAA is enabled) and there are no
// benefits if no floating point depth formats are supported.
mDepthFormat = GL_DEPTH_COMPONENT24;
Log(Debug::Warning) << errPreamble << "'GL_ARB_depth_buffer_float' and 'GL_NV_depth_buffer_float' unsupported.";
return;
}
int width = viewer->getCamera()->getViewport()->width();
int height = viewer->getCamera()->getViewport()->height();
createTexturesAndCamera(width, height);
resize(width, height);
resize(width, height, true);
mRootNode->addChild(mHUDCamera);
mRootNode->addChild(rootNode);
mViewer->setSceneData(mRootNode);
// Main camera is treated specially, we need to manually set the FBO and
// resolve FBO during the cull callback.
// We need to manually set the FBO and resolve FBO during the cull callback. If we were using a separate
// RTT camera this would not be needed.
mViewer->getCamera()->addCullCallback(new CullCallback(this));
mViewer->getCamera()->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
mViewer->getCamera()->attach(osg::Camera::COLOR_BUFFER0, mSceneTex);
@ -103,12 +144,12 @@ namespace MWRender
mViewer->getCamera()->getGraphicsContext()->setResizedCallback(new ResizedCallback(this));
}
void PostProcessor::resize(int width, int height)
void PostProcessor::resize(int width, int height, bool init)
{
mDepthTex->setTextureSize(width, height);
mSceneTex->setTextureSize(width, height);
mDepthTex->dirtyTextureObject();
mSceneTex->dirtyTextureObject();
mDepthTex->dirtyTextureObject();
mSceneTex->dirtyTextureObject();
int samples = Settings::Manager::getInt("antialiasing", "Video");
@ -130,15 +171,13 @@ namespace MWRender
mMsaaFbo->setAttachment(osg::Camera::DEPTH_BUFFER, osg::FrameBufferAttachment(depthRB));
}
double prevWidth = mViewer->getCamera()->getViewport()->width();
double prevHeight = mViewer->getCamera()->getViewport()->height();
double scaleX = prevWidth / width;
double scaleY = prevHeight / height;
if (init)
return;
mViewer->getCamera()->resize(width,height);
mHUDCamera->resize(width,height);
mViewer->getCamera()->resize(width, height);
mHUDCamera->resize(width, height);
mViewer->getCamera()->getProjectionMatrix() *= osg::Matrix::scale(scaleX, scaleY, 1.0);
mRendering.updateProjectionMatrix();
}
void PostProcessor::createTexturesAndCamera(int width, int height)
@ -146,8 +185,8 @@ namespace MWRender
mDepthTex = new osg::Texture2D;
mDepthTex->setTextureSize(width, height);
mDepthTex->setSourceFormat(GL_DEPTH_COMPONENT);
mDepthTex->setSourceType(GL_FLOAT);
mDepthTex->setInternalFormat(GL_DEPTH_COMPONENT32F);
mDepthTex->setSourceType(SceneUtil::isFloatingPointDepthFormat(getDepthFormat()) ? GL_FLOAT : GL_UNSIGNED_INT);
mDepthTex->setInternalFormat(mDepthFormat);
mDepthTex->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST);
mDepthTex->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST);
mDepthTex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
@ -206,6 +245,7 @@ namespace MWRender
program->addShader(fragShader);
mHUDCamera->addChild(createFullScreenTri());
mHUDCamera->setNodeMask(Mask_RenderToTexture);
auto* stateset = mHUDCamera->getOrCreateStateSet();
stateset->setTextureAttributeAndModes(0, mSceneTex, osg::StateAttribute::ON);

@ -18,15 +18,19 @@ namespace osgViewer
namespace MWRender
{
class RenderingManager;
class PostProcessor
{
public:
PostProcessor(osgViewer::Viewer* viewer, osg::Group* rootNode);
PostProcessor(RenderingManager& rendering, osgViewer::Viewer* viewer, osg::Group* rootNode);
auto getMsaaFbo() { return mMsaaFbo; }
auto getFbo() { return mFbo; }
void resize(int width, int height);
int getDepthFormat() { return mDepthFormat; }
void resize(int width, int height, bool init=false);
private:
osgViewer::Viewer* mViewer;
@ -39,7 +43,11 @@ namespace MWRender
osg::ref_ptr<osg::Texture2D> mSceneTex;
osg::ref_ptr<osg::Texture2D> mDepthTex;
int mDepthFormat;
void createTexturesAndCamera(int width, int height);
RenderingManager& mRendering;
};
}

@ -1,11 +1,15 @@
#include "recastmesh.hpp"
#include <components/sceneutil/recastmesh.hpp>
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
#include <osg/PositionAttitudeTransform>
#include "vismask.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
namespace MWRender
{
RecastMesh::RecastMesh(const osg::ref_ptr<osg::Group>& root, bool enabled)
@ -49,6 +53,7 @@ namespace MWRender
|| it->second.mRevision != tile->second->getRevision())
{
const auto group = SceneUtil::createRecastMeshGroup(*tile->second, settings);
MWBase::Environment::get().getResourceSystem()->getSceneManager()->recreateShaders(group, "debug");
group->setNodeMask(Mask_Debug);
mRootNode->removeChild(it->second.mValue);
mRootNode->addChild(group);
@ -66,6 +71,7 @@ namespace MWRender
if (mGroups.count(tile.first))
continue;
const auto group = SceneUtil::createRecastMeshGroup(*tile.second, settings);
MWBase::Environment::get().getResourceSystem()->getSceneManager()->recreateShaders(group, "debug");
group->setNodeMask(Mask_Debug);
mGroups.emplace(tile.first, Group {tile.second->getGeneration(), tile.second->getRevision(), group});
mRootNode->addChild(group);

@ -74,6 +74,45 @@
namespace MWRender
{
class SharedUniformStateUpdater : public SceneUtil::StateSetUpdater
{
public:
SharedUniformStateUpdater()
: mLinearFac(0.f)
{
}
void setDefaults(osg::StateSet *stateset) override
{
stateset->addUniform(new osg::Uniform("projectionMatrix", osg::Matrixf{}));
stateset->addUniform(new osg::Uniform("linearFac", 0.f));
}
void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) override
{
auto* uProjectionMatrix = stateset->getUniform("projectionMatrix");
if (uProjectionMatrix)
uProjectionMatrix->set(mProjectionMatrix);
auto* uLinearFac = stateset->getUniform("linearFac");
if (uLinearFac)
uLinearFac->set(mLinearFac);
}
void setProjectionMatrix(const osg::Matrixf& projectionMatrix)
{
mProjectionMatrix = projectionMatrix;
}
void setLinearFac(float linearFac)
{
mLinearFac = linearFac;
}
private:
osg::Matrixf mProjectionMatrix;
float mLinearFac;
};
class StateUpdater : public SceneUtil::StateSetUpdater
{
@ -202,10 +241,7 @@ namespace MWRender
, mFieldOfViewOverride(0.f)
{
auto ext = osg::GLExtensions::Get(0, false);
bool reverseZ = ext && ext->isClipControlSupported;
if (getenv("OPENMW_DISABLE_REVERSEZ") != nullptr)
reverseZ = false;
bool reverseZ = Settings::Manager::getBool("reverse z", "Camera") && ext && ext->isClipControlSupported;
if (reverseZ)
Log(Debug::Info) << "Using reverse-z depth buffer";
@ -219,7 +255,8 @@ namespace MWRender
bool forceShaders = Settings::Manager::getBool("radial fog", "Shaders")
|| Settings::Manager::getBool("force shaders", "Shaders")
|| Settings::Manager::getBool("enable shadows", "Shadows")
|| lightingMethod != SceneUtil::LightingMethod::FFP;
|| lightingMethod != SceneUtil::LightingMethod::FFP
|| reverseZ;
resourceSystem->getSceneManager()->setForceShaders(forceShaders);
// FIXME: calling dummy method because terrain needs to know whether lighting is clamped
resourceSystem->getSceneManager()->setClampLighting(Settings::Manager::getBool("clamp lighting", "Shaders"));
@ -370,6 +407,10 @@ namespace MWRender
// Use a stub grid to avoid splitting between chunks for active grid and chunks for distant cells.
mGroundcoverWorld->setActiveGrid(osg::Vec4i(0, 0, 0, 0));
}
mPostProcessor.reset(new PostProcessor(*this, viewer, mRootNode));
resourceSystem->getSceneManager()->setDepthFormat(mPostProcessor->getDepthFormat());
// water goes after terrain for correct waterculling order
mWater.reset(new Water(sceneRoot->getParent(0), sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), resourcePath));
@ -412,6 +453,9 @@ namespace MWRender
mStateUpdater = new StateUpdater;
sceneRoot->addUpdateCallback(mStateUpdater);
mSharedUniformStateUpdater = new SharedUniformStateUpdater;
rootNode->addUpdateCallback(mSharedUniformStateUpdater);
osg::Camera::CullingMode cullingMode = osg::Camera::DEFAULT_CULLING|osg::Camera::FAR_PLANE_CULLING;
if (!Settings::Manager::getBool("small feature culling", "Camera"))
@ -433,7 +477,9 @@ namespace MWRender
NifOsg::Loader::setReverseZ(reverseZ);
Nif::NIFFile::setLoadUnsupportedFiles(Settings::Manager::getBool("load unsupported nif files", "Models"));
mNearClip = Settings::Manager::getFloat("near clip", "Camera");
// TODO: Near clip should not need to be bounded like this, but too small values break OSG shadow calculations CPU-side.
// See issue: #6072
mNearClip = std::max(0.005f, Settings::Manager::getFloat("near clip", "Camera"));
mViewDistance = Settings::Manager::getFloat("viewing distance", "Camera");
float fov = Settings::Manager::getFloat("field of view", "Camera");
mFieldOfView = std::min(std::max(1.f, fov), 179.f);
@ -462,11 +508,6 @@ namespace MWRender
mRootNode->getOrCreateStateSet()->setAttributeAndModes(clipcontrol, osg::StateAttribute::ON);
}
if (ext && ext->isFrameBufferObjectSupported)
mPostProcessor.reset(new PostProcessor(viewer, mRootNode));
else
Log(Debug::Warning) << "Disabling postprocessing and using default framebuffer for rendering: FrameBufferObjects not supported";
updateProjectionMatrix();
}
@ -1100,19 +1141,15 @@ namespace MWRender
if (mFieldOfViewOverridden)
fov = mFieldOfViewOverride;
mViewer->getCamera()->setProjectionMatrixAsPerspective(fov, aspect, mNearClip, mViewDistance);
if (mResourceSystem->getSceneManager()->getReverseZ())
{
mViewer->getCamera()->setProjectionMatrix(SceneUtil::getReversedZProjectionMatrixAsPerspectiveInf(fov, aspect, mNearClip));
float linearFac = -mNearClip / (mViewDistance - mNearClip) - 1.0;
mRootNode->getOrCreateStateSet()->getOrCreateUniform("linearFac", osg::Uniform::FLOAT, 1)->set(linearFac);
osg::Matrix shadowProj = osg::Matrix::perspective(fov, aspect, mNearClip, mViewDistance);
mViewer->getCamera()->setUserValue("shadowProj", shadowProj);
mViewer->getCamera()->setUserValue("near", static_cast<double>(mNearClip));
mViewer->getCamera()->setUserValue("far", static_cast<double>(mViewDistance));
mSharedUniformStateUpdater->setLinearFac(-mNearClip / (mViewDistance - mNearClip) - 1.f);
mSharedUniformStateUpdater->setProjectionMatrix(SceneUtil::getReversedZProjectionMatrixAsPerspective(fov, aspect, mNearClip, mViewDistance));
}
else
mViewer->getCamera()->setProjectionMatrixAsPerspective(fov, aspect, mNearClip, mViewDistance);
mSharedUniformStateUpdater->setProjectionMatrix(mViewer->getCamera()->getProjectionMatrix());
mUniformNear->set(mNearClip);
mUniformFar->set(mViewDistance);

@ -72,6 +72,7 @@ namespace MWRender
{
class GroundcoverUpdater;
class StateUpdater;
class SharedUniformStateUpdater;
class EffectManager;
class ScreenshotManager;
@ -240,9 +241,9 @@ namespace MWRender
void pagingBlacklistObject(int type, const MWWorld::ConstPtr &ptr);
bool pagingUnlockCache();
void getPagedRefnums(const osg::Vec4i &activeGrid, std::set<ESM::RefNum> &out);
private:
void updateProjectionMatrix();
private:
void updateTextureFiltering();
void updateAmbient();
void setFogColor(const osg::Vec4f& color);
@ -296,6 +297,7 @@ namespace MWRender
osg::Vec3f mCurrentCameraPos;
osg::ref_ptr<StateUpdater> mStateUpdater;
osg::ref_ptr<SharedUniformStateUpdater> mSharedUniformStateUpdater;
osg::Vec4f mAmbientColor;
float mMinimumAmbientLuminance;

@ -298,7 +298,7 @@ namespace MWRender
camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT,osg::Camera::PIXEL_BUFFER_RTT);
if (MWBase::Environment::get().getResourceSystem()->getSceneManager()->getReverseZ())
if (getReverseZ())
camera->setClearDepth(0.0);
camera->setViewport(0, 0, w, h);
@ -336,7 +336,7 @@ namespace MWRender
float nearClip = Settings::Manager::getFloat("near clip", "Camera");
float viewDistance = Settings::Manager::getFloat("viewing distance", "Camera");
// each cubemap side sees 90 degrees
if (MWBase::Environment::get().getResourceSystem()->getSceneManager()->getReverseZ())
if (getReverseZ())
rttCamera->setProjectionMatrix(SceneUtil::getReversedZProjectionMatrixAsPerspectiveInf(90.0, w/float(h), nearClip));
else
rttCamera->setProjectionMatrixAsPerspective(90.0, w/float(h), nearClip, viewDistance);

@ -54,6 +54,7 @@
#include "vismask.hpp"
#include "renderbin.hpp"
#include "util.hpp"
namespace
{
@ -473,7 +474,7 @@ const float CelestialBody::mDistance = 1000.0f;
class Sun : public CelestialBody
{
public:
Sun(osg::Group* parentNode, Resource::ImageManager& imageManager, bool reverseZ)
Sun(osg::Group* parentNode, Resource::ImageManager& imageManager)
: CelestialBody(parentNode, 1.0f, 1, Mask_Sun)
, mUpdater(new Updater)
{
@ -502,8 +503,8 @@ public:
mTransform->addChild(queryNode);
mOcclusionQueryVisiblePixels = createOcclusionQueryNode(queryNode, true, reverseZ);
mOcclusionQueryTotalPixels = createOcclusionQueryNode(queryNode, false, reverseZ);
mOcclusionQueryVisiblePixels = createOcclusionQueryNode(queryNode, true);
mOcclusionQueryTotalPixels = createOcclusionQueryNode(queryNode, false);
createSunFlash(imageManager);
createSunGlare();
@ -556,7 +557,7 @@ private:
};
/// @param queryVisible If true, queries the amount of visible pixels. If false, queries the total amount of pixels.
osg::ref_ptr<osg::OcclusionQueryNode> createOcclusionQueryNode(osg::Group* parent, bool queryVisible, bool reverseZ)
osg::ref_ptr<osg::OcclusionQueryNode> createOcclusionQueryNode(osg::Group* parent, bool queryVisible)
{
osg::ref_ptr<osg::OcclusionQueryNode> oqn = new osg::OcclusionQueryNode;
oqn->setQueriesEnabled(true);
@ -594,11 +595,11 @@ private:
osg::StateSet* queryStateSet = new osg::StateSet;
if (queryVisible)
{
auto depth = SceneUtil::createDepth(reverseZ);
auto depth = SceneUtil::createDepth(getReverseZ());
// This is a trick to make fragments written by the query always use the maximum depth value,
// without having to retrieve the current far clipping distance.
// We want the sun glare to be "infinitely" far away.
float far = reverseZ ? 0.0 : 1.0;
double far = getReverseZ() ? 0.0 : 1.0;
depth->setZNear(far);
depth->setZFar(far);
depth->setWriteMask(false);
@ -1188,8 +1189,7 @@ void SkyManager::create()
mAtmosphereNightUpdater = new AtmosphereNightUpdater(mSceneManager->getImageManager());
atmosphereNight->addUpdateCallback(mAtmosphereNightUpdater);
bool reverseZ = mSceneManager->getReverseZ();
mSun.reset(new Sun(mEarlyRenderBinRoot, *mSceneManager->getImageManager(), reverseZ));
mSun.reset(new Sun(mEarlyRenderBinRoot, *mSceneManager->getImageManager()));
mMasser.reset(new Moon(mEarlyRenderBinRoot, *mSceneManager->getImageManager(), Fallback::Map::getFloat("Moons_Masser_Size")/125, Moon::Type_Masser));
mSecunda.reset(new Moon(mEarlyRenderBinRoot, *mSceneManager->getImageManager(), Fallback::Map::getFloat("Moons_Secunda_Size")/125, Moon::Type_Secunda));
@ -1210,7 +1210,7 @@ void SkyManager::create()
mCloudMesh2->addUpdateCallback(mCloudUpdater2);
mCloudMesh2->setNodeMask(0);
auto depth = SceneUtil::createDepth(reverseZ);
auto depth = SceneUtil::createDepth(mSceneManager->getReverseZ());
depth->setWriteMask(false);
mEarlyRenderBinRoot->getOrCreateStateSet()->setAttributeAndModes(depth, osg::StateAttribute::ON);
mEarlyRenderBinRoot->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);

@ -4,10 +4,13 @@
#include <osg/ValueObject>
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/resource/imagemanager.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/sceneutil/visitor.hpp>
#include "../mwbase/environment.hpp"
namespace MWRender
{
@ -64,4 +67,9 @@ void overrideTexture(const std::string &texture, Resource::ResourceSystem *resou
node->setStateSet(stateset);
}
bool getReverseZ()
{
return MWBase::Environment::get().getResourceSystem()->getSceneManager()->getReverseZ();
}
}

@ -32,6 +32,8 @@ namespace MWRender
// no traverse()
}
};
bool getReverseZ();
}
#endif

@ -285,6 +285,16 @@ namespace Resource
return mReverseZ;
}
void SceneManager::setDepthFormat(GLenum format)
{
mDepthFormat = format;
}
GLenum SceneManager::getDepthFormat() const
{
return mDepthFormat;
}
void SceneManager::setAutoUseNormalMaps(bool use)
{
mAutoUseNormalMaps = use;

@ -95,6 +95,9 @@ namespace Resource
void setReverseZ(bool reverseZ);
bool getReverseZ() const;
void setDepthFormat(GLenum format);
GLenum getDepthFormat() const;
/// @see ShaderVisitor::setAutoUseNormalMaps
void setAutoUseNormalMaps(bool use);
@ -206,6 +209,7 @@ namespace Resource
SceneUtil::LightManager::SupportedMethods mSupportedLightingMethods;
bool mConvertAlphaTestToAlphaToCoverage;
bool mReverseZ;
GLenum mDepthFormat;
osg::ref_ptr<MultiObjectCache> mInstanceCache;

@ -28,8 +28,6 @@
#include <sstream>
#include "shadowsbin.hpp"
#include <components/sceneutil/util.hpp>
namespace {
using namespace osgShadow;
@ -350,11 +348,6 @@ void VDSMCameraCullCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
_projectionMatrix = cv->getProjectionMatrix();
}
bool isOrthographicViewFrustum(const osg::Matrix& m)
{
return m(0,3)==0.0 && m(1,3)==0.0 && m(2,3)==0.0;
}
} // namespace
MWShadowTechnique::ComputeLightSpaceBounds::ComputeLightSpaceBounds(osg::Viewport* viewport, const osg::Matrixd& projectionMatrix, osg::Matrixd& viewMatrix) :
@ -988,9 +981,6 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
return;
}
osg::Matrix shadowProj;
cv.getCurrentCamera()->getUserValue("shadowProj", shadowProj);
ViewDependentData* vdd = getViewDependentData(&cv);
if (!vdd)
@ -1006,41 +996,34 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
osg::CullSettings::ComputeNearFarMode cachedNearFarMode = cv.getComputeNearFarMode();
osg::RefMatrix& viewProjectionMatrix = *cv.getProjectionMatrix();
// check whether this main views projection is perspective or orthographic
bool orthographicViewFrustum = viewProjectionMatrix(0,3)==0.0 &&
viewProjectionMatrix(1,3)==0.0 &&
viewProjectionMatrix(2,3)==0.0;
double minZNear = 0.0;
double maxZFar = dbl_max;
bool orthographicViewFrustum;
if (_reverseZ)
{
cv.getCurrentCamera()->getUserValue("near", minZNear);
cv.getCurrentCamera()->getUserValue("far", maxZFar);
orthographicViewFrustum = isOrthographicViewFrustum(shadowProj);
}
else
if (cachedNearFarMode==osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR)
{
osg::RefMatrix& viewProjectionMatrix = *cv.getProjectionMatrix();
// check whether this main views projection is perspective or orthographic
orthographicViewFrustum = isOrthographicViewFrustum(viewProjectionMatrix);
if (cachedNearFarMode==osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR)
double left, right, top, bottom;
if (orthographicViewFrustum)
{
double left, right, top, bottom;
if (orthographicViewFrustum)
{
viewProjectionMatrix.getOrtho(left, right, bottom, top, minZNear, maxZFar);
}
else
{
viewProjectionMatrix.getFrustum(left, right, bottom, top, minZNear, maxZFar);
}
viewProjectionMatrix.getOrtho(left, right, bottom, top, minZNear, maxZFar);
}
// set the compute near/far mode to the highest quality setting to ensure we push the near plan out as far as possible
if (settings->getComputeNearFarModeOverride()!=osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR)
else
{
cv.setComputeNearFarMode(settings->getComputeNearFarModeOverride());
viewProjectionMatrix.getFrustum(left, right, bottom, top, minZNear, maxZFar);
}
OSG_INFO<<"minZNear="<<minZNear<<", maxZFar="<<maxZFar<<std::endl;
}
// set the compute near/far mode to the highest quality setting to ensure we push the near plan out as far as possible
if (settings->getComputeNearFarModeOverride()!=osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR)
{
cv.setComputeNearFarMode(settings->getComputeNearFarModeOverride());
}
// 1. Traverse main scene graph
@ -1052,9 +1035,6 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
cv.popStateSet();
if (_reverseZ)
cv.pushProjectionMatrix(new osg::RefMatrix(shadowProj));
if (cv.getComputeNearFarMode()!=osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR)
{
OSG_INFO<<"Just done main subgraph traversak"<<std::endl;
@ -1094,8 +1074,7 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
}
// return compute near far mode back to it's original settings
if (!_reverseZ)
cv.setComputeNearFarMode(cachedNearFarMode);
cv.setComputeNearFarMode(cachedNearFarMode);
OSG_INFO<<"frustum.eye="<<frustum.eye<<", frustum.centerNearPlane, "<<frustum.centerNearPlane<<" distance = "<<(frustum.eye-frustum.centerNearPlane).length()<<std::endl;
@ -1480,8 +1459,6 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv)
prepareStateSetForRenderingShadow(*vdd, cv.getTraversalNumber());
}
if (_reverseZ)
cv.popProjectionMatrix();
// OSG_NOTICE<<"End of shadow setup Projection matrix "<<*cv.getProjectionMatrix()<<std::endl;
}
@ -1670,9 +1647,11 @@ void MWShadowTechnique::createShaders()
_shadowCastingStateSet->addUniform(new osg::Uniform("alphaTestShadows", false));
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
depth->setWriteMask(true);
osg::ref_ptr<osg::ClipControl> clipcontrol = new osg::ClipControl(osg::ClipControl::LOWER_LEFT, osg::ClipControl::NEGATIVE_ONE_TO_ONE);
if (_reverseZ)
{
osg::ref_ptr<osg::ClipControl> clipcontrol = new osg::ClipControl(osg::ClipControl::LOWER_LEFT, osg::ClipControl::NEGATIVE_ONE_TO_ONE);
_shadowCastingStateSet->setAttribute(clipcontrol, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
}
_shadowCastingStateSet->setAttribute(depth, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
_shadowCastingStateSet->setMode(GL_DEPTH_CLAMP, osg::StateAttribute::ON);

@ -95,8 +95,8 @@ namespace SceneUtil
}
ShadowManager::ShadowManager(osg::ref_ptr<osg::Group> sceneRoot, osg::ref_ptr<osg::Group> rootNode, unsigned int outdoorShadowCastingMask, unsigned int indoorShadowCastingMask, Shader::ShaderManager &shaderManager, bool reverseZ)
: mShadowedScene(new osgShadow::ShadowedScene)
, mReverseZ(reverseZ)
: mReverseZ(reverseZ)
, mShadowedScene(new osgShadow::ShadowedScene)
, mShadowTechnique(new MWShadowTechnique)
, mOutdoorShadowCastingMask(outdoorShadowCastingMask)
, mIndoorShadowCastingMask(indoorShadowCastingMask)

@ -9,6 +9,7 @@
#include <osg/TexGen>
#include <osg/TexEnvCombine>
#include <osg/Version>
#include <osg/Fog>
#include <components/resource/imagemanager.hpp>
#include <components/resource/scenemanager.hpp>
@ -314,8 +315,7 @@ bool attachAlphaToCoverageFriendlyFramebufferToCamera(osg::Camera* camera, osg::
osg::ref_ptr<osg::Depth> createDepth(bool reverseZ)
{
static osg::Depth::Function func = reverseZ ? osg::Depth::GEQUAL : osg::Depth::LEQUAL;
return new osg::Depth(func);
return new osg::Depth(reverseZ ? osg::Depth::GEQUAL : osg::Depth::LEQUAL);
}
osg::Matrix getReversedZProjectionMatrixAsPerspectiveInf(double fov, double aspect, double near)
@ -350,5 +350,9 @@ osg::Matrix getReversedZProjectionMatrixAsOrtho(double left, double right, doubl
);
}
bool isFloatingPointDepthFormat(GLenum format)
{
return format == GL_DEPTH_COMPONENT32F || format == GL_DEPTH_COMPONENT32F_NV;
}
}

@ -50,7 +50,7 @@ namespace SceneUtil
};
// Allows camera to render to a color and floating point depth texture with a multisampled framebuffer.
// Must be set on a cameras cull callback.
// Must be set on a camera's cull callback.
// When the depth texture isn't needed as a sampler, use osg::Camera::attach(osg::Camera::DEPTH_COMPONENT, GL_DEPTH_COMPONENT32F) instead.
// If multisampling is not being used on the color buffer attachment, use the osg::Camera::attach() method.
class AttachMultisampledDepthColorCallback : public osg::NodeCallback
@ -99,6 +99,8 @@ namespace SceneUtil
// Returns an orthographic projection matrix for use with a reversed z-buffer.
osg::Matrix getReversedZProjectionMatrixAsOrtho(double left, double right, double bottom, double top, double near, double far);
// Returns true if the GL format is a floating point depth format
bool isFloatingPointDepthFormat(GLenum format);
}
#endif

@ -8,13 +8,16 @@
#include "world.hpp"
#include "../esm/loadland.hpp"
#include <components/resource/scenemanager.hpp>
namespace Terrain
{
CellBorder::CellBorder(Terrain::World *world, osg::Group *root, int borderMask):
mWorld(world),
mRoot(root),
mBorderMask(borderMask)
CellBorder::CellBorder(Terrain::World *world, osg::Group *root, int borderMask, Resource::SceneManager* sceneManager)
: mWorld(world)
, mSceneManager(sceneManager)
, mRoot(root)
, mBorderMask(borderMask)
{
}
@ -73,6 +76,8 @@ void CellBorder::createCellBorderGeometry(int x, int y)
polygonmode->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
stateSet->setAttributeAndModes(polygonmode,osg::StateAttribute::ON);
mSceneManager->recreateShaders(borderGeode, "debug");
borderGeode->setNodeMask(mBorderMask);
mRoot->addChild(borderGeode);

@ -4,6 +4,11 @@
#include <map>
#include <osg/Group>
namespace Resource
{
class SceneManager;
}
namespace Terrain
{
class World;
@ -16,7 +21,7 @@ namespace Terrain
public:
typedef std::map<std::pair<int, int>, osg::ref_ptr<osg::Node> > CellGrid;
CellBorder(Terrain::World *world, osg::Group *root, int borderMask);
CellBorder(Terrain::World *world, osg::Group *root, int borderMask, Resource::SceneManager* sceneManager);
void createCellBorderGeometry(int x, int y);
void destroyCellBorderGeometry(int x, int y);
@ -28,6 +33,7 @@ namespace Terrain
protected:
Terrain::World *mWorld;
Resource::SceneManager* mSceneManager;
osg::Group *mRoot;
CellGrid mCellBorderNodes;

@ -4,6 +4,7 @@
#include <osg/Camera>
#include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
#include "storage.hpp"
#include "texturemanager.hpp"
@ -43,7 +44,7 @@ World::World(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSyst
mTextureManager.reset(new TextureManager(mResourceSystem->getSceneManager()));
mChunkManager.reset(new ChunkManager(mStorage, mResourceSystem->getSceneManager(), mTextureManager.get(), mCompositeMapRenderer));
mChunkManager->setNodeMask(nodeMask);
mCellBorder.reset(new CellBorder(this,mTerrainRoot.get(),borderMask));
mCellBorder.reset(new CellBorder(this,mTerrainRoot.get(),borderMask,mResourceSystem->getSceneManager()));
mResourceSystem->addResourceManager(mChunkManager.get());
mResourceSystem->addResourceManager(mTextureManager.get());

@ -5,8 +5,8 @@ near clip
---------
:Type: floating point
:Range: > 0
:Default: 3.0
:Range: >= 0.005
:Default: 1.0
This setting controls the distance to the near clipping plane. The value must be greater than zero.
Values greater than approximately 18.0 will occasionally clip objects in the world in front of the character.
@ -235,3 +235,23 @@ Maximum roll angle in degrees.
This setting can only be configured by editing the settings configuration file.
reverse z
---------
:Type: boolean
:Range: True/False
:Default: True
Enables a reverse-z depth buffer in which the depth range is reversed. This
allows for small :ref:`near clip` values and removes almost all z-fighting with
terrain and even tightly coupled meshes at extreme view distances. For this to
be useful, a floating point depth buffer is required. These features require
driver and hardware support, but should work on any semi-modern desktop hardware
through OpenGL extensions. The exception is macOS, which has since dropped
development of OpenGL drivers. If unsupported, this setting has no effect.
Note, this will force OpenMW to use shaders as if :ref:`force shaders` was enabled.
The performance impact of this feature should be negligible.
This setting can only be configured by editing the settings configuration file.

@ -15,7 +15,7 @@
[Camera]
# Near clipping plane (>0.0, e.g. 0.01 to 18.0).
near clip = 3
near clip = 1
# Cull objects that occupy less than 'small feature culling pixel size' on the screen.
small feature culling = true
@ -67,6 +67,9 @@ head bobbing height = 3.0
# Maximum camera roll angle (degrees)
head bobbing roll = 0.2
# Reverse the depth range from [0,1] to [1,0].
reverse z = true
[Cells]
# Preload cells in a background thread. All settings starting with 'preload' have no effect unless this is enabled.

@ -34,6 +34,8 @@ set(SHADER_FILES
nv_nolighting_fragment.glsl
gui_vertex.glsl
gui_fragment.glsl
debug_vertex.glsl
debug_fragment.glsl
)
copy_all_resource_files(${CMAKE_CURRENT_SOURCE_DIR} ${OPENMW_SHADERS_ROOT} ${DDIRRELATIVE} "${SHADER_FILES}")

@ -0,0 +1,8 @@
#version 120
varying vec4 passColor;
void main()
{
gl_FragData[0] = passColor;
}

@ -0,0 +1,12 @@
#version 120
uniform mat4 projectionMatrix;
varying vec4 passColor;
void main()
{
gl_Position = projectionMatrix * (gl_ModelViewMatrix * gl_Vertex);
passColor = gl_Color;
}

@ -2,11 +2,11 @@
uniform float linearFac;
#endif
float getLinearDepth(in vec4 viewPos)
float getLinearDepth(in float z, in float viewZ)
{
#if @reverseZ
return linearFac*viewPos.z;
return linearFac*viewZ;
#else
return gl_Position.z;
return z;
#endif
}

@ -46,6 +46,7 @@ uniform mat4 osg_ViewMatrixInverse;
uniform mat4 osg_ViewMatrix;
uniform float windSpeed;
uniform vec3 playerPos;
uniform mat4 projectionMatrix;
#if @groundcoverStompMode == 0
#else
@ -142,9 +143,9 @@ void main(void)
if (length(gl_ModelViewMatrix * vec4(position, 1.0)) > @groundcoverFadeEnd)
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
else
gl_Position = gl_ProjectionMatrix * viewPos;
gl_Position = projectionMatrix * viewPos;
linearDepth = getLinearDepth(viewPos);
linearDepth = getLinearDepth(gl_Position.z, viewPos.z);
#if (!PER_PIXEL_LIGHTING || @shadows_enabled)
vec3 viewNormal = normalize((gl_NormalMatrix * rotation3(rotation) * gl_Normal).xyz);

@ -8,6 +8,8 @@
#extension GL_EXT_gpu_shader4: require
#endif
uniform mat4 projectionMatrix;
#if @diffuseMap
varying vec2 diffuseMapUV;
#endif
@ -36,12 +38,12 @@ varying vec3 passNormal;
void main(void)
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_Position = projectionMatrix * (gl_ModelViewMatrix * gl_Vertex);
vec4 viewPos = (gl_ModelViewMatrix * gl_Vertex);
gl_ClipVertex = viewPos;
euclideanDepth = length(viewPos.xyz);
linearDepth = getLinearDepth(viewPos);
linearDepth = getLinearDepth(gl_Position.z, viewPos.z);
#if @diffuseMap
diffuseMapUV = (gl_TextureMatrix[@diffuseMapUV] * gl_MultiTexCoord@diffuseMapUV).xy;

@ -1,5 +1,7 @@
#version 120
uniform mat4 projectionMatrix;
#if @diffuseMap
varying vec2 diffuseMapUV;
#endif
@ -21,14 +23,14 @@ varying float passFalloff;
void main(void)
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_Position = projectionMatrix * (gl_ModelViewMatrix * gl_Vertex);
vec4 viewPos = (gl_ModelViewMatrix * gl_Vertex);
gl_ClipVertex = viewPos;
#if @radialFog
euclideanDepth = length(viewPos.xyz);
#else
linearDepth = getLinearDepth(viewPos);
linearDepth = getLinearDepth(gl_Position.z, viewPos.z);
#endif
#if @diffuseMap

@ -8,6 +8,8 @@
#extension GL_EXT_gpu_shader4: require
#endif
uniform mat4 projectionMatrix;
#if @diffuseMap
varying vec2 diffuseMapUV;
#endif
@ -66,12 +68,13 @@ varying vec3 passNormal;
void main(void)
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_Position = projectionMatrix * (gl_ModelViewMatrix * gl_Vertex);
vec4 viewPos = (gl_ModelViewMatrix * gl_Vertex);
gl_ClipVertex = viewPos;
euclideanDepth = length(viewPos.xyz);
linearDepth = getLinearDepth(viewPos);
linearDepth = getLinearDepth(gl_Position.z, viewPos.z);
#if (@envMap || !PER_PIXEL_LIGHTING || @shadows_enabled)
vec3 viewNormal = normalize((gl_NormalMatrix * gl_Normal).xyz);

@ -8,6 +8,8 @@
#extension GL_EXT_gpu_shader4: require
#endif
uniform mat4 projectionMatrix;
varying vec2 uv;
varying float euclideanDepth;
varying float linearDepth;
@ -29,12 +31,12 @@ varying vec3 passNormal;
void main(void)
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_Position = projectionMatrix * (gl_ModelViewMatrix * gl_Vertex);
vec4 viewPos = (gl_ModelViewMatrix * gl_Vertex);
gl_ClipVertex = viewPos;
euclideanDepth = length(viewPos.xyz);
linearDepth = getLinearDepth(viewPos);
linearDepth = getLinearDepth(gl_Position.z, viewPos.z);
#if (!PER_PIXEL_LIGHTING || @shadows_enabled)
vec3 viewNormal = normalize((gl_NormalMatrix * gl_Normal).xyz);

@ -1,5 +1,7 @@
#version 120
uniform mat4 projectionMatrix;
varying vec3 screenCoordsPassthrough;
varying vec4 position;
varying float linearDepth;
@ -9,7 +11,7 @@ varying float linearDepth;
void main(void)
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_Position = projectionMatrix * (gl_ModelViewMatrix * gl_Vertex);
mat4 scalemat = mat4(0.5, 0.0, 0.0, 0.0,
0.0, -0.5, 0.0, 0.0,
@ -22,7 +24,7 @@ void main(void)
position = gl_Vertex;
vec4 viewPos = gl_ModelViewMatrix * gl_Vertex;
linearDepth = getLinearDepth(viewPos);
linearDepth = getLinearDepth(gl_Position.z, viewPos.z);
setupShadowCoords(viewPos, normalize((gl_NormalMatrix * gl_Normal).xyz));
}

Loading…
Cancel
Save