mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 11:45:36 +02:00
Developping the Light Clusters, adding visualization
This commit is contained in:
parent
25616be7c1
commit
61de063b29
15 changed files with 412 additions and 69 deletions
|
@ -380,6 +380,23 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
template <class T> class StructBuffer : public gpu::BufferView {
|
||||
public:
|
||||
|
||||
static BufferPointer makeBuffer() {
|
||||
T t;
|
||||
return std::make_shared<gpu::Buffer>(sizeof(T), (const gpu::Byte*) &t);
|
||||
}
|
||||
~StructBuffer<T>() {};
|
||||
StructBuffer<T>() : gpu::BufferView(makeBuffer()) {}
|
||||
|
||||
const T* operator ->() const { return &get<T>(); }
|
||||
T& edit() {
|
||||
return BufferView::edit<T>(0);
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -104,26 +104,6 @@ signals:
|
|||
void dirty();
|
||||
};
|
||||
|
||||
|
||||
namespace gpu {
|
||||
template <class T> class UniformBuffer : public gpu::BufferView {
|
||||
public:
|
||||
|
||||
static BufferPointer makeBuffer() {
|
||||
T t;
|
||||
return std::make_shared<gpu::Buffer>(sizeof(T), (const gpu::Byte*) &t);
|
||||
}
|
||||
~UniformBuffer<T>() {};
|
||||
UniformBuffer<T>() : gpu::BufferView(makeBuffer()) {}
|
||||
|
||||
const T* operator ->() const { return &get<T>(); }
|
||||
T* operator ->() {
|
||||
return &edit<T>(0);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
class AmbientOcclusionEffect {
|
||||
public:
|
||||
using Inputs = render::VaryingSet3<DeferredFrameTransformPointer, DeferredFramebufferPointer, LinearDepthFramebufferPointer>;
|
||||
|
@ -172,7 +152,7 @@ public:
|
|||
bool isDitheringEnabled() const { return ditheringInfo.x; }
|
||||
bool isBorderingEnabled() const { return ditheringInfo.w; }
|
||||
};
|
||||
using ParametersBuffer = gpu::UniformBuffer<Parameters>;
|
||||
using ParametersBuffer = gpu::StructBuffer<Parameters>;
|
||||
|
||||
private:
|
||||
void updateGaussianDistribution();
|
||||
|
@ -232,7 +212,7 @@ private:
|
|||
|
||||
Parameters() {}
|
||||
};
|
||||
gpu::UniformBuffer<Parameters> _parametersBuffer;
|
||||
gpu::StructBuffer<Parameters> _parametersBuffer;
|
||||
|
||||
const gpu::PipelinePointer& getDebugPipeline();
|
||||
|
||||
|
|
|
@ -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<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];
|
||||
|
@ -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<gpu::State>();
|
||||
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<gpu::State>();
|
||||
// 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<int> 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);
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -10,3 +10,114 @@
|
|||
|
||||
#include "LightClusters.h"
|
||||
|
||||
|
||||
#include <gpu/Context.h>
|
||||
#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<gpu::State>();
|
||||
|
||||
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<DeferredLightingEffect>();
|
||||
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);
|
||||
|
||||
}
|
|
@ -11,12 +11,12 @@
|
|||
#ifndef hifi_render_utils_LightClusters_h
|
||||
#define hifi_render_utils_LightClusters_h
|
||||
|
||||
#include "gpu/Framebuffer.h"
|
||||
|
||||
#include <gpu/Buffer.h>
|
||||
#include <render/Engine.h>
|
||||
#include "LightStage.h"
|
||||
|
||||
#include <ViewFrustum.h>
|
||||
/*
|
||||
|
||||
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<FrustumGrid> _frustrumGridBuffer;
|
||||
|
||||
|
||||
gpu::BufferPointer _lightIndicesBuffer;
|
||||
};
|
||||
|
||||
using LightClustersPointer = std::shared_ptr<LightClusters>;
|
||||
|
||||
|
||||
|
||||
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, Config>;
|
||||
|
||||
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
|
||||
|
|
|
@ -32,6 +32,8 @@ public:
|
|||
using Lights = render::indexed_container::IndexedPointerVector<model::Light>;
|
||||
using LightMap = std::unordered_map<LightPointer, Index>;
|
||||
|
||||
using LightIndices = std::vector<Index>;
|
||||
|
||||
class Shadow {
|
||||
public:
|
||||
using UniformBufferView = gpu::BufferView;
|
||||
|
|
|
@ -190,6 +190,11 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
|
|||
addJob<DrawItemSelection>("DrawItemSelection", spatialSelection);
|
||||
}
|
||||
|
||||
// LIght Cluster Grid Debuging job
|
||||
{
|
||||
addJob<DebugLightClusters>("DebugLightClusters");
|
||||
}
|
||||
|
||||
// Status icon rendering job
|
||||
{
|
||||
// Grab a texture map representing the different status icons and assign that to the drawStatsuJob
|
||||
|
|
|
@ -36,12 +36,12 @@ void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const
|
|||
assert(renderContext->args);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
|
||||
const auto& lightStage = DependencyManager::get<DeferredLightingEffect>()->getLightStage();
|
||||
auto lightStage = DependencyManager::get<DeferredLightingEffect>()->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<DeferredLightingEffect>()->getLightStage();
|
||||
const auto globalShadow = lightStage.getShadow(0);
|
||||
auto lightStage = DependencyManager::get<DeferredLightingEffect>()->getLightStage();
|
||||
const auto globalShadow = lightStage->getShadow(0);
|
||||
|
||||
// If the global light is not set, bail
|
||||
if (!globalShadow) {
|
||||
|
|
|
@ -530,7 +530,7 @@ void DebugSubsurfaceScattering::run(const render::SceneContextPointer& sceneCont
|
|||
|
||||
|
||||
|
||||
const auto light = DependencyManager::get<DeferredLightingEffect>()->getLightStage().getLight(0);
|
||||
const auto light = DependencyManager::get<DeferredLightingEffect>()->getLightStage()->getLight(0);
|
||||
|
||||
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
|
|
19
libraries/render-utils/src/lightClusters_drawGrid.slf
Normal file
19
libraries/render-utils/src/lightClusters_drawGrid.slf
Normal file
|
@ -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;
|
||||
}
|
89
libraries/render-utils/src/lightClusters_drawGrid.slv
Normal file
89
libraries/render-utils/src/lightClusters_drawGrid.slv
Normal file
|
@ -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);
|
||||
}
|
|
@ -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());
|
||||
|
|
|
@ -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 };
|
||||
|
|
Loading…
Reference in a new issue