diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HierarchicalZOcclusionCullFeature.cs b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HierarchicalZOcclusionCullFeature.cs index 11191f9..0f351ba 100644 --- a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HierarchicalZOcclusionCullFeature.cs +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HierarchicalZOcclusionCullFeature.cs @@ -476,7 +476,18 @@ namespace X.Rendering.Feature renderingData.cameraData.GetViewMatrix(); if (settings.UseCompute) { + int kernelId = 0; + cmd.SetComputeMatrixParam(settings.CullShader, HizShaderIds.GPUCullingVPId, world2Project); + + cmd.SetComputeTextureParam(settings.CullShader, kernelId, "_ObjectAABBTexture0", Shader.GetGlobalTexture(HizShaderIds.ObjectAABBCenterId)); + cmd.SetComputeTextureParam(settings.CullShader, kernelId, "_ObjectAABBTexture1", Shader.GetGlobalTexture(HizShaderIds.ObjectAABBSizeId)); + cmd.SetComputeTextureParam(settings.CullShader, kernelId, "_DepthPyramidTexture", Shader.GetGlobalTexture(HizShaderIds.DepthPyramidTexId)); + cmd.SetComputeTextureParam(settings.CullShader, kernelId, "_CullResult", cullResult.ResultTex); + + cmd.DispatchCompute(settings.CullShader, kernelId, 8, 8, 1); + cmd.RequestAsyncReadback(cullResult.ResultTex, 0, cullResult.ReadBackAction); + cullResult.DataReady = false; } else { diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/HizCull.compute b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/HizCull.compute index ad8fcb5..b5b6a8f 100644 --- a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/HizCull.compute +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/HizCull.compute @@ -1,14 +1,112 @@ // Each #kernel tells which function to compile; you can have many kernels #pragma kernel CSMain +#pragma enable_d3d11_debug_symbols +#pragma target 5.0 -// Create a RenderTexture with enableRandomWrite flag and set it -// with cs.SetTexture -RWTexture2D Result; +Texture2D _ObjectAABBTexture0; +Texture2D _ObjectAABBTexture1; + +Texture2D _DepthPyramidTexture; + +RWTexture2D _CullResult; + +float4x4 _GPUCullingVP; +float2 _MipmapLevelMinMaxIndex; +float2 _Mip0Size; +float4 _MipOffsetAndSize[16]; + +static const float3 aggressiveExtentArray[8] = +{ + float3(1, 1, 1), + float3(1, 1, -1), + float3(1, -1, 1), + float3(1, -1, -1), + float3(-1, 1, 1), + float3(-1, 1, -1), + float3(-1, -1, 1), + float3(-1, -1, -1) +}; + +#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" [numthreads(8,8,1)] -void CSMain (uint3 id : SV_DispatchThreadID) +void CSMain(uint3 id : SV_DispatchThreadID) { - // TODO: insert actual code here! + uint2 uv = id.xy; + float4 aabbCenter = LOAD_TEXTURE2D_LOD(_ObjectAABBTexture0, uv, 0); + float4 aabbSize = LOAD_TEXTURE2D_LOD(_ObjectAABBTexture1, uv, 0.0); + float3 aabbExtent = aabbSize.xyz; + UNITY_BRANCH + if (aabbCenter.a == 0.0) + { + _CullResult[uv] = 1; + } - Result[id.xy] = float4(id.x & id.y, (id.x & 15)/15.0, (id.y & 15)/15.0, 0.0); + #ifdef UNITY_REVERSED_Z + float minZ = 0; + #else + float minZ = 1; + #endif + + float2 maxXY = 0; + float2 minXY = 1; + for (uint i = 0; i < 8; ++i) + { + float3 boxCorner = aabbCenter + aabbExtent * aggressiveExtentArray[i]; + float4 clipPos = mul(_GPUCullingVP, float4(boxCorner, 1)); + clipPos /= clipPos.w; + clipPos.xy = clipPos.xy * 0.5f + 0.5f; + #if UNITY_UV_STARTS_AT_TOP + clipPos.y = 1 - clipPos.y; + #endif + + minXY = min(clipPos.xy, minXY); + maxXY = max(clipPos.xy, maxXY); + #ifdef UNITY_REVERSED_Z + minZ = max(minZ, clipPos.z); + #else + minZ = min(minZ, clipPos.z); + #endif + } + + if (maxXY.x < 0 || maxXY.y < 0 || minXY.x > 1 || minXY.y > 1) + { + _CullResult[uv] = 1; + } + + float4 boxUVs = float4(minXY, maxXY); + + float2 size = (boxUVs.zw - boxUVs.xy) * _Mip0Size.xy; + float mip = (log2(max(size.x, size.y))); + + mip = ceil(mip); + mip = clamp(mip, _MipmapLevelMinMaxIndex.x, _MipmapLevelMinMaxIndex.y); + + // float level_lower = max(mip - 1, 0); + // float2 scale = exp2(-level_lower) / _Mip0Size.xy; + // float2 a = floor(boxUVs.xy*scale); + // float2 b = ceil(boxUVs.zw*scale); + // float2 dims = b - a; + // + // // Use the lower level if we only touch <= 2 texels in both dimensions + // if (dims.x <= 2 && dims.y <= 2) + // mip = level_lower; + + float4 offsetAndSize = _MipOffsetAndSize[mip]; + int4 pxMinMax = boxUVs * offsetAndSize.zwzw + offsetAndSize.xyxy; + float4 depth = float4(LOAD_TEXTURE2D_LOD(_DepthPyramidTexture, pxMinMax.xy, 0).r, + LOAD_TEXTURE2D_LOD(_DepthPyramidTexture, pxMinMax.zy, 0).r, + LOAD_TEXTURE2D_LOD(_DepthPyramidTexture, pxMinMax.xw, 0).r, + LOAD_TEXTURE2D_LOD(_DepthPyramidTexture, pxMinMax.zw, 0).r + ); + + #ifdef UNITY_REVERSED_Z + depth.xy = min(depth.xy, depth.zw); + depth.x = min(depth.x, depth.y); + _CullResult[uv] = minZ > depth.x ? 0 : 1; + #else + depth.xy = max(depth.xy, depth.zw); + depth.x = max(depth.x, depth.y); + _CullResult[uv] = minZ < depth.x ? 1 : 0; + #endif }