summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2026-04-01 20:21:23 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2026-04-01 20:21:23 +0100
commit30fcb8bce7b60b6754a0d35f2f15b627d0fba4cb (patch)
tree7e782f51affa8a2a40cf47e6ba69335a1289b2be
parentFix VertexArrayConfigurator with derived classes (diff)
downloadilt-30fcb8bce7b60b6754a0d35f2f15b627d0fba4cb.tar.bz2
ilt-30fcb8bce7b60b6754a0d35f2f15b627d0fba4cb.tar.xz
ilt-30fcb8bce7b60b6754a0d35f2f15b627d0fba4cb.zip
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.
-rw-r--r--application/main.cpp4
-rw-r--r--game/scenary/illuminator.cpp55
-rw-r--r--game/scenary/illuminator.h16
-rw-r--r--game/scenary/light.cpp9
-rw-r--r--game/scenary/light.h3
-rw-r--r--gfx/gl/lights.h16
-rw-r--r--gfx/models/lights.cpp11
-rw-r--r--gfx/models/lights.h29
-rw-r--r--gfx/renderable.cpp42
-rw-r--r--gfx/renderable.h15
-rw-r--r--test/test-assetFactory.cpp2
-rw-r--r--test/test-render.cpp8
-rw-r--r--ui/gameMainWindow.cpp4
13 files changed, 126 insertions, 88 deletions
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 <array>
@@ -108,6 +109,9 @@ public:
{0, rotationDistribution(randomdev), 0}});
}
}
+
+ world.create<Light>(assets.at("old-lamp").dynamicCast<Illuminator>(),
+ 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<Illuminator>);
-std::weak_ptr<glVertexArray> Illuminator::commonInstanceVAO, Illuminator::commonInstancesSpotLightVAO,
- Illuminator::commonInstancesPointLightVAO;
+std::weak_ptr<glVertexArray> 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<InstanceVertex, &InstanceVertex::location>(1);
}
- if (!spotLight.empty()) {
- if (!(instancesSpotLightVAO = commonInstancesSpotLightVAO.lock())) {
- commonInstancesSpotLightVAO = instancesSpotLightVAO = std::make_shared<glVertexArray>();
- instancesSpotLightVAO->configure()
- .addAttribs<SpotLightVertex, &SpotLightVertex::position, &SpotLightVertex::direction,
- &SpotLightVertex::colour, &SpotLightVertex::kq, &SpotLightVertex::arc>(0)
- .addAttribs<InstanceVertex, &InstanceVertex::location>(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<glVertexArray>();
- instancesPointLightVAO->configure()
- .addAttribs<PointLightVertex, &PointLightVertex::position, &PointLightVertex::colour,
- &PointLightVertex::kq>(0)
- .addAttribs<InstanceVertex, &InstanceVertex::location>(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<GLsizei>(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<GLsizei>(scount), static_cast<GLsizei>(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<GLsizei>(pcount), static_cast<GLsizei>(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<Illuminator> {
Mesh::Ptr bodyMesh;
Texture::Ptr texture;
- std::shared_ptr<glVertexArray> instanceVAO, instancesSpotLightVAO, instancesPointLightVAO;
- static std::weak_ptr<glVertexArray> commonInstanceVAO, commonInstancesSpotLightVAO, commonInstancesPointLightVAO;
+ std::shared_ptr<glVertexArray> instanceVAO;
+ static std::weak_ptr<glVertexArray> commonInstanceVAO;
public:
[[nodiscard]] std::any createAt(const Location &) const override;
- struct SpotLight : Persistence::Persistable, SpotLightVertex, StdTypeDefs<SpotLight> {
+ struct SpotLight : Persistence::Persistable, SpotLightDef, StdTypeDefs<SpotLight> {
private:
friend Persistence::SelectionPtrBase<std::shared_ptr<SpotLight>>;
bool persist(Persistence::PersistenceStore & store) override;
};
- struct PointLight : Persistence::Persistable, PointLightVertex, StdTypeDefs<PointLight> {
+ struct PointLight : Persistence::Persistable, PointLightDef, StdTypeDefs<PointLight> {
private:
friend Persistence::SelectionPtrBase<std::shared_ptr<PointLight>>;
bool persist(Persistence::PersistenceStore & store) override;
@@ -35,18 +35,14 @@ public:
};
mutable InstanceVertices<InstanceVertex> instances;
- mutable InstanceVertices<SpotLightVertex> instancesSpotLight;
- mutable InstanceVertices<PointLightVertex> instancesPointLight;
void render(const SceneShader &, const Frustum &) const override;
- void lights(const SceneShader &) const override;
protected:
friend Persistence::SelectionPtrBase<std::shared_ptr<Illuminator>>;
bool persist(Persistence::PersistenceStore & store) override;
void postLoad() override;
+public:
std::vector<SpotLight::Ptr> spotLight;
std::vector<PointLight::Ptr> pointLight;
- std::vector<InstanceVertices<SpotLightVertex>::InstanceProxy> spotLightInstances;
- std::vector<InstanceVertices<PointLightVertex>::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<const Illuminator> 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<InstanceVertices<SpotLightVertex>::InstanceProxy> spotLightInstances;
+ std::vector<InstanceVertices<PointLightVertex>::InstanceProxy> pointLightInstances;
+
public:
Light(std::shared_ptr<const Illuminator> 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> Renderable::commonLocationData;
+std::weak_ptr<Renderable::CommonSpotLights> Renderable::commonSpotLights;
+std::weak_ptr<Renderable::CommonPointLights> Renderable::commonPointLights;
+std::weak_ptr<glVertexArray> 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<SpotLightVertex, &SpotLightVertex::position, &SpotLightVertex::direction,
+ &SpotLightVertex::colour, &SpotLightVertex::kq, &SpotLightVertex::arc,
+ &SpotLightVertex::parentObject>(0);
+ }
+ if (createIfRequired(instancesPointLightVAO, commonInstancesPointLightVAO)) {
+ instancesPointLightVAO->configure()
+ .addAttribs<PointLightVertex, &PointLightVertex::position, &PointLightVertex::colour,
+ &PointLightVertex::kq, &PointLightVertex::parentObject>(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<GLsizei>(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<GLsizei>(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 <glm/mat3x3.hpp>
#include <special_members.h>
@@ -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<CommonLocation>;
using CommonLocationInstance = CommonLocationData::InstanceProxy;
-
std::shared_ptr<CommonLocationData> locationData;
-
static std::weak_ptr<CommonLocationData> commonLocationData;
+
+ using CommonSpotLights = InstanceVertices<SpotLightVertex>;
+ std::shared_ptr<CommonSpotLights> spotLights;
+ static std::weak_ptr<CommonSpotLights> commonSpotLights;
+ using CommonPointLights = InstanceVertices<PointLightVertex>;
+ std::shared_ptr<CommonPointLights> pointLights;
+ static std::weak_ptr<CommonPointLights> commonPointLights;
+ std::shared_ptr<glVertexArray> instancesSpotLightVAO, instancesPointLightVAO;
+ static std::weak_ptr<glVertexArray> commonInstancesSpotLightVAO, commonInstancesPointLightVAO;
};
template<> struct gl_traits<InstanceVertices<Renderable::CommonLocation>::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<Light>(gameState->assets.at("old-lamp").dynamicCast<Illuminator>(),
+ Location {.pos = {25000, 52000, 1}, .rot = {}});
+ gameState->world.create<Light>(gameState->assets.at("r-light").dynamicCast<Illuminator>(),
+ 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<const Renderable>(&Renderable::lights, shader);
+ Renderable::lights(sceneShader);
}
void