Shader "Hidden/HizCull" { SubShader { Pass { HLSLPROGRAM #pragma vertex Vertex #pragma fragment CullFrag #pragma enable_d3d11_debug_symbols #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" struct Attributes { float4 positionOS : POSITION; float2 texcoord : TEXCOORD0; }; struct Varyings { float2 uv : TEXCOORD0; float4 positionCS : SV_POSITION; }; Varyings Vertex(Attributes input) { Varyings output = (Varyings)0; output.positionCS = TransformObjectToHClip(input.positionOS.xyz); output.uv = input.texcoord; return output; } TEXTURE2D(_ObjectAABBTexture0); SAMPLER(sampler_ObjectAABBTexture0); TEXTURE2D(_ObjectAABBTexture1); SAMPLER(sampler_ObjectAABBTexture1); TEXTURE2D(_DepthPyramidTexture); SAMPLER(sampler_DepthPyramidTexture); 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) }; half CullFrag(Varyings input) : SV_Target { float2 uv = input.uv; float4 aabbCenter = SAMPLE_TEXTURE2D_LOD(_ObjectAABBTexture0, sampler_ObjectAABBTexture0, uv,0.0); float4 aabbSize = SAMPLE_TEXTURE2D_LOD(_ObjectAABBTexture1, sampler_ObjectAABBTexture1, uv, 0.0); float3 aabbExtent = aabbSize.xyz * 0.5;//贴图可以直接存extent UNITY_BRANCH if (aabbCenter.a == 0.0) { return 1; } #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; 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 } float4 boxUVs = float4(minXY, maxXY); boxUVs = saturate(boxUVs * 0.5 + 0.5); float2 size = (boxUVs.zw - boxUVs.xy) * _Mip0Size.xy; float mip = (log2(max(size.x, size.y) / 2.0f)); 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); return minZ >= depth.x ? 0 : 1; #else depth.xy = max(depth.xy, depth.zw); depth.x = max(depth.x, depth.y); return minZ <= depth.x ? 1 : 0; #endif } ENDHLSL } } }