diff options
| -rw-r--r-- | application/resviewer.cpp | 17 | ||||
| -rw-r--r-- | game/environment.cpp | 8 | ||||
| -rw-r--r-- | game/environment.h | 1 | ||||
| -rw-r--r-- | gfx/gl/sceneRenderer.cpp | 6 | ||||
| -rw-r--r-- | gfx/gl/sceneRenderer.h | 1 | ||||
| -rw-r--r-- | gfx/gl/shadowMapper.cpp | 60 | ||||
| -rw-r--r-- | gfx/gl/shadowMapper.h | 7 | ||||
| -rw-r--r-- | gfx/renderable.cpp | 2 | ||||
| -rw-r--r-- | gfx/renderable.h | 2 | ||||
| -rw-r--r-- | test/test-assetFactory.cpp | 7 | ||||
| -rw-r--r-- | test/test-render.cpp | 8 | ||||
| -rw-r--r-- | ui/gameMainWindow.cpp | 5 |
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); |
