REarrange the light stage construction and light frame usage to produce the light clusters

This commit is contained in:
samcake 2016-09-12 11:07:55 -07:00
parent 7a7a60a5c4
commit 821072bb76
11 changed files with 130 additions and 52 deletions

View file

@ -124,7 +124,7 @@ public:
float _intensity{1.0f}; float _intensity{1.0f};
Vec4 _attenuation{0.1f, 1.0f, 0.0f, 0.0f}; Vec4 _attenuation{0.1f, 1.0f, 0.0f, 0.0f};
Vec4 _spot{0.0f, 0.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 }; float _ambientMapNumMips{ 0.0f };

View file

@ -53,7 +53,7 @@ struct Light {
vec4 _attenuation; vec4 _attenuation;
vec4 _spot; vec4 _spot;
vec4 _shadow; // vec4 _shadow;
vec4 _control; vec4 _control;
vec4 _volumeGeometry; vec4 _volumeGeometry;

View file

@ -118,9 +118,7 @@ void DeferredLightingEffect::init() {
// Light Stage and clusters // Light Stage and clusters
_lightStage = std::make_shared<LightStage>(); _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 // 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>()); _allocatedLights.push_back(std::make_shared<model::Light>());
model::LightPointer lp = _allocatedLights[0]; 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, void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radius, const glm::vec3& color,
float intensity, float falloffRadius) { float intensity, float falloffRadius) {
addSpotLight(position, radius, color, intensity, 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->resize(frameSize.x, frameSize.y);
primaryFramebuffer = _primaryFramebuffer; primaryFramebuffer = _primaryFramebuffer;
} }
@ -508,6 +508,11 @@ void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderC
// For the rest of the rendering, bind the lighting model // For the rest of the rendering, bind the lighting model
batch.setUniformBuffer(LIGHTING_MODEL_BUFFER_SLOT, lightingModel->getParametersBuffer()); batch.setUniformBuffer(LIGHTING_MODEL_BUFFER_SLOT, lightingModel->getParametersBuffer());
}); });
// Prepare a fresh Light Frame
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
deferredLightingEffect->getLightStage()->_currentFrame.clear();
} }

View file

@ -62,7 +62,6 @@ public:
void setGlobalLight(const model::LightPointer& light); void setGlobalLight(const model::LightPointer& light);
const LightStagePointer getLightStage() { return _lightStage; } const LightStagePointer getLightStage() { return _lightStage; }
const LightClustersPointer getLightClusters() { return _lightClusters; }
void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; }; void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; };
void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; } void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; }
@ -73,8 +72,6 @@ private:
LightStagePointer _lightStage; LightStagePointer _lightStage;
LightClustersPointer _lightClusters;
bool _shadowMapEnabled{ false }; bool _shadowMapEnabled{ false };
bool _ambientOcclusionEnabled{ false }; bool _ambientOcclusionEnabled{ false };

View file

@ -47,13 +47,36 @@ void LightClusters::updateFrustum(const ViewFrustum& frustum) {
void LightClusters::updateLightStage(const LightStagePointer& lightStage) { void LightClusters::updateLightStage(const LightStagePointer& lightStage) {
_lightStage = 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(); _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._buffer->setData(_visibleLightIndices.size() * sizeof(int), (const gpu::Byte*) _visibleLightIndices.data());
_lightIndicesBuffer._size = _visibleLightIndices.size() * sizeof(int); _lightIndicesBuffer._size = _visibleLightIndices.size() * sizeof(int);
} }
@ -83,12 +106,9 @@ void LightClusteringPass::run(const render::SceneContextPointer& sceneContext, c
auto lightingModel = inputs.get1(); auto lightingModel = inputs.get1();
auto surfaceGeometryFramebuffer = inputs.get2(); auto surfaceGeometryFramebuffer = inputs.get2();
bool points = lightingModel->isPointLightEnabled();
bool spots = lightingModel->isSpotLightEnabled();
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
if (!_lightClusters) { if (!_lightClusters) {
_lightClusters = deferredLightingEffect->getLightClusters(); _lightClusters = std::make_shared<LightClusters>();
} }
// first update the Grid with the new frustum // first update the Grid with the new frustum
@ -96,28 +116,11 @@ void LightClusteringPass::run(const render::SceneContextPointer& sceneContext, c
_lightClusters->updateFrustum(args->getViewFrustum()); _lightClusters->updateFrustum(args->getViewFrustum());
} }
// Now gather the lights // From the LightStage and the current frame, update the light cluster Grid
// gather lights auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
auto& srcPointLights = deferredLightingEffect->_pointLights; auto lightStage = deferredLightingEffect->getLightStage();
auto& srcSpotLights = deferredLightingEffect->_spotLights; _lightClusters->updateLightStage(lightStage);
int numPointLights = (int) srcPointLights.size(); _lightClusters->updateLightFrame(lightStage->_currentFrame, lightingModel->isPointLightEnabled(), lightingModel->isSpotLightEnabled());
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);
output = _lightClusters; output = _lightClusters;
} }

View file

@ -61,9 +61,8 @@ public:
void updateLightStage(const LightStagePointer& lightStage); 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; ViewFrustum _frustum;
LightStagePointer _lightStage; LightStagePointer _lightStage;

View file

@ -35,11 +35,34 @@ namespace render {
} }
LightPayload::LightPayload() : 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());
}

View file

@ -14,7 +14,7 @@
#include <model/Light.h> #include <model/Light.h>
#include <render/Item.h> #include <render/Item.h>
#include "LightStage.h"
class LightPayload { class LightPayload {
public: public:
@ -22,14 +22,18 @@ public:
using Pointer = Payload::DataPointer; using Pointer = Payload::DataPointer;
LightPayload(); LightPayload();
~LightPayload();
void render(RenderArgs* args); void render(RenderArgs* args);
model::LightPointer editLight() { return _light; } model::LightPointer editLight() { _needUpdate = true; return _light; }
render::Item::Bound& editBound() { return _bound; } render::Item::Bound& editBound() { _needUpdate = true; return _bound; }
protected: protected:
model::LightPointer _light; model::LightPointer _light;
render::Item::Bound _bound; render::Item::Bound _bound;
LightStagePointer _stage;
LightStage::Index _index { LightStage::INVALID_INDEX };
bool _needUpdate { true };
}; };
namespace render { namespace render {

View file

@ -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) { void LightStage::updateLightArrayBuffer(Index lightId) {
if (!_lightArrayBuffer) { if (!_lightArrayBuffer) {
_lightArrayBuffer = std::make_shared<gpu::Buffer>(); _lightArrayBuffer = std::make_shared<gpu::Buffer>();

View file

@ -27,7 +27,8 @@ class LightStage {
public: public:
using Index = render::indexed_container::Index; using Index = render::indexed_container::Index;
static const Index INVALID_INDEX { render::indexed_container::INVALID_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 LightPointer = model::LightPointer;
using Lights = render::indexed_container::IndexedPointerVector<model::Light>; using Lights = render::indexed_container::IndexedPointerVector<model::Light>;
using LightMap = std::unordered_map<LightPointer, Index>; using LightMap = std::unordered_map<LightPointer, Index>;
@ -79,7 +80,8 @@ public:
Index findLight(const LightPointer& light) const; Index findLight(const LightPointer& light) const;
Index addLight(const LightPointer& light); Index addLight(const LightPointer& light);
LightPointer removeLight(Index index);
bool checkLightId(Index index) const { return _lights.checkIndex(index); } bool checkLightId(Index index) const { return _lights.checkIndex(index); }
Index getNumLights() const { return _lights.getNumElements(); } Index getNumLights() const { return _lights.getNumElements(); }
@ -107,10 +109,35 @@ public:
LightMap _lightMap; LightMap _lightMap;
Descs _descs; 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; gpu::BufferPointer _lightArrayBuffer;
void updateLightArrayBuffer(Index lightId); void updateLightArrayBuffer(Index lightId);
Shadows _shadows; Shadows _shadows;
}; };
using LightStagePointer = std::shared_ptr<LightStage>; using LightStagePointer = std::shared_ptr<LightStage>;
#endif #endif

View file

@ -40,6 +40,16 @@ Column {
checked: Render.getConfig("LightClustering")["freeze"] checked: Render.getConfig("LightClustering")["freeze"]
onCheckedChanged: { Render.getConfig("LightClustering")["freeze"] = checked } 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 }
}
} }
} }
} }