diff --git a/libraries/model/src/model/Light.h b/libraries/model/src/model/Light.h index 058d4d4741..c091026ba2 100755 --- a/libraries/model/src/model/Light.h +++ b/libraries/model/src/model/Light.h @@ -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 }; diff --git a/libraries/model/src/model/Light.slh b/libraries/model/src/model/Light.slh index 2b6e55cf7e..888abf5038 100644 --- a/libraries/model/src/model/Light.slh +++ b/libraries/model/src/model/Light.slh @@ -53,7 +53,7 @@ struct Light { vec4 _attenuation; vec4 _spot; - vec4 _shadow; + // vec4 _shadow; vec4 _control; vec4 _volumeGeometry; diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index e6ca901376..1a0a072256 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -118,9 +118,7 @@ void DeferredLightingEffect::init() { // Light Stage and clusters _lightStage = std::make_shared(); - _lightClusters = std::make_shared(); - _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::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->getLightStage()->_currentFrame.clear(); } diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index a66a2ed2ed..690d6ce5e0 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -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 }; diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index e98322da4d..97f91657df 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -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(); if (!_lightClusters) { - _lightClusters = deferredLightingEffect->getLightClusters(); + _lightClusters = std::make_shared(); } // 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 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(); + auto lightStage = deferredLightingEffect->getLightStage(); + _lightClusters->updateLightStage(lightStage); + _lightClusters->updateLightFrame(lightStage->_currentFrame, lightingModel->isPointLightEnabled(), lightingModel->isSpotLightEnabled()); output = _lightClusters; } diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index 0cfaea5ef5..60b4d50ced 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -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; diff --git a/libraries/render-utils/src/LightPayload.cpp b/libraries/render-utils/src/LightPayload.cpp index 8bb9a57145..e8d9e0d5bd 100644 --- a/libraries/render-utils/src/LightPayload.cpp +++ b/libraries/render-utils/src/LightPayload.cpp @@ -35,11 +35,34 @@ namespace render { } LightPayload::LightPayload() : -_light(std::make_shared()) + _light(std::make_shared()) { } -void LightPayload::render(RenderArgs* args) { - DependencyManager::get()->addLight(_light); -} \ No newline at end of file +LightPayload::~LightPayload() { + if (!LightStage::isIndexInvalid(_index)) { + if (_stage) { + _stage->removeLight(_index); + } + } +} + +void LightPayload::render(RenderArgs* args) { + if (!_stage) { + _stage = DependencyManager::get()->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()); +} + diff --git a/libraries/render-utils/src/LightPayload.h b/libraries/render-utils/src/LightPayload.h index 2f065e4b5b..fba4ff15cb 100644 --- a/libraries/render-utils/src/LightPayload.h +++ b/libraries/render-utils/src/LightPayload.h @@ -14,7 +14,7 @@ #include #include - +#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 { diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index bcdee5c0a9..8c8c9406e0 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -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(); diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index c0632a0ebf..34575596dd 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -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; using LightMap = std::unordered_map; @@ -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; + + + + #endif diff --git a/scripts/developer/utilities/render/lightClustering.qml b/scripts/developer/utilities/render/lightClustering.qml index be252441db..9adb137b0f 100644 --- a/scripts/developer/utilities/render/lightClustering.qml +++ b/scripts/developer/utilities/render/lightClustering.qml @@ -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 } + } } } }