From 328ec85757b4dae0ca7b9466148781989c2bdfd6 Mon Sep 17 00:00:00 2001 From: "glassmancody.info" Date: Sun, 28 Mar 2021 11:00:52 -0700 Subject: [PATCH] Code review cleanup, add setting documentation --- apps/openmw/engine.cpp | 1 - components/sceneutil/lightmanager.cpp | 102 +++++++++--------- .../reference/modding/settings/shaders.rst | 63 +++++++++++ files/shaders/objects_fragment.glsl | 2 +- files/shaders/terrain_fragment.glsl | 2 +- 5 files changed, 117 insertions(+), 53 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 019e9f67a9..d7c315323d 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -31,7 +31,6 @@ #include #include -#include #include diff --git a/components/sceneutil/lightmanager.cpp b/components/sceneutil/lightmanager.cpp index d4275e5d28..3c1f31364f 100644 --- a/components/sceneutil/lightmanager.cpp +++ b/components/sceneutil/lightmanager.cpp @@ -16,7 +16,7 @@ #include "apps/openmw/mwrender/vismask.hpp" -namespace +namespace { /* similar to the boost::hash_combine */ template @@ -136,33 +136,35 @@ namespace SceneUtil switch (method) { case LightingMethod::FFP: - break; + { + break; + } case LightingMethod::PerObjectUniform: - { - stateset->addUniform(new osg::Uniform("LightBuffer[0].diffuse", light->getDiffuse()), mode); - stateset->addUniform(new osg::Uniform("LightBuffer[0].ambient", light->getAmbient()), mode); - stateset->addUniform(new osg::Uniform("LightBuffer[0].specular", light->getSpecular()), mode); - stateset->addUniform(new osg::Uniform("LightBuffer[0].position", light->getPosition()), mode); + { + stateset->addUniform(new osg::Uniform("LightBuffer[0].diffuse", light->getDiffuse()), mode); + stateset->addUniform(new osg::Uniform("LightBuffer[0].ambient", light->getAmbient()), mode); + stateset->addUniform(new osg::Uniform("LightBuffer[0].specular", light->getSpecular()), mode); + stateset->addUniform(new osg::Uniform("LightBuffer[0].position", light->getPosition()), mode); - break; - } + break; + } case LightingMethod::SingleUBO: - { - osg::ref_ptr buffer = new LightBuffer(1); + { + osg::ref_ptr buffer = new LightBuffer(1); - buffer->setDiffuse(0, light->getDiffuse()); - buffer->setAmbient(0, light->getAmbient()); - buffer->setSpecular(0, light->getSpecular()); - buffer->setPosition(0, light->getPosition()); + buffer->setDiffuse(0, light->getDiffuse()); + buffer->setAmbient(0, light->getAmbient()); + buffer->setSpecular(0, light->getSpecular()); + buffer->setPosition(0, light->getPosition()); - osg::ref_ptr ubo = new osg::UniformBufferObject; - buffer->mData->setBufferObject(ubo); - osg::ref_ptr ubb = new osg::UniformBufferBinding(static_cast(Shader::UBOBinding::LightBuffer), buffer->mData.get(), 0, buffer->mData->getTotalDataSize()); + osg::ref_ptr ubo = new osg::UniformBufferObject; + buffer->mData->setBufferObject(ubo); + osg::ref_ptr ubb = new osg::UniformBufferBinding(static_cast(Shader::UBOBinding::LightBuffer), buffer->mData.get(), 0, buffer->mData->getTotalDataSize()); - stateset->setAttributeAndModes(ubb, mode); + stateset->setAttributeAndModes(ubb, mode); - break; - } + break; + } } } @@ -201,9 +203,9 @@ namespace SceneUtil void apply(osg::State& state) const override { int lightNum = GL_LIGHT0 + mIndex; - glLightfv( lightNum, GL_AMBIENT, mnullptr.ptr() ); - glLightfv( lightNum, GL_DIFFUSE, mnullptr.ptr() ); - glLightfv( lightNum, GL_SPECULAR, mnullptr.ptr() ); + glLightfv(lightNum, GL_AMBIENT, mnullptr.ptr()); + glLightfv(lightNum, GL_DIFFUSE, mnullptr.ptr()); + glLightfv(lightNum, GL_SPECULAR, mnullptr.ptr()); LightStateCache* cache = getLightStateCache(state.getContextID()); cache->lastAppliedLight[mIndex] = nullptr; @@ -334,7 +336,7 @@ namespace SceneUtil cache->lastAppliedLight[i] = mLights[i]; } } - + state.applyModelViewMatrix(modelViewMatrix); } @@ -344,7 +346,7 @@ namespace SceneUtil }; struct StateSetGenerator - { + { LightManager* mLightManager; virtual ~StateSetGenerator() {} @@ -475,9 +477,9 @@ namespace SceneUtil mLightManager = findLightManager(nv->getNodePath()); if (!mLightManager) - throw std::runtime_error("can't find parent LightManager"); + throw std::runtime_error("can't find parent LightManager"); } - + mLightManager->addLight(static_cast(node), osg::computeLocalToWorld(nv->getNodePath()), nv->getTraversalNumber()); traverse(node, nv); @@ -523,7 +525,7 @@ namespace SceneUtil mLastFrameNumber = cv->getTraversalNumber(); if (mLightManager->getLightingMethod() == LightingMethod::SingleUBO) - { + { auto stateset = mLightManager->getStateSet(); auto bo = mLightManager->getLightBuffer(mLastFrameNumber); osg::ref_ptr ubb = new osg::UniformBufferBinding(static_cast(Shader::UBOBinding::LightBuffer), bo->getData().get(), 0, bo->getData()->getTotalDataSize()); @@ -548,7 +550,7 @@ namespace SceneUtil buf->setDiffuse(0, sun->getDiffuse()); buf->setAmbient(0, sun->getAmbient()); buf->setSpecular(0, sun->getSpecular()); - buf->setPosition(0, sun->getPosition() * (*cv->getCurrentRenderStage()->getInitialViewMatrix())); + buf->setPosition(0, sun->getPosition() * (*cv->getCurrentRenderStage()->getInitialViewMatrix())); } } } @@ -560,12 +562,12 @@ namespace SceneUtil LightManager* mLightManager; size_t mLastFrameNumber; }; - + class LightManagerStateAttribute : public osg::StateAttribute { public: LightManagerStateAttribute() : mLightManager(nullptr) {} - LightManagerStateAttribute(LightManager* lightManager) : mLightManager(lightManager) {} + LightManagerStateAttribute(LightManager* lightManager) : mLightManager(lightManager) {} LightManagerStateAttribute(const LightManagerStateAttribute& copy,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY) : osg::StateAttribute(copy,copyop),mLightManager(copy.mLightManager) {} @@ -595,7 +597,7 @@ namespace SceneUtil : mStartLight(0) , mLightingMask(~0u) , mSun(nullptr) - , mPointLightRadiusMultiplier(std::max(0.f, Settings::Manager::getFloat("light bounds multiplier", "Shaders"))) + , mPointLightRadiusMultiplier(std::clamp(Settings::Manager::getFloat("light bounds multiplier", "Shaders"), 0.f, 10.f)) , mPointLightFadeStart(0.f) { mPointLightFadeEnd = std::max(0.f, Settings::Manager::getFloat("maximum light distance", "Shaders")); @@ -608,7 +610,7 @@ namespace SceneUtil auto lightingModelString = Settings::Manager::getString("lighting method", "Shaders"); bool validLightingModel = isValidLightingModelString(lightingModelString); if (!validLightingModel) - Log(Debug::Error) << "Invalid option for 'lighting model': got '" << lightingModelString + Log(Debug::Error) << "Invalid option for 'lighting model': got '" << lightingModelString << "', expected legacy, default, or experimental."; if (ffp || !validLightingModel) @@ -625,10 +627,10 @@ namespace SceneUtil osg::GLExtensions* exts = osg::GLExtensions::Get(0, false); bool supportsUBO = exts && exts->isUniformBufferObjectSupported; - bool supportsGPU4 = exts && exts->isGpuShader4Supported; + bool supportsGPU4 = exts && exts->isGpuShader4Supported; if (!supportsUBO) - Log(Debug::Info) << "GL_ARB_uniform_buffer_object not supported: using fallback uniforms"; + Log(Debug::Info) << "GL_ARB_uniform_buffer_object not supported: using fallback uniforms"; else if (!supportsGPU4) Log(Debug::Info) << "GL_EXT_gpu_shader4 not supported: using fallback uniforms"; @@ -648,7 +650,7 @@ namespace SceneUtil osg::ref_ptr uambient = new osg::Uniform(osg::Uniform::FLOAT_VEC4, ("LightBuffer[" + std::to_string(i) + "].ambient").c_str()); osg::ref_ptr uposition = new osg::Uniform(osg::Uniform::FLOAT_VEC4, ("LightBuffer[" + std::to_string(i) + "].position").c_str()); osg::ref_ptr uattenuation = new osg::Uniform(osg::Uniform::FLOAT_VEC4, ("LightBuffer[" + std::to_string(i) + "].attenuation").c_str()); - + mLightUniforms[i].emplace(UniformKey::Diffuse, udiffuse); mLightUniforms[i].emplace(UniformKey::Ambient, uambient); mLightUniforms[i].emplace(UniformKey::Specular, uspecular); @@ -681,7 +683,7 @@ namespace SceneUtil stateset->setAttribute(new LightManagerStateAttribute(this), osg::StateAttribute::ON); } - + stateset->addUniform(new osg::Uniform("PointLightCount", 0)); setUpdateCallback(new LightManagerUpdateCallback); @@ -720,10 +722,10 @@ namespace SceneUtil { mMaxLights = value; } - + int LightManager::getMaxLightsInScene() const { - static constexpr int max = 16384 / LightBuffer::queryBlockSize(1); + static constexpr int max = 16384 / LightBuffer::queryBlockSize(1); return max; } @@ -732,7 +734,7 @@ namespace SceneUtil Shader::ShaderManager::DefineMap defines; bool ffp = usingFFP(); - + defines["ffpLighting"] = ffp ? "1" : "0"; defines["maxLights"] = std::to_string(getMaxLights()); defines["maxLightsInScene"] = std::to_string(getMaxLightsInScene()); @@ -794,7 +796,7 @@ namespace SceneUtil } void LightManager::update(size_t frameNum) - { + { getLightIndexMap(frameNum).clear(); mLights.clear(); mLightsInViewSpace.clear(); @@ -802,7 +804,7 @@ namespace SceneUtil // Do an occasional cleanup for orphaned lights. for (int i=0; i<2; ++i) { - if (mStateSetCache[i].size() > 5000) + if (mStateSetCache[i].size() > 5000) mStateSetCache[i].clear(); } } @@ -839,9 +841,9 @@ namespace SceneUtil auto id = lightList[i]->mLightSource->getId(); hash_combine(hash, id); - if (getLightingMethod() != LightingMethod::SingleUBO) + if (getLightingMethod() != LightingMethod::SingleUBO) continue; - + if (getLightIndexMap(frameNum).find(id) != getLightIndexMap(frameNum).end()) continue; @@ -875,11 +877,11 @@ namespace SceneUtil if (it == mLightsInViewSpace.end()) { it = mLightsInViewSpace.insert(std::make_pair(camPtr, LightSourceViewBoundCollection())).first; - + for (const auto& transform : mLights) { osg::Matrixf worldViewMat = transform.mWorldMatrix * (*viewMatrix); - + float radius = transform.mLightSource->getRadius(); osg::BoundingSphere viewBound = osg::BoundingSphere(osg::Vec3f(0,0,0), radius * mPointLightRadiusMultiplier); @@ -901,7 +903,7 @@ namespace SceneUtil LightSourceViewBound l; l.mLightSource = transform.mLightSource; l.mViewBound = viewBound; - it->second.push_back(l); + it->second.push_back(l); } } @@ -985,7 +987,7 @@ namespace SceneUtil // Don't use Camera::getViewMatrix, that one might be relative to another camera! const osg::RefMatrix* viewMatrix = cv->getCurrentRenderStage()->getInitialViewMatrix(); const std::vector& lights = mLightManager->getLightsInViewSpace(cv->getCurrentCamera(), viewMatrix, mLastFrameNumber); - + // get the node bounds in view space // NB do not node->getBound() * modelView, that would apply the node's transformation twice osg::BoundingSphere nodeBound; @@ -1026,7 +1028,7 @@ namespace SceneUtil for (auto it = lightList.begin(); it != lightList.end() && lightList.size() > maxLights; ) { osg::CullStack::CullingStack& stack = cv->getModelViewCullingStack(); - + osg::BoundingSphere bs = (*it)->mViewBound; bs._radius = bs._radius * 2.0; osg::CullingSet& cullingSet = stack.front(); diff --git a/docs/source/reference/modding/settings/shaders.rst b/docs/source/reference/modding/settings/shaders.rst index acc8482991..e1acd9411b 100644 --- a/docs/source/reference/modding/settings/shaders.rst +++ b/docs/source/reference/modding/settings/shaders.rst @@ -148,6 +148,69 @@ By default, the fog becomes thicker proportionally to your distance from the cli This setting makes the fog use the actual eye point distance (or so called Euclidean distance) to calculate the fog, which makes the fog look less artificial, especially if you have a wide FOV. Note that the rendering will act as if you have 'force shaders' option enabled with this on, which means that shaders will be used to render all objects and the terrain. +lighting method +--------------- + +:Type: string +:Range: legacy|default|experimental +:Default: default + +Sets the internal handling of light sources. + +'legacy' is restricted to a maximum of 8 lights per object and guarantees fixed function pipeline compatible lighting. + +'default' removes the light limit via :ref:`max lights` and follows a new attenuation formula which can drastically reduce light popping and seams. +It is recommended to use this mode with older hardware, as the technique ensures a range of compatibility equal to that of 'legacy'. + +'experimental' carries all of the benefits that 'legacy' has, but uses a modern approach that allows for a higher 'max lights' count with little to no performance penalties on modern hardware. + +light bounds multiplier +----------------------- + +:Type: float +:Range: 0.0-10.0 +:Default: 2.0 + +Controls the bounding sphere radius of point lights, which is used to determine if an object should receive lighting from a particular light source. +Note, this has no direct effect on the overall illumination of lights. +Larger multipliers will allow for smoother transitions of light sources, but may require an increase in :ref:`max lights` and thus carries a performance penalty. +This especially helps with abrupt light popping with handheld light sources such as torches and lanterns. + +It is recommended to keep this at 1.0 if :ref:`lighting method` is set to 'legacy', as the number of lights is fixed in that mode. + +maximum light distance +---------------------- + +:Type: float +:Range: The whole range of 32-bit floating point +:Default: 8192 + +The maximum distance from the camera that lights will be illuminated, applies to both interiors and exteriors. +A lower distance will improve performance. +Set this to a non-positive value to disable fading. + +light fade start +---------------- + +:Type: float +:Range: 0.0-1.0 +:Default: 0.85 + +The fraction of the maximum distance at which lights will begin to fade away. +Tweaking it will make the transition proportionally more or less smooth. +This setting has no effect if the maximum light distance is non-positive. + +max lights +---------- + +:Type: integer +:Range: >=2 +:Default: 16 + +Sets the maximum number of lights that each object can receive lighting from. +Has no effect if :ref:`force shaders` option is off or :ref:`lighting method` is 'legacy'. In this case the maximum number of lights is fixed at 8. +Increasing this too much can cause significant performance loss, especially if :ref:`lighting method` is not set to 'experimental' or :ref:`force per pixel lighting` is on. + antialias alpha test --------------------------------------- diff --git a/files/shaders/objects_fragment.glsl b/files/shaders/objects_fragment.glsl index e26d0f44cd..615b57a8a2 100644 --- a/files/shaders/objects_fragment.glsl +++ b/files/shaders/objects_fragment.glsl @@ -76,8 +76,8 @@ varying vec3 passNormal; #include "vertexcolors.glsl" #include "shadows_fragment.glsl" -#include "parallax.glsl" #include "lighting.glsl" +#include "parallax.glsl" #include "alpha.glsl" void main() diff --git a/files/shaders/terrain_fragment.glsl b/files/shaders/terrain_fragment.glsl index a8bf735528..6a7ac0bcc4 100644 --- a/files/shaders/terrain_fragment.glsl +++ b/files/shaders/terrain_fragment.glsl @@ -34,8 +34,8 @@ varying vec3 passNormal; #include "vertexcolors.glsl" #include "shadows_fragment.glsl" -#include "parallax.glsl" #include "lighting.glsl" +#include "parallax.glsl" void main() {