diff --git a/components/sceneutil/mwshadowtechnique.cpp b/components/sceneutil/mwshadowtechnique.cpp index 5ed5e5a99a..ea52ec24a8 100644 --- a/components/sceneutil/mwshadowtechnique.cpp +++ b/components/sceneutil/mwshadowtechnique.cpp @@ -1315,6 +1315,29 @@ void MWShadowTechnique::cull(osgUtil::CullVisitor& cv) 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; + + OpenThreads::ScopedLock lock(_accessUniformsAndProgramMutex); + + for (auto uniform : _uniforms) + { + if (uniform->getName() == validRegionUniformName) + validRegionUniform = uniform; + } + + if (!validRegionUniform) + { + validRegionUniform = new osg::Uniform(osg::Uniform::FLOAT_MAT4, validRegionUniformName); + _uniforms.push_back(validRegionUniform); + } + + validRegionUniform->set(validRegionMatrix); + } + if (settings->getMultipleShadowMapHint() == ShadowSettings::CASCADED) adjustPerspectiveShadowMapCameraSettings(vdsmCallback->getRenderStage(), frustum, pl, camera.get(), cascaseNear, cascadeFar); else diff --git a/components/sceneutil/shadow.cpp b/components/sceneutil/shadow.cpp index a6559e9b9e..d3655dfb5c 100644 --- a/components/sceneutil/shadow.cpp +++ b/components/sceneutil/shadow.cpp @@ -119,6 +119,12 @@ namespace SceneUtil else definesWithShadows["useShadowDebugOverlay"] = "0"; + // switch this to reading settings if it's ever exposed to the user + if (mShadowSettings->getShadowMapProjectionHint() == ShadowSettings::PERSPECTIVE_SHADOW_MAP) + definesWithShadows["perspectiveShadowMaps"] = "1"; + else + definesWithShadows["perspectiveShadowMaps"] = "0"; + return definesWithShadows; } @@ -132,6 +138,8 @@ namespace SceneUtil definesWithShadows["useShadowDebugOverlay"] = "0"; + definesWithShadows["perspectiveShadowMaps"] = "0"; + return definesWithShadows; } void ShadowManager::enableIndoorMode() diff --git a/files/shaders/shadows_fragment.glsl b/files/shaders/shadows_fragment.glsl index 220e00efaa..713473458b 100644 --- a/files/shaders/shadows_fragment.glsl +++ b/files/shaders/shadows_fragment.glsl @@ -4,6 +4,10 @@ @foreach shadow_texture_unit_index @shadow_texture_unit_list uniform sampler2DShadow shadowTexture@shadow_texture_unit_index; varying vec4 shadowSpaceCoords@shadow_texture_unit_index; + +#if @perspectiveShadowMaps + varying vec4 shadowRegionCoords@shadow_texture_unit_index; +#endif @endforeach #endif // SHADOWS @@ -17,13 +21,18 @@ float unshadowedLightRatio() if (!doneShadows) { vec3 shadowXYZ = shadowSpaceCoords@shadow_texture_unit_index.xyz / shadowSpaceCoords@shadow_texture_unit_index.w; - vec2 shadowXY = shadowXYZ.xy; - if (all(lessThan(shadowXY, vec2(1.0, 1.0))) && all(greaterThan(shadowXY, vec2(0.0, 0.0)))) +#if @perspectiveShadowMaps + vec3 shadowRegionXYZ = shadowRegionCoords@shadow_texture_unit_index.xyz / shadowRegionCoords@shadow_texture_unit_index.w; +#endif + if (all(lessThan(shadowXYZ.xy, vec2(1.0, 1.0))) && all(greaterThan(shadowXYZ.xy, vec2(0.0, 0.0)))) { shadowing = min(shadow2DProj(shadowTexture@shadow_texture_unit_index, shadowSpaceCoords@shadow_texture_unit_index).r, shadowing); - if (all(lessThan(shadowXYZ, vec3(0.95, 0.95, 1.0))) && all(greaterThan(shadowXYZ, vec3(0.05, 0.05, 0.0)))) - doneShadows = true; + + doneShadows = all(lessThan(shadowXYZ, vec3(0.95, 0.95, 1.0))) && all(greaterThan(shadowXYZ.xy, vec2(0.05, 0.05))); +#if @perspectiveShadowMaps + doneShadows = doneShadows && all(lessThan(shadowRegionXYZ, vec3(1.0, 1.0, 1.0))) && all(greaterThan(shadowRegionXYZ.xy, vec2(-1.0, -1.0))); +#endif } } @endforeach @@ -44,8 +53,11 @@ void applyShadowDebugOverlay() @foreach shadow_texture_unit_index @shadow_texture_unit_list if (!doneOverlay) { - vec2 shadowXY = shadowSpaceCoords@shadow_texture_unit_index.xy / shadowSpaceCoords@shadow_texture_unit_index.w; - if (all(lessThan(shadowXY, vec2(1.0, 1.0))) && all(greaterThan(shadowXY, vec2(0.0, 0.0)))) + vec3 shadowXYZ = shadowSpaceCoords@shadow_texture_unit_index.xyz / shadowSpaceCoords@shadow_texture_unit_index.w; +#if @perspectiveShadowMaps + vec3 shadowRegionXYZ = shadowRegionCoords@shadow_texture_unit_index.xyz / shadowRegionCoords@shadow_texture_unit_index.w; +#endif + if (all(lessThan(shadowXYZ.xy, vec2(1.0, 1.0))) && all(greaterThan(shadowXYZ.xy, vec2(0.0, 0.0)))) { colourIndex = mod(@shadow_texture_unit_index.0, 3.0); if (colourIndex < 1.0) @@ -55,8 +67,10 @@ void applyShadowDebugOverlay() else gl_FragData[0].z += 0.1; - if (all(lessThan(shadowXY, vec2(0.95, 0.95))) && all(greaterThan(shadowXY, vec2(0.05, 0.05)))) - doneOverlay = true; + doneOverlay = all(lessThan(shadowXYZ, vec3(0.95, 0.95, 1.0))) && all(greaterThan(shadowXYZ.xy, vec2(0.05, 0.05))); +#if @perspectiveShadowMaps + doneOverlay = doneOverlay && all(lessThan(shadowRegionXYZ.xyz, vec3(1.0, 1.0, 1.0))) && all(greaterThan(shadowRegionXYZ.xy, vec2(-1.0, -1.0))); +#endif } } @endforeach diff --git a/files/shaders/shadows_vertex.glsl b/files/shaders/shadows_vertex.glsl index bbc1a40368..4baa249c11 100644 --- a/files/shaders/shadows_vertex.glsl +++ b/files/shaders/shadows_vertex.glsl @@ -4,6 +4,11 @@ @foreach shadow_texture_unit_index @shadow_texture_unit_list uniform int shadowTextureUnit@shadow_texture_unit_index; varying vec4 shadowSpaceCoords@shadow_texture_unit_index; + +#if @perspectiveShadowMaps + uniform mat4 validRegionMatrix@shadow_texture_unit_index; + varying vec4 shadowRegionCoords@shadow_texture_unit_index; +#endif @endforeach #endif // SHADOWS @@ -15,6 +20,10 @@ void setupShadowCoords(vec4 viewPos) @foreach shadow_texture_unit_index @shadow_texture_unit_list eyePlaneMat = mat4(gl_EyePlaneS[shadowTextureUnit@shadow_texture_unit_index], gl_EyePlaneT[shadowTextureUnit@shadow_texture_unit_index], gl_EyePlaneR[shadowTextureUnit@shadow_texture_unit_index], gl_EyePlaneQ[shadowTextureUnit@shadow_texture_unit_index]); shadowSpaceCoords@shadow_texture_unit_index = viewPos * eyePlaneMat; + +#if @perspectiveShadowMaps + shadowRegionCoords@shadow_texture_unit_index = validRegionMatrix@shadow_texture_unit_index * viewPos; +#endif @endforeach #endif // SHADOWS } \ No newline at end of file