summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2022-12-03 03:41:32 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2022-12-03 03:41:32 +0000
commitaa75b018f3b97c72b57de68867417cbda51439c3 (patch)
tree446efaad2727ae6bff6433e8bfbf590e99d5e310
parentAdd GL_DEBUG_OUTPUT with boost test error handling to test-render context (diff)
downloadilt-aa75b018f3b97c72b57de68867417cbda51439c3.tar.bz2
ilt-aa75b018f3b97c72b57de68867417cbda51439c3.tar.xz
ilt-aa75b018f3b97c72b57de68867417cbda51439c3.zip
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.
-rw-r--r--game/terrain.cpp8
-rw-r--r--game/terrain.h1
-rw-r--r--game/vehicles/railVehicle.cpp6
-rw-r--r--game/vehicles/railVehicle.h2
-rw-r--r--game/vehicles/railVehicleClass.cpp7
-rw-r--r--game/vehicles/railVehicleClass.h2
-rw-r--r--game/vehicles/train.cpp5
-rw-r--r--game/vehicles/train.h2
-rw-r--r--gfx/gl/sceneProvider.cpp4
-rw-r--r--gfx/gl/sceneProvider.h2
-rw-r--r--gfx/gl/shaders/shadowCast.fs6
-rw-r--r--gfx/gl/shaders/shadowDynamicPoint.vs12
-rw-r--r--gfx/gl/shaders/shadowFixedPoint.vs13
-rw-r--r--gfx/gl/shadowMapper.cpp92
-rw-r--r--gfx/gl/shadowMapper.h46
-rw-r--r--gfx/renderable.cpp4
-rw-r--r--gfx/renderable.h2
-rw-r--r--ui/gameMainWindow.cpp5
-rw-r--r--ui/gameMainWindow.h1
19 files changed, 220 insertions, 0 deletions
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 <cstddef>
#include <filesystem>
#include <gfx/gl/sceneShader.h>
+#include <gfx/gl/shadowMapper.h>
#include <gfx/image.h>
#include <gfx/models/mesh.h>
#include <gfx/models/vertex.hpp>
@@ -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<GeoData>);
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
@@ -18,6 +18,12 @@ RailVehicle::render(const SceneShader & shader) const
}
void
+RailVehicle::shadows(const ShadowMapper & shadowMapper) const
+{
+ rvClass->shadows(shadowMapper, location);
+}
+
+void
RailVehicle::move(const Train * t, float & trailBy)
{
const auto overhang {(rvClass->length - rvClass->wheelBase) / 2};
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 <utility>
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 <string>
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<Location, 2> &) const;
+ void shadows(const ShadowMapper &, const Location &) const;
std::array<Mesh::Ptr, 2> 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 <vector>
class SceneShader;
+class ShadowMapper;
class Ray;
class Train : public Vehicle, public Collection<RailVehicle, false>, public Can<Go>, public Can<Idle> {
@@ -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 <glm/gtc/type_ptr.hpp>
+#include <glm/gtx/transform.hpp>
+#include <glm/matrix.hpp>
+
+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<float>::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 <glm/vec2.hpp>
+
+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 <special_members.hpp>
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>(&Renderable::lights, shader);
}
+void
+GameMainWindow::shadows(const ShadowMapper & shadowMapper) const
+{
+ gameState->world.apply<Renderable>(&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;
};