From aa75b018f3b97c72b57de68867417cbda51439c3 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 3 Dec 2022 03:41:32 +0000 Subject: Initial commit of the shadow map generator and shadows render interface Lots of hard coding, buggy in places, far from great, but the basics work. --- gfx/gl/sceneProvider.cpp | 4 ++ gfx/gl/sceneProvider.h | 2 + gfx/gl/shaders/shadowCast.fs | 6 +++ gfx/gl/shaders/shadowDynamicPoint.vs | 12 +++++ gfx/gl/shaders/shadowFixedPoint.vs | 13 +++++ gfx/gl/shadowMapper.cpp | 92 ++++++++++++++++++++++++++++++++++++ gfx/gl/shadowMapper.h | 46 ++++++++++++++++++ 7 files changed, 175 insertions(+) create mode 100644 gfx/gl/shaders/shadowCast.fs create mode 100644 gfx/gl/shaders/shadowDynamicPoint.vs create mode 100644 gfx/gl/shaders/shadowFixedPoint.vs create mode 100644 gfx/gl/shadowMapper.cpp create mode 100644 gfx/gl/shadowMapper.h (limited to 'gfx/gl') diff --git a/gfx/gl/sceneProvider.cpp b/gfx/gl/sceneProvider.cpp index d73ac3c..9152bfa 100644 --- a/gfx/gl/sceneProvider.cpp +++ b/gfx/gl/sceneProvider.cpp @@ -7,3 +7,7 @@ SceneProvider::environment(const SceneShader &, const SceneRenderer & renderer) renderer.setAmbientLight({0.5F, 0.5F, 0.5F}); renderer.setDirectionalLight({0.6F, 0.6F, 0.6F}, {1, 0, -1}); } +void +SceneProvider::shadows(const ShadowMapper &) const +{ +} diff --git a/gfx/gl/sceneProvider.h b/gfx/gl/sceneProvider.h index a966f9c..ef269b3 100644 --- a/gfx/gl/sceneProvider.h +++ b/gfx/gl/sceneProvider.h @@ -1,6 +1,7 @@ #pragma once class SceneRenderer; +class ShadowMapper; class SceneShader; class SceneProvider { @@ -9,4 +10,5 @@ public: virtual void content(const SceneShader &) const = 0; virtual void environment(const SceneShader &, const SceneRenderer &) const; virtual void lights(const SceneShader &) const = 0; + virtual void shadows(const ShadowMapper &) const; }; diff --git a/gfx/gl/shaders/shadowCast.fs b/gfx/gl/shaders/shadowCast.fs new file mode 100644 index 0000000..d427da2 --- /dev/null +++ b/gfx/gl/shaders/shadowCast.fs @@ -0,0 +1,6 @@ +#version 330 core + +void +main() +{ +} diff --git a/gfx/gl/shaders/shadowDynamicPoint.vs b/gfx/gl/shaders/shadowDynamicPoint.vs new file mode 100644 index 0000000..91d8bf7 --- /dev/null +++ b/gfx/gl/shaders/shadowDynamicPoint.vs @@ -0,0 +1,12 @@ +#version 330 core + +in vec3 position; + +uniform mat4 viewProjection; +uniform mat4 model; + +void +main() +{ + gl_Position = viewProjection * model * vec4(position, 1.0); +} diff --git a/gfx/gl/shaders/shadowFixedPoint.vs b/gfx/gl/shaders/shadowFixedPoint.vs new file mode 100644 index 0000000..9e1cc62 --- /dev/null +++ b/gfx/gl/shaders/shadowFixedPoint.vs @@ -0,0 +1,13 @@ +#version 330 core + +layout(location = 0) in vec3 position; +layout(location = 1) in vec3 normal; +layout(location = 2) in vec2 tex; + +uniform mat4 viewProjection; + +void +main() +{ + gl_Position = viewProjection * vec4(position, 1.0); +} diff --git a/gfx/gl/shadowMapper.cpp b/gfx/gl/shadowMapper.cpp new file mode 100644 index 0000000..4cc2e24 --- /dev/null +++ b/gfx/gl/shadowMapper.cpp @@ -0,0 +1,92 @@ +#include "shadowMapper.h" +#include "gfx/gl/shaders/fs-shadowCast.h" +#include "gfx/gl/shaders/vs-shadowDynamicPoint.h" +#include "gfx/gl/shaders/vs-shadowFixedPoint.h" +#include "gfx/models/texture.h" +#include "location.hpp" +#include "maths.h" +#include "sceneProvider.h" +#include "sceneShader.h" +#include +#include +#include + +ShadowMapper::ShadowMapper(const glm::ivec2 & s) : 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, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + static constexpr glm::vec3 border {std::numeric_limits::infinity()}; + // static constexpr glm::vec3 border {1}; + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, glm::value_ptr(border)); + + glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 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); +} + +glm::mat4x4 +ShadowMapper::update(const SceneProvider & scene, const glm::vec3 & dir) const +{ + const glm::vec3 centre {1200.F, 1200.F, 0.F}; + const glm::vec3 range = glm::normalize(dir) * 1800.F; + const auto lightProjection = glm::ortho(-1200.F, 1200.F, -1200.F, 1200.F, 0.F, 3600.F); + const auto lightView = glm::lookAt(centre - range, centre, north); + const auto lightViewProjection = lightProjection * lightView; + fixedPoint.setViewProjection(lightViewProjection); + dynamicPoint.setViewProjection(lightViewProjection); + + glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); + glViewport(0, 0, size.x, size.y); + glClear(GL_DEPTH_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); + glCullFace(GL_FRONT); + scene.shadows(*this); + glCullFace(GL_BACK); + + // Texture::saveDepth(depthMap, size, "/tmp/depth.tga"); + return lightViewProjection; +} + +ShadowMapper::FixedPoint::FixedPoint() : + Program {shadowFixedPoint_vs, shadowCast_fs}, viewProjectionLoc {*this, "viewProjection"} +{ +} +void +ShadowMapper::FixedPoint::setViewProjection(const glm::mat4 & viewProjection) const +{ + use(); + glUniformMatrix4fv(viewProjectionLoc, 1, GL_FALSE, glm::value_ptr(viewProjection)); +} +void +ShadowMapper::FixedPoint::use() const +{ + glUseProgram(*this); +} + +ShadowMapper::DynamicPoint::DynamicPoint() : + Program {shadowDynamicPoint_vs, shadowCast_fs}, viewProjectionLoc {*this, "viewProjection"}, modelLoc { + *this, "model"} +{ +} +void +ShadowMapper::DynamicPoint::setViewProjection(const glm::mat4 & viewProjection) const +{ + glUseProgram(*this); + glUniformMatrix4fv(viewProjectionLoc, 1, GL_FALSE, glm::value_ptr(viewProjection)); +} +void +ShadowMapper::DynamicPoint::use(const Location & location) const +{ + glUseProgram(*this); + const auto model = glm::translate(location.pos) * rotate_ypr(location.rot); + glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); +} diff --git a/gfx/gl/shadowMapper.h b/gfx/gl/shadowMapper.h new file mode 100644 index 0000000..dcd0a02 --- /dev/null +++ b/gfx/gl/shadowMapper.h @@ -0,0 +1,46 @@ +#pragma once + +#include "lib/glArrays.h" +#include "program.h" +#include + +class SceneProvider; + +class ShadowMapper { +public: + ShadowMapper(const glm::ivec2 & size = {1024, 1024}); + + glm::mat4x4 update(const SceneProvider &, const glm::vec3 & direction) const; + + class FixedPoint : public Program { + public: + FixedPoint(); + void setViewProjection(const glm::mat4 &) const; + void use() const; + + private: + RequiredUniformLocation viewProjectionLoc; + }; + class DynamicPoint : public Program { + public: + DynamicPoint(); + void setViewProjection(const glm::mat4 &) const; + void use(const Location &) const; + + private: + RequiredUniformLocation viewProjectionLoc; + RequiredUniformLocation modelLoc; + }; + FixedPoint fixedPoint; + DynamicPoint dynamicPoint; + + operator GLuint() const + { + return depthMap; + } + +private: + glFrameBuffer depthMapFBO; + glTexture depthMap; + glm::ivec2 size; +}; -- cgit v1.2.3