From 900d19a41bc1886e7a809d99d6119b12235a4f0a Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 20 Jul 2024 10:57:17 +0100 Subject: Initial commit of basic shadow depth map creation --- gfx/gl/shaders/shadowStencil.fs | 0 gfx/gl/shaders/shadowStencil.vs | 11 +++++++++ gfx/gl/shadowStenciller.cpp | 51 +++++++++++++++++++++++++++++++++++++++++ gfx/gl/shadowStenciller.h | 21 +++++++++++++++++ 4 files changed, 83 insertions(+) create mode 100644 gfx/gl/shaders/shadowStencil.fs create mode 100644 gfx/gl/shaders/shadowStencil.vs create mode 100644 gfx/gl/shadowStenciller.cpp create mode 100644 gfx/gl/shadowStenciller.h (limited to 'gfx/gl') diff --git a/gfx/gl/shaders/shadowStencil.fs b/gfx/gl/shaders/shadowStencil.fs new file mode 100644 index 0000000..e69de29 diff --git a/gfx/gl/shaders/shadowStencil.vs b/gfx/gl/shaders/shadowStencil.vs new file mode 100644 index 0000000..4f4c250 --- /dev/null +++ b/gfx/gl/shaders/shadowStencil.vs @@ -0,0 +1,11 @@ +#version 330 core +#extension GL_ARB_shading_language_420pack : enable + +include(`meshIn.glsl') +uniform mat4 viewProjection; + +void +main() +{ + gl_Position = viewProjection * vec4(position, 1); +} diff --git a/gfx/gl/shadowStenciller.cpp b/gfx/gl/shadowStenciller.cpp new file mode 100644 index 0000000..6d5fa40 --- /dev/null +++ b/gfx/gl/shadowStenciller.cpp @@ -0,0 +1,51 @@ +#include "shadowStenciller.h" +#include "config/types.h" +#include "gfx/gl/program.h" +#include "gfx/gl/shaders/vs-shadowStencil.h" +#include "gfx/models/mesh.h" +#include "glArrays.h" +#include "gl_traits.h" +#include "maths.h" +#include + +ShadowStenciller::ShadowStenciller() : shadowCaster {shadowStencil_vs} +{ + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +glTexture +ShadowStenciller::createStencilTexture(GLsizei width, GLsizei height) +{ + glTexture stencil; + glBindTexture(GL_TEXTURE_2D, stencil); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, nullptr); + + return stencil; +} + +void +ShadowStenciller::renderStencil(const glTexture & stencil, const MeshBase & mesh, const RelativePosition3D & mins, + const RelativePosition3D & maxs) const +{ + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, stencil, 0); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + throw std::runtime_error("Stencil framebuffer not complete!"); + } + glUseProgram(shadowCaster); + glClear(GL_DEPTH_BUFFER_BIT); + glViewport(0, 0, 256, 256); + glEnable(GL_DEPTH_TEST); + const auto extents = glm::ortho(mins.x, maxs.x, mins.z, maxs.z, mins.y, maxs.y); + const auto lightDir = glm::lookAt({}, north, up); + glUniform(viewProjectionLoc, extents * lightDir); + mesh.Draw(); +} diff --git a/gfx/gl/shadowStenciller.h b/gfx/gl/shadowStenciller.h new file mode 100644 index 0000000..460fa68 --- /dev/null +++ b/gfx/gl/shadowStenciller.h @@ -0,0 +1,21 @@ +#pragma once + +#include "config/types.h" +#include "gfx/gl/program.h" +#include "gfx/models/mesh.h" +#include "glArrays.h" + +class ShadowStenciller { +public: + ShadowStenciller(); + + [[nodiscard]] + static glTexture createStencilTexture(GLsizei width, GLsizei height); + void renderStencil(const glTexture &, const MeshBase &, const RelativePosition3D & mins, + const RelativePosition3D & maxs) const; + +private: + glFrameBuffer fbo; + Program shadowCaster; + Program::UniformLocation viewProjectionLoc {shadowCaster, "viewProjection"}; +}; -- cgit v1.2.3 From 4ba67f34eac848e43bad2ccc4b5c09ac65dd7952 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 20 Jul 2024 12:55:15 +0100 Subject: Use mesh extents for shadow stencil extents --- gfx/gl/shadowStenciller.cpp | 5 +++-- gfx/gl/shadowStenciller.h | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'gfx/gl') diff --git a/gfx/gl/shadowStenciller.cpp b/gfx/gl/shadowStenciller.cpp index 6d5fa40..e20eda1 100644 --- a/gfx/gl/shadowStenciller.cpp +++ b/gfx/gl/shadowStenciller.cpp @@ -32,8 +32,7 @@ ShadowStenciller::createStencilTexture(GLsizei width, GLsizei height) } void -ShadowStenciller::renderStencil(const glTexture & stencil, const MeshBase & mesh, const RelativePosition3D & mins, - const RelativePosition3D & maxs) const +ShadowStenciller::renderStencil(const glTexture & stencil, const MeshBase & mesh) const { glBindFramebuffer(GL_FRAMEBUFFER, fbo); glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, stencil, 0); @@ -44,6 +43,8 @@ ShadowStenciller::renderStencil(const glTexture & stencil, const MeshBase & mesh glClear(GL_DEPTH_BUFFER_BIT); glViewport(0, 0, 256, 256); glEnable(GL_DEPTH_TEST); + const auto & mins = mesh.minExtent(); + const auto & maxs = mesh.maxExtent(); const auto extents = glm::ortho(mins.x, maxs.x, mins.z, maxs.z, mins.y, maxs.y); const auto lightDir = glm::lookAt({}, north, up); glUniform(viewProjectionLoc, extents * lightDir); diff --git a/gfx/gl/shadowStenciller.h b/gfx/gl/shadowStenciller.h index 460fa68..5a22a7e 100644 --- a/gfx/gl/shadowStenciller.h +++ b/gfx/gl/shadowStenciller.h @@ -11,8 +11,7 @@ public: [[nodiscard]] static glTexture createStencilTexture(GLsizei width, GLsizei height); - void renderStencil(const glTexture &, const MeshBase &, const RelativePosition3D & mins, - const RelativePosition3D & maxs) const; + void renderStencil(const glTexture &, const MeshBase &) const; private: glFrameBuffer fbo; -- cgit v1.2.3 From f737aada2b7164683303beb3bb490c30a4949fb0 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 21 Jul 2024 02:33:24 +0100 Subject: Use texture alpha in shadow stencil --- gfx/gl/shaders/shadowStencil.fs | 16 ++++++++++++++++ gfx/gl/shaders/shadowStencil.vs | 7 +++++++ gfx/gl/shadowStenciller.cpp | 8 ++++++-- gfx/gl/shadowStenciller.h | 4 ++-- 4 files changed, 31 insertions(+), 4 deletions(-) (limited to 'gfx/gl') diff --git a/gfx/gl/shaders/shadowStencil.fs b/gfx/gl/shaders/shadowStencil.fs index e69de29..f149c23 100644 --- a/gfx/gl/shaders/shadowStencil.fs +++ b/gfx/gl/shaders/shadowStencil.fs @@ -0,0 +1,16 @@ +#version 330 core +#extension GL_ARB_shading_language_420pack : enable + +layout(binding = 0) uniform sampler2D textureAlbedo; + +include(`materialInterface.glsl') +include(`materialCommon.glsl') + +void +main() +{ + if (getTextureColour(Material, TexCoords).a < 0.5) { + discard; + } + gl_FragDepth = gl_FragCoord.z; +} diff --git a/gfx/gl/shaders/shadowStencil.vs b/gfx/gl/shaders/shadowStencil.vs index 4f4c250..45a0867 100644 --- a/gfx/gl/shaders/shadowStencil.vs +++ b/gfx/gl/shaders/shadowStencil.vs @@ -1,11 +1,18 @@ #version 330 core #extension GL_ARB_shading_language_420pack : enable +layout(binding = 1) uniform usampler2DRect materialData; + include(`meshIn.glsl') +include(`materialInterface.glsl') +include(`getMaterialDetail.glsl') uniform mat4 viewProjection; void main() { + TexCoords = texCoord; + Material = getMaterialDetail(material); + gl_Position = viewProjection * vec4(position, 1); } diff --git a/gfx/gl/shadowStenciller.cpp b/gfx/gl/shadowStenciller.cpp index e20eda1..2ba519f 100644 --- a/gfx/gl/shadowStenciller.cpp +++ b/gfx/gl/shadowStenciller.cpp @@ -1,6 +1,7 @@ #include "shadowStenciller.h" #include "config/types.h" #include "gfx/gl/program.h" +#include "gfx/gl/shaders/fs-shadowStencil.h" #include "gfx/gl/shaders/vs-shadowStencil.h" #include "gfx/models/mesh.h" #include "glArrays.h" @@ -8,7 +9,7 @@ #include "maths.h" #include -ShadowStenciller::ShadowStenciller() : shadowCaster {shadowStencil_vs} +ShadowStenciller::ShadowStenciller() : shadowCaster {shadowStencil_vs, shadowStencil_fs} { glBindFramebuffer(GL_FRAMEBUFFER, fbo); glDrawBuffer(GL_NONE); @@ -32,13 +33,16 @@ ShadowStenciller::createStencilTexture(GLsizei width, GLsizei height) } void -ShadowStenciller::renderStencil(const glTexture & stencil, const MeshBase & mesh) const +ShadowStenciller::renderStencil(const glTexture & stencil, const MeshBase & mesh, const Texture::AnyPtr texture) const { glBindFramebuffer(GL_FRAMEBUFFER, fbo); glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, stencil, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { throw std::runtime_error("Stencil framebuffer not complete!"); } + if (texture) { + texture->bind(); + } glUseProgram(shadowCaster); glClear(GL_DEPTH_BUFFER_BIT); glViewport(0, 0, 256, 256); diff --git a/gfx/gl/shadowStenciller.h b/gfx/gl/shadowStenciller.h index 5a22a7e..bf6d204 100644 --- a/gfx/gl/shadowStenciller.h +++ b/gfx/gl/shadowStenciller.h @@ -1,8 +1,8 @@ #pragma once -#include "config/types.h" #include "gfx/gl/program.h" #include "gfx/models/mesh.h" +#include "gfx/models/texture.h" #include "glArrays.h" class ShadowStenciller { @@ -11,7 +11,7 @@ public: [[nodiscard]] static glTexture createStencilTexture(GLsizei width, GLsizei height); - void renderStencil(const glTexture &, const MeshBase &) const; + void renderStencil(const glTexture &, const MeshBase &, const Texture::AnyPtr texture) const; private: glFrameBuffer fbo; -- cgit v1.2.3 From 064864eac61e936af909470fcccc5c67ef6d3169 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 11 Aug 2024 19:32:23 +0100 Subject: Calculate centre and size of mesh, wrap it all in a Dimensions object --- gfx/gl/shadowStenciller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gfx/gl') diff --git a/gfx/gl/shadowStenciller.cpp b/gfx/gl/shadowStenciller.cpp index 2ba519f..dc87d76 100644 --- a/gfx/gl/shadowStenciller.cpp +++ b/gfx/gl/shadowStenciller.cpp @@ -47,8 +47,8 @@ ShadowStenciller::renderStencil(const glTexture & stencil, const MeshBase & mesh glClear(GL_DEPTH_BUFFER_BIT); glViewport(0, 0, 256, 256); glEnable(GL_DEPTH_TEST); - const auto & mins = mesh.minExtent(); - const auto & maxs = mesh.maxExtent(); + const auto & mins = mesh.getDimensions().minExtent; + const auto & maxs = mesh.getDimensions().maxExtent; const auto extents = glm::ortho(mins.x, maxs.x, mins.z, maxs.z, mins.y, maxs.y); const auto lightDir = glm::lookAt({}, north, up); glUniform(viewProjectionLoc, extents * lightDir); -- cgit v1.2.3 From 87ebf7a7587e832d922635021a32c887823d92c7 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 18 Aug 2024 13:11:46 +0100 Subject: Offset shaded position to reduce chance of self-shadowing --- gfx/gl/shaders/directionalLight.fs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'gfx/gl') diff --git a/gfx/gl/shaders/directionalLight.fs b/gfx/gl/shaders/directionalLight.fs index 24457b8..86447ec 100644 --- a/gfx/gl/shaders/directionalLight.fs +++ b/gfx/gl/shaders/directionalLight.fs @@ -34,10 +34,10 @@ isShaded(vec4 Position) const float inside = insideShadowCube(PositionInLightSpace); if (inside > 0) { const float lightSpaceDepth = texture(shadowMap, vec3(PositionInLightSpace.xy, m)).r; - return step(lightSpaceDepth, PositionInLightSpace.z); + return step(PositionInLightSpace.z, lightSpaceDepth + 0.001); } } - return 0; + return 1; } void @@ -46,5 +46,5 @@ main() const vec4 Position = vec4(texture(gPosition, TexCoords).xyz - lightPoint, 1); const vec3 Normal = texture(gNormal, TexCoords).rgb; const float shaded = isShaded(Position); - FragColor = (1 - shaded) * max(dot(-lightDirection, Normal) * lightColour, 0); + FragColor = shaded * max(dot(-lightDirection, Normal) * lightColour, 0); } -- cgit v1.2.3 From 172beac34e82c86f8c16b8a1be5fca9d7ccfc0d1 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 18 Aug 2024 16:14:29 +0100 Subject: Update asset stencils from shadow mapper --- gfx/gl/shadowMapper.cpp | 9 +++++++++ gfx/gl/shadowStenciller.cpp | 15 +++++++-------- gfx/gl/shadowStenciller.h | 3 ++- 3 files changed, 18 insertions(+), 9 deletions(-) (limited to 'gfx/gl') diff --git a/gfx/gl/shadowMapper.cpp b/gfx/gl/shadowMapper.cpp index a846a3d..9b9e404 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 "game/gamestate.h" #include "gfx/gl/shaders/fs-shadowDynamicPointInstWithTextures.h" #include "gfx/gl/shaders/gs-commonShadowPoint.h" #include "gfx/gl/shaders/gs-shadowDynamicPointInstWithTextures.h" @@ -8,6 +9,8 @@ #include "gfx/gl/shaders/vs-shadowDynamicPointInst.h" #include "gfx/gl/shaders/vs-shadowDynamicPointInstWithTextures.h" #include "gfx/gl/shaders/vs-shadowLandmass.h" +#include "gfx/gl/shadowStenciller.h" +#include "gfx/renderable.h" #include "gl_traits.h" #include "location.h" #include "maths.h" @@ -74,6 +77,12 @@ ShadowMapper::getBandViewExtents(const Camera & camera, const glm::mat4 & lightV ShadowMapper::Definitions ShadowMapper::update(const SceneProvider & scene, const Direction3D & dir, const Camera & camera) const { + ShadowStenciller shadowStenciller {dir, up}; + for (const auto & [id, asset] : gameState->assets) { + if (const auto r = std::dynamic_pointer_cast(asset)) { + r->updateStencil(shadowStenciller); + } + } glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); glClear(GL_DEPTH_BUFFER_BIT); glCullFace(GL_FRONT); diff --git a/gfx/gl/shadowStenciller.cpp b/gfx/gl/shadowStenciller.cpp index dc87d76..9f13808 100644 --- a/gfx/gl/shadowStenciller.cpp +++ b/gfx/gl/shadowStenciller.cpp @@ -1,15 +1,14 @@ #include "shadowStenciller.h" -#include "config/types.h" #include "gfx/gl/program.h" #include "gfx/gl/shaders/fs-shadowStencil.h" #include "gfx/gl/shaders/vs-shadowStencil.h" #include "gfx/models/mesh.h" #include "glArrays.h" #include "gl_traits.h" -#include "maths.h" #include -ShadowStenciller::ShadowStenciller() : shadowCaster {shadowStencil_vs, shadowStencil_fs} +ShadowStenciller::ShadowStenciller(const Direction3D & lightDir, const Direction3D & lightDirUp) : + shadowCaster {shadowStencil_vs, shadowStencil_fs}, lightDirMat {glm::lookAt(-lightDir, {}, lightDirUp)} { glBindFramebuffer(GL_FRAMEBUFFER, fbo); glDrawBuffer(GL_NONE); @@ -47,10 +46,10 @@ ShadowStenciller::renderStencil(const glTexture & stencil, const MeshBase & mesh glClear(GL_DEPTH_BUFFER_BIT); glViewport(0, 0, 256, 256); glEnable(GL_DEPTH_TEST); - const auto & mins = mesh.getDimensions().minExtent; - const auto & maxs = mesh.getDimensions().maxExtent; - const auto extents = glm::ortho(mins.x, maxs.x, mins.z, maxs.z, mins.y, maxs.y); - const auto lightDir = glm::lookAt({}, north, up); - glUniform(viewProjectionLoc, extents * lightDir); + const auto & centre = mesh.getDimensions().centre; + const auto & size = mesh.getDimensions().size; + const auto extentsMat + = glm::translate(glm::ortho(-size, size, -size, size, -size, size), {-centre.x, -centre.z, -centre.y}); + glUniform(viewProjectionLoc, extentsMat * lightDirMat); mesh.Draw(); } diff --git a/gfx/gl/shadowStenciller.h b/gfx/gl/shadowStenciller.h index bf6d204..87dc044 100644 --- a/gfx/gl/shadowStenciller.h +++ b/gfx/gl/shadowStenciller.h @@ -7,7 +7,7 @@ class ShadowStenciller { public: - ShadowStenciller(); + ShadowStenciller(const Direction3D & lightDir, const Direction3D & lightDirUp); [[nodiscard]] static glTexture createStencilTexture(GLsizei width, GLsizei height); @@ -16,5 +16,6 @@ public: private: glFrameBuffer fbo; Program shadowCaster; + glm::mat4 lightDirMat; Program::UniformLocation viewProjectionLoc {shadowCaster, "viewProjection"}; }; -- cgit v1.2.3 From 08c9a8ea438f25ae8012d80d2c2c74c799f5543c Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 19 Aug 2024 23:07:12 +0100 Subject: Shuffle some GL state setting Ensures the right things are set at the right times, it's more calls but its less prone to randomly getting screwed over. Also updates the comments about which phases do what. --- gfx/gl/sceneRenderer.cpp | 20 ++++++++++++++++---- gfx/gl/shadowMapper.cpp | 5 ++++- gfx/gl/shadowStenciller.cpp | 1 - 3 files changed, 20 insertions(+), 6 deletions(-) (limited to 'gfx/gl') diff --git a/gfx/gl/sceneRenderer.cpp b/gfx/gl/sceneRenderer.cpp index e0938f2..7aace49 100644 --- a/gfx/gl/sceneRenderer.cpp +++ b/gfx/gl/sceneRenderer.cpp @@ -62,7 +62,7 @@ SceneRenderer::render(const SceneProvider & scene) const shader.setViewProjection(camera.getPosition(), camera.getViewProjection()); glViewport(0, 0, size.x, size.y); - // Geometry pass + // Geometry/colour pass - writes albedo, normal and position textures glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); glEnable(GL_BLEND); glEnable(GL_CULL_FACE); @@ -73,7 +73,13 @@ SceneRenderer::render(const SceneProvider & scene) const glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); scene.content(shader); - // Illumination pass + // Environment pass - + // * ambient - clears illumination texture - see setAmbientLight + // * directional - updates shadowMapper, reads normal and position, writes illumination - see setDirectionalLight + scene.environment(shader, *this); + + // Scene lights pass - + // * per light - reads normal and position, writes illumination glBindFramebuffer(GL_FRAMEBUFFER, gBufferIll); glBlendFunc(GL_ONE, GL_ONE); glActiveTexture(GL_TEXTURE0); @@ -82,11 +88,10 @@ SceneRenderer::render(const SceneProvider & scene) const glBindTexture(GL_TEXTURE_2D, gNormal); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D_ARRAY, shadowMapper); - scene.environment(shader, *this); glDisable(GL_DEPTH_TEST); scene.lights(shader); - // Lighting pass + // Composition pass - reads albedo and illumination, writes output glBindFramebuffer(GL_FRAMEBUFFER, output); glViewport(0, 0, size.x, size.y); glCullFace(GL_BACK); @@ -114,6 +119,13 @@ SceneRenderer::setDirectionalLight(const RGB & colour, const Direction3D & direc if (colour.r > 0 || colour.g > 0 || colour.b > 0) { const auto lvp = shadowMapper.update(scene, direction, camera); glBindFramebuffer(GL_FRAMEBUFFER, gBufferIll); + glBlendFunc(GL_ONE, GL_ONE); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, gPosition); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, gNormal); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D_ARRAY, shadowMapper); glViewport(0, 0, size.x, size.y); dirLight.use(); dirLight.setDirectionalLight(colour, direction, camera.getPosition(), lvp); diff --git a/gfx/gl/shadowMapper.cpp b/gfx/gl/shadowMapper.cpp index 9b9e404..ff0634e 100644 --- a/gfx/gl/shadowMapper.cpp +++ b/gfx/gl/shadowMapper.cpp @@ -77,15 +77,18 @@ ShadowMapper::getBandViewExtents(const Camera & camera, const glm::mat4 & lightV ShadowMapper::Definitions ShadowMapper::update(const SceneProvider & scene, const Direction3D & dir, const Camera & camera) const { + glCullFace(GL_FRONT); + glEnable(GL_DEPTH_TEST); + ShadowStenciller shadowStenciller {dir, up}; for (const auto & [id, asset] : gameState->assets) { if (const auto r = std::dynamic_pointer_cast(asset)) { r->updateStencil(shadowStenciller); } } + 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); diff --git a/gfx/gl/shadowStenciller.cpp b/gfx/gl/shadowStenciller.cpp index 9f13808..fc3d77c 100644 --- a/gfx/gl/shadowStenciller.cpp +++ b/gfx/gl/shadowStenciller.cpp @@ -45,7 +45,6 @@ ShadowStenciller::renderStencil(const glTexture & stencil, const MeshBase & mesh glUseProgram(shadowCaster); glClear(GL_DEPTH_BUFFER_BIT); glViewport(0, 0, 256, 256); - glEnable(GL_DEPTH_TEST); const auto & centre = mesh.getDimensions().centre; const auto & size = mesh.getDimensions().size; const auto extentsMat -- cgit v1.2.3 From dd452f3e9238be954c3ecd325ed11e97a50ec1c3 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 19 Aug 2024 23:26:32 +0100 Subject: Persist a single ShadowStenciller within ShadowMapper --- gfx/gl/shadowMapper.cpp | 2 +- gfx/gl/shadowMapper.h | 2 ++ gfx/gl/shadowStenciller.cpp | 9 +++++++-- gfx/gl/shadowStenciller.h | 6 ++++-- 4 files changed, 14 insertions(+), 5 deletions(-) (limited to 'gfx/gl') diff --git a/gfx/gl/shadowMapper.cpp b/gfx/gl/shadowMapper.cpp index ff0634e..d9dd24f 100644 --- a/gfx/gl/shadowMapper.cpp +++ b/gfx/gl/shadowMapper.cpp @@ -80,7 +80,7 @@ ShadowMapper::update(const SceneProvider & scene, const Direction3D & dir, const glCullFace(GL_FRONT); glEnable(GL_DEPTH_TEST); - ShadowStenciller shadowStenciller {dir, up}; + shadowStenciller.setLightDirection(dir, up); for (const auto & [id, asset] : gameState->assets) { if (const auto r = std::dynamic_pointer_cast(asset)) { r->updateStencil(shadowStenciller); diff --git a/gfx/gl/shadowMapper.h b/gfx/gl/shadowMapper.h index 73dadd0..280a0cd 100644 --- a/gfx/gl/shadowMapper.h +++ b/gfx/gl/shadowMapper.h @@ -1,6 +1,7 @@ #pragma once #include "config/types.h" +#include "gfx/gl/shadowStenciller.h" #include "lib/glArrays.h" #include "program.h" #include @@ -61,4 +62,5 @@ private: glFrameBuffer depthMapFBO; glTexture depthMap; TextureAbsCoord size; + mutable ShadowStenciller shadowStenciller; }; diff --git a/gfx/gl/shadowStenciller.cpp b/gfx/gl/shadowStenciller.cpp index fc3d77c..ac63b4e 100644 --- a/gfx/gl/shadowStenciller.cpp +++ b/gfx/gl/shadowStenciller.cpp @@ -7,8 +7,7 @@ #include "gl_traits.h" #include -ShadowStenciller::ShadowStenciller(const Direction3D & lightDir, const Direction3D & lightDirUp) : - shadowCaster {shadowStencil_vs, shadowStencil_fs}, lightDirMat {glm::lookAt(-lightDir, {}, lightDirUp)} +ShadowStenciller::ShadowStenciller() : shadowCaster {shadowStencil_vs, shadowStencil_fs} { glBindFramebuffer(GL_FRAMEBUFFER, fbo); glDrawBuffer(GL_NONE); @@ -16,6 +15,12 @@ ShadowStenciller::ShadowStenciller(const Direction3D & lightDir, const Direction glBindFramebuffer(GL_FRAMEBUFFER, 0); } +void +ShadowStenciller::setLightDirection(const Direction3D & lightDir, const Direction3D & lightDirUp) +{ + lightDirMat = glm::lookAt(-lightDir, {}, lightDirUp); +} + glTexture ShadowStenciller::createStencilTexture(GLsizei width, GLsizei height) { diff --git a/gfx/gl/shadowStenciller.h b/gfx/gl/shadowStenciller.h index 87dc044..009285c 100644 --- a/gfx/gl/shadowStenciller.h +++ b/gfx/gl/shadowStenciller.h @@ -7,15 +7,17 @@ class ShadowStenciller { public: - ShadowStenciller(const Direction3D & lightDir, const Direction3D & lightDirUp); + ShadowStenciller(); [[nodiscard]] static glTexture createStencilTexture(GLsizei width, GLsizei height); + void setLightDirection(const Direction3D & lightDir, const Direction3D & lightDirUp); void renderStencil(const glTexture &, const MeshBase &, const Texture::AnyPtr texture) const; private: glFrameBuffer fbo; Program shadowCaster; - glm::mat4 lightDirMat; Program::UniformLocation viewProjectionLoc {shadowCaster, "viewProjection"}; + + glm::mat4 lightDirMat {}; }; -- cgit v1.2.3 From c493369c5686fdd66175024444aca196cff54502 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 26 Aug 2024 13:38:55 +0100 Subject: Include sizes of shadow box extents as uniforms to shaders --- gfx/gl/shadowMapper.cpp | 16 +++++++++++----- gfx/gl/shadowMapper.h | 5 ++++- 2 files changed, 15 insertions(+), 6 deletions(-) (limited to 'gfx/gl') diff --git a/gfx/gl/shadowMapper.cpp b/gfx/gl/shadowMapper.cpp index d9dd24f..55167e5 100644 --- a/gfx/gl/shadowMapper.cpp +++ b/gfx/gl/shadowMapper.cpp @@ -95,23 +95,28 @@ ShadowMapper::update(const SceneProvider & scene, const Direction3D & dir, const const auto lightViewPoint = camera.getPosition(); const auto bandViewExtents = getBandViewExtents(camera, lightViewDir); Definitions out; + Sizes sizes; std::transform(bandViewExtents.begin(), std::prev(bandViewExtents.end()), std::next(bandViewExtents.begin()), std::back_inserter(out), - [bands = bandViewExtents.size() - 2, &lightViewDir](const auto & near, const auto & far) mutable { + [bands = bandViewExtents.size() - 2, &lightViewDir, &sizes](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)); }; + const std::array extents + = {extents_minmax(CompareBy {0}), extents_minmax(CompareBy {1}), extents_minmax(CompareBy {2})}; const auto lightProjection = [](const auto & x, const auto & y, const auto & z) { 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})); + }(extents[0], extents[1], extents[2]); + sizes.emplace_back(extents[0].second - extents[0].first, extents[1].second - extents[1].first, + extents[2].second - extents[2].first); return lightProjection * lightViewDir; }); for (const auto p : std::initializer_list { &landmess, &dynamicPoint, &dynamicPointInst, &dynamicPointInstWithTextures}) { - p->setView(out, lightViewPoint); + p->setView(out, sizes, lightViewPoint); } scene.shadows(*this); @@ -128,12 +133,13 @@ ShadowMapper::ShadowProgram::ShadowProgram(const Shader & vs, const Shader & gs, } void -ShadowMapper::ShadowProgram::setView( - const std::span viewProjection, const GlobalPosition3D viewPoint) const +ShadowMapper::ShadowProgram::setView(const std::span viewProjection, + const std::span sizes, const GlobalPosition3D viewPoint) const { use(); glUniform(viewPointLoc, viewPoint); glUniform(viewProjectionLoc, viewProjection); + glUniform(sizesLoc, sizes); glUniform(viewProjectionsLoc, static_cast(viewProjection.size())); } diff --git a/gfx/gl/shadowMapper.h b/gfx/gl/shadowMapper.h index 280a0cd..19c3d23 100644 --- a/gfx/gl/shadowMapper.h +++ b/gfx/gl/shadowMapper.h @@ -19,6 +19,7 @@ public: static constexpr std::size_t SHADOW_BANDS {4}; using Definitions = std::vector; + using Sizes = std::vector; [[nodiscard]] Definitions update(const SceneProvider &, const Direction3D & direction, const Camera &) const; @@ -27,12 +28,14 @@ public: explicit ShadowProgram(const Shader & vs); explicit ShadowProgram(const Shader & vs, const Shader & gs, const Shader & fs); - void setView(const std::span, const GlobalPosition3D) const; + void setView(const std::span, const std::span, + const GlobalPosition3D) const; void use() const; private: RequiredUniformLocation viewProjectionLoc {*this, "viewProjection"}; RequiredUniformLocation viewProjectionsLoc {*this, "viewProjections"}; + UniformLocation sizesLoc {*this, "sizes"}; RequiredUniformLocation viewPointLoc {*this, "viewPoint"}; }; -- cgit v1.2.3 From 10e0fee323e6277ba73ee1fc148417882bc381c3 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 26 Aug 2024 13:55:32 +0100 Subject: Add helper to test if a uniform was found --- gfx/gl/program.h | 6 ++++++ gfx/gl/sceneShader.cpp | 2 +- gfx/gl/shadowMapper.cpp | 4 +++- gfx/gl/shadowStenciller.h | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) (limited to 'gfx/gl') diff --git a/gfx/gl/program.h b/gfx/gl/program.h index c89a128..20be1aa 100644 --- a/gfx/gl/program.h +++ b/gfx/gl/program.h @@ -33,6 +33,12 @@ public: return location; } + explicit + operator bool() const + { + return location >= 0; + } + protected: GLint location; }; diff --git a/gfx/gl/sceneShader.cpp b/gfx/gl/sceneShader.cpp index 4cbccb3..571538a 100644 --- a/gfx/gl/sceneShader.cpp +++ b/gfx/gl/sceneShader.cpp @@ -65,7 +65,7 @@ SceneShader::SceneProgram::setViewProjection(const GlobalPosition3D & viewPoint, void SceneShader::SceneProgram::setViewPort(const ViewPort & viewPort) const { - if (viewPortLoc >= 0) { + if (viewPortLoc) { glUseProgram(*this); glUniform(viewPortLoc, viewPort); } diff --git a/gfx/gl/shadowMapper.cpp b/gfx/gl/shadowMapper.cpp index 55167e5..177bd22 100644 --- a/gfx/gl/shadowMapper.cpp +++ b/gfx/gl/shadowMapper.cpp @@ -139,7 +139,9 @@ ShadowMapper::ShadowProgram::setView(const std::span viewProj use(); glUniform(viewPointLoc, viewPoint); glUniform(viewProjectionLoc, viewProjection); - glUniform(sizesLoc, sizes); + if (sizesLoc) { + glUniform(sizesLoc, sizes); + } glUniform(viewProjectionsLoc, static_cast(viewProjection.size())); } diff --git a/gfx/gl/shadowStenciller.h b/gfx/gl/shadowStenciller.h index 009285c..925f82a 100644 --- a/gfx/gl/shadowStenciller.h +++ b/gfx/gl/shadowStenciller.h @@ -17,7 +17,7 @@ public: private: glFrameBuffer fbo; Program shadowCaster; - Program::UniformLocation viewProjectionLoc {shadowCaster, "viewProjection"}; + Program::RequiredUniformLocation viewProjectionLoc {shadowCaster, "viewProjection"}; glm::mat4 lightDirMat {}; }; -- cgit v1.2.3 From ce6659f5581a7d1f6b0f7b42e29c831e93315be8 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 26 Aug 2024 19:07:37 +0100 Subject: Set stencil texture min/mag filters --- gfx/gl/shadowStenciller.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'gfx/gl') diff --git a/gfx/gl/shadowStenciller.cpp b/gfx/gl/shadowStenciller.cpp index ac63b4e..0c34da5 100644 --- a/gfx/gl/shadowStenciller.cpp +++ b/gfx/gl/shadowStenciller.cpp @@ -28,6 +28,8 @@ ShadowStenciller::createStencilTexture(GLsizei width, GLsizei height) glBindTexture(GL_TEXTURE_2D, stencil); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -- cgit v1.2.3 From ae9087aea7aa2b19bf78daa6593d14dfba98183d Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 28 Aug 2024 03:48:19 +0100 Subject: Initial cut of shadow map creation with support for billboard shadows --- gfx/gl/shaders/shadowDynamicPointStencil.fs | 16 +++++++++++++++ gfx/gl/shaders/shadowDynamicPointStencil.gs | 32 +++++++++++++++++++++++++++++ gfx/gl/shaders/shadowDynamicPointStencil.vs | 17 +++++++++++++++ gfx/gl/shadowMapper.cpp | 18 +++++++++++++++- gfx/gl/shadowMapper.h | 11 ++++++++++ 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 gfx/gl/shaders/shadowDynamicPointStencil.fs create mode 100644 gfx/gl/shaders/shadowDynamicPointStencil.gs create mode 100644 gfx/gl/shaders/shadowDynamicPointStencil.vs (limited to 'gfx/gl') diff --git a/gfx/gl/shaders/shadowDynamicPointStencil.fs b/gfx/gl/shaders/shadowDynamicPointStencil.fs new file mode 100644 index 0000000..57b8aa3 --- /dev/null +++ b/gfx/gl/shaders/shadowDynamicPointStencil.fs @@ -0,0 +1,16 @@ +#version 330 core +#extension GL_ARB_shading_language_420pack : enable + +layout(binding = 0) uniform sampler2D stencilDepth; +flat in vec3 scale; +in vec2 texCoord; + +void +main() +{ + float stDepth = texture(stencilDepth, texCoord).r; + if (stDepth >= 1) { + discard; + } + gl_FragDepth = gl_FragCoord.z + (stDepth * scale.z); +} diff --git a/gfx/gl/shaders/shadowDynamicPointStencil.gs b/gfx/gl/shaders/shadowDynamicPointStencil.gs new file mode 100644 index 0000000..6d707ae --- /dev/null +++ b/gfx/gl/shaders/shadowDynamicPointStencil.gs @@ -0,0 +1,32 @@ +#version 330 core +#extension GL_ARB_viewport_array : enable + +const vec2[] corners = vec2[4](vec2(-1, -1), vec2(-1, 1), vec2(1, -1), vec2(1, 1)); + +uniform mat4 viewProjection[4]; +uniform int viewProjections; +uniform vec3 sizes[4]; +uniform float size; + +in ivec3 vworldPos[]; + +flat out vec3 scale; +out vec2 texCoord; + +layout(points) in; +layout(triangle_strip, max_vertices = 16) out; + +void +main() +{ + for (gl_Layer = 0; gl_Layer < viewProjections; ++gl_Layer) { + scale = 2.0 * size / sizes[gl_Layer]; + vec4 pos = viewProjection[gl_Layer] * vec4(vworldPos[0], 1); + for (int c = 0; c < corners.length(); ++c) { + gl_Position = pos + vec4(scale.xy * corners[c], 0, 0); + texCoord = (corners[c] * 0.5) + 0.5; + EmitVertex(); + } + EndPrimitive(); + } +} diff --git a/gfx/gl/shaders/shadowDynamicPointStencil.vs b/gfx/gl/shaders/shadowDynamicPointStencil.vs new file mode 100644 index 0000000..dadf9c2 --- /dev/null +++ b/gfx/gl/shaders/shadowDynamicPointStencil.vs @@ -0,0 +1,17 @@ +#version 330 core +#extension GL_ARB_shading_language_420pack : enable + +layout(location = 0) in mat3 model; +layout(location = 3) in ivec3 worldPos; +uniform ivec3 viewPoint; +uniform vec3 centre; + +out mat3 vmodel; +out ivec3 vworldPos; + +void +main() +{ + vmodel = model; + vworldPos = worldPos - viewPoint + ivec3(centre); +} diff --git a/gfx/gl/shadowMapper.cpp b/gfx/gl/shadowMapper.cpp index 177bd22..ac161e2 100644 --- a/gfx/gl/shadowMapper.cpp +++ b/gfx/gl/shadowMapper.cpp @@ -3,11 +3,14 @@ #include "collections.h" #include "game/gamestate.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/renderable.h" @@ -115,7 +118,7 @@ ShadowMapper::update(const SceneProvider & scene, const Direction3D & dir, const return lightProjection * lightViewDir; }); for (const auto p : std::initializer_list { - &landmess, &dynamicPoint, &dynamicPointInst, &dynamicPointInstWithTextures}) { + &landmess, &dynamicPoint, &dynamicPointInst, &dynamicPointInstWithTextures, &stencilShadowProgram}) { p->setView(out, sizes, lightViewPoint); } scene.shadows(*this); @@ -166,3 +169,16 @@ ShadowMapper::DynamicPoint::setModel(const Location & location) const glUniform(modelLoc, location.getRotationTransform()); glUniform(modelPosLoc, location.pos); } + +ShadowMapper::StencilShadowProgram::StencilShadowProgram() : + ShadowProgram {shadowDynamicPointStencil_vs, shadowDynamicPointStencil_gs, shadowDynamicPointStencil_fs} +{ +} + +void +ShadowMapper::StencilShadowProgram::use(const RelativePosition3D & centre, const float size) const +{ + Program::use(); + glUniform(centreLoc, centre); + glUniform(sizeLoc, size); +} diff --git a/gfx/gl/shadowMapper.h b/gfx/gl/shadowMapper.h index 19c3d23..3aa224e 100644 --- a/gfx/gl/shadowMapper.h +++ b/gfx/gl/shadowMapper.h @@ -50,8 +50,19 @@ public: RequiredUniformLocation modelPosLoc {*this, "modelPos"}; }; + class StencilShadowProgram : public ShadowProgram { + public: + StencilShadowProgram(); + void use(const RelativePosition3D & centre, const float size) const; + + private: + RequiredUniformLocation centreLoc {*this, "centre"}; + RequiredUniformLocation sizeLoc {*this, "size"}; + }; + ShadowProgram landmess, dynamicPointInst, dynamicPointInstWithTextures; DynamicPoint dynamicPoint; + StencilShadowProgram stencilShadowProgram; // NOLINTNEXTLINE(hicpp-explicit-conversions) operator GLuint() const -- cgit v1.2.3 From 7299b08977acafe7eeba620f229a7169256f23cf Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 1 Sep 2024 18:42:27 +0100 Subject: Extend depth of shadow box 10m to allow for depth offsets and clamp stencil to it --- gfx/gl/shaders/shadowDynamicPointStencil.gs | 1 + gfx/gl/shadowMapper.cpp | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'gfx/gl') diff --git a/gfx/gl/shaders/shadowDynamicPointStencil.gs b/gfx/gl/shaders/shadowDynamicPointStencil.gs index 6d707ae..2873691 100644 --- a/gfx/gl/shaders/shadowDynamicPointStencil.gs +++ b/gfx/gl/shaders/shadowDynamicPointStencil.gs @@ -24,6 +24,7 @@ main() vec4 pos = viewProjection[gl_Layer] * vec4(vworldPos[0], 1); for (int c = 0; c < corners.length(); ++c) { gl_Position = pos + vec4(scale.xy * corners[c], 0, 0); + gl_Position.z = max(gl_Position.z, -1); texCoord = (corners[c] * 0.5) + 0.5; EmitVertex(); } diff --git a/gfx/gl/shadowMapper.cpp b/gfx/gl/shadowMapper.cpp index ac161e2..b08538d 100644 --- a/gfx/gl/shadowMapper.cpp +++ b/gfx/gl/shadowMapper.cpp @@ -102,12 +102,13 @@ ShadowMapper::update(const SceneProvider & scene, const Direction3D & dir, const std::transform(bandViewExtents.begin(), std::prev(bandViewExtents.end()), std::next(bandViewExtents.begin()), std::back_inserter(out), [bands = bandViewExtents.size() - 2, &lightViewDir, &sizes](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)); - }; - const std::array extents - = {extents_minmax(CompareBy {0}), extents_minmax(CompareBy {1}), extents_minmax(CompareBy {2})}; + const auto extents_minmax + = [extents = std::span {near.begin(), far.end()}](auto && comp, RelativeDistance extra) { + const auto mm = std::minmax_element(extents.begin(), extents.end(), comp); + return std::make_pair(comp.get(*mm.first) - extra, comp.get(*mm.second) + extra); + }; + const std::array extents = {extents_minmax(CompareBy {0}, 0), extents_minmax(CompareBy {1}, 0), + extents_minmax(CompareBy {2}, 10'000)}; const auto lightProjection = [](const auto & x, const auto & y, const auto & z) { return glm::ortho(x.first, x.second, y.first, y.second, -z.second, -z.first); -- cgit v1.2.3 From 052b2b49d9bfdaaa7f7c5603fa7c47b881df93c2 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 2 Sep 2024 21:00:41 +0100 Subject: Update stencil texture to 2d array --- gfx/gl/shaders/shadowDynamicPointStencil.fs | 4 ++-- gfx/gl/shaders/shadowDynamicPointStencil.gs | 4 ++-- gfx/gl/shadowStenciller.cpp | 13 +++++++------ 3 files changed, 11 insertions(+), 10 deletions(-) (limited to 'gfx/gl') diff --git a/gfx/gl/shaders/shadowDynamicPointStencil.fs b/gfx/gl/shaders/shadowDynamicPointStencil.fs index 57b8aa3..e612691 100644 --- a/gfx/gl/shaders/shadowDynamicPointStencil.fs +++ b/gfx/gl/shaders/shadowDynamicPointStencil.fs @@ -1,9 +1,9 @@ #version 330 core #extension GL_ARB_shading_language_420pack : enable -layout(binding = 0) uniform sampler2D stencilDepth; +layout(binding = 0) uniform sampler2DArray stencilDepth; flat in vec3 scale; -in vec2 texCoord; +in vec3 texCoord; void main() diff --git a/gfx/gl/shaders/shadowDynamicPointStencil.gs b/gfx/gl/shaders/shadowDynamicPointStencil.gs index 2873691..b91937d 100644 --- a/gfx/gl/shaders/shadowDynamicPointStencil.gs +++ b/gfx/gl/shaders/shadowDynamicPointStencil.gs @@ -11,7 +11,7 @@ uniform float size; in ivec3 vworldPos[]; flat out vec3 scale; -out vec2 texCoord; +out vec3 texCoord; layout(points) in; layout(triangle_strip, max_vertices = 16) out; @@ -25,7 +25,7 @@ main() for (int c = 0; c < corners.length(); ++c) { gl_Position = pos + vec4(scale.xy * corners[c], 0, 0); gl_Position.z = max(gl_Position.z, -1); - texCoord = (corners[c] * 0.5) + 0.5; + texCoord = vec3((corners[c] * 0.5) + 0.5, 0); EmitVertex(); } EndPrimitive(); diff --git a/gfx/gl/shadowStenciller.cpp b/gfx/gl/shadowStenciller.cpp index 0c34da5..01248bd 100644 --- a/gfx/gl/shadowStenciller.cpp +++ b/gfx/gl/shadowStenciller.cpp @@ -25,15 +25,16 @@ glTexture ShadowStenciller::createStencilTexture(GLsizei width, GLsizei height) { glTexture stencil; - glBindTexture(GL_TEXTURE_2D, stencil); + glBindTexture(GL_TEXTURE_2D_ARRAY, stencil); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameter(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameter(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameter(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameter(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameter(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, nullptr); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_DEPTH_COMPONENT, width, height, 8, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, + nullptr); return stencil; } -- cgit v1.2.3 From f22f79330f9b8851cda76d1e11555877cbb72d80 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Tue, 3 Sep 2024 01:37:03 +0100 Subject: Populate all layers of the stencil texture Albeit with the same projection --- gfx/gl/shaders/shadowStencil.fs | 6 ++++-- gfx/gl/shaders/shadowStencil.gs | 28 ++++++++++++++++++++++++++++ gfx/gl/shaders/shadowStencil.vs | 10 ++++++---- gfx/gl/shadowStenciller.cpp | 3 ++- 4 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 gfx/gl/shaders/shadowStencil.gs (limited to 'gfx/gl') diff --git a/gfx/gl/shaders/shadowStencil.fs b/gfx/gl/shaders/shadowStencil.fs index f149c23..1164cc9 100644 --- a/gfx/gl/shaders/shadowStencil.fs +++ b/gfx/gl/shaders/shadowStencil.fs @@ -3,13 +3,15 @@ layout(binding = 0) uniform sampler2D textureAlbedo; -include(`materialInterface.glsl') +include(`materialDetail.glsl') include(`materialCommon.glsl') +in vec2 gTexCoords; +flat in MaterialDetail gMaterial; void main() { - if (getTextureColour(Material, TexCoords).a < 0.5) { + if (getTextureColour(gMaterial, gTexCoords).a < 0.5) { discard; } gl_FragDepth = gl_FragCoord.z; diff --git a/gfx/gl/shaders/shadowStencil.gs b/gfx/gl/shaders/shadowStencil.gs new file mode 100644 index 0000000..eea4643 --- /dev/null +++ b/gfx/gl/shaders/shadowStencil.gs @@ -0,0 +1,28 @@ +#version 330 core +#extension GL_ARB_viewport_array : enable + +include(`materialDetail.glsl') + +layout(triangles) in; +layout(triangle_strip, max_vertices = 24) out; + +uniform mat4 viewProjection; +in vec3 FragPos[]; +in vec2 TexCoords[]; +flat in MaterialDetail Material[]; +out vec2 gTexCoords; +flat out MaterialDetail gMaterial; + +void +main() +{ + for (gl_Layer = 0; gl_Layer < 8; ++gl_Layer) { + for (int v = 0; v < FragPos.length(); ++v) { + gl_Position = viewProjection * vec4(FragPos[v], 1); + gTexCoords = TexCoords[v]; + gMaterial = Material[v]; + EmitVertex(); + } + EndPrimitive(); + } +} diff --git a/gfx/gl/shaders/shadowStencil.vs b/gfx/gl/shaders/shadowStencil.vs index 45a0867..a15c4fb 100644 --- a/gfx/gl/shaders/shadowStencil.vs +++ b/gfx/gl/shaders/shadowStencil.vs @@ -4,15 +4,17 @@ layout(binding = 1) uniform usampler2DRect materialData; include(`meshIn.glsl') -include(`materialInterface.glsl') +include(`materialDetail.glsl') include(`getMaterialDetail.glsl') -uniform mat4 viewProjection; + +out vec3 FragPos; +out vec2 TexCoords; +flat out MaterialDetail Material; void main() { TexCoords = texCoord; Material = getMaterialDetail(material); - - gl_Position = viewProjection * vec4(position, 1); + FragPos = position; } diff --git a/gfx/gl/shadowStenciller.cpp b/gfx/gl/shadowStenciller.cpp index 01248bd..1063b71 100644 --- a/gfx/gl/shadowStenciller.cpp +++ b/gfx/gl/shadowStenciller.cpp @@ -1,13 +1,14 @@ #include "shadowStenciller.h" #include "gfx/gl/program.h" #include "gfx/gl/shaders/fs-shadowStencil.h" +#include "gfx/gl/shaders/gs-shadowStencil.h" #include "gfx/gl/shaders/vs-shadowStencil.h" #include "gfx/models/mesh.h" #include "glArrays.h" #include "gl_traits.h" #include -ShadowStenciller::ShadowStenciller() : shadowCaster {shadowStencil_vs, shadowStencil_fs} +ShadowStenciller::ShadowStenciller() : shadowCaster {shadowStencil_vs, shadowStencil_gs, shadowStencil_fs} { glBindFramebuffer(GL_FRAMEBUFFER, fbo); glDrawBuffer(GL_NONE); -- cgit v1.2.3 From 5ec74c35fb1f2524add7fd03ace78667f93edb2e Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 7 Sep 2024 12:35:03 +0100 Subject: Populate all layers of shadow stencil with view from all around --- gfx/gl/shaders/shadowStencil.gs | 6 +++--- gfx/gl/shadowStenciller.cpp | 18 ++++++++++++++++-- gfx/gl/shadowStenciller.h | 1 + 3 files changed, 20 insertions(+), 5 deletions(-) (limited to 'gfx/gl') diff --git a/gfx/gl/shaders/shadowStencil.gs b/gfx/gl/shaders/shadowStencil.gs index eea4643..2c3f9bd 100644 --- a/gfx/gl/shaders/shadowStencil.gs +++ b/gfx/gl/shaders/shadowStencil.gs @@ -6,7 +6,7 @@ include(`materialDetail.glsl') layout(triangles) in; layout(triangle_strip, max_vertices = 24) out; -uniform mat4 viewProjection; +uniform mat4 viewProjection[8]; in vec3 FragPos[]; in vec2 TexCoords[]; flat in MaterialDetail Material[]; @@ -16,9 +16,9 @@ flat out MaterialDetail gMaterial; void main() { - for (gl_Layer = 0; gl_Layer < 8; ++gl_Layer) { + for (gl_Layer = 0; gl_Layer < viewProjection.length(); ++gl_Layer) { for (int v = 0; v < FragPos.length(); ++v) { - gl_Position = viewProjection * vec4(FragPos[v], 1); + gl_Position = viewProjection[gl_Layer] * vec4(FragPos[v], 1); gTexCoords = TexCoords[v]; gMaterial = Material[v]; EmitVertex(); diff --git a/gfx/gl/shadowStenciller.cpp b/gfx/gl/shadowStenciller.cpp index 1063b71..da2b3a0 100644 --- a/gfx/gl/shadowStenciller.cpp +++ b/gfx/gl/shadowStenciller.cpp @@ -6,9 +6,18 @@ #include "gfx/models/mesh.h" #include "glArrays.h" #include "gl_traits.h" +#include "maths.h" #include -ShadowStenciller::ShadowStenciller() : shadowCaster {shadowStencil_vs, shadowStencil_gs, shadowStencil_fs} +namespace { + static constexpr std::array anglesEigthPi {-3, -2, -1, 0, 1, 2, 3, 4}; + static const auto angles = anglesEigthPi * [](auto ep) { + return rotate_yaw(ep * quarter_pi); + }; +} + +ShadowStenciller::ShadowStenciller() : + shadowCaster {shadowStencil_vs, shadowStencil_gs, shadowStencil_fs}, viewProjections {} { glBindFramebuffer(GL_FRAMEBUFFER, fbo); glDrawBuffer(GL_NONE); @@ -20,6 +29,9 @@ void ShadowStenciller::setLightDirection(const Direction3D & lightDir, const Direction3D & lightDirUp) { lightDirMat = glm::lookAt(-lightDir, {}, lightDirUp); + viewProjections = angles * [this](const auto & a) { + return lightDirMat * a; + }; } glTexture @@ -58,6 +70,8 @@ ShadowStenciller::renderStencil(const glTexture & stencil, const MeshBase & mesh const auto & size = mesh.getDimensions().size; const auto extentsMat = glm::translate(glm::ortho(-size, size, -size, size, -size, size), {-centre.x, -centre.z, -centre.y}); - glUniform(viewProjectionLoc, extentsMat * lightDirMat); + glUniform(viewProjectionLoc, std::span {viewProjections * [&](const auto & vp) { + return extentsMat * vp; + }}); mesh.Draw(); } diff --git a/gfx/gl/shadowStenciller.h b/gfx/gl/shadowStenciller.h index 925f82a..2edb955 100644 --- a/gfx/gl/shadowStenciller.h +++ b/gfx/gl/shadowStenciller.h @@ -20,4 +20,5 @@ private: Program::RequiredUniformLocation viewProjectionLoc {shadowCaster, "viewProjection"}; glm::mat4 lightDirMat {}; + std::array viewProjections; }; -- cgit v1.2.3