From 30fcb8bce7b60b6754a0d35f2f15b627d0fba4cb Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 1 Apr 2026 20:21:23 +0100 Subject: Have Renderable manage all instance lights Spot and point lights now existing in Renderable, the vertex data contains the owning parent object's index in CommonLocationData, the render step is just a single draw call. --- application/main.cpp | 4 ++++ game/scenary/illuminator.cpp | 55 +------------------------------------------- game/scenary/illuminator.h | 16 +++++-------- game/scenary/light.cpp | 9 ++++++++ game/scenary/light.h | 3 +++ gfx/gl/lights.h | 16 ------------- gfx/models/lights.cpp | 11 +++++++++ gfx/models/lights.h | 29 +++++++++++++++++++++++ gfx/renderable.cpp | 42 ++++++++++++++++++++++++++++++++- gfx/renderable.h | 15 +++++++++--- test/test-assetFactory.cpp | 2 +- test/test-render.cpp | 8 ++++++- ui/gameMainWindow.cpp | 4 ++-- 13 files changed, 126 insertions(+), 88 deletions(-) delete mode 100644 gfx/gl/lights.h create mode 100644 gfx/models/lights.cpp create mode 100644 gfx/models/lights.h diff --git a/application/main.cpp b/application/main.cpp index f5acb3b..d64d799 100644 --- a/application/main.cpp +++ b/application/main.cpp @@ -1,3 +1,4 @@ +#include "game/scenary/light.h" #include "ui/mainApplication.h" #include "ui/mainWindow.h" #include @@ -108,6 +109,9 @@ public: {0, rotationDistribution(randomdev), 0}}); } } + + world.create(assets.at("old-lamp").dynamicCast(), + Location {.pos = terrain->positionAt({{311000000, 491100000}})}); } mainLoop(); diff --git a/game/scenary/illuminator.cpp b/game/scenary/illuminator.cpp index 3b73cd3..55791a5 100644 --- a/game/scenary/illuminator.cpp +++ b/game/scenary/illuminator.cpp @@ -6,8 +6,7 @@ static_assert(std::is_constructible_v); -std::weak_ptr Illuminator::commonInstanceVAO, Illuminator::commonInstancesSpotLightVAO, - Illuminator::commonInstancesPointLightVAO; +std::weak_ptr Illuminator::commonInstanceVAO; std::any Illuminator::createAt(const Location & position) const @@ -48,32 +47,6 @@ Illuminator::postLoad() if (createIfRequired(instanceVAO, commonInstanceVAO)) { bodyMesh->configureVAO(*instanceVAO, 0).addAttribs(1); } - if (!spotLight.empty()) { - if (!(instancesSpotLightVAO = commonInstancesSpotLightVAO.lock())) { - commonInstancesSpotLightVAO = instancesSpotLightVAO = std::make_shared(); - instancesSpotLightVAO->configure() - .addAttribs(0) - .addAttribs(1); - } - std::transform( - spotLight.begin(), spotLight.end(), std::back_inserter(spotLightInstances), [this](const auto & s) { - return instancesSpotLight.acquire(*s); - }); - } - if (!pointLight.empty()) { - if (!(instancesPointLightVAO = commonInstancesPointLightVAO.lock())) { - commonInstancesPointLightVAO = instancesPointLightVAO = std::make_shared(); - instancesPointLightVAO->configure() - .addAttribs(0) - .addAttribs(1); - } - std::transform( - pointLight.begin(), pointLight.end(), std::back_inserter(pointLightInstances), [this](const auto & s) { - return instancesPointLight.acquire(*s); - }); - } } void @@ -89,29 +62,3 @@ Illuminator::render(const SceneShader & shader, const Frustum &) const bodyMesh->drawInstanced(*instanceVAO, static_cast(count)); } } - -void -Illuminator::lights(const SceneShader & shader) const -{ - if (const auto count = instances.size()) { - glDebugScope _ {*instanceVAO}; - if (const auto scount = instancesSpotLight.size()) { - glDebugScope _ {*instancesSpotLightVAO, "Spot lights"}; - shader.spotLightInst.use(); - glBindVertexArray(*instancesSpotLightVAO); - instancesSpotLightVAO->useBuffer(0, instancesSpotLight); - instancesSpotLightVAO->useBuffer(1, instances); - glDrawArraysInstanced(GL_POINTS, 0, static_cast(scount), static_cast(count)); - } - if (const auto pcount = instancesPointLight.size()) { - glDebugScope _ {*instancesPointLightVAO, "Point llights"}; - shader.pointLightInst.use(); - glBindVertexArray(*instancesPointLightVAO); - instancesPointLightVAO->useBuffer(0, instancesPointLight); - instancesPointLightVAO->useBuffer(1, instances); - glDrawArraysInstanced(GL_POINTS, 0, static_cast(pcount), static_cast(count)); - } - - glBindVertexArray(0); - } -} diff --git a/game/scenary/illuminator.h b/game/scenary/illuminator.h index c342bd4..b99a19e 100644 --- a/game/scenary/illuminator.h +++ b/game/scenary/illuminator.h @@ -2,7 +2,7 @@ #include "assetFactory/asset.h" #include "gfx/gl/instanceVertices.h" -#include "gfx/gl/lights.h" +#include "gfx/models/lights.h" #include "gfx/models/texture.h" #include "gfx/renderable.h" @@ -12,19 +12,19 @@ class Location; class Illuminator : public Asset, public Renderable, public StdTypeDefs { Mesh::Ptr bodyMesh; Texture::Ptr texture; - std::shared_ptr instanceVAO, instancesSpotLightVAO, instancesPointLightVAO; - static std::weak_ptr commonInstanceVAO, commonInstancesSpotLightVAO, commonInstancesPointLightVAO; + std::shared_ptr instanceVAO; + static std::weak_ptr commonInstanceVAO; public: [[nodiscard]] std::any createAt(const Location &) const override; - struct SpotLight : Persistence::Persistable, SpotLightVertex, StdTypeDefs { + struct SpotLight : Persistence::Persistable, SpotLightDef, StdTypeDefs { private: friend Persistence::SelectionPtrBase>; bool persist(Persistence::PersistenceStore & store) override; }; - struct PointLight : Persistence::Persistable, PointLightVertex, StdTypeDefs { + struct PointLight : Persistence::Persistable, PointLightDef, StdTypeDefs { private: friend Persistence::SelectionPtrBase>; bool persist(Persistence::PersistenceStore & store) override; @@ -35,18 +35,14 @@ public: }; mutable InstanceVertices instances; - mutable InstanceVertices instancesSpotLight; - mutable InstanceVertices instancesPointLight; void render(const SceneShader &, const Frustum &) const override; - void lights(const SceneShader &) const override; protected: friend Persistence::SelectionPtrBase>; bool persist(Persistence::PersistenceStore & store) override; void postLoad() override; +public: std::vector spotLight; std::vector pointLight; - std::vector::InstanceProxy> spotLightInstances; - std::vector::InstanceProxy> pointLightInstances; }; diff --git a/game/scenary/light.cpp b/game/scenary/light.cpp index 7c38ca2..bd83f04 100644 --- a/game/scenary/light.cpp +++ b/game/scenary/light.cpp @@ -5,4 +5,13 @@ Light::Light(std::shared_ptr type, const Location & position) type {std::move(type)}, instance {this->type->instances.acquire(Renderable::commonLocationData.lock()->acquire(position))} { + std::ranges::transform(this->type->spotLight, std::back_inserter(spotLightInstances), + [spotLights = Renderable::commonSpotLights.lock(), this](const Illuminator::SpotLight::CPtr & spotLight) { + return spotLights->acquire(*spotLight, instance->location.index); + }); + std::ranges::transform(this->type->pointLight, std::back_inserter(pointLightInstances), + [pointLights = Renderable::commonPointLights.lock(), this]( + const Illuminator::PointLight::CPtr & pointLight) { + return pointLights->acquire(*pointLight, instance->location.index); + }); } diff --git a/game/scenary/light.h b/game/scenary/light.h index afb7e03..b1ea469 100644 --- a/game/scenary/light.h +++ b/game/scenary/light.h @@ -14,6 +14,9 @@ class Light : public WorldObject { { } + std::vector::InstanceProxy> spotLightInstances; + std::vector::InstanceProxy> pointLightInstances; + public: Light(std::shared_ptr type, const Location & position); }; diff --git a/gfx/gl/lights.h b/gfx/gl/lights.h deleted file mode 100644 index 3247e25..0000000 --- a/gfx/gl/lights.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "config/types.h" - -struct LightCommonVertex { - RelativePosition3D position; - RGB colour; - RelativeDistance kq; -}; - -struct SpotLightVertex : LightCommonVertex { - Direction3D direction; - Angle arc; -}; - -struct PointLightVertex : LightCommonVertex { }; diff --git a/gfx/models/lights.cpp b/gfx/models/lights.cpp new file mode 100644 index 0000000..8c0e9e6 --- /dev/null +++ b/gfx/models/lights.cpp @@ -0,0 +1,11 @@ +#include "lights.h" + +SpotLightVertex::SpotLightVertex(const SpotLightDef & light, uint32_t parentObjectIdx) : + SpotLightDef {light}, LightCommonVertex {parentObjectIdx} +{ +} + +PointLightVertex::PointLightVertex(const PointLightDef & light, uint32_t parentObjectIdx) : + PointLightDef {light}, LightCommonVertex {parentObjectIdx} +{ +} diff --git a/gfx/models/lights.h b/gfx/models/lights.h new file mode 100644 index 0000000..586b3ef --- /dev/null +++ b/gfx/models/lights.h @@ -0,0 +1,29 @@ +#pragma once + +#include "config/types.h" + +struct LightCommon { + RelativePosition3D position; + RGB colour; + RelativeDistance kq; +}; + +struct LightCommonVertex { + uint32_t parentObject; +}; + +struct SpotLightDef : LightCommon { + Direction3D direction; + Angle arc; +}; + +struct PointLightDef : LightCommon { }; + +struct SpotLightVertex : SpotLightDef, LightCommonVertex { + SpotLightVertex(const SpotLightDef &, uint32_t); +}; + +struct PointLightVertex : PointLightDef, LightCommonVertex { + PointLightVertex(const PointLightDef &, uint32_t); +}; + diff --git a/gfx/renderable.cpp b/gfx/renderable.cpp index 90035c3..8523118 100644 --- a/gfx/renderable.cpp +++ b/gfx/renderable.cpp @@ -1,10 +1,14 @@ #include "renderable.h" +#include "gfx/gl/sceneShader.h" #include "gl_traits.h" #include "location.h" #include "maths.h" #include "util.h" std::weak_ptr Renderable::commonLocationData; +std::weak_ptr Renderable::commonSpotLights; +std::weak_ptr Renderable::commonPointLights; +std::weak_ptr Renderable::commonInstancesSpotLightVAO, Renderable::commonInstancesPointLightVAO; Renderable::CommonLocation::CommonLocation(Location const & location) : position {location.pos, 0}, rotation {location.rot, 0}, rotationMatrix {location.getRotationTransform()} @@ -23,6 +27,19 @@ Renderable::CommonLocation ::operator=(Location const & location) Renderable::Renderable() { createIfRequired(locationData, commonLocationData); + createIfRequired(spotLights, commonSpotLights); + createIfRequired(pointLights, commonPointLights); + if (createIfRequired(instancesSpotLightVAO, commonInstancesSpotLightVAO)) { + instancesSpotLightVAO->configure() + .addAttribs(0); + } + if (createIfRequired(instancesPointLightVAO, commonInstancesPointLightVAO)) { + instancesPointLightVAO->configure() + .addAttribs(0); + } } GLuint @@ -40,8 +57,31 @@ Renderable::preFrame(const Frustum &, const Frustum &) } void -Renderable::lights(const SceneShader &) const +Renderable::lights(const SceneShader & shader) { + glDebugScope _ {0}; + if (const auto instancesSpotLight = commonSpotLights.lock()) { + if (const auto scount = instancesSpotLight->size()) { + if (const auto instancesSpotLightVAO = commonInstancesSpotLightVAO.lock()) { + glDebugScope _ {*instancesSpotLightVAO, "Spot lights"}; + shader.spotLightInst.use(); + glBindVertexArray(*instancesSpotLightVAO); + instancesSpotLightVAO->useBuffer(0, *instancesSpotLight); + glDrawArrays(GL_POINTS, 0, static_cast(scount)); + } + } + } + if (const auto instancesPointLight = commonPointLights.lock()) { + if (const auto pcount = instancesPointLight->size()) { + if (const auto instancesPointLightVAO = commonInstancesPointLightVAO.lock()) { + glDebugScope _ {*instancesPointLightVAO, "Point lights"}; + shader.pointLightInst.use(); + glBindVertexArray(*instancesPointLightVAO); + instancesPointLightVAO->useBuffer(0, *instancesPointLight); + glDrawArrays(GL_POINTS, 0, static_cast(pcount)); + } + } + } } void diff --git a/gfx/renderable.h b/gfx/renderable.h index b0a42f2..7f4f52e 100644 --- a/gfx/renderable.h +++ b/gfx/renderable.h @@ -1,6 +1,8 @@ #pragma once +#include "gfx/gl/glVertexArray.h" #include "gfx/gl/instanceVertices.h" +#include "gfx/models/lights.h" #include "gl_traits.h" #include #include @@ -20,7 +22,7 @@ public: virtual void preFrame(const Frustum &, const Frustum &); virtual void render(const SceneShader & shader, const Frustum &) const = 0; - virtual void lights(const SceneShader & shader) const; + static void lights(const SceneShader & shader); virtual void shadows(const ShadowMapper & shadowMapper, const Frustum &) const; virtual void updateStencil(const ShadowStenciller & lightDir) const; @@ -37,10 +39,17 @@ public: using CommonLocationData = InstanceVertices; using CommonLocationInstance = CommonLocationData::InstanceProxy; - std::shared_ptr locationData; - static std::weak_ptr commonLocationData; + + using CommonSpotLights = InstanceVertices; + std::shared_ptr spotLights; + static std::weak_ptr commonSpotLights; + using CommonPointLights = InstanceVertices; + std::shared_ptr pointLights; + static std::weak_ptr commonPointLights; + std::shared_ptr instancesSpotLightVAO, instancesPointLightVAO; + static std::weak_ptr commonInstancesSpotLightVAO, commonInstancesPointLightVAO; }; template<> struct gl_traits::InstanceProxy> { diff --git a/test/test-assetFactory.cpp b/test/test-assetFactory.cpp index 90fae9b..b1cd822 100644 --- a/test/test-assetFactory.cpp +++ b/test/test-assetFactory.cpp @@ -51,7 +51,7 @@ namespace { void lights(const SceneShader & shader) const override { - objects.apply(&Renderable::lights, shader); + Renderable::lights(shader); } void diff --git a/test/test-render.cpp b/test/test-render.cpp index b21f440..688275c 100644 --- a/test/test-render.cpp +++ b/test/test-render.cpp @@ -1,3 +1,4 @@ +#include "game/scenary/light.h" #define BOOST_TEST_MODULE test_render #include "testHelpers.h" @@ -65,6 +66,10 @@ namespace { } rail->addLinksBetween({42000, 50000, 1000}, {65000, 50000, 1000}); rail->addLinksBetween({65000, 50000, 1000}, {75000, 45000, 2000}); + gameState->world.create(gameState->assets.at("old-lamp").dynamicCast(), + Location {.pos = {25000, 52000, 1}, .rot = {}}); + gameState->world.create(gameState->assets.at("r-light").dynamicCast(), + Location {.pos = {20000, 57000, 1}, .rot = {}}); } void @@ -94,8 +99,9 @@ namespace { } void - lights(const SceneShader &) const override + lights(const SceneShader & shader) const override { + Renderable::lights(shader); } void diff --git a/ui/gameMainWindow.cpp b/ui/gameMainWindow.cpp index cc81a9b..01b93bb 100644 --- a/ui/gameMainWindow.cpp +++ b/ui/gameMainWindow.cpp @@ -124,9 +124,9 @@ GameMainWindow::environment(const SceneShader &, const SceneRenderer & r) const } void -GameMainWindow::lights(const SceneShader & shader) const +GameMainWindow::lights(const SceneShader & sceneShader) const { - gameState->world.apply(&Renderable::lights, shader); + Renderable::lights(sceneShader); } void -- cgit v1.3