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};
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 };

View file

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

View file

@ -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();
}

View file

@ -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 };

View file

@ -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;
}

View file

@ -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;

View file

@ -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());
}

View file

@ -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 {

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) {
if (!_lightArrayBuffer) {
_lightArrayBuffer = std::make_shared<gpu::Buffer>();

View file

@ -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

View file

@ -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 }
}
}
}
}