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. --- game/terrain.cpp | 8 ++++ game/terrain.h | 1 + game/vehicles/railVehicle.cpp | 6 +++ game/vehicles/railVehicle.h | 2 + game/vehicles/railVehicleClass.cpp | 7 +++ game/vehicles/railVehicleClass.h | 2 + game/vehicles/train.cpp | 5 ++ game/vehicles/train.h | 2 + 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 ++++++++++++++++++ gfx/renderable.cpp | 4 ++ gfx/renderable.h | 2 + ui/gameMainWindow.cpp | 5 ++ ui/gameMainWindow.h | 1 + 19 files changed, 220 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 diff --git a/game/terrain.cpp b/game/terrain.cpp index 31f7fb1..f798254 100644 --- a/game/terrain.cpp +++ b/game/terrain.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -93,3 +94,10 @@ Terrain::render(const SceneShader & shader) const water->bind(); meshes.apply(&Mesh::Draw); } + +void +Terrain::shadows(const ShadowMapper & shadowMapper) const +{ + shadowMapper.fixedPoint.use(); + meshes.apply(&Mesh::Draw); +} diff --git a/game/terrain.h b/game/terrain.h index 70f947c..879d173 100644 --- a/game/terrain.h +++ b/game/terrain.h @@ -16,6 +16,7 @@ public: explicit Terrain(std::shared_ptr); void render(const SceneShader & shader) const override; + void shadows(const ShadowMapper &) const override; void tick(TickDuration) override; float waveCycle {0.F}; diff --git a/game/vehicles/railVehicle.cpp b/game/vehicles/railVehicle.cpp index 0cf4e72..bcde68f 100644 --- a/game/vehicles/railVehicle.cpp +++ b/game/vehicles/railVehicle.cpp @@ -17,6 +17,12 @@ RailVehicle::render(const SceneShader & shader) const rvClass->render(shader, location, bogies); } +void +RailVehicle::shadows(const ShadowMapper & shadowMapper) const +{ + rvClass->shadows(shadowMapper, location); +} + void RailVehicle::move(const Train * t, float & trailBy) { diff --git a/game/vehicles/railVehicle.h b/game/vehicles/railVehicle.h index 39900cc..f172a28 100644 --- a/game/vehicles/railVehicle.h +++ b/game/vehicles/railVehicle.h @@ -10,6 +10,7 @@ #include class SceneShader; +class ShadowMapper; class Ray; class Train; @@ -20,6 +21,7 @@ public: void move(const Train *, float & trailBy); void render(const SceneShader & shader) const override; + void shadows(const ShadowMapper & shadowMapper) const override; [[nodiscard]] bool intersectRay(const Ray &, glm::vec2 *, float *) const override; Location location; diff --git a/game/vehicles/railVehicleClass.cpp b/game/vehicles/railVehicleClass.cpp index 5bcdc6e..dff1416 100644 --- a/game/vehicles/railVehicleClass.cpp +++ b/game/vehicles/railVehicleClass.cpp @@ -1,5 +1,6 @@ #include "railVehicleClass.h" #include "gfx/gl/sceneShader.h" +#include "gfx/gl/shadowMapper.h" #include "gfx/models/mesh.h" #include "gfx/models/obj.h" #include "gfx/models/texture.h" @@ -50,6 +51,12 @@ RailVehicleClass::render( bogies[b]->Draw(); } } +void +RailVehicleClass::shadows(const ShadowMapper & shadowMapper, const Location & location) const +{ + shadowMapper.dynamicPoint.use(location); + bodyMesh->Draw(); +} float RailVehicleClass::bogieOffset(ObjParser & o) diff --git a/game/vehicles/railVehicleClass.h b/game/vehicles/railVehicleClass.h index 7249e76..bd74ab9 100644 --- a/game/vehicles/railVehicleClass.h +++ b/game/vehicles/railVehicleClass.h @@ -6,6 +6,7 @@ #include class SceneShader; +class ShadowMapper; class Texture; class ObjParser; class Location; @@ -15,6 +16,7 @@ public: explicit RailVehicleClass(const std::string & name); void render(const SceneShader &, const Location &, const std::array &) const; + void shadows(const ShadowMapper &, const Location &) const; std::array bogies; Mesh::Ptr bodyMesh; diff --git a/game/vehicles/train.cpp b/game/vehicles/train.cpp index 8fb48f5..0332c04 100644 --- a/game/vehicles/train.cpp +++ b/game/vehicles/train.cpp @@ -16,6 +16,11 @@ Train::render(const SceneShader & shader) const { apply(&Renderable::render, shader); } +void +Train::shadows(const ShadowMapper & shadowMapper) const +{ + apply(&Renderable::shadows, shadowMapper); +} Location Train::getBogiePosition(float linkDist, float dist) const diff --git a/game/vehicles/train.h b/game/vehicles/train.h index dfdcf62..91f7ddb 100644 --- a/game/vehicles/train.h +++ b/game/vehicles/train.h @@ -14,6 +14,7 @@ #include class SceneShader; +class ShadowMapper; class Ray; class Train : public Vehicle, public Collection, public Can, public Can { @@ -27,6 +28,7 @@ public: } void render(const SceneShader & shader) const override; + void shadows(const ShadowMapper & shadowMapper) const override; [[nodiscard]] bool intersectRay(const Ray &, glm::vec2 *, float *) const override; 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; +}; diff --git a/gfx/renderable.cpp b/gfx/renderable.cpp index 9e8d122..539efb1 100644 --- a/gfx/renderable.cpp +++ b/gfx/renderable.cpp @@ -4,3 +4,7 @@ void Renderable::lights(const SceneShader &) const { } +void +Renderable::shadows(const ShadowMapper &) const +{ +} diff --git a/gfx/renderable.h b/gfx/renderable.h index f75c36f..5a9b1cd 100644 --- a/gfx/renderable.h +++ b/gfx/renderable.h @@ -3,6 +3,7 @@ #include class SceneShader; +class ShadowMapper; class Renderable { public: @@ -12,4 +13,5 @@ public: virtual void render(const SceneShader & shader) const = 0; virtual void lights(const SceneShader & shader) const; + virtual void shadows(const ShadowMapper & shadowMapper) const; }; diff --git a/ui/gameMainWindow.cpp b/ui/gameMainWindow.cpp index 7a47a25..0b30cad 100644 --- a/ui/gameMainWindow.cpp +++ b/ui/gameMainWindow.cpp @@ -65,3 +65,8 @@ GameMainWindow::lights(const SceneShader & shader) const { gameState->world.apply(&Renderable::lights, shader); } +void +GameMainWindow::shadows(const ShadowMapper & shadowMapper) const +{ + gameState->world.apply(&Renderable::shadows, shadowMapper); +} diff --git a/ui/gameMainWindow.h b/ui/gameMainWindow.h index f3fc21f..d5bcf41 100644 --- a/ui/gameMainWindow.h +++ b/ui/gameMainWindow.h @@ -17,4 +17,5 @@ private: void content(const SceneShader &) const override; void environment(const SceneShader &, const SceneRenderer &) const override; void lights(const SceneShader &) const override; + void shadows(const ShadowMapper &) const override; }; -- cgit v1.2.3