Improved the culling result of HizCulling;
Added custom inspector for VolumeObject; Change the name of AoVolume to VolumeObject;
This commit is contained in:
@@ -5,16 +5,17 @@
|
||||
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
|
||||
#include "Packages/com.misaki.ao-volume/Runtime/Shader/Includes/GeometryData.cs.hlsl"
|
||||
|
||||
#define FLT_MIN 1.175494351e-38 // Minimum representable positive floating-point number
|
||||
#define FLT_MAX 3.402823466e+38 // Maximum representable floating-point number
|
||||
#define _FLT_MIN 1.175494351e-38 // Minimum representable positive floating-point number
|
||||
#define _FLT_MAX 3.402823466e+38 // Maximum representable floating-point number
|
||||
|
||||
#define _CORNERS_COUNT 8
|
||||
|
||||
uint _FullVolumeCount;
|
||||
uint _DepthPyramidMaxMip;
|
||||
|
||||
StructuredBuffer<OrientedBoundingBox> _VolumeBounds;
|
||||
StructuredBuffer<int2> _DepthPyramidMipLevelOffsets;
|
||||
|
||||
uint _FullVolumeCount;
|
||||
|
||||
uint _DepthPyramidMaxMip;
|
||||
|
||||
RWByteAddressBuffer _VisibleVolumeCount : register(u0);
|
||||
RWByteAddressBuffer _VisibleVolumeIndices : register(u1);
|
||||
|
||||
@@ -37,40 +38,12 @@ float SampleDepthLod(int2 uv, int lod)
|
||||
return deviceDepth;
|
||||
}
|
||||
|
||||
float GetOccluderDepth(float2 screenMin, float2 screenMax)
|
||||
{
|
||||
float rectWidth = (screenMax.x - screenMin.x);
|
||||
float rectHeight = (screenMax.y - screenMin.y);
|
||||
float rectSize = max(rectWidth, rectHeight);
|
||||
|
||||
int maxMipLevel = min(_DepthPyramidMaxMip, 14);
|
||||
int mipLevel = clamp((int)ceil(log2(rectSize)), 0, maxMipLevel);
|
||||
|
||||
float4 boxUV = float4(screenMin, screenMax);
|
||||
|
||||
const int depthSampleCount = 5;
|
||||
float occluderDepth[depthSampleCount];
|
||||
occluderDepth[0] = SampleDepthLod(boxUV.xy, mipLevel);
|
||||
occluderDepth[1] = SampleDepthLod(boxUV.xw, mipLevel);
|
||||
occluderDepth[2] = SampleDepthLod(boxUV.zy, mipLevel);
|
||||
occluderDepth[3] = SampleDepthLod(boxUV.zw, mipLevel);
|
||||
occluderDepth[4] = SampleDepthLod((screenMin + screenMax) * 0.5, mipLevel);
|
||||
|
||||
float minDepth = 1.0;
|
||||
for (int i = 0; i < depthSampleCount; ++i)
|
||||
{
|
||||
minDepth = min(minDepth, occluderDepth[i]);
|
||||
}
|
||||
|
||||
return minDepth;
|
||||
}
|
||||
|
||||
[numthreads(64,1,1)]
|
||||
void CSMain(uint3 dispatchThreadId : SV_DispatchThreadID)
|
||||
{
|
||||
if (dispatchThreadId.x >= _FullVolumeCount)
|
||||
{
|
||||
return; // early exit if outside our range
|
||||
return;
|
||||
}
|
||||
|
||||
OrientedBoundingBox box = _VolumeBounds[dispatchThreadId.x];
|
||||
@@ -83,7 +56,7 @@ void CSMain(uint3 dispatchThreadId : SV_DispatchThreadID)
|
||||
float3 forward = normalize(cross(box.right, box.up));
|
||||
float3 forwardExtent = forward * box.extent.z;
|
||||
|
||||
float3 corners[8];
|
||||
float3 corners[_CORNERS_COUNT];
|
||||
corners[0] = box.center + rightExtent + upExtent + forwardExtent;
|
||||
corners[1] = box.center + rightExtent + upExtent - forwardExtent;
|
||||
corners[2] = box.center + rightExtent - upExtent + forwardExtent;
|
||||
@@ -93,36 +66,53 @@ void CSMain(uint3 dispatchThreadId : SV_DispatchThreadID)
|
||||
corners[6] = box.center - rightExtent - upExtent + forwardExtent;
|
||||
corners[7] = box.center - rightExtent - upExtent - forwardExtent;
|
||||
|
||||
// Compute screen-space bounding rectangle and find the minimum depth (closest point)
|
||||
float2 screenMin = float2(FLT_MAX, FLT_MAX);
|
||||
float2 screenMax = float2(-FLT_MAX, -FLT_MAX);
|
||||
float boxMaxDepth = -FLT_MAX;
|
||||
|
||||
// Compute screen-space bounding rectangle and find the maximum depth (closest point)
|
||||
float2 screenMin = float2(_FLT_MAX, _FLT_MAX);
|
||||
float2 screenMax = float2(-_FLT_MAX, -_FLT_MAX);
|
||||
float boxMaxDepth = 0.0;
|
||||
|
||||
float2 cornerPositionSS[_CORNERS_COUNT];
|
||||
|
||||
[unroll]
|
||||
for (int j = 0; j < 8; ++j)
|
||||
for (int i = 0; i < _CORNERS_COUNT; i++)
|
||||
{
|
||||
float3 cornerRWS = GetCameraRelativePositionWS(corners[j]);
|
||||
float3 cornerRWS = GetCameraRelativePositionWS(corners[i]);
|
||||
float4 positionCS = TransformWorldToHClip(cornerRWS);
|
||||
positionCS /= positionCS.w;
|
||||
|
||||
float2 screenPos = ComputeScreenPos(positionCS, _ProjectionParams.x).xy * _ScreenSize.xy;
|
||||
float2 screenPos = ComputeScreenPos(positionCS, _ProjectionParams.x).xy;
|
||||
|
||||
screenMin = min(screenMin, screenPos);
|
||||
screenMax = max(screenMax, screenPos);
|
||||
|
||||
boxMaxDepth = max(boxMaxDepth, positionCS.z);
|
||||
cornerPositionSS[i] = screenPos * _ScreenSize.xy;
|
||||
}
|
||||
|
||||
float occluderDepth = GetOccluderDepth(screenMin, screenMax);
|
||||
float rectWidth = (screenMax.x - screenMin.x);
|
||||
float rectHeight = (screenMax.y - screenMin.y);
|
||||
float rectSize = max(rectWidth, rectHeight);
|
||||
|
||||
// Perform the occlusion test:
|
||||
// If the closest point of the box (boxMaxDepth) is behind the occluder,
|
||||
// then the box is completely occluded.
|
||||
// TODO: pack 16 bits index to save memory
|
||||
if (occluderDepth <= boxMaxDepth)
|
||||
int maxMipLevel = min(_DepthPyramidMaxMip, 14);
|
||||
int mipLevel = (int)ceil((float)maxMipLevel - max(log2(1.0 / (rectSize * rectSize)), 0));
|
||||
|
||||
[unroll]
|
||||
for (int j = 0; j < _CORNERS_COUNT; j++)
|
||||
{
|
||||
uint index;
|
||||
_VisibleVolumeCount.InterlockedAdd(0, 1, index);
|
||||
_VisibleVolumeIndices.Store(index << 2, dispatchThreadId.x);
|
||||
float2 uv = cornerPositionSS[j];
|
||||
float occluderDepth = SampleDepthLod(uv, mipLevel);
|
||||
|
||||
// Perform the occlusion test:
|
||||
// If the closest point of the box (boxMaxDepth) is behind the occluder, then the box is completely occluded.
|
||||
// Note that depth buffer in hdrp is stored in a non-normalized reversed range [0, 1] (0 is far, 1 is near).
|
||||
// TODO: pack 16 bits index to save memory
|
||||
if (occluderDepth <= boxMaxDepth)
|
||||
{
|
||||
uint index;
|
||||
_VisibleVolumeCount.InterlockedAdd(0, 1, index);
|
||||
_VisibleVolumeIndices.Store(index << 2, dispatchThreadId.x);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user