Better vizualization, first set of culling improvment

This commit is contained in:
samcake 2016-09-14 16:36:01 -07:00
parent af48d4f0bd
commit fdba78db6f
5 changed files with 76 additions and 46 deletions

View file

@ -123,6 +123,38 @@ ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) {
return ivec3(gridPos);
}
int frustumGrid_eyeToClusterDirH(vec3 eyeDir) {
if (eyeDir.z >= 0.0) {
return (eyeDir.x > 0 ? frustumGrid.dims.x : -1);
}
float eyeDepth = -eyeDir.z;
float nclipDir = eyeDir.x / eyeDepth;
float ndcDir = nclipDir * frustumGrid.eyeToGridProj[0][0] - frustumGrid.eyeToGridProj[2][0];
float volumeDir = 0.5 * (ndcDir + 1.0);
float gridPos = volumeDir * float(frustumGrid.dims.x);
return int(gridPos);
}
int frustumGrid_eyeToClusterDirV(vec3 eyeDir) {
if (eyeDir.z >= 0.0) {
return (eyeDir.y > 0 ? frustumGrid.dims.y : -1);
}
float eyeDepth = -eyeDir.z;
float nclipDir = eyeDir.y / eyeDepth;
float ndcDir = nclipDir * frustumGrid.eyeToGridProj[1][1] - frustumGrid.eyeToGridProj[2][1];
float volumeDir = 0.5 * (ndcDir + 1.0);
float gridPos = volumeDir * float(frustumGrid.dims.y);
return int(gridPos);
}
ivec2 frustumGrid_eyeToClusterDir(vec3 eyeDir) {
return ivec2(frustumGrid_eyeToClusterDirH(eyeDir), frustumGrid_eyeToClusterDirV(eyeDir));
}
vec4 frustumGrid_eyeToWorld(vec4 eyePos) {
return frustumGrid.eyeToWorldMat * eyePos;
}

View file

@ -124,6 +124,27 @@ void LightClusters::updateLightFrame(const LightStage::Frame& lightFrame, bool p
_lightIndicesBuffer._size = _visibleLightIndices.size() * sizeof(int);
}
bool scanLightVolume(FrustumGrid& grid, int zMin, int zMax, int yMin, int yMax, int xMin, int xMax, LightClusters::LightID lightId, const glm::vec4& eyePosRadius,
uint32_t& numClustersTouched, int maxNumIndices, std::vector< std::vector<LightClusters::LightID>>& clusterGrid) {
glm::ivec3 gridPosToOffset(1, grid.dims.x, grid.dims.x * grid.dims.y);
bool hasBudget = true;
for (auto z = zMin; (z <= zMax) && hasBudget; z++) {
for (auto y = yMin; (y <= yMax) && hasBudget; y++) {
for (auto x = xMin; (x <= xMax) && hasBudget; x++) {
auto index = x + gridPosToOffset.y * y + gridPosToOffset.z * z;
clusterGrid[index].emplace_back(lightId);
numClustersTouched++;
if (numClustersTouched >= maxNumIndices) {
hasBudget = false;
}
}
}
}
return hasBudget;
}
void LightClusters::updateClusters() {
// Clean up last info
std::vector< std::vector< LightID > > clusterGrid(_numClusters);
@ -167,7 +188,8 @@ void LightClusters::updateClusters() {
continue;
}
// is it a light whose origin is behind the near ?
bool behindLight = (eyeOri.z >= -theFrustumGrid.rangeNear);
//
float eyeOriLen2 = glm::length2(eyeOri);
@ -199,8 +221,6 @@ void LightClusters::updateClusters() {
float eyeToTangentCircleLenH = sqrt(eyeOriLen2H - radius2);
float eyeToTangentCircleTanH = radius / eyeToTangentCircleLenH;
float eyeToTangentCircleCosH = eyeToTangentCircleLenH / eyeOriLenH;
float eyeToTangentCircleSinH = radius / eyeOriLenH;
@ -210,15 +230,11 @@ void LightClusters::updateClusters() {
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);
auto lc = theFrustumGrid.frustumGrid_eyeToClusterDirH(leftDir);
auto rc = theFrustumGrid.frustumGrid_eyeToClusterDirH(rightDir);
glm::vec3 leftPosAtNear = leftDir * theFrustumGrid.rangeNear * 2.0f;
glm::vec3 rightPosAtNear = rightDir * theFrustumGrid.rangeNear * 2.0f;
auto lc = theFrustumGrid.frustumGrid_eyeToClusterPos(leftPosAtNear);
auto rc = theFrustumGrid.frustumGrid_eyeToClusterPos(rightPosAtNear);
xMin = std::max(0, lc.x);
xMax = std::max(0, std::min(rc.x, xMax));
xMin = std::max(xMin, lc);
xMax = std::max(0, std::min(rc, xMax));
}
if ((eyeOriLen2V > radius2)) {
@ -226,12 +242,8 @@ void LightClusters::updateClusters() {
auto eyeOriDirV = glm::vec3(eyeOriV) / eyeOriLenV;
float eyeToTangentCircleLenV = sqrt(eyeOriLen2V - radius2);
float eyeToTangentCircleTanV = radius / eyeToTangentCircleLenV;
float eyeToTangentCircleCosV = eyeToTangentCircleLenV / eyeOriLenV;
float eyeToTangentCircleSinV = radius / eyeOriLenV;
@ -241,29 +253,17 @@ void LightClusters::updateClusters() {
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);
auto bc = theFrustumGrid.frustumGrid_eyeToClusterDirV(bottomDir);
auto tc = theFrustumGrid.frustumGrid_eyeToClusterDirV(topDir);
glm::vec3 bottomPosAtNear = bottomDir * theFrustumGrid.rangeNear * 2.0f;
glm::vec3 topPosAtNear = topDir * theFrustumGrid.rangeNear * 2.0f;
auto bc = theFrustumGrid.frustumGrid_eyeToClusterPos(bottomPosAtNear);
auto tc = theFrustumGrid.frustumGrid_eyeToClusterPos(topPosAtNear);
yMin = std::max(0, bc.y);
yMax = std::max(0, std::min(tc.y, yMax));
yMin = std::max(yMin, bc);
yMax = std::max(yMin, std::min(tc, yMax));
}
// 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++;
}
}
}
bool hasBudget = scanLightVolume(theFrustumGrid, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), numClusterTouched, maxNumIndices, clusterGrid);
if (numClusterTouched >= maxNumIndices) {
if (!hasBudget) {
break;
}
}
@ -486,6 +486,7 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co
}
if (doDrawContent) {
// bind the one gpu::Pipeline we need
batch.setPipeline(getDrawClusterContentPipeline());

View file

@ -74,7 +74,7 @@ public:
LightStagePointer _lightStage;
gpu::StructBuffer<FrustumGrid> _frustumGridBuffer;

View file

@ -1,4 +1,4 @@
<@include gpu/Config.slh@>
<@include gpu / Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
@ -12,17 +12,15 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include gpu/Transform.slh@>
<@include gpu / Transform.slh@>
<$declareStandardTransform()$>
<@include LightClusterGrid.slh@>
<@include gpu/Color.slh@>
<@include gpu / Color.slh@>
<$declareColorWheel()$>
out vec4 varColor;

View file

@ -53,16 +53,15 @@ void main(void) {
);
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);
ivec2 cluster = clusterGrid_getCluster(gl_InstanceID);
int numLights = cluster.x;
int layer = gl_InstanceID / summedDims.x;
int offsetInLayer = gl_InstanceID % summedDims.x;
ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);
ivec3 clusterPos = clusterGrid_indexToCluster(gl_InstanceID);
vec3 eyePos = frustumGrid_clusterPosToEye(clusterPos, vec3(0.05) + 0.9 * pos.xyz);
float boxScale = 1.0;
vec3 eyePos = frustumGrid_clusterPosToEye(clusterPos, vec3(1.0 - boxScale) * 0.5 + boxScale * pos.xyz);
vec4 worldPos = frustumGrid_eyeToWorld(vec4(eyePos.xyz, 1.0));
@ -70,5 +69,5 @@ void main(void) {
TransformCamera cam = getTransformCamera();
<$transformWorldToClipPos(cam, worldPos, gl_Position)$>
varColor = vec4(colorWheel(fract(float(gl_InstanceID) / float(frustumGrid_numClusters()))), 0.9);
varColor = vec4(colorWheel(fract(float(gl_InstanceID) / float(frustumGrid_numClusters()))), (numLights > 0 ? 0.9 : 0.0));
}