summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2024-01-30 22:48:33 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2024-01-30 22:48:33 +0000
commit3c239338f5d1e97e3c0ddd05976e14b20758e07d (patch)
tree7eb3c254b681d2cafbc9ce8f13b285a9313474c4
parent3D relative scaling in asset factory (diff)
parentAdjust light view projection matrix upfront (diff)
downloadilt-3c239338f5d1e97e3c0ddd05976e14b20758e07d.tar.bz2
ilt-3c239338f5d1e97e3c0ddd05976e14b20758e07d.tar.xz
ilt-3c239338f5d1e97e3c0ddd05976e14b20758e07d.zip
Merge branch 'geo-shadows'
-rw-r--r--gfx/gl/sceneRenderer.cpp23
-rw-r--r--gfx/gl/sceneRenderer.h7
-rw-r--r--gfx/gl/shaders/commonShadowPoint.glsl5
-rw-r--r--gfx/gl/shaders/commonShadowPoint.gs22
-rw-r--r--gfx/gl/shaders/directionalLight.fs10
-rw-r--r--gfx/gl/shaders/shadowDynamicPoint.vs1
-rw-r--r--gfx/gl/shaders/shadowDynamicPointInst.vs1
-rw-r--r--gfx/gl/shaders/shadowFixedPoint.vs1
-rw-r--r--gfx/gl/shadowMapper.cpp126
-rw-r--r--gfx/gl/shadowMapper.h27
10 files changed, 89 insertions, 134 deletions
diff --git a/gfx/gl/sceneRenderer.cpp b/gfx/gl/sceneRenderer.cpp
index 4c96902..517d51e 100644
--- a/gfx/gl/sceneRenderer.cpp
+++ b/gfx/gl/sceneRenderer.cpp
@@ -81,7 +81,7 @@ SceneRenderer::render(const SceneProvider & scene) const
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, gNormal);
glActiveTexture(GL_TEXTURE2);
- glBindTexture(GL_TEXTURE_2D, shadowMapper);
+ glBindTexture(GL_TEXTURE_2D_ARRAY, shadowMapper);
scene.environment(shader, *this);
glDisable(GL_DEPTH_TEST);
scene.lights(shader);
@@ -116,7 +116,7 @@ SceneRenderer::setDirectionalLight(const RGB & colour, const Direction3D & direc
glBindFramebuffer(GL_FRAMEBUFFER, gBufferIll);
glViewport(0, 0, size.x, size.y);
dirLight.use();
- dirLight.setDirectionalLight(colour, direction, camera.getPosition(), lvp.projections, lvp.regions, lvp.maps);
+ dirLight.setDirectionalLight(colour, direction, camera.getPosition(), lvp);
renderQuad();
}
}
@@ -133,21 +133,24 @@ SceneRenderer::DirectionalLightProgram::DirectionalLightProgram() :
Program {lighting_vs, directionalLight_fs}, directionLoc {*this, "lightDirection"},
colourLoc {*this, "lightColour"}, lightPointLoc {*this, "lightPoint"},
lightViewProjectionLoc {*this, "lightViewProjection"},
- lightViewProjectionCountLoc {*this, "lightViewProjectionCount"},
- lightViewShadowMapRegionLoc {*this, "shadowMapRegion"}
+ lightViewProjectionCountLoc {*this, "lightViewProjectionCount"}
{
}
+const auto toTextureSpaceMat = glm::translate(glm::identity<glm::mat4>(), glm::vec3 {0.5F})
+ * glm::scale(glm::identity<glm::mat4>(), glm::vec3 {0.5F});
+
void
-SceneRenderer::DirectionalLightProgram::setDirectionalLight(const RGB & c, const Direction3D & d,
- const GlobalPosition3D & p, const std::span<const glm::mat4x4> lvp,
- const std::span<const TextureRelRegion> shadowMapRegions, std::size_t maps) const
+SceneRenderer::DirectionalLightProgram::setDirectionalLight(
+ const RGB & c, const Direction3D & d, const GlobalPosition3D & p, const std::span<const glm::mat4x4> lvp) const
{
+ const auto toTextureSpace = [](const glm::mat4 & m) {
+ return toTextureSpaceMat * m;
+ };
glUniform(colourLoc, c);
const auto nd = glm::normalize(d);
glUniform(directionLoc, nd);
glUniform(lightPointLoc, p);
- glUniform(lightViewProjectionCountLoc, static_cast<GLuint>(maps));
- glUniform(lightViewProjectionLoc, lvp);
- glUniform(lightViewShadowMapRegionLoc, shadowMapRegions);
+ glUniform(lightViewProjectionCountLoc, static_cast<GLuint>(lvp.size()));
+ glUniform(lightViewProjectionLoc, std::span<const glm::mat4> {lvp * toTextureSpace});
}
diff --git a/gfx/gl/sceneRenderer.h b/gfx/gl/sceneRenderer.h
index 797ecf1..021936f 100644
--- a/gfx/gl/sceneRenderer.h
+++ b/gfx/gl/sceneRenderer.h
@@ -6,7 +6,6 @@
#include "sceneProvider.h"
#include "sceneShader.h"
#include "shadowMapper.h"
-#include <functional>
#include <glm/fwd.hpp>
class SceneRenderer {
@@ -39,12 +38,12 @@ protected:
DirectionalLightProgram();
using Program::use;
- void setDirectionalLight(const RGB &, const Direction3D &, const GlobalPosition3D &,
- const std::span<const glm::mat4x4>, const std::span<const TextureRelRegion>, std::size_t maps) const;
+ void setDirectionalLight(
+ const RGB &, const Direction3D &, const GlobalPosition3D &, const std::span<const glm::mat4x4>) const;
private:
RequiredUniformLocation directionLoc, colourLoc, lightPointLoc, lightViewProjectionLoc,
- lightViewProjectionCountLoc, lightViewShadowMapRegionLoc;
+ lightViewProjectionCountLoc;
};
DeferredLightProgram lighting;
diff --git a/gfx/gl/shaders/commonShadowPoint.glsl b/gfx/gl/shaders/commonShadowPoint.glsl
index 47722d6..ba4611a 100644
--- a/gfx/gl/shaders/commonShadowPoint.glsl
+++ b/gfx/gl/shaders/commonShadowPoint.glsl
@@ -1,7 +1,8 @@
+out vec4 vworldPos;
+
void
main()
{
vec3 worldPos = model * position;
- gl_Position = viewProjection * vec4(worldPos - viewPoint + modelPos, 1);
- gl_Position.z = max(gl_Position.z, -1);
+ vworldPos = vec4(worldPos - viewPoint + modelPos, 1);
}
diff --git a/gfx/gl/shaders/commonShadowPoint.gs b/gfx/gl/shaders/commonShadowPoint.gs
new file mode 100644
index 0000000..b008f29
--- /dev/null
+++ b/gfx/gl/shaders/commonShadowPoint.gs
@@ -0,0 +1,22 @@
+#version 330 core
+#extension GL_ARB_viewport_array : enable
+
+uniform mat4 viewProjection[4];
+uniform int viewProjections;
+in vec4 vworldPos[];
+layout(triangles) in;
+layout(triangle_strip, max_vertices = 12) out;
+
+void
+main()
+{
+ for (int vp = 0; vp < viewProjections; ++vp) {
+ for (int v = 0; v < vworldPos.length(); ++v) {
+ gl_Position = viewProjection[vp] * vworldPos[v];
+ gl_Position.z = max(gl_Position.z, -1);
+ gl_Layer = vp;
+ EmitVertex();
+ }
+ EndPrimitive();
+ }
+}
diff --git a/gfx/gl/shaders/directionalLight.fs b/gfx/gl/shaders/directionalLight.fs
index f36d83f..24457b8 100644
--- a/gfx/gl/shaders/directionalLight.fs
+++ b/gfx/gl/shaders/directionalLight.fs
@@ -9,16 +9,15 @@ in vec2 TexCoords;
layout(binding = 0) uniform isampler2D gPosition;
layout(binding = 1) uniform sampler2D gNormal;
-layout(binding = 2) uniform sampler2D shadowMap;
+layout(binding = 2) uniform sampler2DArray shadowMap;
uniform vec3 lightDirection;
uniform vec3 lightColour;
uniform ivec3 lightPoint;
uniform mat4 lightViewProjection[MAX_MAPS];
-uniform vec4 shadowMapRegion[MAX_MAPS];
uniform uint lightViewProjectionCount;
-const vec3 e1 = vec3(-1, -1, -1), e2 = vec3(1, 1, 1);
+const vec3 e1 = vec3(0, 0, 0), e2 = vec3(1, 1, 1);
float
insideShadowCube(vec3 v)
@@ -34,9 +33,8 @@ isShaded(vec4 Position)
const vec3 PositionInLightSpace = (lightViewProjection[m] * Position).xyz;
const float inside = insideShadowCube(PositionInLightSpace);
if (inside > 0) {
- const float lightSpaceDepth
- = texture(shadowMap, PositionInLightSpace.xy * shadowMapRegion[m].xy + shadowMapRegion[m].zw).r;
- return step(lightSpaceDepth, PositionInLightSpace.z * .5 + .5);
+ const float lightSpaceDepth = texture(shadowMap, vec3(PositionInLightSpace.xy, m)).r;
+ return step(lightSpaceDepth, PositionInLightSpace.z);
}
}
return 0;
diff --git a/gfx/gl/shaders/shadowDynamicPoint.vs b/gfx/gl/shaders/shadowDynamicPoint.vs
index bf0f0a1..7335b9a 100644
--- a/gfx/gl/shaders/shadowDynamicPoint.vs
+++ b/gfx/gl/shaders/shadowDynamicPoint.vs
@@ -2,7 +2,6 @@
include(`meshIn.glsl')
-uniform mat4 viewProjection;
uniform ivec3 viewPoint;
uniform mat3 model;
uniform ivec3 modelPos;
diff --git a/gfx/gl/shaders/shadowDynamicPointInst.vs b/gfx/gl/shaders/shadowDynamicPointInst.vs
index b0b80da..d0eb649 100644
--- a/gfx/gl/shaders/shadowDynamicPointInst.vs
+++ b/gfx/gl/shaders/shadowDynamicPointInst.vs
@@ -2,7 +2,6 @@
include(`meshIn.glsl')
-uniform mat4 viewProjection;
uniform ivec3 viewPoint;
layout(location = 5) in mat3 model;
layout(location = 8) in ivec3 modelPos;
diff --git a/gfx/gl/shaders/shadowFixedPoint.vs b/gfx/gl/shaders/shadowFixedPoint.vs
index 307aac2..1376388 100644
--- a/gfx/gl/shaders/shadowFixedPoint.vs
+++ b/gfx/gl/shaders/shadowFixedPoint.vs
@@ -2,7 +2,6 @@
include(`meshIn.glsl')
-uniform mat4 viewProjection;
uniform ivec3 viewPoint;
const mat3 model = mat3(1);
const ivec3 modelPos = ivec3(0);
diff --git a/gfx/gl/shadowMapper.cpp b/gfx/gl/shadowMapper.cpp
index ab4ac50..4dbee8d 100644
--- a/gfx/gl/shadowMapper.cpp
+++ b/gfx/gl/shadowMapper.cpp
@@ -1,6 +1,7 @@
#include "shadowMapper.h"
#include "camera.h"
#include "collections.h"
+#include "gfx/gl/shaders/gs-commonShadowPoint.h"
#include "gfx/gl/shaders/vs-shadowDynamicPoint.h"
#include "gfx/gl/shaders/vs-shadowDynamicPointInst.h"
#include "gfx/gl/shaders/vs-shadowFixedPoint.h"
@@ -19,17 +20,18 @@
ShadowMapper::ShadowMapper(const TextureAbsCoord & s) :
fixedPoint {shadowFixedPoint_vs}, dynamicPointInst {shadowDynamicPointInst_vs}, size {s}
{
- glBindTexture(GL_TEXTURE_2D, depthMap);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size.x, size.y, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
- glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+ 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);
static constexpr RGBA border {std::numeric_limits<RGBA::value_type>::infinity()};
- glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border);
+ glTexParameter(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BORDER_COLOR, border);
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0);
+ glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthMap, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
@@ -38,48 +40,6 @@ ShadowMapper::ShadowMapper(const TextureAbsCoord & s) :
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
-constexpr std::array<std::array<TextureAbsRegion, ShadowMapper::SHADOW_BANDS>, ShadowMapper::SHADOW_BANDS> viewports {{
- {{
- {31, 31, 0, 0}, // full
- }},
- {{
- {31, 31, 0, 1}, // lower half
- {31, 1, 0, 1}, // upper half
- }},
- {{
- {31, 31, 0, 1}, // lower half
- {31, 1, 1, 1}, // upper left
- {1, 1, 1, 1}, // upper right
- }},
- {{
- {31, 31, 1, 1}, // lower left
- {1, 31, 1, 1}, // lower right
- {31, 1, 1, 1}, // upper left
- {1, 1, 1, 1}, // upper right
- }},
-}};
-constexpr std::array<std::array<TextureRelRegion, ShadowMapper::SHADOW_BANDS>, ShadowMapper::SHADOW_BANDS>
- shadowMapRegions {{
- {{
- {0.5F, 0.5F, 0.5F, 0.5F}, // full
- }},
- {{
- {0.5F, 0.25F, 0.5F, 0.25F}, // lower half
- {0.5F, 0.25F, 0.5F, 0.75F}, // upper half
- }},
- {{
- {0.5F, 0.25F, 0.5F, 0.25F}, // lower half
- {0.25F, 0.25F, 0.25F, 0.75F}, // upper left
- {0.25F, 0.25F, 0.75F, 0.75F}, // upper right
- }},
-
- {{
- {0.25F, 0.25F, 0.25F, 0.25F}, // lower left
- {0.25F, 0.25F, 0.75F, 0.25F}, // lower right
- {0.25F, 0.25F, 0.25F, 0.75F}, // upper left
- {0.25F, 0.25F, 0.75F, 0.75F}, // upper right
- }},
- }};
constexpr std::array<GlobalDistance, ShadowMapper::SHADOW_BANDS + 1> shadowBands {
1000,
250000,
@@ -87,24 +47,6 @@ constexpr std::array<GlobalDistance, ShadowMapper::SHADOW_BANDS + 1> shadowBands
2500000,
10000000,
};
-static_assert(viewports.size() == shadowMapRegions.size());
-static_assert(shadowBands.size() == shadowMapRegions.size() + 1);
-
-struct DefinitionsInserter {
- auto
- operator++()
- {
- return out.maps++;
- };
-
- auto
- operator*()
- {
- return std::tie(out.projections[out.maps], out.regions[out.maps]);
- }
-
- ShadowMapper::Definitions & out;
-};
std::vector<std::array<RelativePosition3D, 4>>
ShadowMapper::getBandViewExtents(const Camera & camera, const glm::mat4 & lightViewDir)
@@ -130,16 +72,15 @@ ShadowMapper::update(const SceneProvider & scene, const Direction3D & dir, const
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glClear(GL_DEPTH_BUFFER_BIT);
glCullFace(GL_FRONT);
+ glViewport(0, 0, size.x, size.y);
const auto lightViewDir = glm::lookAt({}, dir, up);
const auto lightViewPoint = camera.getPosition();
const auto bandViewExtents = getBandViewExtents(camera, lightViewDir);
-
Definitions out;
std::transform(bandViewExtents.begin(), std::prev(bandViewExtents.end()), std::next(bandViewExtents.begin()),
- DefinitionsInserter {out},
- [&scene, this, bands = bandViewExtents.size() - 2, &out, &lightViewPoint, &lightViewDir](
- const auto & near, const auto & far) {
+ std::back_inserter(out),
+ [bands = bandViewExtents.size() - 2, &lightViewDir](const auto & near, const auto & far) mutable {
const auto extents_minmax = [extents = std::span {near.begin(), far.end()}](auto && comp) {
const auto mm = std::minmax_element(extents.begin(), extents.end(), comp);
return std::make_pair(comp.get(*mm.first), comp.get(*mm.second));
@@ -149,54 +90,45 @@ ShadowMapper::update(const SceneProvider & scene, const Direction3D & dir, const
return glm::ortho(x.first, x.second, y.first, y.second, -z.second, -z.first);
}(extents_minmax(CompareBy {0}), extents_minmax(CompareBy {1}), extents_minmax(CompareBy {2}));
- const auto lightViewDirProjection = lightProjection * lightViewDir;
- fixedPoint.setViewProjection(lightViewPoint, lightViewDirProjection);
- dynamicPoint.setViewProjection(lightViewPoint, lightViewDirProjection);
- dynamicPointInst.setViewProjection(lightViewPoint, lightViewDirProjection);
-
- const auto & viewport = viewports[bands][out.maps];
- glViewport(size.x >> viewport.x, size.y >> viewport.y, size.x >> viewport.z, size.y >> viewport.w);
- scene.shadows(*this);
-
- return std::make_pair(lightViewDirProjection, shadowMapRegions[bands][out.maps]);
+ return lightProjection * lightViewDir;
});
+ for (const auto p : std::initializer_list<const ShadowProgram *> {&fixedPoint, &dynamicPoint, &dynamicPointInst}) {
+ p->setView(out, lightViewPoint);
+ }
+ scene.shadows(*this);
glCullFace(GL_BACK);
return out;
}
-ShadowMapper::FixedPoint::FixedPoint(const Shader & vs) :
- Program {vs}, viewProjectionLoc {*this, "viewProjection"}, viewPointLoc {*this, "viewPoint"}
+ShadowMapper::ShadowProgram::ShadowProgram(const Shader & vs) :
+ Program {vs, commonShadowPoint_gs}, viewProjectionLoc {*this, "viewProjection"},
+ viewProjectionsLoc {*this, "viewProjections"}, viewPointLoc {*this, "viewPoint"}
{
}
void
-ShadowMapper::FixedPoint::setViewProjection(const GlobalPosition3D viewPoint, const glm::mat4 & viewProjection) const
+ShadowMapper::ShadowProgram::setView(
+ const std::span<const glm::mat4> viewProjection, const GlobalPosition3D viewPoint) const
{
use();
- glUniform(viewProjectionLoc, viewProjection);
glUniform(viewPointLoc, viewPoint);
+ glUniform(viewProjectionLoc, viewProjection);
+ glUniform(viewProjectionsLoc, static_cast<GLint>(viewProjection.size()));
}
void
-ShadowMapper::FixedPoint::use() const
+ShadowMapper::ShadowProgram::use() const
{
glUseProgram(*this);
}
-ShadowMapper::DynamicPoint::DynamicPoint() :
- Program {shadowDynamicPoint_vs}, viewProjectionLoc {*this, "viewProjection"}, viewPointLoc {*this, "viewPoint"},
- modelLoc {*this, "model"}, modelPosLoc {*this, "modelPos"}
-{
-}
+ShadowMapper::FixedPoint::FixedPoint(const Shader & vs) : ShadowProgram {vs} { }
-void
-ShadowMapper::DynamicPoint::setViewProjection(const GlobalPosition3D viewPoint, const glm::mat4 & viewProjection) const
+ShadowMapper::DynamicPoint::DynamicPoint() :
+ ShadowProgram {shadowDynamicPoint_vs}, modelLoc {*this, "model"}, modelPosLoc {*this, "modelPos"}
{
- glUseProgram(*this);
- glUniform(viewProjectionLoc, viewProjection);
- glUniform(viewPointLoc, viewPoint);
}
void
diff --git a/gfx/gl/shadowMapper.h b/gfx/gl/shadowMapper.h
index d1e4e10..a95d4c1 100644
--- a/gfx/gl/shadowMapper.h
+++ b/gfx/gl/shadowMapper.h
@@ -5,6 +5,7 @@
#include "program.h"
#include <gfx/models/texture.h>
#include <glm/vec2.hpp>
+#include <span>
#include <vector>
class SceneProvider;
@@ -16,33 +17,35 @@ public:
static constexpr std::size_t SHADOW_BANDS {4};
- struct Definitions {
- std::array<glm::mat4x4, SHADOW_BANDS> projections {};
- std::array<TextureRelRegion, SHADOW_BANDS> regions {};
- size_t maps {};
- };
+ using Definitions = std::vector<glm::mat4x4>;
[[nodiscard]] Definitions update(const SceneProvider &, const Direction3D & direction, const Camera &) const;
- class FixedPoint : public Program {
+ class ShadowProgram : public Program {
public:
- FixedPoint(const Shader & vs);
- void setViewProjection(const GlobalPosition3D, const glm::mat4 &) const;
+ explicit ShadowProgram(const Shader & vs);
+
+ void setView(const std::span<const glm::mat4>, const GlobalPosition3D) const;
void use() const;
private:
- RequiredUniformLocation viewProjectionLoc, viewPointLoc;
+ RequiredUniformLocation viewProjectionLoc;
+ RequiredUniformLocation viewProjectionsLoc;
+ RequiredUniformLocation viewPointLoc;
+ };
+
+ class FixedPoint : public ShadowProgram {
+ public:
+ explicit FixedPoint(const Shader & vs);
};
- class DynamicPoint : public Program {
+ class DynamicPoint : public ShadowProgram {
public:
DynamicPoint();
- void setViewProjection(const GlobalPosition3D, const glm::mat4 &) const;
void use(const Location &) const;
void setModel(const Location &) const;
private:
- RequiredUniformLocation viewProjectionLoc, viewPointLoc;
RequiredUniformLocation modelLoc;
RequiredUniformLocation modelPosLoc;
};