From 2762be9f85e5b12a18d53536538defc9d2376e21 Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Sun, 26 Jan 2025 14:57:34 +0100 Subject: [PATCH 01/12] opaque depth texture must account for multiview --- files/shaders/compatibility/bs/default.frag | 4 +--- files/shaders/compatibility/bs/nolighting.frag | 3 +-- files/shaders/compatibility/objects.frag | 6 ++---- files/shaders/lib/core/fragment.glsl | 7 +++++++ files/shaders/lib/core/fragment.h.glsl | 2 ++ files/shaders/lib/core/fragment_multiview.glsl | 8 ++++++++ 6 files changed, 21 insertions(+), 9 deletions(-) diff --git a/files/shaders/compatibility/bs/default.frag b/files/shaders/compatibility/bs/default.frag index 5068c01d80..3d2ad07d1d 100644 --- a/files/shaders/compatibility/bs/default.frag +++ b/files/shaders/compatibility/bs/default.frag @@ -26,8 +26,6 @@ uniform sampler2D normalMap; varying vec2 normalMapUV; #endif -uniform sampler2D opaqueDepthTex; - varying float euclideanDepth; varying float linearDepth; @@ -59,7 +57,7 @@ void main() #if defined(DISTORTION) && DISTORTION vec2 screenCoords = gl_FragCoord.xy / (screenRes * @distorionRTRatio); gl_FragData[0].a *= getDiffuseColor().a; - gl_FragData[0] = applyDistortion(gl_FragData[0], distortionStrength, gl_FragCoord.z, texture2D(opaqueDepthTex, screenCoords).x); + gl_FragData[0] = applyDistortion(gl_FragData[0], distortionStrength, gl_FragCoord.z, sampleOpaqueDepthTex(screenCoords).x); return; #endif diff --git a/files/shaders/compatibility/bs/nolighting.frag b/files/shaders/compatibility/bs/nolighting.frag index c9e3ca4e13..da267d7858 100644 --- a/files/shaders/compatibility/bs/nolighting.frag +++ b/files/shaders/compatibility/bs/nolighting.frag @@ -35,7 +35,6 @@ uniform float alphaRef; #if @softParticles #include "lib/particle/soft.glsl" -uniform sampler2D opaqueDepthTex; uniform float particleSize; uniform bool particleFade; uniform float softFalloffDepth; @@ -70,7 +69,7 @@ void main() viewNormal, near, far, - texture2D(opaqueDepthTex, screenCoords).x, + sampleOpaqueDepthTex(screenCoords).x, particleSize, particleFade, softFalloffDepth diff --git a/files/shaders/compatibility/objects.frag b/files/shaders/compatibility/objects.frag index 8bd9664b41..999079a31d 100644 --- a/files/shaders/compatibility/objects.frag +++ b/files/shaders/compatibility/objects.frag @@ -113,8 +113,6 @@ uniform sampler2D orthoDepthMap; varying vec3 orthoDepthMapCoord; #endif -uniform sampler2D opaqueDepthTex; - void main() { #if @particleOcclusion @@ -143,7 +141,7 @@ vec2 screenCoords = gl_FragCoord.xy / screenRes; #if defined(DISTORTION) && DISTORTION gl_FragData[0].a *= getDiffuseColor().a; - gl_FragData[0] = applyDistortion(gl_FragData[0], distortionStrength, gl_FragCoord.z, texture2D(opaqueDepthTex, screenCoords / @distorionRTRatio).x); + gl_FragData[0] = applyDistortion(gl_FragData[0], distortionStrength, gl_FragCoord.z, sampleOpaqueDepthTex(screenCoords / @distorionRTRatio).x); return; #endif @@ -258,7 +256,7 @@ vec2 screenCoords = gl_FragCoord.xy / screenRes; viewNormal, near, far, - texture2D(opaqueDepthTex, screenCoords).x, + sampleOpaqueDepthTex(screenCoords).x, particleSize, particleFade, softFalloffDepth diff --git a/files/shaders/lib/core/fragment.glsl b/files/shaders/lib/core/fragment.glsl index 9b983148cb..d58e17feaf 100644 --- a/files/shaders/lib/core/fragment.glsl +++ b/files/shaders/lib/core/fragment.glsl @@ -40,3 +40,10 @@ vec3 sampleSkyColor(vec2 uv) return texture2D(sky, uv).xyz; } #endif + +uniform sampler2D opaqueDepthTex; + +vec4 sampleOpaqueDepthTex(vec2 uv) +{ + return texture2D(opaqueDepthTex, uv); +} diff --git a/files/shaders/lib/core/fragment.h.glsl b/files/shaders/lib/core/fragment.h.glsl index b8c3f9a32b..9b7ef768e6 100644 --- a/files/shaders/lib/core/fragment.h.glsl +++ b/files/shaders/lib/core/fragment.h.glsl @@ -17,4 +17,6 @@ vec4 samplerLastShader(vec2 uv); vec3 sampleSkyColor(vec2 uv); #endif +vec4 sampleOpaqueDepthTex(vec2 uv); + #endif // OPENMW_FRAGMENT_H_GLSL diff --git a/files/shaders/lib/core/fragment_multiview.glsl b/files/shaders/lib/core/fragment_multiview.glsl index 2880087104..767a3e04bd 100644 --- a/files/shaders/lib/core/fragment_multiview.glsl +++ b/files/shaders/lib/core/fragment_multiview.glsl @@ -2,6 +2,7 @@ #extension GL_OVR_multiview : require #extension GL_OVR_multiview2 : require +#extension GL_EXT_texture_array : require #include "lib/core/fragment.h.glsl" @@ -44,3 +45,10 @@ vec3 sampleSkyColor(vec2 uv) return texture(sky, vec3((uv), gl_ViewID_OVR)).xyz; } #endif + +uniform sampler2DArray opaqueDepthTex; + +vec4 sampleOpaqueDepthTex(vec2 uv) +{ + return texture2DArray(opaqueDepthTex, vec3((uv), gl_ViewID_OVR)); +} From 6071de9d1d647a43182716df22e579558b7bbc00 Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Tue, 1 Oct 2024 19:18:11 +0200 Subject: [PATCH 02/12] Set a dummy texture for sky blending, when multiview is enabled. --- apps/openmw/mwrender/characterpreview.cpp | 19 ++++++++++++++++++- apps/openmw/mwrender/localmap.cpp | 18 +++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 123eadfdec..b9ebfd0c52 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -258,12 +259,28 @@ namespace MWRender // TODO: Clean up this mess of loose uniforms that shaders depend on. // turn off sky blending + int skyTextureSlot = mResourceSystem->getSceneManager()->getShaderManager().reserveGlobalTextureUnits(Shader::ShaderManager::Slot::SkyTexture); stateset->addUniform(new osg::Uniform("far", 10000000.0f)); stateset->addUniform(new osg::Uniform("skyBlendingStart", 8000000.0f)); - stateset->addUniform(new osg::Uniform("sky", 0)); + stateset->addUniform(new osg::Uniform("sky", skyTextureSlot)); stateset->addUniform(new osg::Uniform("screenRes", osg::Vec2f{ 1, 1 })); + if (Stereo::getMultiview()) + { + // The above set the sky texture unit to 0. Normally this is fine since texture unit 0 is the sampler2d diffuseMap, which will be set. + // However, in multiview the sky texture is a sampler2darray, and so needs to be set separately with a dummy texture + osg::Texture2DArray* textureArray = new osg::Texture2DArray; + textureArray->setTextureSize(1, 1, 2); + textureArray->setName("fakeSkyTexture"); + textureArray->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); + textureArray->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); + textureArray->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + textureArray->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + textureArray->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE); + stateset->setTextureAttributeAndModes(skyTextureSlot, textureArray, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED); + } stateset->addUniform(new osg::Uniform("emissiveMult", 1.f)); + // Opaque stuff must have 1 as its fragment alpha as the FBO is translucent, so having blending off isn't enough osg::ref_ptr noBlendAlphaEnv = new osg::TexEnvCombine(); diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 968903f6a3..dcc2e3d887 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -734,10 +735,25 @@ namespace MWRender stateset->setAttributeAndModes(fog, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); // turn of sky blending + int skyTextureSlot = MWBase::Environment::get().getResourceSystem()->getSceneManager()->getShaderManager().reserveGlobalTextureUnits(Shader::ShaderManager::Slot::SkyTexture); stateset->addUniform(new osg::Uniform("far", 10000000.0f)); stateset->addUniform(new osg::Uniform("skyBlendingStart", 8000000.0f)); - stateset->addUniform(new osg::Uniform("sky", 0)); + stateset->addUniform(new osg::Uniform("sky", skyTextureSlot)); stateset->addUniform(new osg::Uniform("screenRes", osg::Vec2f{ 1, 1 })); + if (Stereo::getMultiview()) + { + // The above set the sky texture unit to 0. Normally this is fine since texture unit 0 is the sampler2d diffuseMap, which will be set. + // However, in multiview the sky texture is a sampler2darray, and so needs to be set separately with a dummy texture + osg::Texture2DArray* textureArray = new osg::Texture2DArray; + textureArray->setTextureSize(1, 1, 2); + textureArray->setName("fakeSkyTexture"); + textureArray->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); + textureArray->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); + textureArray->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + textureArray->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + textureArray->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE); + stateset->setTextureAttributeAndModes(skyTextureSlot, textureArray, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED); + } osg::ref_ptr lightmodel = new osg::LightModel; lightmodel->setAmbientIntensity(osg::Vec4(0.3f, 0.3f, 0.3f, 1.f)); From a2f5e1c07545e21825770044c86ba5bf37b11d01 Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Sun, 26 Jan 2025 16:23:56 +0100 Subject: [PATCH 03/12] Fix multiview use in techniques --- components/fx/pass.cpp | 21 +++++++++++++++---- components/fx/technique.cpp | 2 +- files/data/shaders/internal_distortion.omwfx | 4 ++-- .../compatibility/multiview_resolve.frag | 2 +- .../shaders/lib/core/fragment_multiview.glsl | 2 +- 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/components/fx/pass.cpp b/components/fx/pass.cpp index cf50d20fe2..c55bee76e3 100644 --- a/components/fx/pass.cpp +++ b/components/fx/pass.cpp @@ -81,6 +81,7 @@ namespace fx #define omw_Position @position #define omw_Texture1D @texture1D #define omw_Texture2D @texture2D +#define omw_Texture2DArray @texture2DArray #define omw_Texture3D @texture3D #define omw_Vertex @vertex #define omw_FragColor @fragColor @@ -154,7 +155,7 @@ mat4 omw_InvProjectionMatrix() float omw_GetDepth(vec2 uv) { #if OMW_MULTIVIEW - float depth = omw_Texture2D(omw_SamplerDepth, vec3(uv, gl_ViewID_OVR)).r; + float depth = omw_Texture2DArray(omw_SamplerDepth, vec3(uv, gl_ViewID_OVR)).r; #else float depth = omw_Texture2D(omw_SamplerDepth, uv).r; #endif @@ -165,10 +166,19 @@ mat4 omw_InvProjectionMatrix() #endif } + vec4 omw_GetDistortion(vec2 uv) + { +#if OMW_MULTIVIEW + return omw_Texture2DArray(omw_SamplerDistortion, vec3(uv, gl_ViewID_OVR)); +#else + return omw_Texture2D(omw_SamplerDistortion, uv); +#endif + } + vec4 omw_GetLastShader(vec2 uv) { #if OMW_MULTIVIEW - return omw_Texture2D(omw_SamplerLastShader, vec3(uv, gl_ViewID_OVR)); + return omw_Texture2DArray(omw_SamplerLastShader, vec3(uv, gl_ViewID_OVR)); #else return omw_Texture2D(omw_SamplerLastShader, uv); #endif @@ -177,7 +187,7 @@ mat4 omw_InvProjectionMatrix() vec4 omw_GetLastPass(vec2 uv) { #if OMW_MULTIVIEW - return omw_Texture2D(omw_SamplerLastPass, vec3(uv, gl_ViewID_OVR)); + return omw_Texture2DArray(omw_SamplerLastPass, vec3(uv, gl_ViewID_OVR)); #else return omw_Texture2D(omw_SamplerLastPass, uv); #endif @@ -186,7 +196,7 @@ mat4 omw_InvProjectionMatrix() vec3 omw_GetNormals(vec2 uv) { #if OMW_MULTIVIEW - return omw_Texture2D(omw_SamplerNormals, vec3(uv, gl_ViewID_OVR)).rgb * 2.0 - 1.0; + return omw_Texture2DArray(omw_SamplerNormals, vec3(uv, gl_ViewID_OVR)).rgb * 2.0 - 1.0; #else return omw_Texture2D(omw_SamplerNormals, uv).rgb * 2.0 - 1.0; #endif @@ -275,6 +285,9 @@ float omw_EstimateFogCoverageFromUV(vec2 uv) { "@hdr", technique.getHDR() ? "1" : "0" }, { "@in", mLegacyGLSL ? "varying" : "in" }, { "@out", mLegacyGLSL ? "varying" : "out" }, { "@position", "gl_Position" }, { "@texture1D", mLegacyGLSL ? "texture1D" : "texture" }, + // Note, @texture2DArray must be defined before @texture2D since @texture2D is a perfect prefix of + // texture2DArray + { "@texture2DArray", mLegacyGLSL ? "texture2DArray" : "texture" }, { "@texture2D", mLegacyGLSL ? "texture2D" : "texture" }, { "@texture3D", mLegacyGLSL ? "texture3D" : "texture" }, { "@vertex", mLegacyGLSL ? "gl_Vertex" : "_omw_Vertex" }, diff --git a/components/fx/technique.cpp b/components/fx/technique.cpp index f56e0d498e..5963e274ec 100644 --- a/components/fx/technique.cpp +++ b/components/fx/technique.cpp @@ -85,7 +85,7 @@ namespace fx mDescription = {}; mVersion = {}; mGLSLExtensions.clear(); - mGLSLVersion = mUBO ? 330 : 120; + mGLSLVersion = (mUBO || Stereo::getMultiview()) ? 330 : 120; mGLSLProfile.clear(); mDynamic = false; } diff --git a/files/data/shaders/internal_distortion.omwfx b/files/data/shaders/internal_distortion.omwfx index b641bb6711..b8e62ff229 100644 --- a/files/data/shaders/internal_distortion.omwfx +++ b/files/data/shaders/internal_distortion.omwfx @@ -6,11 +6,11 @@ fragment main { { const float multiplier = 0.14; - vec2 offset = omw_Texture2D(omw_SamplerDistortion, omw_TexCoord).rg; + vec2 offset = omw_GetDistortion(omw_TexCoord).rg; offset *= multiplier; offset = clamp(offset, vec2(-1.0), vec2(1.0)); - float occlusionFactor = omw_Texture2D(omw_SamplerDistortion, omw_TexCoord+offset).b; + float occlusionFactor = omw_GetDistortion(omw_TexCoord+offset).b; omw_FragColor = mix(omw_GetLastShader(omw_TexCoord + offset), omw_GetLastShader(omw_TexCoord), occlusionFactor); } diff --git a/files/shaders/compatibility/multiview_resolve.frag b/files/shaders/compatibility/multiview_resolve.frag index a77a3b35d1..9aeb54314b 100644 --- a/files/shaders/compatibility/multiview_resolve.frag +++ b/files/shaders/compatibility/multiview_resolve.frag @@ -1,4 +1,4 @@ -#version 120 +#version 330 #extension GL_EXT_texture_array : require varying vec2 uv; diff --git a/files/shaders/lib/core/fragment_multiview.glsl b/files/shaders/lib/core/fragment_multiview.glsl index 767a3e04bd..e29c5afbc9 100644 --- a/files/shaders/lib/core/fragment_multiview.glsl +++ b/files/shaders/lib/core/fragment_multiview.glsl @@ -50,5 +50,5 @@ uniform sampler2DArray opaqueDepthTex; vec4 sampleOpaqueDepthTex(vec2 uv) { - return texture2DArray(opaqueDepthTex, vec3((uv), gl_ViewID_OVR)); + return texture(opaqueDepthTex, vec3((uv), gl_ViewID_OVR)); } From ea51c55d007c9d070950a9b4d610b9148d580051 Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Sat, 18 Jan 2025 16:11:47 +0100 Subject: [PATCH 04/12] Restore valid per view shadow settings. --- components/sceneutil/mwshadowtechnique.cpp | 128 +++++++++++++-------- components/sceneutil/mwshadowtechnique.hpp | 10 +- 2 files changed, 89 insertions(+), 49 deletions(-) diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index 9fd435f40d..929ffadcbf 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -986,9 +986,12 @@ void SceneUtil::MWShadowTechnique::copyShadowMap(osgUtil::CullVisitor& cv, ViewD lhs_sd->_camera = rhs_sd->_camera; lhs_sd->_textureUnit = rhs_sd->_textureUnit; lhs_sd->_texture = rhs_sd->_texture; + lhs_sd->_sm_i = rhs_sd->_sm_i; sdl.push_back(lhs_sd); } + copyShadowStateSettings(cv, lhs); + if (lhs->_numValidShadows > 0) { prepareStateSetForRenderingShadow(*lhs, cv.getTraversalNumber()); @@ -1000,6 +1003,15 @@ void SceneUtil::MWShadowTechnique::setCustomFrustumCallback(CustomFrustumCallbac _customFrustumCallback = cfc; } +void SceneUtil::MWShadowTechnique::copyShadowStateSettings(osgUtil::CullVisitor& cv, ViewDependentData* vdd) +{ + for (const auto& sd : vdd->getShadowDataList()) + { + //assignTexGenSettings(&cv, sd->_camera, sd->_textureUnit, sd->_texgen); + assignValidRegionSettings(cv, sd->_camera, sd->_sm_i, vdd->_uniforms[cv.getTraversalNumber()%2]); + assignShadowStateSettings(cv, sd->_camera, sd->_sm_i, vdd->_uniforms[cv.getTraversalNumber()%2]); + } +} void MWShadowTechnique::update(osg::NodeVisitor& nv) { @@ -1053,6 +1065,8 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv) _shadowedScene->osg::Group::traverse(cv); return; } + + Uniforms& vddUniforms = vdd->_uniforms[cv.getTraversalNumber() % 2]; ShadowSettings* settings = getShadowedScene()->getShadowSettings(); @@ -1498,31 +1512,10 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv) cv.popStateSet(); + if (!orthographicViewFrustum && settings->getShadowMapProjectionHint()==ShadowSettings::PERSPECTIVE_SHADOW_MAP) { - { - osg::Matrix validRegionMatrix = cv.getCurrentCamera()->getInverseViewMatrix() * camera->getViewMatrix() * camera->getProjectionMatrix(); - - std::string validRegionUniformName = "validRegionMatrix" + std::to_string(sm_i); - osg::ref_ptr validRegionUniform; - - for (const auto & uniform : _uniforms[cv.getTraversalNumber() % 2]) - { - if (uniform->getName() == validRegionUniformName) - { - validRegionUniform = uniform; - break; - } - } - - if (!validRegionUniform) - { - validRegionUniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, validRegionUniformName); - _uniforms[cv.getTraversalNumber() % 2].push_back(validRegionUniform); - } - - validRegionUniform->set(validRegionMatrix); - } + assignValidRegionSettings(cv, camera, sm_i, vddUniforms); if (settings->getMultipleShadowMapHint() == ShadowSettings::CASCADED) adjustPerspectiveShadowMapCameraSettings(vdsmCallback->getRenderStage(), frustum, pl, camera.get(), cascaseNear, cascadeFar); @@ -1537,31 +1530,7 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv) // 4.4 compute main scene graph TexGen + uniform settings + setup state // { - osg::Matrix shadowSpaceMatrix = cv.getCurrentCamera()->getInverseViewMatrix() * - camera->getViewMatrix() * - camera->getProjectionMatrix() * - osg::Matrix::translate(1.0,1.0,1.0) * - osg::Matrix::scale(0.5,0.5,0.5); - - std::string shadowSpaceUniformName = "shadowSpaceMatrix" + std::to_string(sm_i); - osg::ref_ptr shadowSpaceUniform; - - for (const auto & uniform : _uniforms[cv.getTraversalNumber() % 2]) - { - if (uniform->getName() == shadowSpaceUniformName) - { - shadowSpaceUniform = uniform; - break; - } - } - - if (!shadowSpaceUniform) - { - shadowSpaceUniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, shadowSpaceUniformName); - _uniforms[cv.getTraversalNumber() % 2].push_back(shadowSpaceUniform); - } - - shadowSpaceUniform->set(shadowSpaceMatrix); + assignShadowStateSettings(cv, camera, sm_i, vddUniforms); } // mark the light as one that has active shadows and requires shaders @@ -1569,6 +1538,7 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv) // pass on shadow data to ShadowDataList sd->_textureUnit = textureUnit; + sd->_sm_i = sm_i; sdl.push_back(sd); @@ -3080,6 +3050,62 @@ bool MWShadowTechnique::adjustPerspectiveShadowMapCameraSettings(osgUtil::Render return true; } +void MWShadowTechnique::assignShadowStateSettings(osgUtil::CullVisitor& cv, osg::Camera* camera, unsigned int sm_i, Uniforms& uniforms) +{ + osg::Matrix inverseViewMatrix = osg::Matrix::inverse(*cv.getModelViewMatrix()); + osg::Matrix shadowSpaceMatrix = inverseViewMatrix * + camera->getViewMatrix() * + camera->getProjectionMatrix() * + osg::Matrix::translate(1.0,1.0,1.0) * + osg::Matrix::scale(0.5,0.5,0.5); + + std::string shadowSpaceUniformName = "shadowSpaceMatrix" + std::to_string(sm_i); + osg::ref_ptr shadowSpaceUniform; + + for (const auto & uniform : uniforms) + { + if (uniform->getName() == shadowSpaceUniformName) + { + shadowSpaceUniform = uniform; + break; + } + } + + if (!shadowSpaceUniform) + { + shadowSpaceUniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, shadowSpaceUniformName); + uniforms.push_back(shadowSpaceUniform); + } + + shadowSpaceUniform->set(shadowSpaceMatrix); + return; +} + +void SceneUtil::MWShadowTechnique::assignValidRegionSettings(osgUtil::CullVisitor & cv, osg::Camera* camera, unsigned int sm_i, Uniforms & uniforms) +{ + osg::Matrix validRegionMatrix = osg::Matrix::inverse(*cv.getModelViewMatrix()) * camera->getViewMatrix() * camera->getProjectionMatrix(); + + std::string validRegionUniformName = "validRegionMatrix" + std::to_string(sm_i); + osg::ref_ptr validRegionUniform; + + for (const auto & uniform : uniforms) + { + if (uniform->getName() == validRegionUniformName) + { + validRegionUniform = uniform; + break; + } + } + + if (!validRegionUniform) + { + validRegionUniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, validRegionUniformName); + uniforms.push_back(validRegionUniform); + } + + validRegionUniform->set(validRegionMatrix); +} + void MWShadowTechnique::cullShadowReceivingScene(osgUtil::CullVisitor* cv) const { OSG_INFO<<"cullShadowReceivingScene()"<addUniform(uniform); } + for(const auto& uniform : vdd._uniforms[traversalNumber % 2]) + { + OSG_INFO<<"addUniform("<getName()<<")"<addUniform(uniform); + } + if (_program.valid()) { stateset->setAttribute(_program.get()); diff --git a/components/sceneutil/mwshadowtechnique.hpp b/components/sceneutil/mwshadowtechnique.hpp index 8b39818e2e..4b9de9364a 100644 --- a/components/sceneutil/mwshadowtechnique.hpp +++ b/components/sceneutil/mwshadowtechnique.hpp @@ -157,6 +157,7 @@ namespace SceneUtil { * the resulting shadow map may be invalid. */ virtual void operator()(osgUtil::CullVisitor& cv, osg::BoundingBoxd& customClipSpace, osgUtil::CullVisitor*& sharedFrustumHint) = 0; }; + typedef std::vector< osg::ref_ptr > Uniforms; // forward declare class ViewDependentData; @@ -192,6 +193,7 @@ namespace SceneUtil { ViewDependentData* _viewDependentData; unsigned int _textureUnit; + unsigned int _sm_i; osg::ref_ptr _texture; osg::ref_ptr _camera; }; @@ -228,6 +230,7 @@ namespace SceneUtil { LightDataList _lightDataList; ShadowDataList _shadowDataList; + std::array _uniforms; unsigned int _numValidShadows; }; @@ -240,6 +243,8 @@ namespace SceneUtil { void setCustomFrustumCallback(CustomFrustumCallback* cfc); + void copyShadowStateSettings(osgUtil::CullVisitor& cv, ViewDependentData* vdd); + virtual void createShaders(); virtual bool selectActiveLights(osgUtil::CullVisitor* cv, ViewDependentData* vdd) const; @@ -251,6 +256,10 @@ namespace SceneUtil { virtual bool cropShadowCameraToMainFrustum(Frustum& frustum, osg::Camera* camera, double viewNear, double viewFar, std::vector& planeList); virtual bool adjustPerspectiveShadowMapCameraSettings(osgUtil::RenderStage* renderStage, Frustum& frustum, LightData& positionedLight, osg::Camera* camera, double viewNear, double viewFar); + + virtual void assignShadowStateSettings(osgUtil::CullVisitor& cv, osg::Camera* camera, unsigned int sm_i, Uniforms& uniforms); + + virtual void assignValidRegionSettings(osgUtil::CullVisitor& cv, osg::Camera* camera, unsigned int sm_i, Uniforms& uniforms); virtual void cullShadowReceivingScene(osgUtil::CullVisitor* cv) const; @@ -280,7 +289,6 @@ namespace SceneUtil { osg::ref_ptr _fallbackBaseTexture; osg::ref_ptr _fallbackShadowMapTexture; - typedef std::vector< osg::ref_ptr > Uniforms; std::array _uniforms; osg::ref_ptr _program; From a1df9afc9a6909a934fcaf4a02bf438499723490 Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Sun, 26 Jan 2025 17:05:42 +0100 Subject: [PATCH 05/12] Formatting changes --- apps/openmw/mwrender/characterpreview.cpp | 4 +-- apps/openmw/mwrender/localmap.cpp | 38 +++++++++++++--------- components/sceneutil/mwshadowtechnique.cpp | 1 - 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index b9ebfd0c52..3c43227013 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -266,8 +266,7 @@ namespace MWRender stateset->addUniform(new osg::Uniform("screenRes", osg::Vec2f{ 1, 1 })); if (Stereo::getMultiview()) { - // The above set the sky texture unit to 0. Normally this is fine since texture unit 0 is the sampler2d diffuseMap, which will be set. - // However, in multiview the sky texture is a sampler2darray, and so needs to be set separately with a dummy texture + // Multiview needs a texture2DArray dummy texture applied here osg::Texture2DArray* textureArray = new osg::Texture2DArray; textureArray->setTextureSize(1, 1, 2); textureArray->setName("fakeSkyTexture"); @@ -280,7 +279,6 @@ namespace MWRender } stateset->addUniform(new osg::Uniform("emissiveMult", 1.f)); - // Opaque stuff must have 1 as its fragment alpha as the FBO is translucent, so having blending off isn't enough osg::ref_ptr noBlendAlphaEnv = new osg::TexEnvCombine(); diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index dcc2e3d887..afa29b3f93 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -5,10 +5,10 @@ #include #include #include -#include #include #include #include +#include #include @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include #include @@ -735,25 +737,29 @@ namespace MWRender stateset->setAttributeAndModes(fog, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); // turn of sky blending - int skyTextureSlot = MWBase::Environment::get().getResourceSystem()->getSceneManager()->getShaderManager().reserveGlobalTextureUnits(Shader::ShaderManager::Slot::SkyTexture); + int skyTextureSlot = MWBase::Environment::get() + .getResourceSystem() + ->getSceneManager() + ->getShaderManager() + .reserveGlobalTextureUnits(Shader::ShaderManager::Slot::SkyTexture); stateset->addUniform(new osg::Uniform("far", 10000000.0f)); stateset->addUniform(new osg::Uniform("skyBlendingStart", 8000000.0f)); stateset->addUniform(new osg::Uniform("sky", skyTextureSlot)); stateset->addUniform(new osg::Uniform("screenRes", osg::Vec2f{ 1, 1 })); - if (Stereo::getMultiview()) - { - // The above set the sky texture unit to 0. Normally this is fine since texture unit 0 is the sampler2d diffuseMap, which will be set. - // However, in multiview the sky texture is a sampler2darray, and so needs to be set separately with a dummy texture - osg::Texture2DArray* textureArray = new osg::Texture2DArray; - textureArray->setTextureSize(1, 1, 2); - textureArray->setName("fakeSkyTexture"); - textureArray->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); - textureArray->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); - textureArray->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); - textureArray->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); - textureArray->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE); - stateset->setTextureAttributeAndModes(skyTextureSlot, textureArray, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED); - } + if (Stereo::getMultiview()) + { + // Multiview needs a texture2DArray dummy texture applied here + osg::Texture2DArray* textureArray = new osg::Texture2DArray; + textureArray->setTextureSize(1, 1, 2); + textureArray->setName("fakeSkyTexture"); + textureArray->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); + textureArray->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); + textureArray->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + textureArray->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + textureArray->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE); + stateset->setTextureAttributeAndModes(skyTextureSlot, textureArray, + osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED); + } osg::ref_ptr lightmodel = new osg::LightModel; lightmodel->setAmbientIntensity(osg::Vec4(0.3f, 0.3f, 0.3f, 1.f)); diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index 929ffadcbf..4cd4fdd84a 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -1007,7 +1007,6 @@ void SceneUtil::MWShadowTechnique::copyShadowStateSettings(osgUtil::CullVisitor& { for (const auto& sd : vdd->getShadowDataList()) { - //assignTexGenSettings(&cv, sd->_camera, sd->_textureUnit, sd->_texgen); assignValidRegionSettings(cv, sd->_camera, sd->_sm_i, vdd->_uniforms[cv.getTraversalNumber()%2]); assignShadowStateSettings(cv, sd->_camera, sd->_sm_i, vdd->_uniforms[cv.getTraversalNumber()%2]); } From dec9ce4a5fd9d1e442fc99c5768f809e4fcad6e6 Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Sun, 26 Jan 2025 17:41:43 +0100 Subject: [PATCH 06/12] sky dummy texture not actually needed when using sky texture slot. --- apps/openmw/mwrender/characterpreview.cpp | 13 ------------- apps/openmw/mwrender/localmap.cpp | 14 -------------- 2 files changed, 27 deletions(-) diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 3c43227013..3a5bbf45fa 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -264,19 +264,6 @@ namespace MWRender stateset->addUniform(new osg::Uniform("skyBlendingStart", 8000000.0f)); stateset->addUniform(new osg::Uniform("sky", skyTextureSlot)); stateset->addUniform(new osg::Uniform("screenRes", osg::Vec2f{ 1, 1 })); - if (Stereo::getMultiview()) - { - // Multiview needs a texture2DArray dummy texture applied here - osg::Texture2DArray* textureArray = new osg::Texture2DArray; - textureArray->setTextureSize(1, 1, 2); - textureArray->setName("fakeSkyTexture"); - textureArray->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); - textureArray->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); - textureArray->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); - textureArray->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); - textureArray->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE); - stateset->setTextureAttributeAndModes(skyTextureSlot, textureArray, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED); - } stateset->addUniform(new osg::Uniform("emissiveMult", 1.f)); diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index afa29b3f93..d31d08f04a 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -746,20 +746,6 @@ namespace MWRender stateset->addUniform(new osg::Uniform("skyBlendingStart", 8000000.0f)); stateset->addUniform(new osg::Uniform("sky", skyTextureSlot)); stateset->addUniform(new osg::Uniform("screenRes", osg::Vec2f{ 1, 1 })); - if (Stereo::getMultiview()) - { - // Multiview needs a texture2DArray dummy texture applied here - osg::Texture2DArray* textureArray = new osg::Texture2DArray; - textureArray->setTextureSize(1, 1, 2); - textureArray->setName("fakeSkyTexture"); - textureArray->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); - textureArray->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); - textureArray->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); - textureArray->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); - textureArray->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE); - stateset->setTextureAttributeAndModes(skyTextureSlot, textureArray, - osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED); - } osg::ref_ptr lightmodel = new osg::LightModel; lightmodel->setAmbientIntensity(osg::Vec4(0.3f, 0.3f, 0.3f, 1.f)); From 152dfacab27b226875a9624f5e36096ea2d72982 Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Sun, 26 Jan 2025 19:20:46 +0100 Subject: [PATCH 07/12] multiview_resolve did not need to be version 330 --- files/shaders/compatibility/multiview_resolve.frag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/shaders/compatibility/multiview_resolve.frag b/files/shaders/compatibility/multiview_resolve.frag index 9aeb54314b..a77a3b35d1 100644 --- a/files/shaders/compatibility/multiview_resolve.frag +++ b/files/shaders/compatibility/multiview_resolve.frag @@ -1,4 +1,4 @@ -#version 330 +#version 120 #extension GL_EXT_texture_array : require varying vec2 uv; From efe72ea2d5555faf5a55ccb559d9ac563a4d0188 Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Sun, 26 Jan 2025 19:23:12 +0100 Subject: [PATCH 08/12] Clang format --- apps/openmw/mwrender/characterpreview.cpp | 4 ++-- apps/openmw/mwrender/localmap.cpp | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 3a5bbf45fa..a6e9b848b4 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -3,7 +3,6 @@ #include #include -#include #include #include #include @@ -259,7 +258,8 @@ namespace MWRender // TODO: Clean up this mess of loose uniforms that shaders depend on. // turn off sky blending - int skyTextureSlot = mResourceSystem->getSceneManager()->getShaderManager().reserveGlobalTextureUnits(Shader::ShaderManager::Slot::SkyTexture); + int skyTextureSlot = mResourceSystem->getSceneManager()->getShaderManager().reserveGlobalTextureUnits( + Shader::ShaderManager::Slot::SkyTexture); stateset->addUniform(new osg::Uniform("far", 10000000.0f)); stateset->addUniform(new osg::Uniform("skyBlendingStart", 8000000.0f)); stateset->addUniform(new osg::Uniform("sky", skyTextureSlot)); diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index d31d08f04a..d51088d729 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include From b2c0d20d56319189c5ad8955a73aa7a7c425b93b Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Tue, 28 Jan 2025 20:05:08 +0100 Subject: [PATCH 09/12] explicitly include lib/core/fragment.h.glsl --- files/shaders/compatibility/bs/default.frag | 1 + files/shaders/compatibility/bs/nolighting.frag | 1 + files/shaders/compatibility/objects.frag | 1 + 3 files changed, 3 insertions(+) diff --git a/files/shaders/compatibility/bs/default.frag b/files/shaders/compatibility/bs/default.frag index 3d2ad07d1d..6f38c4df5e 100644 --- a/files/shaders/compatibility/bs/default.frag +++ b/files/shaders/compatibility/bs/default.frag @@ -40,6 +40,7 @@ uniform float specStrength; uniform bool useTreeAnim; uniform float distortionStrength; +#include "lib/core/fragment.h.glsl" #include "lib/light/lighting.glsl" #include "lib/material/alpha.glsl" #include "lib/util/distortion.glsl" diff --git a/files/shaders/compatibility/bs/nolighting.frag b/files/shaders/compatibility/bs/nolighting.frag index da267d7858..a46e99aa82 100644 --- a/files/shaders/compatibility/bs/nolighting.frag +++ b/files/shaders/compatibility/bs/nolighting.frag @@ -26,6 +26,7 @@ uniform float far; uniform float near; uniform float alphaRef; +#include "lib/core/fragment.h.glsl" #include "lib/material/alpha.glsl" #include "compatibility/vertexcolors.glsl" diff --git a/files/shaders/compatibility/objects.frag b/files/shaders/compatibility/objects.frag index 999079a31d..ad6d262f6d 100644 --- a/files/shaders/compatibility/objects.frag +++ b/files/shaders/compatibility/objects.frag @@ -89,6 +89,7 @@ varying vec4 passTangent; #define ADDITIVE_BLENDING #endif +#include "lib/core/fragment.h.glsl" #include "lib/light/lighting.glsl" #include "lib/material/parallax.glsl" #include "lib/material/alpha.glsl" From 517aa81938aaaca0882f8423fa525927aa18a6c3 Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Wed, 29 Jan 2025 22:35:19 +0100 Subject: [PATCH 10/12] Change sky blending fix to remove changing the "sky" texture slot when disabling sky blending. --- apps/openmw/mwrender/characterpreview.cpp | 3 --- apps/openmw/mwrender/localmap.cpp | 6 ------ 2 files changed, 9 deletions(-) diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index a6e9b848b4..18604e78ca 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -258,11 +258,8 @@ namespace MWRender // TODO: Clean up this mess of loose uniforms that shaders depend on. // turn off sky blending - int skyTextureSlot = mResourceSystem->getSceneManager()->getShaderManager().reserveGlobalTextureUnits( - Shader::ShaderManager::Slot::SkyTexture); stateset->addUniform(new osg::Uniform("far", 10000000.0f)); stateset->addUniform(new osg::Uniform("skyBlendingStart", 8000000.0f)); - stateset->addUniform(new osg::Uniform("sky", skyTextureSlot)); stateset->addUniform(new osg::Uniform("screenRes", osg::Vec2f{ 1, 1 })); stateset->addUniform(new osg::Uniform("emissiveMult", 1.f)); diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index d51088d729..6785ce29bf 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -736,14 +736,8 @@ namespace MWRender stateset->setAttributeAndModes(fog, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); // turn of sky blending - int skyTextureSlot = MWBase::Environment::get() - .getResourceSystem() - ->getSceneManager() - ->getShaderManager() - .reserveGlobalTextureUnits(Shader::ShaderManager::Slot::SkyTexture); stateset->addUniform(new osg::Uniform("far", 10000000.0f)); stateset->addUniform(new osg::Uniform("skyBlendingStart", 8000000.0f)); - stateset->addUniform(new osg::Uniform("sky", skyTextureSlot)); stateset->addUniform(new osg::Uniform("screenRes", osg::Vec2f{ 1, 1 })); osg::ref_ptr lightmodel = new osg::LightModel; From 5b1aafb77ac2b2c78ba58b40d23d09d20010aa23 Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Wed, 29 Jan 2025 23:01:34 +0100 Subject: [PATCH 11/12] Formatting mistakes --- components/sceneutil/mwshadowtechnique.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index 4cd4fdd84a..9fa01385d5 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -1511,7 +1511,6 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv) cv.popStateSet(); - if (!orthographicViewFrustum && settings->getShadowMapProjectionHint()==ShadowSettings::PERSPECTIVE_SHADOW_MAP) { assignValidRegionSettings(cv, camera, sm_i, vddUniforms); @@ -3077,7 +3076,6 @@ void MWShadowTechnique::assignShadowStateSettings(osgUtil::CullVisitor& cv, osg: } shadowSpaceUniform->set(shadowSpaceMatrix); - return; } void SceneUtil::MWShadowTechnique::assignValidRegionSettings(osgUtil::CullVisitor & cv, osg::Camera* camera, unsigned int sm_i, Uniforms & uniforms) From 4428c1db7de19d87c71fee1c2228bcd34e3cdb46 Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Thu, 30 Jan 2025 20:53:56 +0100 Subject: [PATCH 12/12] Unused includes --- apps/openmw/mwrender/localmap.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 6785ce29bf..e582bb76ee 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -16,8 +16,6 @@ #include #include #include -#include -#include #include #include #include