From b0fdea58e61c47ac553e9f0938c09d415eebda5b Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 20 Feb 2026 23:39:42 +0000 Subject: Simplified and tidied ShadowMapper No arbitrary 10m extra extents. No runtime vectors. Simpler code. Consts. etc. --- gfx/gl/shadowMapper.cpp | 73 +++++++++++++++++++++++-------------------------- gfx/gl/shadowMapper.h | 14 ++++++---- 2 files changed, 42 insertions(+), 45 deletions(-) diff --git a/gfx/gl/shadowMapper.cpp b/gfx/gl/shadowMapper.cpp index a73caa0..35c225b 100644 --- a/gfx/gl/shadowMapper.cpp +++ b/gfx/gl/shadowMapper.cpp @@ -8,7 +8,6 @@ #include "gl_traits.h" #include "gldebug.h" #include "location.h" -#include "maths.h" #include "sceneProvider.h" #include "sceneShader.h" #include @@ -25,7 +24,6 @@ #include #include #include -#include ShadowMapper::ShadowMapper(const TextureAbsCoord & s) : landmess {shadowLandmass_vert}, dynamicPointInst {shadowDynamicPointInst_vert}, @@ -54,66 +52,63 @@ ShadowMapper::ShadowMapper(const TextureAbsCoord & s) : glBindFramebuffer(GL_FRAMEBUFFER, 0); } -constexpr auto shadowBands - = [](const float scaleFactor, std::integer_sequence) { - const auto base = 10'000'000 / pow(scaleFactor, sizeof...(ints) - 1); - return std::array {1, static_cast((base * pow(scaleFactor, ints)))...}; +constexpr GlobalDistance SHADOW_NEAR = 1; +constexpr GlobalDistance SHADOW_FAR = 10'000'000; +constexpr auto SHADOW_BANDS_DISTS + = [](const float scaleFactor, std::integer_sequence) { + const auto base = SHADOW_FAR / pow(scaleFactor, sizeof...(Ints) - 1); + return std::array {SHADOW_NEAR, static_cast((base * pow(scaleFactor, Ints)))...}; }(4.6F, std::make_integer_sequence()); -static_assert(shadowBands.front() == 1); -static_assert(shadowBands.back() == 10'000'000); -static_assert(shadowBands.size() == ShadowMapper::SHADOW_BANDS + 1); +static_assert(SHADOW_BANDS_DISTS.front() == 1); +static_assert(SHADOW_BANDS_DISTS.back() == SHADOW_FAR); +static_assert(SHADOW_BANDS_DISTS.size() == ShadowMapper::SHADOW_BANDS + 1); -std::vector> -ShadowMapper::getBandViewExtents(const Camera & camera, const glm::mat4 & lightViewDir) +size_t +ShadowMapper::getBandViewExtents( + BandViewExtents & bandViewExtents, const Camera & camera, const glm::mat4 & lightViewDir) { - std::vector> bandViewExtents; - for (const auto dist : shadowBands) { + size_t band = 0; + for (const auto dist : SHADOW_BANDS_DISTS) { const auto extents = camera.extentsAtDist(dist); - bandViewExtents.emplace_back(extents * [&lightViewDir, cameraPos = camera.getPosition()](const auto & e) { - return glm::mat3(lightViewDir) * (e.xyz() - cameraPos); - }); - if (std::none_of(extents.begin(), extents.end(), [targetDist = dist - 1](const auto & e) { - return e.w > targetDist; + bandViewExtents[band++] = extents * [&lightViewDir, cameraPos = camera.getPosition()](const auto & extent) { + return glm::mat3(lightViewDir) * (extent.xyz() - cameraPos); + }; + if (std::ranges::none_of(extents, [dist](const auto & extent) { + return extent.w >= dist; })) { break; } } - return bandViewExtents; + return band; } const Frustum & ShadowMapper::preFrame(const LightDirection & dir, const Camera & camera) { - const auto lightViewDir = glm::lookAt({}, dir.vector(), up); + const auto lightViewDir = glm::lookAt({}, dir.vector(), Camera::upFromForward(dir.vector())); const auto lightViewPoint = camera.getPosition(); - const auto bandViewExtents = getBandViewExtents(camera, lightViewDir); + const auto bandViewExtentCount = getBandViewExtents(bandViewExtents, camera, lightViewDir); + const auto activeBandViewExtents = std::span(bandViewExtents).subspan(0, bandViewExtentCount); + using ExtentsBoundingBox = AxisAlignedBoundingBox; - definitions.clear(); - sizes.clear(); - std::ranges::transform(bandViewExtents | std::views::pairwise, std::back_inserter(definitions), - [&lightViewDir, this](const auto & band) mutable { - const auto & [near, far] = band; - auto extents = ExtentsBoundingBox::fromPoints(std::span {near.begin(), far.end()}); - extents.min.z -= 10'000.F; - extents.max.z += 10'000.F; - const auto lightProjection = glm::ortho( - extents.min.x, extents.max.x, extents.min.y, extents.max.y, -extents.max.z, -extents.min.z); - sizes.emplace_back(extents.max - extents.min); - return lightProjection * lightViewDir; - }); - - ExtentsBoundingBox extents {lightViewPoint, lightViewPoint}; - for (const auto & point : bandViewExtents.back()) { - extents += point; + for (auto out = std::make_pair(sizes.begin(), definitions.begin()); + const auto & [near, far] : activeBandViewExtents | std::views::pairwise) { + const auto extents = ExtentsBoundingBox::fromPoints(std::span {near.begin(), far.end()}); + const auto lightProjection = glm::ortho( + extents.min.x, extents.max.x, extents.min.y, extents.max.y, -extents.max.z, -extents.min.z); + *out.first++ = extents.max - extents.min; + *out.second++ = lightProjection * lightViewDir; } + + const auto extents = ExtentsBoundingBox::fromPoints(activeBandViewExtents.back()) += {}; const auto lightProjection = glm::ortho(extents.min.x, extents.max.x, extents.min.y, extents.max.y, -extents.max.z, -extents.min.z); frustum = {lightViewPoint, lightViewDir, lightProjection}; return frustum; } -ShadowMapper::Definitions +std::span ShadowMapper::update(const SceneProvider & scene, const LightDirection & dir, const Camera & camera) const { glDebugScope _ {depthMap}; diff --git a/gfx/gl/shadowMapper.h b/gfx/gl/shadowMapper.h index 82374cb..8b5e0b6 100644 --- a/gfx/gl/shadowMapper.h +++ b/gfx/gl/shadowMapper.h @@ -5,10 +5,10 @@ #include "gfx/gl/shadowStenciller.h" #include "lib/glArrays.h" #include "program.h" +#include #include #include #include -#include class SceneProvider; class Camera; @@ -20,11 +20,12 @@ public: static constexpr std::size_t SHADOW_BANDS {4}; - using Definitions = std::vector; - using Sizes = std::vector; + using Definitions = std::array; + using Sizes = std::array; const Frustum & preFrame(const LightDirection & direction, const Camera &); - [[nodiscard]] Definitions update(const SceneProvider &, const LightDirection & direction, const Camera &) const; + [[nodiscard]] std::span update( + const SceneProvider &, const LightDirection & direction, const Camera &) const; class ShadowProgram : public Program { public: @@ -74,12 +75,13 @@ public: } private: - [[nodiscard]] static std::vector> getBandViewExtents( - const Camera &, const glm::mat4 & lightView); + using BandViewExtents = std::array, SHADOW_BANDS + 1>; + [[nodiscard]] static size_t getBandViewExtents(BandViewExtents &, const Camera &, const glm::mat4 & lightView); glFrameBuffer depthMapFBO; glTexture depthMap; TextureAbsCoord size; + BandViewExtents bandViewExtents; Definitions definitions; Sizes sizes; Frustum frustum; -- cgit v1.3