mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 16:36:54 +02:00
Debugging the grid content
This commit is contained in:
parent
821072bb76
commit
efc4406b47
12 changed files with 379 additions and 22 deletions
|
@ -391,11 +391,14 @@ public:
|
||||||
~StructBuffer<T>() {};
|
~StructBuffer<T>() {};
|
||||||
StructBuffer<T>() : gpu::BufferView(makeBuffer()) {}
|
StructBuffer<T>() : gpu::BufferView(makeBuffer()) {}
|
||||||
|
|
||||||
const T* operator ->() const { return &get<T>(); }
|
|
||||||
T& edit() {
|
T& edit() {
|
||||||
return BufferView::edit<T>(0);
|
return BufferView::edit<T>(0);
|
||||||
}
|
}
|
||||||
|
const T& get() const {
|
||||||
|
return BufferView::get<T>(0);
|
||||||
|
}
|
||||||
|
const T* operator ->() const { return &get(); }
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ const Element Element::VEC2F_UV{ VEC2, FLOAT, UV };
|
||||||
const Element Element::VEC2F_XY{ VEC2, FLOAT, XY };
|
const Element Element::VEC2F_XY{ VEC2, FLOAT, XY };
|
||||||
const Element Element::VEC3F_XYZ{ VEC3, FLOAT, XYZ };
|
const Element Element::VEC3F_XYZ{ VEC3, FLOAT, XYZ };
|
||||||
const Element Element::VEC4F_XYZW{ VEC4, FLOAT, XYZW };
|
const Element Element::VEC4F_XYZW{ VEC4, FLOAT, XYZW };
|
||||||
const Element Element::INDEX_UINT16{ SCALAR, UINT16, INDEX };
|
const Element Element::INDEX_UINT16 { SCALAR, UINT16, INDEX };
|
||||||
|
const Element Element::INDEX_INT32 { SCALAR, INT32, INDEX };
|
||||||
const Element Element::PART_DRAWCALL{ VEC4, UINT32, PART };
|
const Element Element::PART_DRAWCALL{ VEC4, UINT32, PART };
|
||||||
|
|
||||||
|
|
|
@ -236,6 +236,7 @@ public:
|
||||||
static const Element VEC3F_XYZ;
|
static const Element VEC3F_XYZ;
|
||||||
static const Element VEC4F_XYZW;
|
static const Element VEC4F_XYZW;
|
||||||
static const Element INDEX_UINT16;
|
static const Element INDEX_UINT16;
|
||||||
|
static const Element INDEX_INT32;
|
||||||
static const Element PART_DRAWCALL;
|
static const Element PART_DRAWCALL;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -46,4 +46,13 @@ float projection_getFar(mat4 projection) {
|
||||||
|
|
||||||
// end of hybrid include
|
// end of hybrid include
|
||||||
|
|
||||||
|
|
||||||
|
uniform clusterGridBuffer {
|
||||||
|
int _clusterGridTable[10000];
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform clusterContentBuffer {
|
||||||
|
int _clusterGridContent[10000];
|
||||||
|
};
|
||||||
|
|
||||||
<@endif@>
|
<@endif@>
|
||||||
|
|
|
@ -17,11 +17,16 @@ vec3 frustumGrid_gridToVolume(vec3 pos, ivec3 dims) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float frustumGrid_volumeToGridDepth(float vposZ, ivec3 dims) {
|
||||||
|
return frustumGrid_depthRampInverse(vposZ) * float(dims.z);
|
||||||
|
}
|
||||||
|
|
||||||
vec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {
|
vec3 frustumGrid_volumeToGrid(vec3 vpos, ivec3 dims) {
|
||||||
vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverse(vpos.z)) * vec3(dims);
|
vec3 gridPos = vec3(vpos.x, vpos.y, frustumGrid_depthRampInverse(vpos.z)) * vec3(dims);
|
||||||
return gridPos;
|
return gridPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
vec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {
|
vec4 frustumGrid_volumeToClip(vec3 vpos, float rangeNear, float rangeFar) {
|
||||||
vec3 ndcPos = vec3(-1.0 + 2.0 * vpos.x, -1.0 + 2.0 * vpos.y, vpos.z);
|
vec3 ndcPos = vec3(-1.0 + 2.0 * vpos.x, -1.0 + 2.0 * vpos.y, vpos.z);
|
||||||
float depth = rangeNear * (1 - ndcPos.z) + rangeFar * (ndcPos.z);
|
float depth = rangeNear * (1 - ndcPos.z) + rangeFar * (ndcPos.z);
|
||||||
|
@ -42,6 +47,10 @@ vec3 frustumGrid_volumeToEye(vec3 vpos, mat4 projection, float rangeNear, float
|
||||||
return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);
|
return frustumGrid_clipToEye(frustumGrid_volumeToClip(vpos, rangeNear, rangeFar), projection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float frustumGrid_eyeToVolumeDepth(float eposZ, float rangeNear, float rangeFar) {
|
||||||
|
return (-eposZ - rangeNear) / (rangeFar - rangeNear);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
vec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {
|
vec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float rangeFar) {
|
||||||
vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],
|
vec4 clipPos = vec4(epos.x * projection[0][0] + epos.z * projection[2][0],
|
||||||
|
@ -57,7 +66,7 @@ vec3 frustumGrid_eyeToVolume(vec3 epos, mat4 projection, float rangeNear, float
|
||||||
|
|
||||||
|
|
||||||
int frustumGrid_numClusters() {
|
int frustumGrid_numClusters() {
|
||||||
return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z);
|
return frustumGrid.dims.x * frustumGrid.dims.y * (frustumGrid.dims.z + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {
|
vec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {
|
||||||
|
@ -73,6 +82,27 @@ vec3 frustumGrid_clusterPosToEye(ivec3 clusterPos, vec3 offset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int frustumGrid_eyeDepthToClusterLayer(float eyeZ) {
|
||||||
|
if ((eyeZ > -frustumGrid.frustumNear) || (eyeZ < -frustumGrid.frustumFar)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eyeZ > -frustumGrid.rangeNear) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
float volumeZ = frustumGrid_eyeToVolumeDepth(eyeZ, frustumGrid.rangeNear, frustumGrid.rangeFar);
|
||||||
|
|
||||||
|
float gridZ = frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims);
|
||||||
|
|
||||||
|
if (gridZ >= frustumGrid.dims.z) {
|
||||||
|
gridZ = frustumGrid.dims.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return int(gridZ);
|
||||||
|
}
|
||||||
|
|
||||||
ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {
|
ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {
|
||||||
if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {
|
if ((eyePos.z > -frustumGrid.frustumNear) || (eyePos.z < -frustumGrid.frustumFar)) {
|
||||||
return ivec3(-1);
|
return ivec3(-1);
|
||||||
|
|
|
@ -21,6 +21,10 @@
|
||||||
//#include "lightClusters_drawClusterFromDepth_vert.h"
|
//#include "lightClusters_drawClusterFromDepth_vert.h"
|
||||||
#include "lightClusters_drawClusterFromDepth_frag.h"
|
#include "lightClusters_drawClusterFromDepth_frag.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "lightClusters_drawClusterContent_vert.h"
|
||||||
|
#include "lightClusters_drawClusterContent_frag.h"
|
||||||
|
|
||||||
enum LightClusterGridShader_MapSlot {
|
enum LightClusterGridShader_MapSlot {
|
||||||
DEFERRED_BUFFER_LINEAR_DEPTH_UNIT = 0,
|
DEFERRED_BUFFER_LINEAR_DEPTH_UNIT = 0,
|
||||||
};
|
};
|
||||||
|
@ -31,14 +35,32 @@ enum LightClusterGridShader_BufferSlot {
|
||||||
CAMERA_CORRECTION_BUFFER_SLOT,
|
CAMERA_CORRECTION_BUFFER_SLOT,
|
||||||
LIGHT_GPU_SLOT = render::ShapePipeline::Slot::LIGHT,
|
LIGHT_GPU_SLOT = render::ShapePipeline::Slot::LIGHT,
|
||||||
LIGHT_INDEX_GPU_SLOT,
|
LIGHT_INDEX_GPU_SLOT,
|
||||||
|
|
||||||
|
LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT,
|
||||||
|
LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT,
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "DeferredLightingEffect.h"
|
#include "DeferredLightingEffect.h"
|
||||||
|
|
||||||
LightClusters::LightClusters() :
|
LightClusters::LightClusters() :
|
||||||
_lightIndicesBuffer(std::make_shared<gpu::Buffer>()) {
|
_lightIndicesBuffer(std::make_shared<gpu::Buffer>()),
|
||||||
|
_clusterGridBuffer(std::make_shared<gpu::Buffer>(), gpu::Element::INDEX_INT32),
|
||||||
|
_clusterContentBuffer(std::make_shared<gpu::Buffer>(), gpu::Element::INDEX_INT32) {
|
||||||
|
setDimensions(_frustumGridBuffer->dims, 10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LightClusters::setDimensions(glm::uvec3 gridDims, uint32_t listBudget) {
|
||||||
|
_frustumGridBuffer.edit().dims = gridDims;
|
||||||
|
|
||||||
|
_numClusters = _frustumGridBuffer.edit().frustumGrid_numClusters();
|
||||||
|
|
||||||
|
_clusterGridBuffer._size = _clusterGridBuffer._buffer->resize(_numClusters * sizeof(uint32_t));
|
||||||
|
_clusterContentBuffer._size = _clusterContentBuffer._buffer->resize(listBudget * sizeof(uint32_t));
|
||||||
|
_clusterGrid.resize(_numClusters, EMPTY_CLUSTER);
|
||||||
|
_clusterContent.resize(listBudget, INVALID_LIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void LightClusters::updateFrustum(const ViewFrustum& frustum) {
|
void LightClusters::updateFrustum(const ViewFrustum& frustum) {
|
||||||
_frustum = frustum;
|
_frustum = frustum;
|
||||||
|
|
||||||
|
@ -51,23 +73,23 @@ void LightClusters::updateLightStage(const LightStagePointer& lightStage) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightClusters::updateLightFrame(const LightStage::Frame& lightFrame, bool points, bool spots) {
|
void LightClusters::updateLightFrame(const LightStage::Frame& lightFrame, bool points, bool spots) {
|
||||||
|
|
||||||
// start fresh
|
// start fresh
|
||||||
_visibleLightIndices.clear();
|
_visibleLightIndices.clear();
|
||||||
|
|
||||||
// Now gather the lights
|
// Now gather the lights
|
||||||
// gather lights
|
// gather lights
|
||||||
auto& srcPointLights = lightFrame._pointLights;
|
auto& srcPointLights = lightFrame._pointLights;
|
||||||
auto& srcSpotLights = lightFrame._spotLights;
|
auto& srcSpotLights = lightFrame._spotLights;
|
||||||
int numPointLights = (int) srcPointLights.size();
|
int numPointLights = (int)srcPointLights.size();
|
||||||
// int offsetPointLights = 0;
|
// int offsetPointLights = 0;
|
||||||
int numSpotLights = (int) srcSpotLights.size();
|
int numSpotLights = (int)srcSpotLights.size();
|
||||||
// int offsetSpotLights = numPointLights;
|
// int offsetSpotLights = numPointLights;
|
||||||
|
|
||||||
_visibleLightIndices.resize(numPointLights + numSpotLights + 1);
|
_visibleLightIndices.resize(numPointLights + numSpotLights + 1);
|
||||||
|
|
||||||
_visibleLightIndices[0] = 0;
|
_visibleLightIndices[0] = 0;
|
||||||
|
|
||||||
if (points && !srcPointLights.empty()) {
|
if (points && !srcPointLights.empty()) {
|
||||||
memcpy(_visibleLightIndices.data() + (_visibleLightIndices[0] + 1), srcPointLights.data(), srcPointLights.size() * sizeof(int));
|
memcpy(_visibleLightIndices.data() + (_visibleLightIndices[0] + 1), srcPointLights.data(), srcPointLights.size() * sizeof(int));
|
||||||
_visibleLightIndices[0] += (int)srcPointLights.size();
|
_visibleLightIndices[0] += (int)srcPointLights.size();
|
||||||
|
@ -76,11 +98,144 @@ void LightClusters::updateLightFrame(const LightStage::Frame& lightFrame, bool p
|
||||||
memcpy(_visibleLightIndices.data() + (_visibleLightIndices[0] + 1), srcSpotLights.data(), srcSpotLights.size() * sizeof(int));
|
memcpy(_visibleLightIndices.data() + (_visibleLightIndices[0] + 1), srcSpotLights.data(), srcSpotLights.size() * sizeof(int));
|
||||||
_visibleLightIndices[0] += (int)srcSpotLights.size();
|
_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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LightClusters::updateClusters() {
|
||||||
|
// Clean up last info
|
||||||
|
std::vector< std::vector< uint32_t > > clusterGrid(_numClusters);
|
||||||
|
|
||||||
|
_clusterGrid.resize(_numClusters, EMPTY_CLUSTER);
|
||||||
|
uint32_t maxNumIndices = _clusterContent.size();
|
||||||
|
_clusterContent.resize(maxNumIndices, INVALID_LIGHT);
|
||||||
|
|
||||||
|
auto theFrustumGrid(_frustumGridBuffer.get());
|
||||||
|
|
||||||
|
glm::ivec3 gridPosToOffset(1, theFrustumGrid.dims.x, theFrustumGrid.dims.x * theFrustumGrid.dims.y);
|
||||||
|
|
||||||
|
uint32_t numClusterTouched = 0;
|
||||||
|
for (size_t lightNum = 1; lightNum < _visibleLightIndices.size(); ++lightNum) {
|
||||||
|
auto lightId = _visibleLightIndices[lightNum];
|
||||||
|
auto light = _lightStage->getLight(lightId);
|
||||||
|
if (!light)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto worldOri = light->getPosition();
|
||||||
|
auto radius = light->getMaximumRadius();
|
||||||
|
|
||||||
|
// Bring into frustum eye space
|
||||||
|
auto eyeOri = theFrustumGrid.frustumGrid_worldToEye(glm::vec4(worldOri, 1.0f));
|
||||||
|
|
||||||
|
// Remove light that slipped through and is not in the z range
|
||||||
|
float eyeZMax = eyeOri.z - radius;
|
||||||
|
if (eyeZMax > -theFrustumGrid.rangeNear) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
float eyeZMin = eyeOri.z + radius;
|
||||||
|
if (eyeZMin < -theFrustumGrid.rangeFar) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get z slices
|
||||||
|
int zMin = theFrustumGrid.frustumGrid_eyeDepthToClusterLayer(eyeZMin);
|
||||||
|
int zMax = theFrustumGrid.frustumGrid_eyeDepthToClusterLayer(eyeZMax);
|
||||||
|
// That should never happen
|
||||||
|
if (zMin == -1 && zMax == -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
float eyeOriLen2 = glm::length2(eyeOri);
|
||||||
|
|
||||||
|
// CLamp the z range
|
||||||
|
zMin = std::max(0, zMin);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// find 2D corners of the sphere in grid
|
||||||
|
int xMin { 0 };
|
||||||
|
int xMax { theFrustumGrid.dims.x - 1 };
|
||||||
|
int yMin { 0 };
|
||||||
|
int yMax { theFrustumGrid.dims.y - 1 };
|
||||||
|
|
||||||
|
float radius2 = radius * radius;
|
||||||
|
auto eyeOriH = eyeOri;
|
||||||
|
auto eyeOriV = eyeOri;
|
||||||
|
|
||||||
|
eyeOriH.y = 0.0f;
|
||||||
|
eyeOriV.x = 0.0f;
|
||||||
|
|
||||||
|
float eyeOriLen2H = glm::length2(eyeOriH);
|
||||||
|
float eyeOriLen2V = glm::length2(eyeOriV);
|
||||||
|
|
||||||
|
if ((eyeOriLen2H > radius2) && (eyeOriLen2V > radius2)) {
|
||||||
|
float eyeOriLenH = sqrt(eyeOriLen2H);
|
||||||
|
float eyeOriLenV = sqrt(eyeOriLen2V);
|
||||||
|
|
||||||
|
auto eyeOriDirH = glm::vec3(eyeOriH) / eyeOriLenH;
|
||||||
|
auto eyeOriDirV = glm::vec3(eyeOriV) / eyeOriLenV;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
float eyeToTangentCircleLenH = sqrt(eyeOriLen2H - radius2);
|
||||||
|
float eyeToTangentCircleLenV = sqrt(eyeOriLen2V - radius2);
|
||||||
|
|
||||||
|
float eyeToTangentCircleTanH = radius / eyeToTangentCircleLenH;
|
||||||
|
float eyeToTangentCircleTanV = radius / eyeToTangentCircleLenV;
|
||||||
|
|
||||||
|
float eyeToTangentCircleCosH = eyeToTangentCircleLenH / eyeOriLenH;
|
||||||
|
float eyeToTangentCircleCosV = eyeToTangentCircleLenV / eyeOriLenV;
|
||||||
|
|
||||||
|
float eyeToTangentCircleSinH = radius / eyeOriLenH;
|
||||||
|
float eyeToTangentCircleSinV = radius / eyeOriLenV;
|
||||||
|
|
||||||
|
|
||||||
|
// rotate the eyeToOriDir (H & V) in both directions
|
||||||
|
glm::vec3 leftDir(eyeOriDirH.x * eyeToTangentCircleCosH - eyeOriDirH.z * eyeToTangentCircleSinH, 0.0f, eyeOriDirH.x * eyeToTangentCircleSinH + eyeOriDirH.z * eyeToTangentCircleCosH);
|
||||||
|
glm::vec3 rightDir(eyeOriDirH.x * eyeToTangentCircleCosH + eyeOriDirH.z * eyeToTangentCircleSinH, 0.0f, eyeOriDirH.x * -eyeToTangentCircleSinH + eyeOriDirH.z * eyeToTangentCircleCosH);
|
||||||
|
glm::vec3 bottomDir(0.0f, eyeOriDirV.y * eyeToTangentCircleCosV - eyeOriDirV.z * eyeToTangentCircleSinV, eyeOriDirV.y * eyeToTangentCircleSinV + eyeOriDirV.z * eyeToTangentCircleCosV);
|
||||||
|
glm::vec3 topDir(0.0f, eyeOriDirV.y * eyeToTangentCircleCosV + eyeOriDirV.z * eyeToTangentCircleSinV, eyeOriDirV.y * -eyeToTangentCircleSinV + eyeOriDirV.z * eyeToTangentCircleCosV);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// now voxelize
|
||||||
|
for (auto z = zMin; z <= zMax; z++) {
|
||||||
|
for (auto y = yMin; y <= yMax; y++) {
|
||||||
|
for (auto x = xMin; x <= xMax; x++) {
|
||||||
|
auto index = x + gridPosToOffset.y * y + gridPosToOffset.z * z;
|
||||||
|
clusterGrid[index].emplace_back(lightId);
|
||||||
|
numClusterTouched++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lights have been gathered now reexpress in terms of 2 sequential buffers
|
||||||
|
|
||||||
|
uint16_t indexOffset = 0;
|
||||||
|
for (int i = 0; i < clusterGrid.size(); i++) {
|
||||||
|
auto& cluster = clusterGrid[i];
|
||||||
|
uint16_t numLights = ((uint16_t)cluster.size());
|
||||||
|
uint16_t offset = indexOffset;
|
||||||
|
|
||||||
|
_clusterGrid[i] = (uint32_t)((numLights << 16) | offset);
|
||||||
|
|
||||||
|
if (numLights) {
|
||||||
|
memcpy(_clusterContent.data() + indexOffset, cluster.data(), numLights * sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
indexOffset += numLights;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the buffers
|
||||||
|
_clusterGridBuffer._buffer->setData(_clusterGridBuffer._size, (gpu::Byte*) _clusterGrid.data());
|
||||||
|
_clusterContentBuffer._buffer->setSubData(0, indexOffset * sizeof(uint32_t), (gpu::Byte*) _clusterContent.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LightClusteringPass::LightClusteringPass() {
|
LightClusteringPass::LightClusteringPass() {
|
||||||
}
|
}
|
||||||
|
@ -122,6 +277,8 @@ void LightClusteringPass::run(const render::SceneContextPointer& sceneContext, c
|
||||||
_lightClusters->updateLightStage(lightStage);
|
_lightClusters->updateLightStage(lightStage);
|
||||||
_lightClusters->updateLightFrame(lightStage->_currentFrame, lightingModel->isPointLightEnabled(), lightingModel->isSpotLightEnabled());
|
_lightClusters->updateLightFrame(lightStage->_currentFrame, lightingModel->isPointLightEnabled(), lightingModel->isSpotLightEnabled());
|
||||||
|
|
||||||
|
_lightClusters->updateClusters();
|
||||||
|
|
||||||
output = _lightClusters;
|
output = _lightClusters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,6 +347,35 @@ const gpu::PipelinePointer DebugLightClusters::getDrawClusterFromDepthPipeline()
|
||||||
return _drawClusterFromDepth;
|
return _drawClusterFromDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const gpu::PipelinePointer DebugLightClusters::getDrawClusterContentPipeline() {
|
||||||
|
if (!_drawClusterContent) {
|
||||||
|
auto vs = gpu::Shader::createVertex(std::string(lightClusters_drawClusterContent_vert));
|
||||||
|
auto ps = gpu::Shader::createPixel(std::string(lightClusters_drawClusterContent_frag));
|
||||||
|
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||||
|
|
||||||
|
gpu::Shader::BindingSet slotBindings;
|
||||||
|
slotBindings.insert(gpu::Shader::Binding(std::string("frustumGridBuffer"), LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT));
|
||||||
|
slotBindings.insert(gpu::Shader::Binding(std::string("clusterGridBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT));
|
||||||
|
slotBindings.insert(gpu::Shader::Binding(std::string("clusterContentBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_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
|
||||||
|
_drawClusterContent = gpu::Pipeline::create(program, state);
|
||||||
|
}
|
||||||
|
return _drawClusterContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs) {
|
void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& inputs) {
|
||||||
auto deferredTransform = inputs.get0();
|
auto deferredTransform = inputs.get0();
|
||||||
auto deferredFramebuffer = inputs.get1();
|
auto deferredFramebuffer = inputs.get1();
|
||||||
|
@ -232,6 +418,17 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co
|
||||||
batch.setResourceTexture(DEFERRED_BUFFER_LINEAR_DEPTH_UNIT, nullptr);
|
batch.setResourceTexture(DEFERRED_BUFFER_LINEAR_DEPTH_UNIT, nullptr);
|
||||||
batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, nullptr);
|
batch.setUniformBuffer(DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (doDrawContent) {
|
||||||
|
// bind the one gpu::Pipeline we need
|
||||||
|
batch.setPipeline(getDrawClusterContentPipeline());
|
||||||
|
batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer);
|
||||||
|
batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, lightClusters->_clusterContentBuffer);
|
||||||
|
|
||||||
|
auto dims = lightClusters->_frustumGridBuffer->dims;
|
||||||
|
glm::ivec3 summedDims(dims.x*dims.y * dims.z, dims.x*dims.y, dims.x);
|
||||||
|
batch.drawInstanced(summedDims.x, gpu::LINES, 24, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (doDrawGrid) {
|
if (doDrawGrid) {
|
||||||
// bind the one gpu::Pipeline we need
|
// bind the one gpu::Pipeline we need
|
||||||
|
|
|
@ -57,12 +57,16 @@ public:
|
||||||
|
|
||||||
LightClusters();
|
LightClusters();
|
||||||
|
|
||||||
|
void setDimensions(glm::uvec3 gridDims, uint32_t listBudget);
|
||||||
|
|
||||||
void updateFrustum(const ViewFrustum& frustum);
|
void updateFrustum(const ViewFrustum& frustum);
|
||||||
|
|
||||||
void updateLightStage(const LightStagePointer& lightStage);
|
void updateLightStage(const LightStagePointer& lightStage);
|
||||||
|
|
||||||
void updateLightFrame(const LightStage::Frame& lightFrame, bool points = true, bool spots = true);
|
void updateLightFrame(const LightStage::Frame& lightFrame, bool points = true, bool spots = true);
|
||||||
|
|
||||||
|
void updateClusters();
|
||||||
|
|
||||||
ViewFrustum _frustum;
|
ViewFrustum _frustum;
|
||||||
|
|
||||||
LightStagePointer _lightStage;
|
LightStagePointer _lightStage;
|
||||||
|
@ -72,8 +76,17 @@ public:
|
||||||
gpu::StructBuffer<FrustumGrid> _frustumGridBuffer;
|
gpu::StructBuffer<FrustumGrid> _frustumGridBuffer;
|
||||||
|
|
||||||
LightStage::LightIndices _visibleLightIndices;
|
LightStage::LightIndices _visibleLightIndices;
|
||||||
|
|
||||||
gpu::BufferView _lightIndicesBuffer;
|
gpu::BufferView _lightIndicesBuffer;
|
||||||
|
|
||||||
|
uint32_t _numClusters { 0 };
|
||||||
|
|
||||||
|
const uint32_t EMPTY_CLUSTER { 0x0000FFFF };
|
||||||
|
const uint32_t INVALID_LIGHT { 0xFFFFFFFF };
|
||||||
|
|
||||||
|
std::vector<uint32_t> _clusterGrid;
|
||||||
|
std::vector<uint32_t> _clusterContent;
|
||||||
|
gpu::BufferView _clusterGridBuffer;
|
||||||
|
gpu::BufferView _clusterContentBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
using LightClustersPointer = std::shared_ptr<LightClusters>;
|
using LightClustersPointer = std::shared_ptr<LightClusters>;
|
||||||
|
@ -162,10 +175,13 @@ protected:
|
||||||
gpu::BufferPointer _gridBuffer;
|
gpu::BufferPointer _gridBuffer;
|
||||||
gpu::PipelinePointer _drawClusterGrid;
|
gpu::PipelinePointer _drawClusterGrid;
|
||||||
gpu::PipelinePointer _drawClusterFromDepth;
|
gpu::PipelinePointer _drawClusterFromDepth;
|
||||||
|
gpu::PipelinePointer _drawClusterContent;
|
||||||
const gpu::PipelinePointer getDrawClusterGridPipeline();
|
const gpu::PipelinePointer getDrawClusterGridPipeline();
|
||||||
const gpu::PipelinePointer getDrawClusterFromDepthPipeline();
|
const gpu::PipelinePointer getDrawClusterFromDepthPipeline();
|
||||||
|
const gpu::PipelinePointer getDrawClusterContentPipeline();
|
||||||
bool doDrawGrid{ false };
|
bool doDrawGrid{ false };
|
||||||
bool doDrawClusterFromDepth{ false };
|
bool doDrawClusterFromDepth { false };
|
||||||
|
bool doDrawContent { true };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -55,6 +55,7 @@ void LightPayload::render(RenderArgs* args) {
|
||||||
// Do we need to allocate the light in the stage ?
|
// Do we need to allocate the light in the stage ?
|
||||||
if (LightStage::isIndexInvalid(_index)) {
|
if (LightStage::isIndexInvalid(_index)) {
|
||||||
_index = _stage->addLight(_light);
|
_index = _stage->addLight(_light);
|
||||||
|
_needUpdate = false;
|
||||||
}
|
}
|
||||||
// Need an update ?
|
// Need an update ?
|
||||||
if (_needUpdate) {
|
if (_needUpdate) {
|
||||||
|
|
|
@ -146,8 +146,12 @@ void LightStage::updateLightArrayBuffer(Index lightId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// lightArray is big enough so we can remap
|
// lightArray is big enough so we can remap
|
||||||
auto& light = _lights._elements[lightId];
|
auto light = _lights._elements[lightId];
|
||||||
auto lightSchema = light->getSchemaBuffer().get<model::Light::Schema>();
|
if (light) {
|
||||||
_lightArrayBuffer->setSubData<model::Light::Schema>(lightId, lightSchema);
|
auto lightSchema = light->getSchemaBuffer().get<model::Light::Schema>();
|
||||||
|
_lightArrayBuffer->setSubData<model::Light::Schema>(lightId, lightSchema);
|
||||||
|
} else {
|
||||||
|
// this should not happen ?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -192,7 +192,9 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) {
|
||||||
const auto debugFramebuffers = render::Varying(DebugDeferredBuffer::Inputs(deferredFramebuffer, linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer));
|
const auto debugFramebuffers = render::Varying(DebugDeferredBuffer::Inputs(deferredFramebuffer, linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer));
|
||||||
addJob<DebugDeferredBuffer>("DebugDeferredBuffer", debugFramebuffers);
|
addJob<DebugDeferredBuffer>("DebugDeferredBuffer", debugFramebuffers);
|
||||||
|
|
||||||
addJob<DebugSubsurfaceScattering>("DebugScattering", deferredLightingInputs);
|
const auto debugSubsurfaceScatteringInputs = DebugSubsurfaceScattering::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel,
|
||||||
|
surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource).hasVarying();
|
||||||
|
addJob<DebugSubsurfaceScattering>("DebugScattering", debugSubsurfaceScatteringInputs);
|
||||||
|
|
||||||
const auto debugAmbientOcclusionInputs = DebugAmbientOcclusion::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget, ambientOcclusionUniforms).hasVarying();
|
const auto debugAmbientOcclusionInputs = DebugAmbientOcclusion::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget, ambientOcclusionUniforms).hasVarying();
|
||||||
addJob<DebugAmbientOcclusion>("DebugAmbientOcclusion", debugAmbientOcclusionInputs);
|
addJob<DebugAmbientOcclusion>("DebugAmbientOcclusion", debugAmbientOcclusionInputs);
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
<@include gpu/Config.slh@>
|
||||||
|
<$VERSION_HEADER$>
|
||||||
|
// Generated on <$_SCRIBE_DATE$>
|
||||||
|
// lightClusters_drawClusterContent.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;
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
<@include gpu/Config.slh@>
|
||||||
|
<$VERSION_HEADER$>
|
||||||
|
// Generated on <$_SCRIBE_DATE$>
|
||||||
|
//
|
||||||
|
// lightClusters_drawClusterContent.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 LightClusterGrid.slh@>
|
||||||
|
|
||||||
|
<@include gpu/Color.slh@>
|
||||||
|
<$declareColorWheel()$>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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]];
|
||||||
|
|
||||||
|
ivec3 dims = frustumGrid.dims.xyz;
|
||||||
|
|
||||||
|
ivec3 summedDims = ivec3(dims.x * dims.y, dims.x, 1);
|
||||||
|
|
||||||
|
int layer = gl_InstanceID / summedDims.x;
|
||||||
|
int offsetInLayer = gl_InstanceID % summedDims.x;
|
||||||
|
ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);
|
||||||
|
|
||||||
|
|
||||||
|
vec3 eyePos = frustumGrid_clusterPosToEye(clusterPos, vec3(0.05) + 0.9 * pos.xyz);
|
||||||
|
vec4 worldPos = frustumGrid_eyeToWorld(vec4(eyePos.xyz, 1.0));
|
||||||
|
|
||||||
|
|
||||||
|
// standard transform
|
||||||
|
TransformCamera cam = getTransformCamera();
|
||||||
|
<$transformWorldToClipPos(cam, worldPos, gl_Position)$>
|
||||||
|
|
||||||
|
varColor = vec4(colorWheel(fract(float(gl_InstanceID) / float(frustumGrid_numClusters()))), 0.9);
|
||||||
|
}
|
Loading…
Reference in a new issue