summaryrefslogtreecommitdiff
path: root/gfx/gl/shadowMapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/gl/shadowMapper.cpp')
-rw-r--r--gfx/gl/shadowMapper.cpp156
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}
{
}