diff options
| author | Dan Goodliffe <dan@randomdan.homeip.net> | 2026-03-04 03:12:26 +0000 |
|---|---|---|
| committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2026-03-04 03:12:26 +0000 |
| commit | 5273a03417b0bb1b1f9f0baabee22466c8ea440c (patch) | |
| tree | ef13d3639f54bd62db95dccfa34c54e30e2f9f74 | |
| parent | Calculate an appropriate billboardSize and useMeshClipDist (diff) | |
| download | ilt-5273a03417b0bb1b1f9f0baabee22466c8ea440c.tar.bz2 ilt-5273a03417b0bb1b1f9f0baabee22466c8ea440c.tar.xz ilt-5273a03417b0bb1b1f9f0baabee22466c8ea440c.zip | |
Update stencils and billboards less often
No need to update these every frame when little of nothing has changed.
Instead, track the angle previously rendered and updated only when the
new angle has diverged sufficiently from this. Larger updates update
more frequently.
| -rw-r--r-- | game/scenary/foliage.cpp | 15 | ||||
| -rw-r--r-- | game/scenary/foliage.h | 2 | ||||
| -rw-r--r-- | gfx/gl/billboardPainter.cpp | 13 | ||||
| -rw-r--r-- | gfx/gl/billboardPainter.h | 4 | ||||
| -rw-r--r-- | gfx/gl/sceneRenderer.cpp | 2 | ||||
| -rw-r--r-- | gfx/gl/shadowStenciller.cpp | 9 | ||||
| -rw-r--r-- | gfx/gl/shadowStenciller.h | 2 |
7 files changed, 35 insertions, 12 deletions
diff --git a/game/scenary/foliage.cpp b/game/scenary/foliage.cpp index 680d902..0981ffc 100644 --- a/game/scenary/foliage.cpp +++ b/game/scenary/foliage.cpp @@ -9,8 +9,9 @@ static_assert(std::is_constructible_v<Foliage>); constexpr float OBJECT_BILLBOARD_DIVISOR = 64; +constexpr float BILLBOARD_ANGLE_TOLERANCE = 250.F; // Radians per mm size constexpr float ASSUMED_VIEWPORT = 1440; -constexpr float OVER_SAMPLE_MULTIPLIER = 4; // Use mesh until billboard 1/4 of rendered size +constexpr float OVER_SAMPLE_MULTIPLIER = 2; // Use mesh until billboard 1/2 of rendered size namespace { GLsizei @@ -51,18 +52,22 @@ Foliage::postLoad() } void -Foliage::updateStencil(const ShadowStenciller & ss) const +Foliage::updateStencil(const ShadowStenciller & shadowStenciller) const { - if (instancePartitions.second.second != instancePartitions.second.first) { - ss.renderStencil(shadowStencil, *bodyMesh, texture); + if (instancePartitions.second.second != instancePartitions.second.first + && glm::distance(shadowStenciller.getLightDirection(), shadowStencilDir) + > BILLBOARD_ANGLE_TOLERANCE / bodyMesh->getDimensions().size) { + shadowStenciller.renderStencil(shadowStencil, *bodyMesh, texture); } } void Foliage::updateBillboard(const BillboardPainter & bbp) const { - if (instancePartitions.first != instancePartitions.second.first) { + if (instancePartitions.first != instancePartitions.second.first + && std::abs(bbp.getAngle() - billboardAngle) > BILLBOARD_ANGLE_TOLERANCE / bodyMesh->getDimensions().size) { bbp.renderBillBoard(billboard, *bodyMesh, texture); + billboardAngle = bbp.getAngle(); } } diff --git a/game/scenary/foliage.h b/game/scenary/foliage.h index c457404..3d73573 100644 --- a/game/scenary/foliage.h +++ b/game/scenary/foliage.h @@ -37,7 +37,9 @@ protected: void postLoad() override; GLsizei billboardSize {}; RelativeDistance useMeshClipDist {}; + mutable Direction2D shadowStencilDir {std::numeric_limits<Direction2D::value_type>::infinity()}; glTexture shadowStencil; + mutable Angle billboardAngle = std::numeric_limits<Angle>::infinity(); glTextures<3> billboard; private: diff --git a/gfx/gl/billboardPainter.cpp b/gfx/gl/billboardPainter.cpp index 06e13ca..58fdce6 100644 --- a/gfx/gl/billboardPainter.cpp +++ b/gfx/gl/billboardPainter.cpp @@ -1,6 +1,4 @@ #include "billboardPainter.h" -#include "gfx/models/mesh.h" -#include "glArrays.h" #include "gl_traits.h" #include "gldebug.h" #include "maths.h" @@ -15,7 +13,7 @@ const auto VIEWS = []<GLint... Ep>(std::integer_sequence<GLint, Ep...>) { }(std::make_integer_sequence<GLint, BillboardPainter::VIEW_ANGLES<GLint>>()); BillboardPainter::BillboardPainter() : - program {billboardPainter_vert, billboardPainter_geom, billboardPainter_frag}, view {} + program {billboardPainter_vert, billboardPainter_geom, billboardPainter_frag}, angle {}, view {} { glDebugScope _ {fbo}; glBindFramebuffer(GL_FRAMEBUFFER, fbo); @@ -28,11 +26,18 @@ BillboardPainter::BillboardPainter() : } void -BillboardPainter::setView(const glm::mat4 & newView) +BillboardPainter::setView(const Angle newAngle, const glm::mat4 & newView) { + angle = newAngle; view = newView; } +Angle +BillboardPainter::getAngle() const +{ + return angle; +} + glTextures<3> BillboardPainter::createBillBoardTextures(GLsizei width, GLsizei height) { diff --git a/gfx/gl/billboardPainter.h b/gfx/gl/billboardPainter.h index 4ce7b10..33c807c 100644 --- a/gfx/gl/billboardPainter.h +++ b/gfx/gl/billboardPainter.h @@ -15,7 +15,8 @@ public: [[nodiscard]] static glTextures<3> createBillBoardTextures(GLsizei width, GLsizei height); - void setView(const glm::mat4 &); + void setView(Angle angle, const glm::mat4 &); + [[nodiscard]] Angle getAngle() const; void renderBillBoard(const glTextures<3> &, const MeshBase &, Texture::AnyPtr texture) const; private: @@ -24,5 +25,6 @@ private: Program::RequiredUniformLocation viewProjectionLoc {program, "viewProjection"}; Program::RequiredUniformLocation viewLoc {program, "view"}; + Angle angle; glm::mat4 view; }; diff --git a/gfx/gl/sceneRenderer.cpp b/gfx/gl/sceneRenderer.cpp index efa08ef..15dde1b 100644 --- a/gfx/gl/sceneRenderer.cpp +++ b/gfx/gl/sceneRenderer.cpp @@ -83,7 +83,7 @@ SceneRenderer::preFrame(const SceneProvider & scene, const LightDirection lightD { glDebugScope _ {output}; const auto lightView = shadowMapper.preFrame(lightDirection, camera); - billboardPainter.setView(camera.getView()); + billboardPainter.setView(std::asin(camera.getForward().z), camera.getView()); scene.forEachRenderable([&lightView, this](Renderable * renderable) { renderable->preFrame(camera, lightView); renderable->updateBillboard(billboardPainter); diff --git a/gfx/gl/shadowStenciller.cpp b/gfx/gl/shadowStenciller.cpp index 7a0fc9b..19c8bef 100644 --- a/gfx/gl/shadowStenciller.cpp +++ b/gfx/gl/shadowStenciller.cpp @@ -10,7 +10,7 @@ #include <stdexcept> ShadowStenciller::ShadowStenciller() : - shadowCaster {shadowStencil_vert, shadowStencil_geom, shadowStencil_frag}, viewProjections {} + shadowCaster {shadowStencil_vert, shadowStencil_geom, shadowStencil_frag}, lightDir {}, viewProjections {} { glDebugScope _ {fbo}; glBindFramebuffer(GL_FRAMEBUFFER, fbo); @@ -22,6 +22,7 @@ ShadowStenciller::ShadowStenciller() : void ShadowStenciller::setLightDirection(const LightDirection & lightDir) { + this->lightDir = lightDir.position(); viewProjections = [&lightDir]<GLint... Ep>(std::integer_sequence<GLint, Ep...>) { constexpr float STEP = two_pi / STENCIL_ANGLES<decltype(two_pi)>; return std::array {rotate_pitch<4>(half_pi - lightDir.position().y) @@ -29,6 +30,12 @@ ShadowStenciller::setLightDirection(const LightDirection & lightDir) }(std::make_integer_sequence<GLint, STENCIL_ANGLES<GLint>>()); } +Direction2D +ShadowStenciller::getLightDirection() const +{ + return lightDir; +} + glTexture ShadowStenciller::createStencilTexture(GLsizei width, GLsizei height) { diff --git a/gfx/gl/shadowStenciller.h b/gfx/gl/shadowStenciller.h index f774ac7..27ad9f9 100644 --- a/gfx/gl/shadowStenciller.h +++ b/gfx/gl/shadowStenciller.h @@ -16,6 +16,7 @@ public: [[nodiscard]] static glTexture createStencilTexture(GLsizei width, GLsizei height); void setLightDirection(const LightDirection & lightDir); + [[nodiscard]] Direction2D getLightDirection() const; void renderStencil(const glTexture &, const MeshBase &, Texture::AnyPtr texture) const; private: @@ -23,5 +24,6 @@ private: Program shadowCaster; Program::RequiredUniformLocation viewProjectionLoc {shadowCaster, "viewProjection"}; + Direction2D lightDir; std::array<glm::mat4, STENCIL_ANGLES<size_t>> viewProjections; }; |
