Fixing Depth culling out of bounds errors

This commit is contained in:
Dynamitos
2024-08-29 11:23:55 +02:00
parent 6eb114e892
commit 0be1a3cbde
9 changed files with 136 additions and 44 deletions
+36 -17
View File
@@ -1,6 +1,7 @@
import Common;
import Scene;
import Bounding;
import DepthCommon;
groupshared MeshPayload p;
groupshared uint head;
@@ -10,37 +11,55 @@ groupshared Frustum viewFrustum;
groupshared float4x4 modelViewProjection;
groupshared bool meshVisible;
struct DepthData
{
Texture2D<float> texture;
RWStructuredBuffer<float> buffer;
}
//void writeDebug(uint mipLevel, uint mipOffset, int2 mipDimensions, int2 screenMin, int2 screenMax, int2 origScreenMin, int2 origScreenMax)
//{
// uint index = 0;
// InterlockedAdd(pDepthAttachment.debugHead[0], 1, index);
// index = min(index, 10000);
// {
// pDepthAttachment.debugData[index].mipLevel = mipLevel;
// pDepthAttachment.debugData[index].mipOffset = mipOffset;
// pDepthAttachment.debugData[index].mipDimensions = mipDimensions;
// pDepthAttachment.debugData[index].screenCornerMax = screenMax;
// pDepthAttachment.debugData[index].screenCornerMin = screenMin;
// pDepthAttachment.debugData[index].origScreenMax = origScreenMax;
// pDepthAttachment.debugData[index].origScreenMin = origScreenMin;
// }
//}
ParameterBlock<DepthData> pDepthAttachment;
bool isBoxVisible(AABB bounding)
{
uint2 mipDimensions = uint2(uint(pViewParams.screenDimensions.x), uint(pViewParams.screenDimensions.y));
int2 mipDimensions = uint2(uint(pViewParams.screenDimensions.x), uint(pViewParams.screenDimensions.y));
// now we calculate what mip level we need to only sample up to 4 texels covering the entire meshlet
uint2 screenCornerMin = mipDimensions;
uint2 screenCornerMax = uint2(0, 0);
int2 screenCornerMin = mipDimensions;
int2 screenCornerMax = uint2(0, 0);
// lower values are closer
float maxDepth = bounding.projectScreenDepth(modelViewProjection, screenCornerMin, screenCornerMax);
uint mipOffset = 0;
// uint mipLevel = 0;
// int2 origScreenMin = screenCornerMin;
// int2 origScreenMax = screenCornerMax;
// in theory this wouldnt work if no corner was in screen, as min would be greater that max, however we verified that with view culling
while(screenCornerMax.x - screenCornerMin.x > 1 || screenCornerMax.y - screenCornerMin.y > 1)
{
// mipLevel++;
mipOffset += mipDimensions.x * mipDimensions.y;
mipDimensions = uint2(mipDimensions.x + 1, mipDimensions.y + 1) / 2;
screenCornerMin = uint2(screenCornerMin.x + 1, screenCornerMin.y + 1) / 2;
screenCornerMax = uint2(screenCornerMax.x, screenCornerMax.y) / 2;
mipDimensions = int2(mipDimensions.x + 1, mipDimensions.y + 1) / 2;
screenCornerMin = int2(screenCornerMin.x + 1, screenCornerMin.y + 1) / 2;
screenCornerMax = int2(screenCornerMax.x, screenCornerMax.y) / 2;
}
uint i0 = mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMin.x;
uint i1 = mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMax.x;
uint i2 = mipOffset + (screenCornerMax.y * mipDimensions.x) + screenCornerMin.x;
uint i3 = mipOffset + (screenCornerMax.y * mipDimensions.x) + screenCornerMax.x;
// now we sample 4 texels from the depth at the calculated mip level, this should give us the screen extent of the meshlet
float d1 = pDepthAttachment.buffer[mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMin.x];
float d2 = pDepthAttachment.buffer[mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMax.x];
float d3 = pDepthAttachment.buffer[mipOffset + (screenCornerMax.y * mipDimensions.x) + screenCornerMin.x];
float d4 = pDepthAttachment.buffer[mipOffset + (screenCornerMax.y * mipDimensions.x) + screenCornerMax.x];
float d1 = pDepthAttachment.buffer[i0];
float d2 = pDepthAttachment.buffer[i1];
float d3 = pDepthAttachment.buffer[i2];
float d4 = pDepthAttachment.buffer[i3];
// we want to check if the minimum depth (the value farthest away) is smaller than the maximum bounding box depth
// otherwise, there is no way for the meshlet to be visible
@@ -102,7 +121,7 @@ void taskMain(
{
#ifdef DEPTH_CULLING
// if the meshlet bounding box is behind the cached depth buffer, we skip
//if(isBoxVisible(meshlet.bounding))
if(isBoxVisible(meshlet.bounding))
#endif
{
uint index;