From 61de063b29ebc0f93ee88a3a245dbe2cce45b8a7 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 8 Sep 2016 18:02:35 -0700 Subject: [PATCH] Developping the Light Clusters, adding visualization --- libraries/gpu/src/gpu/Buffer.h | 17 +++ .../src/AmbientOcclusionEffect.cpp | 30 ++--- .../render-utils/src/AmbientOcclusionEffect.h | 24 +--- .../src/DeferredLightingEffect.cpp | 40 +++++-- .../render-utils/src/DeferredLightingEffect.h | 11 +- libraries/render-utils/src/LightClusters.cpp | 111 ++++++++++++++++++ libraries/render-utils/src/LightClusters.h | 98 ++++++++++++++-- libraries/render-utils/src/LightStage.h | 2 + .../render-utils/src/RenderDeferredTask.cpp | 5 + .../render-utils/src/RenderShadowTask.cpp | 10 +- .../render-utils/src/SubsurfaceScattering.cpp | 2 +- .../src/lightClusters_drawGrid.slf | 19 +++ .../src/lightClusters_drawGrid.slv | 89 ++++++++++++++ libraries/shared/src/ViewFrustum.cpp | 20 ++++ libraries/shared/src/ViewFrustum.h | 3 + 15 files changed, 412 insertions(+), 69 deletions(-) create mode 100644 libraries/render-utils/src/lightClusters_drawGrid.slf create mode 100644 libraries/render-utils/src/lightClusters_drawGrid.slv diff --git a/libraries/gpu/src/gpu/Buffer.h b/libraries/gpu/src/gpu/Buffer.h index 3233dad8a9..e8e04f471a 100644 --- a/libraries/gpu/src/gpu/Buffer.h +++ b/libraries/gpu/src/gpu/Buffer.h @@ -380,6 +380,23 @@ public: } }; + + template class StructBuffer : public gpu::BufferView { + public: + + static BufferPointer makeBuffer() { + T t; + return std::make_shared(sizeof(T), (const gpu::Byte*) &t); + } + ~StructBuffer() {}; + StructBuffer() : gpu::BufferView(makeBuffer()) {} + + const T* operator ->() const { return &get(); } + T& edit() { + return BufferView::edit(0); + } + + }; }; #endif diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 61a8c1f994..4d8403fc4d 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -184,46 +184,46 @@ void AmbientOcclusionEffect::configure(const Config& config) { const double RADIUS_POWER = 6.0; const auto& radius = config.radius; if (radius != _parametersBuffer->getRadius()) { - auto& current = _parametersBuffer->radiusInfo; + auto& current = _parametersBuffer.edit().radiusInfo; current.x = radius; current.y = radius * radius; current.z = (float)(1.0 / pow((double)radius, RADIUS_POWER)); } if (config.obscuranceLevel != _parametersBuffer->getObscuranceLevel()) { - auto& current = _parametersBuffer->radiusInfo; + auto& current = _parametersBuffer.edit().radiusInfo; current.w = config.obscuranceLevel; } if (config.falloffBias != _parametersBuffer->getFalloffBias()) { - auto& current = _parametersBuffer->ditheringInfo; + auto& current = _parametersBuffer.edit().ditheringInfo; current.z = config.falloffBias; } if (config.edgeSharpness != _parametersBuffer->getEdgeSharpness()) { - auto& current = _parametersBuffer->blurInfo; + auto& current = _parametersBuffer.edit().blurInfo; current.x = config.edgeSharpness; } if (config.blurDeviation != _parametersBuffer->getBlurDeviation()) { - auto& current = _parametersBuffer->blurInfo; + auto& current = _parametersBuffer.edit().blurInfo; current.z = config.blurDeviation; shouldUpdateGaussian = true; } if (config.numSpiralTurns != _parametersBuffer->getNumSpiralTurns()) { - auto& current = _parametersBuffer->sampleInfo; + auto& current = _parametersBuffer.edit().sampleInfo; current.z = config.numSpiralTurns; } if (config.numSamples != _parametersBuffer->getNumSamples()) { - auto& current = _parametersBuffer->sampleInfo; + auto& current = _parametersBuffer.edit().sampleInfo; current.x = config.numSamples; current.y = 1.0f / config.numSamples; } if (config.fetchMipsEnabled != _parametersBuffer->isFetchMipsEnabled()) { - auto& current = _parametersBuffer->sampleInfo; + auto& current = _parametersBuffer.edit().sampleInfo; current.w = (float)config.fetchMipsEnabled; } @@ -232,26 +232,26 @@ void AmbientOcclusionEffect::configure(const Config& config) { } if (config.perspectiveScale != _parametersBuffer->getPerspectiveScale()) { - _parametersBuffer->resolutionInfo.z = config.perspectiveScale; + _parametersBuffer.edit().resolutionInfo.z = config.perspectiveScale; } if (config.resolutionLevel != _parametersBuffer->getResolutionLevel()) { - auto& current = _parametersBuffer->resolutionInfo; + auto& current = _parametersBuffer.edit().resolutionInfo; current.x = (float) config.resolutionLevel; } if (config.blurRadius != _parametersBuffer->getBlurRadius()) { - auto& current = _parametersBuffer->blurInfo; + auto& current = _parametersBuffer.edit().blurInfo; current.y = (float)config.blurRadius; shouldUpdateGaussian = true; } if (config.ditheringEnabled != _parametersBuffer->isDitheringEnabled()) { - auto& current = _parametersBuffer->ditheringInfo; + auto& current = _parametersBuffer.edit().ditheringInfo; current.x = (float)config.ditheringEnabled; } if (config.borderingEnabled != _parametersBuffer->isBorderingEnabled()) { - auto& current = _parametersBuffer->ditheringInfo; + auto& current = _parametersBuffer.edit().ditheringInfo; current.w = (float)config.borderingEnabled; } @@ -334,7 +334,7 @@ const gpu::PipelinePointer& AmbientOcclusionEffect::getVBlurPipeline() { } void AmbientOcclusionEffect::updateGaussianDistribution() { - auto coefs = _parametersBuffer->_gaussianCoefs; + auto coefs = _parametersBuffer.edit()._gaussianCoefs; GaussianDistribution::evalSampling(coefs, Parameters::GAUSSIAN_COEFS_LENGTH, _parametersBuffer->getBlurRadius(), _parametersBuffer->getBlurDeviation()); } @@ -451,7 +451,7 @@ void DebugAmbientOcclusion::configure(const Config& config) { auto cursorPos = glm::vec2(_parametersBuffer->pixelInfo); if (cursorPos != config.debugCursorTexcoord) { - _parametersBuffer->pixelInfo = glm::vec4(config.debugCursorTexcoord, 0.0f, 0.0f); + _parametersBuffer.edit().pixelInfo = glm::vec4(config.debugCursorTexcoord, 0.0f, 0.0f); } } diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 80904c80a3..4e41926f9f 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -104,26 +104,6 @@ signals: void dirty(); }; - -namespace gpu { -template class UniformBuffer : public gpu::BufferView { - public: - - static BufferPointer makeBuffer() { - T t; - return std::make_shared(sizeof(T), (const gpu::Byte*) &t); - } - ~UniformBuffer() {}; - UniformBuffer() : gpu::BufferView(makeBuffer()) {} - - const T* operator ->() const { return &get(); } - T* operator ->() { - return &edit(0); - } - -}; -} - class AmbientOcclusionEffect { public: using Inputs = render::VaryingSet3; @@ -172,7 +152,7 @@ public: bool isDitheringEnabled() const { return ditheringInfo.x; } bool isBorderingEnabled() const { return ditheringInfo.w; } }; - using ParametersBuffer = gpu::UniformBuffer; + using ParametersBuffer = gpu::StructBuffer; private: void updateGaussianDistribution(); @@ -232,7 +212,7 @@ private: Parameters() {} }; - gpu::UniformBuffer _parametersBuffer; + gpu::StructBuffer _parametersBuffer; const gpu::PipelinePointer& getDebugPipeline(); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 94c12f7d99..7c81aeea22 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -116,6 +116,11 @@ void DeferredLightingEffect::init() { loadLightVolumeProgram(deferred_light_spot_vert, no_light_frag, false, _spotLightBack, _spotLightLocations); loadLightVolumeProgram(deferred_light_spot_vert, no_light_frag, true, _spotLightFront, _spotLightLocations); + // 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]; @@ -127,13 +132,13 @@ void DeferredLightingEffect::init() { lp->setAmbientSpherePreset(gpu::SphericalHarmonics::Preset::OLD_TOWN_SQUARE); // Add the global light to the light stage (for later shadow rendering) - _globalLights.push_back(_lightStage.addLight(lp)); + _globalLights.push_back(_lightStage->addLight(lp)); } void DeferredLightingEffect::addLight(const model::LightPointer& light) { assert(light); - auto lightID = _lightStage.addLight(light); + auto lightID = _lightStage->addLight(light); if (light->getType() == model::Light::POINT) { _pointLights.push_back(lightID); } else { @@ -239,10 +244,8 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo auto state = std::make_shared(); state->setColorWriteMask(true, true, true, false); - // state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); - if (lightVolume) { - state->setStencilTest(true, 0x00, gpu::State::StencilTest(1, 0xFF, gpu::GREATER_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); + state->setStencilTest(true, 0x00, gpu::State::StencilTest(1, 0xFF, gpu::LESS_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); state->setCullMode(gpu::State::CULL_BACK); // state->setCullMode(gpu::State::CULL_FRONT); @@ -270,27 +273,29 @@ static void loadLightVolumeProgram(const char* vertSource, const char* fragSourc gpu::ShaderPointer program = makeLightProgram(vertSource, fragSource, locations); auto state = std::make_shared(); - // state->setColorWriteMask(true, true, true, false); - state->setColorWriteMask(false, false, false, false); // Stencil test all the light passes for objects pixels only, not the background if (front) { state->setCullMode(gpu::State::CULL_BACK); state->setDepthTest(true, false, gpu::LESS_EQUAL); - state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_DECR)); + state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_DECR, gpu::State::STENCIL_OP_KEEP)); // state->setDepthClampEnable(true); // TODO: We should use DepthClamp and avoid changing geometry for inside /outside cases // additive blending // state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + //state->setColorWriteMask(true, true, true, false); + state->setColorWriteMask(false, false, false, false); } else { state->setCullMode(gpu::State::CULL_FRONT); state->setDepthTest(true, false, gpu::LESS_EQUAL); - state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_INCR)); + state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_INCR, gpu::State::STENCIL_OP_KEEP)); // additive blending // state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + // state->setColorWriteMask(true, true, true, false); + state->setColorWriteMask(false, false, false, false); } pipeline = gpu::Pipeline::create(program, state); @@ -568,8 +573,8 @@ void RenderDeferredSetup::run(const render::SceneContextPointer& sceneContext, c // Global directional light and ambient pass - assert(deferredLightingEffect->getLightStage().getNumLights() > 0); - auto lightAndShadow = deferredLightingEffect->getLightStage().getLightAndShadow(0); + assert(deferredLightingEffect->getLightStage()->getNumLights() > 0); + auto lightAndShadow = deferredLightingEffect->getLightStage()->getLightAndShadow(0); const auto& globalShadow = lightAndShadow.second; // Bind the shadow buffer @@ -682,6 +687,8 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, int numSpotLights = (int) srcSpotLights.size(); int offsetSpotLights = numPointLights; + auto lightClusters = deferredLightingEffect->_lightClusters; + std::vector lightIndices(numPointLights + numSpotLights + 1); lightIndices[0] = 0; @@ -695,11 +702,20 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext, } if (lightIndices[0] > 0) { + static int frame = 0; + frame++; + + if (frame % 1000 == 0) { + lightClusters->updateFrustum(viewFrustum); + + lightClusters->updateVisibleLights(lightIndices); + } _localLightsBuffer._buffer->setData(lightIndices.size() * sizeof(int), (const gpu::Byte*) lightIndices.data()); _localLightsBuffer._size = lightIndices.size() * sizeof(int); + // Bind the global list of lights and the visible lights this frame - batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()._lightArrayBuffer); + batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, deferredLightingEffect->getLightStage()->_lightArrayBuffer); batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightIndexBufferUnit, _localLightsBuffer); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index cbf5ff6ab3..ce29480950 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -28,6 +28,8 @@ #include "LightingModel.h" #include "LightStage.h" +#include "LightClusters.h" + #include "SurfaceGeometryPass.h" #include "SubsurfaceScattering.h" #include "AmbientOcclusionEffect.h" @@ -59,7 +61,8 @@ public: // update global lighting void setGlobalLight(const model::LightPointer& light); - const LightStage& getLightStage() { return _lightStage; } + const LightStagePointer getLightStage() { return _lightStage; } + const LightClustersPointer getLightClusters() { return _lightClusters; } void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; }; void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; } @@ -68,7 +71,9 @@ public: private: DeferredLightingEffect() = default; - LightStage _lightStage; + LightStagePointer _lightStage; + + LightClustersPointer _lightClusters; bool _shadowMapEnabled{ false }; bool _ambientOcclusionEnabled{ false }; @@ -200,4 +205,6 @@ protected: gpu::RangeTimerPointer _gpuTimer; }; + + #endif // hifi_DeferredLightingEffect_h diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index f266be988a..77fe7fa798 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -10,3 +10,114 @@ #include "LightClusters.h" + +#include +#include "lightClusters_drawGrid_vert.h" +#include "lightClusters_drawGrid_frag.h" + +enum LightClusterGridShader_BufferSlot { + LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT = 0, +}; + +#include "DeferredLightingEffect.h" + +LightClusters::LightClusters() { +} + +void LightClusters::updateFrustum(const ViewFrustum& frustum) { + _frustum = frustum; + + _frustrumGridBuffer.edit().updateFrustrum(frustum); +} + +void LightClusters::updateLightStage(const LightStagePointer& lightStage) { + _lightStage = lightStage; +} + +void LightClusters::updateVisibleLights(const LightStage::LightIndices& visibleLights) { + +} + + + + + +DebugLightClusters::DebugLightClusters() { + +} + + +void DebugLightClusters::configure(const Config& config) { +} + +const gpu::PipelinePointer DebugLightClusters::getDrawClusterGridPipeline() { + if (!_drawClusterGrid) { + auto vs = gpu::Shader::createVertex(std::string(lightClusters_drawGrid_vert)); + auto ps = gpu::Shader::createPixel(std::string(lightClusters_drawGrid_frag)); + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("frustrumGridBuffer"), LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT)); + + gpu::Shader::makeProgram(*program, slotBindings); + + + auto state = std::make_shared(); + + state->setDepthTest(true, false, gpu::LESS_EQUAL); + + // Blend on transparent + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + + // Good to go add the brand new pipeline + _drawClusterGrid = gpu::Pipeline::create(program, state); + } + return _drawClusterGrid; +} + +void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { + auto deferredLightingEffect = DependencyManager::get(); + auto lightClusters = deferredLightingEffect->getLightClusters(); + + + /* auto deferredTransform = inputs.get0(); + auto deferredFramebuffer = inputs.get1(); + auto lightingModel = inputs.get2(); + auto surfaceGeometryFramebuffer = inputs.get3(); + auto ssaoFramebuffer = inputs.get4(); + auto subsurfaceScatteringResource = inputs.get5(); + */ + auto args = renderContext->args; + + + auto drawPipeline = getDrawClusterGridPipeline(); + + gpu::Batch batch; + + + // Assign the camera transform + batch.setViewportTransform(args->_viewport); + glm::mat4 projMat; + Transform viewMat; + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat, true); + + + // Then the actual ClusterGrid attributes + batch.setModelTransform(Transform()); + + batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, lightClusters->_frustrumGridBuffer); + + // bind the one gpu::Pipeline we need + batch.setPipeline(drawPipeline); + + if (true) { + batch.draw(gpu::LINES, 24, 0); + } + + + args->_context->appendFrameBatch(batch); + +} \ No newline at end of file diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index b3a2271b2e..9cec0786ed 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -11,12 +11,12 @@ #ifndef hifi_render_utils_LightClusters_h #define hifi_render_utils_LightClusters_h -#include "gpu/Framebuffer.h" - +#include +#include #include "LightStage.h" #include -/* + class FrustumGrid { public: float _near { 0.1f }; @@ -25,6 +25,12 @@ public: float _far { 10000.0f }; glm::uvec3 _dims { 16, 16, 16 }; + float spare; + + glm::mat4 _eyeToGridProj; + glm::mat4 _eyeToGridProjInv; + glm::mat4 _worldToEyeMat; + glm::mat4 _eyeToWorldMat; float viewToLinearDepth(float depth) const { float nDepth = -depth; @@ -43,36 +49,104 @@ public: return depth / (float) _dims.z; } - glm::vec2 linearToGridXY(const glm::vec3& cpos) const { - return glm::vec2(cpos.x / (float) _dims.x, cpos.y / (float) _dims.y); - } - int gridDepthToLayer(float gridDepth) const { return (int) gridDepth; } + glm::vec2 ndcToGridXY(const glm::vec3& ncpos) const { + return 0.5f * glm::vec2((ncpos.x + 1.0f) / (float)_dims.x, (ncpos.y + 1.0f) / (float)_dims.y); + } + glm::ivec3 viewToGridPos(const glm::vec3& pos) const { - - return glm::ivec3(0); + float z = linearToGridDepth(viewToLinearDepth(pos.z)); + + auto cpos = _eyeToGridProj * glm::vec4(pos, 1.0f); + + glm::vec3 ncpos(cpos); + ncpos /= cpos.w; + + + return glm::ivec3(ndcToGridXY(ncpos), (int) linearToGridDepth(z)); + } + + void updateFrustrum(const ViewFrustum& frustum) { + _eyeToGridProj = frustum.evalProjectionMatrixRange(_nearPrime, _farPrime); + _eyeToGridProjInv = glm::inverse(_eyeToGridProj); + + Transform view; + frustum.evalViewTransform(view); + _eyeToWorldMat = view.getMatrix(); + _worldToEyeMat = view.getInverseMatrix(); } }; -*/ + class LightClusters { public: LightClusters(); - void updateFrustum(const ViewFrustum& frustum); - + void updateLightStage(const LightStagePointer& lightStage); + + void updateVisibleLights(const LightStage::LightIndices& visibleLights); + + + // FrustumGrid _grid; ViewFrustum _frustum; LightStagePointer _lightStage; + + + gpu::StructBuffer _frustrumGridBuffer; + + gpu::BufferPointer _lightIndicesBuffer; }; +using LightClustersPointer = std::shared_ptr; + + + +class DebugLightClustersConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(int numDrawn READ getNumDrawn NOTIFY numDrawnChanged) + Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) +public: + DebugLightClustersConfig() : render::Job::Config(true){} + + int getNumDrawn() { return numDrawn; } + void setNumDrawn(int num) { numDrawn = num; emit numDrawnChanged(); } + + int maxDrawn { -1 }; + +signals: + void numDrawnChanged(); + void dirty(); + +protected: + int numDrawn { 0 }; +}; + +class DebugLightClusters { +public: + // using Inputs = render::VaryingSet6 < DeferredFrameTransformPointer, DeferredFramebufferPointer, LightingModelPointer, SurfaceGeometryFramebufferPointer, AmbientOcclusionFramebufferPointer, SubsurfaceScatteringResourcePointer>; + using Config = DebugLightClustersConfig; + using JobModel = render::Job::Model; + + DebugLightClusters(); + + void configure(const Config& config); + + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + +protected: + gpu::BufferPointer _gridBuffer; + gpu::PipelinePointer _drawClusterGrid; + const gpu::PipelinePointer getDrawClusterGridPipeline(); +}; + #endif diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index b0d5c1749f..c0632a0ebf 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -32,6 +32,8 @@ public: using Lights = render::indexed_container::IndexedPointerVector; using LightMap = std::unordered_map; + using LightIndices = std::vector; + class Shadow { public: using UniformBufferView = gpu::BufferView; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 942419a8a4..6076cf697d 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -190,6 +190,11 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { addJob("DrawItemSelection", spatialSelection); } + // LIght Cluster Grid Debuging job + { + addJob("DebugLightClusters"); + } + // Status icon rendering job { // Grab a texture map representing the different status icons and assign that to the drawStatsuJob diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 2efbe7bf89..aed360823d 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -36,12 +36,12 @@ void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); - const auto& lightStage = DependencyManager::get()->getLightStage(); + auto lightStage = DependencyManager::get()->getLightStage(); LightStage::Index globalLightIndex { 0 }; - const auto globalLight = lightStage.getLight(globalLightIndex); - const auto shadow = lightStage.getShadow(globalLightIndex); + const auto globalLight = lightStage->getLight(globalLightIndex); + const auto shadow = lightStage->getShadow(globalLightIndex); if (!shadow) return; const auto& fbo = shadow->framebuffer; @@ -144,8 +144,8 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render return; } - const auto& lightStage = DependencyManager::get()->getLightStage(); - const auto globalShadow = lightStage.getShadow(0); + auto lightStage = DependencyManager::get()->getLightStage(); + const auto globalShadow = lightStage->getShadow(0); // If the global light is not set, bail if (!globalShadow) { diff --git a/libraries/render-utils/src/SubsurfaceScattering.cpp b/libraries/render-utils/src/SubsurfaceScattering.cpp index d78cbdb304..d49c388da3 100644 --- a/libraries/render-utils/src/SubsurfaceScattering.cpp +++ b/libraries/render-utils/src/SubsurfaceScattering.cpp @@ -530,7 +530,7 @@ void DebugSubsurfaceScattering::run(const render::SceneContextPointer& sceneCont - const auto light = DependencyManager::get()->getLightStage().getLight(0); + const auto light = DependencyManager::get()->getLightStage()->getLight(0); gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { batch.enableStereo(false); diff --git a/libraries/render-utils/src/lightClusters_drawGrid.slf b/libraries/render-utils/src/lightClusters_drawGrid.slf new file mode 100644 index 0000000000..33c8cc56b8 --- /dev/null +++ b/libraries/render-utils/src/lightClusters_drawGrid.slf @@ -0,0 +1,19 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// lightClusters_drawGrid.slf +// +// Created by Sam Gateau on 9/8/2016. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +in vec4 varColor; +out vec4 outFragColor; + + +void main(void) { + outFragColor = varColor; +} diff --git a/libraries/render-utils/src/lightClusters_drawGrid.slv b/libraries/render-utils/src/lightClusters_drawGrid.slv new file mode 100644 index 0000000000..db7006322c --- /dev/null +++ b/libraries/render-utils/src/lightClusters_drawGrid.slv @@ -0,0 +1,89 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// lightClusters_drawGrid.slv +// Vertex shader +// +// Created by Sam Gateau on 9/8/2016 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> + +<@include gpu/Color.slh@> +<$declareColorWheel()$> + + +struct FrustrumGrid { + vec4 nearFarRange; + ivec4 dims; + mat4 eyeToGridProj; + mat4 eyeToGridProjInv; + mat4 worldToEyeMat; + mat4 eyeToWorldMat; +}; + +uniform frustrumGridBuffer { + FrustrumGrid frustrumGrid; +}; + +//uniform ivec4 inClusterLocation; + +out vec4 varColor; + + +void main(void) { + const vec4 UNIT_BOX[8] = vec4[8]( + vec4(0.0, 0.0, 0.0, 1.0), + vec4(1.0, 0.0, 0.0, 1.0), + vec4(0.0, 1.0, 0.0, 1.0), + vec4(1.0, 1.0, 0.0, 1.0), + vec4(0.0, 0.0, 1.0, 1.0), + vec4(1.0, 0.0, 1.0, 1.0), + vec4(0.0, 1.0, 1.0, 1.0), + vec4(1.0, 1.0, 1.0, 1.0) + ); + const int UNIT_BOX_LINE_INDICES[24] = int[24]( + 0, 1, + 1, 3, + 3, 2, + 2, 0, + 4, 5, + 5, 7, + 7, 6, + 6, 4, + 2, 6, + 3, 7, + 0, 4, + 1, 5 + ); + vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]]; + + // pos.z -= 10.0f; + + + vec4 eyePos = frustrumGrid.eyeToGridProjInv * (pos); + + eyePos.xyz *= eyePos.w; + + vec4 worldPos = frustrumGrid.eyeToWorldMat * vec4(eyePos.xyz, 1.0); + + /* + int cellIsEmpty = sign(inClusterLocation.w); + ivec4 cellLocation = ivec4(inClusterLocation.xyz, (inClusterLocation.w < 0 ? -inClusterLocation.w : inClusterLocation.w)); + vec4 cellBound = evalBound(cellLocation); + + pos.xyz = cellBound.xyz + vec3(cellBound.w) * pos.xyz; + */ + // standard transform + TransformCamera cam = getTransformCamera(); + <$transformWorldToClipPos(cam, worldPos, gl_Position)$> + + varColor = vec4(colorWheel(fract(float(gl_VertexID) / 24.0)), 0.9); +} \ No newline at end of file diff --git a/libraries/shared/src/ViewFrustum.cpp b/libraries/shared/src/ViewFrustum.cpp index 4a7d4eff95..0a1a41ace1 100644 --- a/libraries/shared/src/ViewFrustum.cpp +++ b/libraries/shared/src/ViewFrustum.cpp @@ -657,6 +657,26 @@ void ViewFrustum::evalProjectionMatrix(glm::mat4& proj) const { proj = _projection; } +glm::mat4 ViewFrustum::evalProjectionMatrixRange(float rangeNear, float rangeFar) const { + + // make sure range near far make sense + assert(rangeNear > 0.0); + assert(rangeFar > rangeNear); + + // recreate a projection matrix for only a range of depth of this frustum. + + // take the current projection + glm::mat4 rangeProj = _projection; + + float A = -(rangeFar + rangeNear) / (rangeFar - rangeNear); + float B = -2 * rangeFar*rangeNear / ((rangeFar - rangeNear)); + + rangeProj[2][2] = A; + rangeProj[3][2] = B; + return rangeProj; +} + + void ViewFrustum::evalViewTransform(Transform& view) const { view.setTranslation(getPosition()); view.setRotation(getOrientation()); diff --git a/libraries/shared/src/ViewFrustum.h b/libraries/shared/src/ViewFrustum.h index 48d45ab455..091aff7a92 100644 --- a/libraries/shared/src/ViewFrustum.h +++ b/libraries/shared/src/ViewFrustum.h @@ -129,6 +129,9 @@ public: float distanceToCamera(const glm::vec3& point) const; void evalProjectionMatrix(glm::mat4& proj) const; + + glm::mat4 evalProjectionMatrixRange(float rangeNear, float rangeFar) const; + void evalViewTransform(Transform& view) const; enum PlaneIndex { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE, NUM_PLANES };