diff options
Diffstat (limited to 'gfx/gl/shadowMapper.cpp')
| -rw-r--r-- | gfx/gl/shadowMapper.cpp | 156 |
1 files changed, 78 insertions, 78 deletions
diff --git a/gfx/gl/shadowMapper.cpp b/gfx/gl/shadowMapper.cpp index 3cb73f7..e01fd20 100644 --- a/gfx/gl/shadowMapper.cpp +++ b/gfx/gl/shadowMapper.cpp @@ -2,87 +2,110 @@ #include "collections.h" #include "game/gamestate.h" #include "gfx/aabb.h" -#include "gfx/gl/shaders/fs-shadowDynamicPointInstWithTextures.h" -#include "gfx/gl/shaders/fs-shadowDynamicPointStencil.h" -#include "gfx/gl/shaders/gs-commonShadowPoint.h" -#include "gfx/gl/shaders/gs-shadowDynamicPointInstWithTextures.h" -#include "gfx/gl/shaders/gs-shadowDynamicPointStencil.h" -#include "gfx/gl/shaders/vs-shadowDynamicPoint.h" -#include "gfx/gl/shaders/vs-shadowDynamicPointInst.h" -#include "gfx/gl/shaders/vs-shadowDynamicPointInstWithTextures.h" -#include "gfx/gl/shaders/vs-shadowDynamicPointStencil.h" -#include "gfx/gl/shaders/vs-shadowLandmass.h" #include "gfx/gl/shadowStenciller.h" #include "gfx/lightDirection.h" #include "gfx/renderable.h" #include "gl_traits.h" +#include "gldebug.h" #include "location.h" -#include "maths.h" #include "sceneProvider.h" #include "sceneShader.h" #include <gfx/camera.h> +#include <gfx/gl/shaders/commonShadowPoint-geom.h> +#include <gfx/gl/shaders/shadowDynamicPoint-vert.h> +#include <gfx/gl/shaders/shadowDynamicPointInst-vert.h> +#include <gfx/gl/shaders/shadowDynamicPointInstWithTextures-frag.h> +#include <gfx/gl/shaders/shadowDynamicPointInstWithTextures-geom.h> +#include <gfx/gl/shaders/shadowDynamicPointInstWithTextures-vert.h> +#include <gfx/gl/shaders/shadowDynamicPointStencil-frag.h> +#include <gfx/gl/shaders/shadowDynamicPointStencil-geom.h> +#include <gfx/gl/shaders/shadowDynamicPointStencil-vert.h> +#include <gfx/gl/shaders/shadowLandmass-vert.h> #include <glm/gtc/type_ptr.hpp> #include <glm/gtx/transform.hpp> #include <glm/matrix.hpp> -#include <vector> +#include <maths.h> ShadowMapper::ShadowMapper(const TextureAbsCoord & s) : - landmess {shadowLandmass_vs}, dynamicPointInst {shadowDynamicPointInst_vs}, - dynamicPointInstWithTextures {shadowDynamicPointInstWithTextures_vs, shadowDynamicPointInstWithTextures_gs, - shadowDynamicPointInstWithTextures_fs}, - size {s} + landmess {shadowLandmass_vert}, dynamicPointInst {shadowDynamicPointInst_vert}, + dynamicPointInstWithTextures {shadowDynamicPointInstWithTextures_vert, shadowDynamicPointInstWithTextures_geom, + shadowDynamicPointInstWithTextures_frag}, + size {s}, frustum {{}, {}, {}} { - glBindTexture(GL_TEXTURE_2D_ARRAY, depthMap); - glTexImage3D( - GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT, size.x, size.y, 4, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); - glTexParameter(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameter(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameter(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameter(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + glDebugScope _ {depthMap}; + depthMap.storage(1, GL_DEPTH_COMPONENT16, size || static_cast<GLsizei>(SHADOW_BANDS)); + depthMap.parameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST); + depthMap.parameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST); + depthMap.parameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + depthMap.parameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); static constexpr RGBA border {std::numeric_limits<RGBA::value_type>::infinity()}; - glTexParameter(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, border); + depthMap.parameter(GL_TEXTURE_BORDER_COLOR, border); - glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); - glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthMap, 0); - glDrawBuffer(GL_NONE); - glReadBuffer(GL_NONE); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - throw std::runtime_error("Framebuffer not complete!"); - } - glBindFramebuffer(GL_FRAMEBUFFER, 0); + depthMapFBO.texture(GL_DEPTH_ATTACHMENT, depthMap); + depthMapFBO.drawBuffers(GL_NONE); + depthMapFBO.assertComplete(); } -constexpr auto shadowBands - = []<GlobalDistance... ints>(const float scaleFactor, std::integer_sequence<GlobalDistance, ints...>) { - const auto base = 10'000'000 / pow(scaleFactor, sizeof...(ints) - 1); - return std::array {1, static_cast<GlobalDistance>((base * pow(scaleFactor, ints)))...}; +constexpr GlobalDistance SHADOW_NEAR = 1; +constexpr GlobalDistance SHADOW_FAR = 10'000'000; +constexpr auto SHADOW_BANDS_DISTS + = []<GlobalDistance... Ints>(const float scaleFactor, std::integer_sequence<GlobalDistance, Ints...>) { + const auto base = SHADOW_FAR / pow(scaleFactor, sizeof...(Ints) - 1); + return std::array {SHADOW_NEAR, static_cast<GlobalDistance>((base * pow(scaleFactor, Ints)))...}; }(4.6F, std::make_integer_sequence<GlobalDistance, ShadowMapper::SHADOW_BANDS>()); -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<std::array<RelativePosition3D, 4>> -ShadowMapper::getBandViewExtents(const Camera & camera, const glm::mat4 & lightViewDir) +size_t +ShadowMapper::getBandViewExtents( + BandViewExtents & bandViewExtents, const Camera & camera, const glm::mat4 & lightViewDir) { - std::vector<std::array<RelativePosition3D, 4>> 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(), Camera::upFromForward(dir.vector())); + const auto lightViewPoint = camera.getPosition(); + const auto bandViewExtentCount = getBandViewExtents(bandViewExtents, camera, lightViewDir); + const auto activeBandViewExtents = std::span(bandViewExtents).subspan(0, bandViewExtentCount); + + using ExtentsBoundingBox = AxisAlignedBoundingBox<RelativeDistance>; + 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<const glm::mat4> ShadowMapper::update(const SceneProvider & scene, const LightDirection & dir, const Camera & camera) const { + glDebugScope _ {depthMap}; glCullFace(GL_FRONT); glEnable(GL_DEPTH_TEST); @@ -97,42 +120,19 @@ ShadowMapper::update(const SceneProvider & scene, const LightDirection & dir, co glClear(GL_DEPTH_BUFFER_BIT); glViewport(0, 0, size.x, size.y); - const auto lightViewDir = glm::lookAt({}, dir.vector(), up); const auto lightViewPoint = camera.getPosition(); - const auto bandViewExtents = getBandViewExtents(camera, lightViewDir); - Definitions out; - Sizes sizes; - using ExtentsBoundingBox = AxisAlignedBoundingBox<RelativeDistance>; - std::ranges::transform(bandViewExtents | std::views::pairwise, std::back_inserter(out), - [&lightViewDir, &sizes](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; - }); for (const auto p : std::initializer_list<const ShadowProgram *> { &landmess, &dynamicPoint, &dynamicPointInst, &dynamicPointInstWithTextures, &stencilShadowProgram}) { - p->setView(out, sizes, lightViewPoint); - } - ExtentsBoundingBox extents {lightViewPoint, lightViewPoint}; - for (const auto & point : bandViewExtents.back()) { - extents += point; + p->setView(definitions, sizes, lightViewPoint); } - const auto lightProjection - = glm::ortho(extents.min.x, extents.max.x, extents.min.y, extents.max.y, -extents.max.z, -extents.min.z); - Frustum frustum {lightViewPoint, lightViewDir, lightProjection}; scene.shadows(*this, frustum); glCullFace(GL_BACK); - return out; + return definitions; } -ShadowMapper::ShadowProgram::ShadowProgram(const Shader & vs) : Program {vs, commonShadowPoint_gs} { } +ShadowMapper::ShadowProgram::ShadowProgram(const Shader & vs) : Program {vs, commonShadowPoint_geom} { } ShadowMapper::ShadowProgram::ShadowProgram(const Shader & vs, const Shader & gs, const Shader & fs) : Program {vs, gs, fs} @@ -158,7 +158,7 @@ ShadowMapper::ShadowProgram::use() const glUseProgram(*this); } -ShadowMapper::DynamicPoint::DynamicPoint() : ShadowProgram {shadowDynamicPoint_vs} { } +ShadowMapper::DynamicPoint::DynamicPoint() : ShadowProgram {shadowDynamicPoint_vert} { } void ShadowMapper::DynamicPoint::use(const Location & location) const @@ -175,7 +175,7 @@ ShadowMapper::DynamicPoint::setModel(const Location & location) const } ShadowMapper::StencilShadowProgram::StencilShadowProgram() : - ShadowProgram {shadowDynamicPointStencil_vs, shadowDynamicPointStencil_gs, shadowDynamicPointStencil_fs} + ShadowProgram {shadowDynamicPointStencil_vert, shadowDynamicPointStencil_geom, shadowDynamicPointStencil_frag} { } |
