From 6433b56c3af8721f8301255818a8dd692e75492e Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 4 Dec 2022 17:16:31 +0000 Subject: Generate and use a shadow map Generated when the directional light is specified in the environment call, passed to the directional light shader pass to conditionally illuminate each pixel. --- gfx/gl/sceneProvider.cpp | 2 +- gfx/gl/sceneRenderer.cpp | 22 +++++++++++++++++----- gfx/gl/sceneRenderer.h | 8 +++++--- gfx/gl/shaders/directionalLight.fs | 9 +++++++++ test/test-render.cpp | 2 +- 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/gfx/gl/sceneProvider.cpp b/gfx/gl/sceneProvider.cpp index 9152bfa..8ff7d73 100644 --- a/gfx/gl/sceneProvider.cpp +++ b/gfx/gl/sceneProvider.cpp @@ -5,7 +5,7 @@ void SceneProvider::environment(const SceneShader &, const SceneRenderer & renderer) const { renderer.setAmbientLight({0.5F, 0.5F, 0.5F}); - renderer.setDirectionalLight({0.6F, 0.6F, 0.6F}, {1, 0, -1}); + renderer.setDirectionalLight({0.6F, 0.6F, 0.6F}, {1, 0, -1}, *this); } void SceneProvider::shadows(const ShadowMapper &) const diff --git a/gfx/gl/sceneRenderer.cpp b/gfx/gl/sceneRenderer.cpp index a06a163..49c73a2 100644 --- a/gfx/gl/sceneRenderer.cpp +++ b/gfx/gl/sceneRenderer.cpp @@ -78,11 +78,15 @@ SceneRenderer::render(const SceneProvider & scene) const glBindTexture(GL_TEXTURE_2D, gPosition); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, gNormal); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, shadowMapper); scene.environment(shader, *this); scene.lights(shader); // Lighting pass glBindFramebuffer(GL_FRAMEBUFFER, output); + glViewport(0, 0, size.x, size.y); + glCullFace(GL_BACK); glDisable(GL_BLEND); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glActiveTexture(GL_TEXTURE0); @@ -102,32 +106,40 @@ SceneRenderer::render(const SceneProvider & scene) const void SceneRenderer::setAmbientLight(const glm::vec3 & colour) const { + glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); glClearColor(colour.r, colour.g, colour.b, 1.0F); glClear(GL_COLOR_BUFFER_BIT); } void -SceneRenderer::setDirectionalLight(const glm::vec3 & colour, const glm::vec3 & direction) const +SceneRenderer::setDirectionalLight( + const glm::vec3 & colour, const glm::vec3 & direction, const SceneProvider & scene) const { if (colour.r > 0 || colour.g > 0 || colour.b > 0) { + const auto lvp = shadowMapper.update(scene, direction); + glBindFramebuffer(GL_FRAMEBUFFER, gBuffer); + glViewport(0, 0, size.x, size.y); dirLight.use(); - dirLight.setDirectionalLight(colour, direction); + dirLight.setDirectionalLight(colour, direction, lvp); glBindVertexArray(displayVAO); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindVertexArray(0); + glEnable(GL_DEPTH_TEST); } } SceneRenderer::DirectionalLightProgram::DirectionalLightProgram() : - Program {lightingShader_vs, directionalLight_fs}, directionLoc {*this, "lightDirection"}, colourLoc {*this, - "lightColour"} + Program {lightingShader_vs, directionalLight_fs}, directionLoc {*this, "lightDirection"}, + colourLoc {*this, "lightColour"}, lightViewProjectionLoc {*this, "lightViewProjection"} { } void -SceneRenderer::DirectionalLightProgram::setDirectionalLight(const glm::vec3 & c, const glm::vec3 & d) const +SceneRenderer::DirectionalLightProgram::setDirectionalLight( + const glm::vec3 & c, const glm::vec3 & d, const glm::mat4x4 & lvp) const { glUniform3fv(colourLoc, 1, glm::value_ptr(c)); const auto nd = glm::normalize(d); glUniform3fv(directionLoc, 1, glm::value_ptr(nd)); + glUniformMatrix4fv(lightViewProjectionLoc, 1, GL_FALSE, glm::value_ptr(lvp)); } diff --git a/gfx/gl/sceneRenderer.h b/gfx/gl/sceneRenderer.h index 736b15a..d7a92b7 100644 --- a/gfx/gl/sceneRenderer.h +++ b/gfx/gl/sceneRenderer.h @@ -5,6 +5,7 @@ #include "program.h" #include "sceneProvider.h" #include "sceneShader.h" +#include "shadowMapper.h" #include #include @@ -14,7 +15,7 @@ public: void render(const SceneProvider &) const; void setAmbientLight(const glm::vec3 & colour) const; - void setDirectionalLight(const glm::vec3 & colour, const glm::vec3 & direction) const; + void setDirectionalLight(const glm::vec3 & colour, const glm::vec3 & direction, const SceneProvider &) const; Camera camera; @@ -34,10 +35,10 @@ private: DirectionalLightProgram(); using Program::use; - void setDirectionalLight(const glm::vec3 &, const glm::vec3 &) const; + void setDirectionalLight(const glm::vec3 &, const glm::vec3 &, const glm::mat4x4 &) const; private: - RequiredUniformLocation directionLoc, colourLoc; + RequiredUniformLocation directionLoc, colourLoc, lightViewProjectionLoc; }; DeferredLightProgram lighting; @@ -45,4 +46,5 @@ private: glVertexArray displayVAO; glBuffer displayVBO; SceneShader shader; + ShadowMapper shadowMapper; }; diff --git a/gfx/gl/shaders/directionalLight.fs b/gfx/gl/shaders/directionalLight.fs index 7562f96..5350bf3 100644 --- a/gfx/gl/shaders/directionalLight.fs +++ b/gfx/gl/shaders/directionalLight.fs @@ -5,14 +5,23 @@ out vec3 FragColor; in vec2 TexCoords; +layout(binding = 0) uniform sampler2D gPosition; layout(binding = 1) uniform sampler2D gNormal; +layout(binding = 2) uniform sampler2D shadowMap; uniform vec3 lightDirection; uniform vec3 lightColour; +uniform mat4 lightViewProjection; void main() { + const vec3 Position = texture(gPosition, TexCoords).xyz; + const vec4 PositionInLightSpace = (lightViewProjection * vec4(Position, 1)) * 0.5 + 0.5; + const float lightSpaceDepth = texture(shadowMap, PositionInLightSpace.xy).r; + if (lightSpaceDepth < PositionInLightSpace.z) { + discard; + } const vec3 Normal = texture(gNormal, TexCoords).rgb; FragColor = dot(-lightDirection, Normal) * lightColour; } diff --git a/test/test-render.cpp b/test/test-render.cpp index f6185b4..d6e4094 100644 --- a/test/test-render.cpp +++ b/test/test-render.cpp @@ -119,7 +119,7 @@ BOOST_AUTO_TEST_CASE(pointlight) environment(const SceneShader &, const SceneRenderer & r) const override { r.setAmbientLight({0.2F, 0.2F, 0.2F}); - r.setDirectionalLight({}, down); + r.setDirectionalLight({}, down, *this); } void lights(const SceneShader & shader) const override -- cgit v1.2.3