summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--application/resviewer.cpp17
-rw-r--r--game/environment.cpp8
-rw-r--r--game/environment.h1
-rw-r--r--gfx/gl/sceneRenderer.cpp6
-rw-r--r--gfx/gl/sceneRenderer.h1
-rw-r--r--gfx/gl/shadowMapper.cpp60
-rw-r--r--gfx/gl/shadowMapper.h7
-rw-r--r--gfx/renderable.cpp2
-rw-r--r--gfx/renderable.h2
-rw-r--r--test/test-assetFactory.cpp7
-rw-r--r--test/test-render.cpp8
-rw-r--r--ui/gameMainWindow.cpp5
12 files changed, 88 insertions, 36 deletions
diff --git a/application/resviewer.cpp b/application/resviewer.cpp
index e0c36f6..0e34c05 100644
--- a/application/resviewer.cpp
+++ b/application/resviewer.cpp
@@ -44,8 +44,9 @@ private:
void
render() override
{
+ const auto & [camFrust, lightFrust] = preFrame(gameState->environment->getSunPos());
SceneRenderer::render(*this);
- controls();
+ controls(camFrust, lightFrust);
}
void
@@ -89,12 +90,12 @@ private:
}
void
- controls()
+ controls(const Frustum & camFrust, const Frustum & lightFrust)
{
if (ImGui::Begin("Resource view")) {
ImGui::SetWindowSize({});
fileSelection();
- assetSelection();
+ assetSelection(camFrust, lightFrust);
}
ImGui::End();
@@ -130,7 +131,7 @@ private:
}
void
- assetSelection()
+ assetSelection(const Frustum & camFrust, const Frustum & lightFrust)
{
if (!gameState->assets.empty()) {
ImGui::BeginListBox("Asset");
@@ -141,7 +142,7 @@ private:
selectedAssetId = asset.first;
selectedAsset = renderable;
location = asset.second->createAt(position);
- renderable->preFrame(camera);
+ renderable->preFrame(camFrust, lightFrust);
}
}
}
@@ -175,6 +176,12 @@ private:
}
}
+ void
+ environment(const SceneShader &, const SceneRenderer & renderer) const override
+ {
+ gameState->environment->render(renderer, *this);
+ }
+
std::span<const std::filesystem::path> fileList;
std::filesystem::file_time_type fileTime;
const std::filesystem::path * selectedFile {};
diff --git a/game/environment.cpp b/game/environment.cpp
index acb4f21..1ef6e22 100644
--- a/game/environment.cpp
+++ b/game/environment.cpp
@@ -11,13 +11,19 @@ Environment::tick(TickDuration)
worldTime += 50;
}
+Direction2D
+Environment::getSunPos() const
+{
+ return getSunPos({}, worldTime);
+}
+
void
Environment::render(const SceneRenderer & renderer, const SceneProvider & scene) const
{
constexpr RGB baseAmbient {0.1F}, baseDirectional {0.0F};
constexpr RGB relativeAmbient {0.3F, 0.3F, 0.4F}, relativeDirectional {0.6F, 0.6F, 0.5F};
- const LightDirection sunPos = getSunPos({}, worldTime);
+ const LightDirection sunPos = getSunPos();
const auto ambient = baseAmbient + relativeAmbient * sunPos.ambient();
const auto directional = baseDirectional + relativeDirectional * sunPos.directional();
diff --git a/game/environment.h b/game/environment.h
index a6f3036..6a2e1ad 100644
--- a/game/environment.h
+++ b/game/environment.h
@@ -11,6 +11,7 @@ public:
Environment();
void tick(TickDuration elapsed) override;
void render(const SceneRenderer &, const SceneProvider &) const;
+ Direction2D getSunPos() const;
static Direction2D getSunPos(const Direction2D position, const time_t time);
private:
diff --git a/gfx/gl/sceneRenderer.cpp b/gfx/gl/sceneRenderer.cpp
index 5e8241f..d005dfa 100644
--- a/gfx/gl/sceneRenderer.cpp
+++ b/gfx/gl/sceneRenderer.cpp
@@ -77,6 +77,12 @@ SceneRenderer::resize(ScreenAbsCoord newSize)
shader.setViewPort({0, 0, size.x, size.y});
}
+std::pair<const Frustum &, const Frustum &>
+SceneRenderer::preFrame(const LightDirection & lightDirection)
+{
+ return {camera, shadowMapper.preFrame(lightDirection, camera)};
+}
+
void
SceneRenderer::render(const SceneProvider & scene) const
{
diff --git a/gfx/gl/sceneRenderer.h b/gfx/gl/sceneRenderer.h
index 05921a1..2ec8057 100644
--- a/gfx/gl/sceneRenderer.h
+++ b/gfx/gl/sceneRenderer.h
@@ -18,6 +18,7 @@ public:
void resize(ScreenAbsCoord size);
void render(const SceneProvider &) const;
+ std::pair<const Frustum &, const Frustum &> preFrame(const LightDirection &);
void setAmbientLight(const RGB & colour) const;
void setDirectionalLight(const RGB & colour, const LightDirection & direction, const SceneProvider &) const;
diff --git a/gfx/gl/shadowMapper.cpp b/gfx/gl/shadowMapper.cpp
index 7035162..a73caa0 100644
--- a/gfx/gl/shadowMapper.cpp
+++ b/gfx/gl/shadowMapper.cpp
@@ -31,7 +31,7 @@ ShadowMapper::ShadowMapper(const TextureAbsCoord & s) :
landmess {shadowLandmass_vert}, dynamicPointInst {shadowDynamicPointInst_vert},
dynamicPointInstWithTextures {shadowDynamicPointInstWithTextures_vert, shadowDynamicPointInstWithTextures_geom,
shadowDynamicPointInstWithTextures_frag},
- size {s}
+ size {s}, frustum {{}, {}, {}}
{
glDebugScope _ {depthMap};
glBindTexture(GL_TEXTURE_2D_ARRAY, depthMap);
@@ -82,6 +82,37 @@ ShadowMapper::getBandViewExtents(const Camera & camera, const glm::mat4 & lightV
return bandViewExtents;
}
+const Frustum &
+ShadowMapper::preFrame(const LightDirection & dir, const Camera & camera)
+{
+ const auto lightViewDir = glm::lookAt({}, dir.vector(), up);
+ const auto lightViewPoint = camera.getPosition();
+ const auto bandViewExtents = getBandViewExtents(camera, lightViewDir);
+ using ExtentsBoundingBox = AxisAlignedBoundingBox<RelativeDistance>;
+ definitions.clear();
+ sizes.clear();
+ std::ranges::transform(bandViewExtents | std::views::pairwise, std::back_inserter(definitions),
+ [&lightViewDir, this](const auto & band) mutable {
+ const auto & [near, far] = band;
+ auto extents = ExtentsBoundingBox::fromPoints(std::span {near.begin(), far.end()});
+ extents.min.z -= 10'000.F;
+ extents.max.z += 10'000.F;
+ const auto lightProjection = glm::ortho(
+ extents.min.x, extents.max.x, extents.min.y, extents.max.y, -extents.max.z, -extents.min.z);
+ sizes.emplace_back(extents.max - extents.min);
+ return lightProjection * lightViewDir;
+ });
+
+ ExtentsBoundingBox extents {lightViewPoint, lightViewPoint};
+ for (const auto & point : bandViewExtents.back()) {
+ extents += point;
+ }
+ const auto lightProjection
+ = glm::ortho(extents.min.x, extents.max.x, extents.min.y, extents.max.y, -extents.max.z, -extents.min.z);
+ frustum = {lightViewPoint, lightViewDir, lightProjection};
+ return frustum;
+}
+
ShadowMapper::Definitions
ShadowMapper::update(const SceneProvider & scene, const LightDirection & dir, const Camera & camera) const
{
@@ -100,39 +131,16 @@ ShadowMapper::update(const SceneProvider & scene, const LightDirection & dir, co
glClear(GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, size.x, size.y);
- const auto lightViewDir = glm::lookAt({}, dir.vector(), up);
const auto lightViewPoint = camera.getPosition();
- const auto bandViewExtents = getBandViewExtents(camera, lightViewDir);
- Definitions out;
- Sizes sizes;
- using ExtentsBoundingBox = AxisAlignedBoundingBox<RelativeDistance>;
- std::ranges::transform(bandViewExtents | std::views::pairwise, std::back_inserter(out),
- [&lightViewDir, &sizes](const auto & band) mutable {
- const auto & [near, far] = band;
- auto extents = ExtentsBoundingBox::fromPoints(std::span {near.begin(), far.end()});
- extents.min.z -= 10'000.F;
- extents.max.z += 10'000.F;
- const auto lightProjection = glm::ortho(
- extents.min.x, extents.max.x, extents.min.y, extents.max.y, -extents.max.z, -extents.min.z);
- sizes.emplace_back(extents.max - extents.min);
- return lightProjection * lightViewDir;
- });
for (const auto p : std::initializer_list<const ShadowProgram *> {
&landmess, &dynamicPoint, &dynamicPointInst, &dynamicPointInstWithTextures, &stencilShadowProgram}) {
- p->setView(out, sizes, lightViewPoint);
- }
- ExtentsBoundingBox extents {lightViewPoint, lightViewPoint};
- for (const auto & point : bandViewExtents.back()) {
- extents += point;
+ p->setView(definitions, sizes, lightViewPoint);
}
- const auto lightProjection
- = glm::ortho(extents.min.x, extents.max.x, extents.min.y, extents.max.y, -extents.max.z, -extents.min.z);
- Frustum frustum {lightViewPoint, lightViewDir, lightProjection};
scene.shadows(*this, frustum);
glCullFace(GL_BACK);
- return out;
+ return definitions;
}
ShadowMapper::ShadowProgram::ShadowProgram(const Shader & vs) : Program {vs, commonShadowPoint_geom} { }
diff --git a/gfx/gl/shadowMapper.h b/gfx/gl/shadowMapper.h
index 951e29c..82374cb 100644
--- a/gfx/gl/shadowMapper.h
+++ b/gfx/gl/shadowMapper.h
@@ -1,6 +1,7 @@
#pragma once
#include "config/types.h"
+#include "gfx/frustum.h"
#include "gfx/gl/shadowStenciller.h"
#include "lib/glArrays.h"
#include "program.h"
@@ -22,6 +23,7 @@ public:
using Definitions = std::vector<glm::mat4x4>;
using Sizes = std::vector<RelativePosition3D>;
+ const Frustum & preFrame(const LightDirection & direction, const Camera &);
[[nodiscard]] Definitions update(const SceneProvider &, const LightDirection & direction, const Camera &) const;
class ShadowProgram : public Program {
@@ -77,5 +79,10 @@ private:
glFrameBuffer depthMapFBO;
glTexture depthMap;
TextureAbsCoord size;
+
+ Definitions definitions;
+ Sizes sizes;
+ Frustum frustum;
+
mutable ShadowStenciller shadowStenciller;
};
diff --git a/gfx/renderable.cpp b/gfx/renderable.cpp
index 7df5851..9fbc85b 100644
--- a/gfx/renderable.cpp
+++ b/gfx/renderable.cpp
@@ -1,7 +1,7 @@
#include "renderable.h"
void
-Renderable::preFrame(const Frustum &)
+Renderable::preFrame(const Frustum &, const Frustum &)
{
}
diff --git a/gfx/renderable.h b/gfx/renderable.h
index d7f593a..ea72bb6 100644
--- a/gfx/renderable.h
+++ b/gfx/renderable.h
@@ -13,7 +13,7 @@ public:
virtual ~Renderable() = default;
DEFAULT_MOVE_COPY(Renderable);
- virtual void preFrame(const Frustum &);
+ virtual void preFrame(const Frustum &, const Frustum &);
virtual void render(const SceneShader & shader, const Frustum &) const = 0;
virtual void lights(const SceneShader & shader) const;
virtual void shadows(const ShadowMapper & shadowMapper, const Frustum &) const;
diff --git a/test/test-assetFactory.cpp b/test/test-assetFactory.cpp
index ac7e04c..ff38369 100644
--- a/test/test-assetFactory.cpp
+++ b/test/test-assetFactory.cpp
@@ -72,6 +72,13 @@ namespace {
render(float dist)
{
sceneRenderer.camera.setView({-dist, dist * 1.2F, dist * 1.2F}, south + east + down);
+ const auto & [camFrust, lightFrust] = sceneRenderer.preFrame({{0.9, 0.5}});
+ for (const auto & [assetId, asset] : gameState.assets) {
+ if (const auto renderable = asset.getAs<Renderable>()) {
+ renderable->preFrame(camFrust, lightFrust);
+ }
+ }
+ gameState.world.apply<Renderable>(&Renderable::preFrame, camFrust, lightFrust);
sceneRenderer.render(*this);
}
diff --git a/test/test-render.cpp b/test/test-render.cpp
index 073239f..ac71276 100644
--- a/test/test-render.cpp
+++ b/test/test-render.cpp
@@ -162,6 +162,13 @@ BOOST_AUTO_TEST_CASE(Basic)
TestSceneRenderer renderer {size, output};
renderer.camera.setView({-10000, -10000, 60000}, glm::normalize(glm::vec3 {1, 1, -0.5F}));
const TestScene scene;
+ const auto & [camFrust, lightFrust] = renderer.preFrame(gameState.environment->getSunPos());
+ for (const auto & [assetId, asset] : gameState.assets) {
+ if (const auto renderable = asset.getAs<Renderable>()) {
+ renderable->preFrame(camFrust, lightFrust);
+ }
+ }
+ gameState.world.apply<Renderable>(&Renderable::preFrame, camFrust, lightFrust);
renderer.render(scene);
renderer.saveBuffers(ANALYSIS_DIRECTORY / "basic");
Texture::save(outImage, (ANALYSIS_DIRECTORY / "basic/final.tga").c_str());
@@ -203,6 +210,7 @@ BOOST_AUTO_TEST_CASE(TerrainSD19)
}
};
+ renderer.preFrame(gameState.environment->getSunPos());
renderer.render(TestTerrain {});
Texture::save(outImage, (ANALYSIS_DIRECTORY / "terrain.tga").c_str());
}
diff --git a/ui/gameMainWindow.cpp b/ui/gameMainWindow.cpp
index eec5512..9f224a2 100644
--- a/ui/gameMainWindow.cpp
+++ b/ui/gameMainWindow.cpp
@@ -85,12 +85,13 @@ GameMainWindow::handleInput(const SDL_Event & event)
void
GameMainWindow::render()
{
+ const auto & [camFrust, lightFrust] = SceneRenderer::preFrame(gameState->environment->getSunPos());
for (const auto & [assetId, asset] : gameState->assets) {
if (const auto renderable = asset.getAs<Renderable>()) {
- renderable->preFrame(camera);
+ renderable->preFrame(camFrust, lightFrust);
}
}
- gameState->world.apply<const Renderable>(&Renderable::preFrame, camera);
+ gameState->world.apply<const Renderable>(&Renderable::preFrame, camFrust, lightFrust);
SceneRenderer::render(*this);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);