From a8dc22f3ff28cdd116ad245cd895add7c6779668 Mon Sep 17 00:00:00 2001 From: Roagen7 Date: Fri, 21 Jun 2024 15:52:47 +0200 Subject: [PATCH] make the directional mapping frustum-dependent --- examples/scene3.cpp | 12 +-- src/main.cpp | 2 +- src/shaders/depth/{ => map2d}/fs.glsl | 0 src/shaders/depth/{ => map2d}/vs.glsl | 0 src/shaders/depth/omni/fs.glsl | 11 +++ src/shaders/depth/omni/gs.glsl | 20 ++++ src/shaders/depth/omni/vs.glsl | 7 ++ src/shaders/solid/fs.glsl | 2 +- src/tricore/Renderer.cpp | 17 +++- src/tricore/light/LightSource.h | 127 ++++++++++++-------------- 10 files changed, 116 insertions(+), 82 deletions(-) rename src/shaders/depth/{ => map2d}/fs.glsl (100%) rename src/shaders/depth/{ => map2d}/vs.glsl (100%) create mode 100644 src/shaders/depth/omni/fs.glsl create mode 100644 src/shaders/depth/omni/gs.glsl create mode 100644 src/shaders/depth/omni/vs.glsl diff --git a/examples/scene3.cpp b/examples/scene3.cpp index d75e40d..e26b96d 100644 --- a/examples/scene3.cpp +++ b/examples/scene3.cpp @@ -104,12 +104,12 @@ int main(){ .quadratic = 0.0 } })) - // .addLightSource(dirLight) - .addLightSource(light::make_dir({ - .direction = {-1, -1, 0}, - .color = {1, 1, 1}, - .intensity = 1 - })) + .addLightSource(dirLight) + // .addLightSource(light::make_dir({ + // .direction = {-1, -1, 0}, + // .color = {1, 1, 1}, + // .intensity = 1 + // })) // .addLightSource(light::make_dir({ // .direction = {1, -1, 0}, // .color = {1, 1, 1}, diff --git a/src/main.cpp b/src/main.cpp index c7e2063..d53a640 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,7 @@ /* small TODO list: -> add CSM > add shadows from point lights +> add CSM > add sprites > add cel shader material ... diff --git a/src/shaders/depth/fs.glsl b/src/shaders/depth/map2d/fs.glsl similarity index 100% rename from src/shaders/depth/fs.glsl rename to src/shaders/depth/map2d/fs.glsl diff --git a/src/shaders/depth/vs.glsl b/src/shaders/depth/map2d/vs.glsl similarity index 100% rename from src/shaders/depth/vs.glsl rename to src/shaders/depth/map2d/vs.glsl diff --git a/src/shaders/depth/omni/fs.glsl b/src/shaders/depth/omni/fs.glsl new file mode 100644 index 0000000..c43efc7 --- /dev/null +++ b/src/shaders/depth/omni/fs.glsl @@ -0,0 +1,11 @@ +in vec4 FragPos; + +uniform vec3 lightPos; +uniform float far_plane; + +void main() +{ + float lightDistance = length(FragPos.xyz - lightPos); + lightDistance = lightDistance / far_plane; + gl_FragDepth = lightDistance; +} \ No newline at end of file diff --git a/src/shaders/depth/omni/gs.glsl b/src/shaders/depth/omni/gs.glsl new file mode 100644 index 0000000..ed6a900 --- /dev/null +++ b/src/shaders/depth/omni/gs.glsl @@ -0,0 +1,20 @@ +layout (triangles) in; +layout (triangle_strip, max_vertices=18) out; + +uniform mat4 shadowMatrices[6]; + +out vec4 FragPos; + +void main() +{ + for(int face = 0; face < 6; ++face) + { + gl_Layer = face; + for(int i = 0; i < 3; ++i){ + FragPos = gl_in[i].gl_Position; + gl_Position = shadowMatrices[face] * FragPos; + EmitVertex(); + } + EndPrimitive(); + } +} \ No newline at end of file diff --git a/src/shaders/depth/omni/vs.glsl b/src/shaders/depth/omni/vs.glsl new file mode 100644 index 0000000..d2a0dd5 --- /dev/null +++ b/src/shaders/depth/omni/vs.glsl @@ -0,0 +1,7 @@ +uniform mat4 rotation; +uniform mat4 transform; +in vec3 vPos; + +void main(){ + gl_Position = transform * rotation * vec4(vPos, 1.0); +} \ No newline at end of file diff --git a/src/shaders/solid/fs.glsl b/src/shaders/solid/fs.glsl index 7357455..bdc6827 100644 --- a/src/shaders/solid/fs.glsl +++ b/src/shaders/solid/fs.glsl @@ -109,7 +109,7 @@ void main() outColor += calcDirLight(uDirectionalLights[i], normal_val, viewDir, uShininess, specular_val, uDiffuse); } - if(hasShadow == 1){ + if(hasShadow == 1 && uNumDirLights != 0){ float sh = 0.0; for(int i = 0; i < uNumDirLights; i++){ vec4 shadowSpacePos = shadowSpaceMatrix[i] * model * ogPos; diff --git a/src/tricore/Renderer.cpp b/src/tricore/Renderer.cpp index 2ea8a51..837815f 100644 --- a/src/tricore/Renderer.cpp +++ b/src/tricore/Renderer.cpp @@ -12,13 +12,20 @@ using namespace tri::core; using namespace tri::core::materials; -static constexpr auto DEPTH = "depth"; +static constexpr auto DEPTH = "depth/map2d"; class ShadowProgram : public Program { - public: - ShadowProgram() : Program( - fmt::format("{}/{}/vs.glsl", SHADER_PATH, DEPTH), - fmt::format("{}/{}/fs.glsl", SHADER_PATH, DEPTH)){} +public: + ShadowProgram() : Program( + fmt::format("{}/{}/vs.glsl", SHADER_PATH, DEPTH), + fmt::format("{}/{}/fs.glsl", SHADER_PATH, DEPTH)){} +}; + +class OmniShadowProgram : public Program { +public: + OmniShadowProgram() : Program( + fmt::format("{}/{}/vs.glsl", SHADER_PATH, DEPTH), + fmt::format("{}/{}/fs.glsl", SHADER_PATH, DEPTH)){} }; void Renderer::render(){ diff --git a/src/tricore/light/LightSource.h b/src/tricore/light/LightSource.h index 2626669..bd4ef6a 100644 --- a/src/tricore/light/LightSource.h +++ b/src/tricore/light/LightSource.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace tri::core { @@ -53,13 +54,21 @@ namespace tri::core { return ptr; } - inline glm::mat4x4 get_lightspace_matrix(PointLight point){ + inline std::array get_lightspace_matrices(PointLight point){ + float near = 1.f; + float far = 25.f; auto shadowWidth = config::SHADOW_RESOLUTION.w; auto shadowHeight = config::SHADOW_RESOLUTION.h; - return glm::perspective(glm::radians(45.0f), - (GLfloat)shadowWidth / (GLfloat)shadowHeight, - config::CAMERA_NEAR_PLANE, - config::CAMERA_FAR_PLANE); + auto perspective = glm::perspective(glm::radians(45.0f), (GLfloat)shadowWidth / (GLfloat)shadowHeight, near, far); + + return { + perspective * glm::lookAt(point.pos, point.pos + glm::vec3{1.f, 0.f, 0.f}, {0.f, -1.f, 0.f}), + perspective * glm::lookAt(point.pos, point.pos + glm::vec3{-1.f, 0.f, 0.f}, {0.f, -1.f, 0.f}), + perspective * glm::lookAt(point.pos, point.pos + glm::vec3{0.f, 1.f, 0.f}, {0.f, 0.f, 1.f}), + perspective * glm::lookAt(point.pos, point.pos + glm::vec3{1.f, -1.f, 0.f}, {0.f, -1.f, -1.f}), + perspective * glm::lookAt(point.pos, point.pos + glm::vec3{1.f, 0.f, 1.f}, {0.f, -1.f, 0.f}), + perspective * glm::lookAt(point.pos, point.pos + glm::vec3{1.f, 0.f, -1.f}, {0.f, -1.f, 0.f}) + }; } @@ -79,72 +88,52 @@ namespace tri::core { return frustumCorners; } - inline glm::mat4x4 get_lightspace_matrix(DirectionalLight dir, Camera& camera){ - // float farPlane = config::CAMERA_FAR_PLANE; - // float nearPlane = config::CAMERA_NEAR_PLANE; - // const auto corners = getFrustumCornersWorldSpace(camera.view()); - - // glm::vec3 center = glm::vec3(0, 0, 0); - // for (const auto& v : corners){ - // center += glm::vec3(v); - // } - // center /= corners.size(); - - // const auto lightView = glm::lookAt(center + dir.direction, center, UP); - - // float minX = std::numeric_limits::max(); - // float maxX = std::numeric_limits::lowest(); - // float minY = std::numeric_limits::max(); - // float maxY = std::numeric_limits::lowest(); - // float minZ = std::numeric_limits::max(); - // float maxZ = std::numeric_limits::lowest(); - // for (const auto& v : corners){ - // const auto trf = lightView * v; - // minX = std::min(minX, trf.x); - // maxX = std::max(maxX, trf.x); - // minY = std::min(minY, trf.y); - // maxY = std::max(maxY, trf.y); - // minZ = std::min(minZ, trf.z); - // maxZ = std::max(maxZ, trf.z); - // } - - // // Tune this parameter according to the scene - // constexpr float zMult = 1.0f; - // if (minZ < 0){ - // minZ *= zMult; - // } else { - // minZ /= zMult; - // } - // if (maxZ < 0){ - // maxZ /= zMult; - // } else - // { - // maxZ *= zMult; - // } - - // const glm::mat4 lightProjection = glm::ortho(minX, maxX, minY, maxY, minZ, maxZ); - // return lightProjection * lightView; - - static constexpr auto lightScale = 5.f; - - auto shadowWidth = config::SHADOW_RESOLUTION.w; - auto shadowHeight = config::SHADOW_RESOLUTION.h; - auto lightProjection = glm::perspective(glm::radians(45.0f), - (GLfloat)shadowWidth / (GLfloat)shadowHeight, - config::CAMERA_NEAR_PLANE, - config::CAMERA_FAR_PLANE); - - // TODO: make dependent on camera pos - lightProjection = glm::ortho(-30.0f, 30.0f, -30.0f, 30.0f, -30.0f, 30.f); - auto lightView = glm::lookAt(-dir.direction * lightScale, glm::vec3(0.0f), glm::vec3(0.0, 1.0, 0.0)); + inline glm::mat4x4 get_lightspace_matrix(DirectionalLight dir, Camera& camera, float nearPlane=0.1, float farPlane=25.0){ + auto pv = glm::perspective(glm::radians(camera.getFov()), + camera.getAspectRatio(), nearPlane, farPlane) * glm::lookAt(camera.getPos(), camera.getPos() + camera.getDir(), UP); + + const auto corners = getFrustumCornersWorldSpace(pv); + + glm::vec3 center = glm::vec3(0, 0, 0); + for (const auto& v : corners){ + center += glm::vec3(v); + } + center /= corners.size(); + + const auto lightView = glm::lookAt(center - dir.direction, center, UP); + + float minX = std::numeric_limits::max(); + float maxX = std::numeric_limits::lowest(); + float minY = std::numeric_limits::max(); + float maxY = std::numeric_limits::lowest(); + float minZ = std::numeric_limits::max(); + float maxZ = std::numeric_limits::lowest(); + for (const auto& v : corners){ + const auto trf = lightView * v; + minX = std::min(minX, trf.x); + maxX = std::max(maxX, trf.x); + minY = std::min(minY, trf.y); + maxY = std::max(maxY, trf.y); + minZ = std::min(minZ, trf.z); + maxZ = std::max(maxZ, trf.z); + } + + // Tune this parameter according to the scene + constexpr float zMult = 1.f; + if (minZ < 0){ + minZ *= zMult; + } else { + minZ /= zMult; + } + if (maxZ < 0){ + maxZ /= zMult; + } else { + maxZ *= zMult; + } + + const glm::mat4 lightProjection = glm::ortho(minX, maxX, minY, maxY, minZ, maxZ); return lightProjection * lightView; } - - - - - - } }