mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 23:33:48 +02:00
REarrange the light stage construction and light frame usage to produce the light clusters
This commit is contained in:
parent
7a7a60a5c4
commit
821072bb76
11 changed files with 130 additions and 52 deletions
|
@ -124,7 +124,7 @@ public:
|
|||
float _intensity{1.0f};
|
||||
Vec4 _attenuation{0.1f, 1.0f, 0.0f, 0.0f};
|
||||
Vec4 _spot{0.0f, 0.0f, 0.0f, 0.0f};
|
||||
Vec4 _shadow{0.0f};
|
||||
//Vec4 _shadow{0.0f};
|
||||
|
||||
|
||||
float _ambientMapNumMips{ 0.0f };
|
||||
|
|
|
@ -53,7 +53,7 @@ struct Light {
|
|||
vec4 _attenuation;
|
||||
vec4 _spot;
|
||||
|
||||
vec4 _shadow;
|
||||
// vec4 _shadow;
|
||||
vec4 _control;
|
||||
|
||||
vec4 _volumeGeometry;
|
||||
|
|
|
@ -118,9 +118,7 @@ void DeferredLightingEffect::init() {
|
|||
|
||||
// Light Stage and clusters
|
||||
_lightStage = std::make_shared<LightStage>();
|
||||
_lightClusters = std::make_shared<LightClusters>();
|
||||
_lightClusters->updateLightStage(_lightStage);
|
||||
|
||||
|
||||
// Allocate a global light representing the Global Directional light casting shadow (the sun) and the ambient light
|
||||
_allocatedLights.push_back(std::make_shared<model::Light>());
|
||||
model::LightPointer lp = _allocatedLights[0];
|
||||
|
@ -146,6 +144,7 @@ void DeferredLightingEffect::addLight(const model::LightPointer& light) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radius, const glm::vec3& color,
|
||||
float intensity, float falloffRadius) {
|
||||
addSpotLight(position, radius, color, intensity, falloffRadius);
|
||||
|
@ -472,6 +471,7 @@ void PreparePrimaryFramebuffer::run(const SceneContextPointer& sceneContext, con
|
|||
}
|
||||
_primaryFramebuffer->resize(frameSize.x, frameSize.y);
|
||||
|
||||
|
||||
primaryFramebuffer = _primaryFramebuffer;
|
||||
}
|
||||
|
||||
|
@ -508,6 +508,11 @@ void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderC
|
|||
// For the rest of the rendering, bind the lighting model
|
||||
batch.setUniformBuffer(LIGHTING_MODEL_BUFFER_SLOT, lightingModel->getParametersBuffer());
|
||||
});
|
||||
|
||||
|
||||
// Prepare a fresh Light Frame
|
||||
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
|
||||
deferredLightingEffect->getLightStage()->_currentFrame.clear();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -62,7 +62,6 @@ public:
|
|||
void setGlobalLight(const model::LightPointer& light);
|
||||
|
||||
const LightStagePointer getLightStage() { return _lightStage; }
|
||||
const LightClustersPointer getLightClusters() { return _lightClusters; }
|
||||
|
||||
void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; };
|
||||
void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; }
|
||||
|
@ -73,8 +72,6 @@ private:
|
|||
|
||||
LightStagePointer _lightStage;
|
||||
|
||||
LightClustersPointer _lightClusters;
|
||||
|
||||
bool _shadowMapEnabled{ false };
|
||||
bool _ambientOcclusionEnabled{ false };
|
||||
|
||||
|
|
|
@ -47,13 +47,36 @@ void LightClusters::updateFrustum(const ViewFrustum& frustum) {
|
|||
|
||||
void LightClusters::updateLightStage(const LightStagePointer& lightStage) {
|
||||
_lightStage = lightStage;
|
||||
}
|
||||
|
||||
void LightClusters::updateVisibleLights(const LightStage::LightIndices& visibleLights) {
|
||||
|
||||
}
|
||||
|
||||
void LightClusters::updateLightFrame(const LightStage::Frame& lightFrame, bool points, bool spots) {
|
||||
|
||||
// start fresh
|
||||
_visibleLightIndices.clear();
|
||||
// _lightClusters->_visibleLightIndices.push_back(0);
|
||||
_visibleLightIndices = visibleLights;
|
||||
|
||||
// Now gather the lights
|
||||
// gather lights
|
||||
auto& srcPointLights = lightFrame._pointLights;
|
||||
auto& srcSpotLights = lightFrame._spotLights;
|
||||
int numPointLights = (int) srcPointLights.size();
|
||||
// int offsetPointLights = 0;
|
||||
int numSpotLights = (int) srcSpotLights.size();
|
||||
// int offsetSpotLights = numPointLights;
|
||||
|
||||
_visibleLightIndices.resize(numPointLights + numSpotLights + 1);
|
||||
|
||||
_visibleLightIndices[0] = 0;
|
||||
|
||||
if (points && !srcPointLights.empty()) {
|
||||
memcpy(_visibleLightIndices.data() + (_visibleLightIndices[0] + 1), srcPointLights.data(), srcPointLights.size() * sizeof(int));
|
||||
_visibleLightIndices[0] += (int)srcPointLights.size();
|
||||
}
|
||||
if (spots && !srcSpotLights.empty()) {
|
||||
memcpy(_visibleLightIndices.data() + (_visibleLightIndices[0] + 1), srcSpotLights.data(), srcSpotLights.size() * sizeof(int));
|
||||
_visibleLightIndices[0] += (int)srcSpotLights.size();
|
||||
}
|
||||
|
||||
_lightIndicesBuffer._buffer->setData(_visibleLightIndices.size() * sizeof(int), (const gpu::Byte*) _visibleLightIndices.data());
|
||||
_lightIndicesBuffer._size = _visibleLightIndices.size() * sizeof(int);
|
||||
}
|
||||
|
@ -83,12 +106,9 @@ void LightClusteringPass::run(const render::SceneContextPointer& sceneContext, c
|
|||
auto lightingModel = inputs.get1();
|
||||
auto surfaceGeometryFramebuffer = inputs.get2();
|
||||
|
||||
bool points = lightingModel->isPointLightEnabled();
|
||||
bool spots = lightingModel->isSpotLightEnabled();
|
||||
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
|
||||
|
||||
if (!_lightClusters) {
|
||||
_lightClusters = deferredLightingEffect->getLightClusters();
|
||||
_lightClusters = std::make_shared<LightClusters>();
|
||||
}
|
||||
|
||||
// first update the Grid with the new frustum
|
||||
|
@ -96,28 +116,11 @@ void LightClusteringPass::run(const render::SceneContextPointer& sceneContext, c
|
|||
_lightClusters->updateFrustum(args->getViewFrustum());
|
||||
}
|
||||
|
||||
// Now gather the lights
|
||||
// gather lights
|
||||
auto& srcPointLights = deferredLightingEffect->_pointLights;
|
||||
auto& srcSpotLights = deferredLightingEffect->_spotLights;
|
||||
int numPointLights = (int) srcPointLights.size();
|
||||
int offsetPointLights = 0;
|
||||
int numSpotLights = (int) srcSpotLights.size();
|
||||
int offsetSpotLights = numPointLights;
|
||||
|
||||
std::vector<int> lightIndices(numPointLights + numSpotLights + 1);
|
||||
lightIndices[0] = 0;
|
||||
|
||||
if (points && !srcPointLights.empty()) {
|
||||
memcpy(lightIndices.data() + (lightIndices[0] + 1), srcPointLights.data(), srcPointLights.size() * sizeof(int));
|
||||
lightIndices[0] += (int)srcPointLights.size();
|
||||
}
|
||||
if (spots && !srcSpotLights.empty()) {
|
||||
memcpy(lightIndices.data() + (lightIndices[0] + 1), srcSpotLights.data(), srcSpotLights.size() * sizeof(int));
|
||||
lightIndices[0] += (int)srcSpotLights.size();
|
||||
}
|
||||
|
||||
_lightClusters->updateVisibleLights(lightIndices);
|
||||
// From the LightStage and the current frame, update the light cluster Grid
|
||||
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
|
||||
auto lightStage = deferredLightingEffect->getLightStage();
|
||||
_lightClusters->updateLightStage(lightStage);
|
||||
_lightClusters->updateLightFrame(lightStage->_currentFrame, lightingModel->isPointLightEnabled(), lightingModel->isSpotLightEnabled());
|
||||
|
||||
output = _lightClusters;
|
||||
}
|
||||
|
|
|
@ -61,9 +61,8 @@ public:
|
|||
|
||||
void updateLightStage(const LightStagePointer& lightStage);
|
||||
|
||||
void updateVisibleLights(const LightStage::LightIndices& visibleLights);
|
||||
|
||||
|
||||
void updateLightFrame(const LightStage::Frame& lightFrame, bool points = true, bool spots = true);
|
||||
|
||||
ViewFrustum _frustum;
|
||||
|
||||
LightStagePointer _lightStage;
|
||||
|
|
|
@ -35,11 +35,34 @@ namespace render {
|
|||
}
|
||||
|
||||
LightPayload::LightPayload() :
|
||||
_light(std::make_shared<model::Light>())
|
||||
_light(std::make_shared<model::Light>())
|
||||
{
|
||||
}
|
||||
|
||||
void LightPayload::render(RenderArgs* args) {
|
||||
|
||||
DependencyManager::get<DeferredLightingEffect>()->addLight(_light);
|
||||
}
|
||||
LightPayload::~LightPayload() {
|
||||
if (!LightStage::isIndexInvalid(_index)) {
|
||||
if (_stage) {
|
||||
_stage->removeLight(_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LightPayload::render(RenderArgs* args) {
|
||||
if (!_stage) {
|
||||
_stage = DependencyManager::get<DeferredLightingEffect>()->getLightStage();
|
||||
}
|
||||
// Do we need to allocate the light in the stage ?
|
||||
if (LightStage::isIndexInvalid(_index)) {
|
||||
_index = _stage->addLight(_light);
|
||||
}
|
||||
// Need an update ?
|
||||
if (_needUpdate) {
|
||||
_stage->updateLightArrayBuffer(_index);
|
||||
_needUpdate = false;
|
||||
}
|
||||
|
||||
// FInally, push the light visible in the frame
|
||||
_stage->_currentFrame.pushLight(_index, _light->getType());
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include <model/Light.h>
|
||||
#include <render/Item.h>
|
||||
|
||||
#include "LightStage.h"
|
||||
|
||||
class LightPayload {
|
||||
public:
|
||||
|
@ -22,14 +22,18 @@ public:
|
|||
using Pointer = Payload::DataPointer;
|
||||
|
||||
LightPayload();
|
||||
~LightPayload();
|
||||
void render(RenderArgs* args);
|
||||
|
||||
model::LightPointer editLight() { return _light; }
|
||||
render::Item::Bound& editBound() { return _bound; }
|
||||
|
||||
model::LightPointer editLight() { _needUpdate = true; return _light; }
|
||||
render::Item::Bound& editBound() { _needUpdate = true; return _bound; }
|
||||
|
||||
protected:
|
||||
model::LightPointer _light;
|
||||
render::Item::Bound _bound;
|
||||
LightStagePointer _stage;
|
||||
LightStage::Index _index { LightStage::INVALID_INDEX };
|
||||
bool _needUpdate { true };
|
||||
};
|
||||
|
||||
namespace render {
|
||||
|
|
|
@ -123,6 +123,16 @@ LightStage::Index LightStage::addLight(const LightPointer& light) {
|
|||
}
|
||||
}
|
||||
|
||||
LightStage::LightPointer LightStage::removeLight(Index index) {
|
||||
LightPointer removed = _lights.freeElement(index);
|
||||
|
||||
if (removed) {
|
||||
_lightMap.erase(removed);
|
||||
_descs[index] = Desc();
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
void LightStage::updateLightArrayBuffer(Index lightId) {
|
||||
if (!_lightArrayBuffer) {
|
||||
_lightArrayBuffer = std::make_shared<gpu::Buffer>();
|
||||
|
|
|
@ -27,7 +27,8 @@ class LightStage {
|
|||
public:
|
||||
using Index = render::indexed_container::Index;
|
||||
static const Index INVALID_INDEX { render::indexed_container::INVALID_INDEX };
|
||||
|
||||
static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; }
|
||||
|
||||
using LightPointer = model::LightPointer;
|
||||
using Lights = render::indexed_container::IndexedPointerVector<model::Light>;
|
||||
using LightMap = std::unordered_map<LightPointer, Index>;
|
||||
|
@ -79,7 +80,8 @@ public:
|
|||
|
||||
Index findLight(const LightPointer& light) const;
|
||||
Index addLight(const LightPointer& light);
|
||||
|
||||
LightPointer removeLight(Index index);
|
||||
|
||||
bool checkLightId(Index index) const { return _lights.checkIndex(index); }
|
||||
|
||||
Index getNumLights() const { return _lights.getNumElements(); }
|
||||
|
@ -107,10 +109,35 @@ public:
|
|||
LightMap _lightMap;
|
||||
Descs _descs;
|
||||
|
||||
class Frame {
|
||||
public:
|
||||
Frame() {}
|
||||
|
||||
void clear() { _pointLights.clear(); _spotLights.clear(); }
|
||||
void pushLight(LightStage::Index index, model::Light::Type type) {
|
||||
switch (type) {
|
||||
case model::Light::POINT: { pushPointLight(index); break; }
|
||||
case model::Light::SPOT: { pushSpotLight(index); break; }
|
||||
default: { break; }
|
||||
}
|
||||
}
|
||||
void pushPointLight(LightStage::Index index) { _pointLights.emplace_back(index); }
|
||||
void pushSpotLight(LightStage::Index index) { _spotLights.emplace_back(index); }
|
||||
|
||||
LightStage::LightIndices _pointLights;
|
||||
LightStage::LightIndices _spotLights;
|
||||
};
|
||||
|
||||
Frame _currentFrame;
|
||||
|
||||
gpu::BufferPointer _lightArrayBuffer;
|
||||
void updateLightArrayBuffer(Index lightId);
|
||||
|
||||
Shadows _shadows;
|
||||
};
|
||||
using LightStagePointer = std::shared_ptr<LightStage>;
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -40,6 +40,16 @@ Column {
|
|||
checked: Render.getConfig("LightClustering")["freeze"]
|
||||
onCheckedChanged: { Render.getConfig("LightClustering")["freeze"] = checked }
|
||||
}
|
||||
CheckBox {
|
||||
text: "Draw Grid"
|
||||
checked: Render.getConfig("DebugLightClusters")["doDrawGrid"]
|
||||
onCheckedChanged: { Render.getConfig("DebugLightClusters")["doDrawGrid"] = checked }
|
||||
}
|
||||
CheckBox {
|
||||
text: "Draw Cluster From Depth"
|
||||
checked: Render.getConfig("DebugLightClusters")["doDrawClusterFromDepth"]
|
||||
onCheckedChanged: { Render.getConfig("DebugLightClusters")["doDrawClusterFromDepth"] = checked }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue