From 7a6c54e8761f1796b034ec4758f1379b38319eb6 Mon Sep 17 00:00:00 2001 From: StarBeats <977663818@qq.com> Date: Wed, 18 Jun 2025 19:13:30 +0800 Subject: [PATCH] add hi-z occlusion culling. depth pyramid --- Assets/Settings/Mobile/Mobile_High.asset | 4 +- .../Mobile/Mobile_High_Renderer.asset | 22 +- .../Runtime/CheckerboardRendering.meta | 8 + .../CheckerboardRenderFeature.cs | 22 ++ .../CheckerboardRenderFeature.cs.meta | 11 + .../Runtime/OcclusionCulling.meta | 8 + .../OcclusionCulling/HierarchicalZFeature.cs | 352 ++++++++++++++++++ .../HierarchicalZFeature.cs.meta | 11 + .../OcclusionCulling/HziCullingFeature.cs | 54 +++ .../HziCullingFeature.cs.meta | 11 + .../Runtime/OcclusionCulling/Shaders.meta | 8 + .../OcclusionCulling/Shaders/CopyDepth.shader | 106 ++++++ .../Shaders/CopyDepth.shader.meta | 9 + .../Shaders/DepthPyramid.compute | 145 ++++++++ .../Shaders/DepthPyramid.compute.meta | 7 + .../Shaders/Hidden_CopyDepth.mat | 29 ++ .../Shaders/Hidden_CopyDepth.mat.meta | 8 + .../OcclusionCulling/Shaders/SPD.compute | 14 + .../OcclusionCulling/Shaders/SPD.compute.meta | 7 + 19 files changed, 833 insertions(+), 3 deletions(-) create mode 100644 Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/CheckerboardRendering.meta create mode 100644 Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/CheckerboardRendering/CheckerboardRenderFeature.cs create mode 100644 Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/CheckerboardRendering/CheckerboardRenderFeature.cs.meta create mode 100644 Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling.meta create mode 100644 Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HierarchicalZFeature.cs create mode 100644 Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HierarchicalZFeature.cs.meta create mode 100644 Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HziCullingFeature.cs create mode 100644 Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HziCullingFeature.cs.meta create mode 100644 Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders.meta create mode 100644 Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/CopyDepth.shader create mode 100644 Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/CopyDepth.shader.meta create mode 100644 Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/DepthPyramid.compute create mode 100644 Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/DepthPyramid.compute.meta create mode 100644 Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/Hidden_CopyDepth.mat create mode 100644 Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/Hidden_CopyDepth.mat.meta create mode 100644 Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/SPD.compute create mode 100644 Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/SPD.compute.meta diff --git a/Assets/Settings/Mobile/Mobile_High.asset b/Assets/Settings/Mobile/Mobile_High.asset index 5bbacbc..f896eca 100644 --- a/Assets/Settings/Mobile/Mobile_High.asset +++ b/Assets/Settings/Mobile/Mobile_High.asset @@ -28,7 +28,7 @@ MonoBehaviour: m_SupportsHDR: 1 m_HDRColorBufferPrecision: 0 m_MSAA: 1 - m_RenderScale: 1 + m_RenderScale: 0.6667969 m_UpscalingFilter: 1 m_FsrOverrideSharpness: 1 m_FsrSharpness: 1 @@ -114,5 +114,5 @@ MonoBehaviour: m_PrefilterNativeRenderPass: 1 m_ShaderVariantLogLevel: 0 m_ShadowCascades: 0 - superResolution: 3 + superResolution: 16 vrsRate: 0 diff --git a/Assets/Settings/Mobile/Mobile_High_Renderer.asset b/Assets/Settings/Mobile/Mobile_High_Renderer.asset index 030232f..37f656a 100644 --- a/Assets/Settings/Mobile/Mobile_High_Renderer.asset +++ b/Assets/Settings/Mobile/Mobile_High_Renderer.asset @@ -187,6 +187,25 @@ MonoBehaviour: - {fileID: 2800000, guid: 3302065f671a8450b82c9ddf07426f3a, type: 3} - {fileID: 2800000, guid: 56a77a3e8d64f47b6afe9e3c95cb57d5, type: 3} m_Shader: {fileID: 4800000, guid: 0849e84e3d62649e8882e9d6f056a017, type: 3} +--- !u!114 &-1629415145513658388 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9f7bf3c01c632d044877a67f9e9abb21, type: 3} + m_Name: HierarchicalZFeature + m_EditorClassIdentifier: + m_Active: 1 + settings: + PyramidFunc: 0 + SkipThreeMip: 0 + ComputeShader: {fileID: 0} + Spd: {fileID: 0} + CopyDepth: {fileID: 0} --- !u!114 &-1133205096357012623 MonoBehaviour: m_ObjectHideFlags: 0 @@ -251,7 +270,8 @@ MonoBehaviour: - {fileID: -8043853166483734676} - {fileID: 4071882023117421450} - {fileID: -7284859345190182597} - m_RendererFeatureMap: bc3f630842f2e70dd6a559c442a94bfd4529d15534f2d3de228858dca8d12222716523fbf3439fdb7a327b7bff4bdd446ac59dfa966ffa88ca6373cd5da9013d6cff55ca297e5e908a7b3653203b82383b2141bb05fbe69a + - {fileID: -1629415145513658388} + m_RendererFeatureMap: bc3f630842f2e70dd6a559c442a94bfd4529d15534f2d3de228858dca8d12222716523fbf3439fdb7a327b7bff4bdd446ac59dfa966ffa88ca6373cd5da9013d6cff55ca297e5e908a7b3653203b82383b2141bb05fbe69aec5704e48e2763e9 m_UseNativeRenderPass: 0 postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2} shaders: diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/CheckerboardRendering.meta b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/CheckerboardRendering.meta new file mode 100644 index 0000000..698b801 --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/CheckerboardRendering.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 254de63035289b541b164255ef99689e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/CheckerboardRendering/CheckerboardRenderFeature.cs b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/CheckerboardRendering/CheckerboardRenderFeature.cs new file mode 100644 index 0000000..da82d12 --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/CheckerboardRendering/CheckerboardRenderFeature.cs @@ -0,0 +1,22 @@ +using System; +using UnityEngine.Rendering.Universal; + +namespace X.Rendering.Feature +{ + + public class CheckerboardRenderFeature : ScriptableRendererFeature + { + [Serializable] + public class Settings + { + } + + public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) + { + } + + public override void Create() + { + } + } +} diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/CheckerboardRendering/CheckerboardRenderFeature.cs.meta b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/CheckerboardRendering/CheckerboardRenderFeature.cs.meta new file mode 100644 index 0000000..5198368 --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/CheckerboardRendering/CheckerboardRenderFeature.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3d151bb2c5d317147aadf868d86c644b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling.meta b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling.meta new file mode 100644 index 0000000..a27cc5e --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 966cb1ff9ec849a49b72b81985f4b1a7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HierarchicalZFeature.cs b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HierarchicalZFeature.cs new file mode 100644 index 0000000..0926496 --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HierarchicalZFeature.cs @@ -0,0 +1,352 @@ +using Codice.Client.GameUI.Update; +using System; +using Unity.Burst.CompilerServices; +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; + +namespace X.Rendering.Feature +{ + public class HierarchicalZFeature : ScriptableRendererFeature + { + public enum EDepthPyramidFunc + { + CopyDepth, + Compute, + SPD + } + + [Serializable] + public class Settings + { + public EDepthPyramidFunc PyramidFunc = EDepthPyramidFunc.CopyDepth; + public bool SkipThreeMip; + public bool UseThreeFrameReadback; + public ComputeShader ComputeShader; + public ComputeShader Spd; + public Material CopyDepth; + } + + [SerializeField] + private Settings settings; + + private HizPass hizPass; + + public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) + { + if (renderingData.cameraData.cameraType == UnityEngine.CameraType.Game) + { + renderer.EnqueuePass(hizPass); + } + } + + public override void Create() + { + hizPass = new(settings); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if(hizPass != null) + { + hizPass.Dispose(); + } + } + + internal class HizPass : ScriptableRenderPass, IDisposable + { + private static readonly int depthTextureId = Shader.PropertyToID("_CameraDepthTexture"); + private static readonly int depthInputId = Shader.PropertyToID("_InputDepth"); + private static readonly int depthPyramidTexId = Shader.PropertyToID("_DepthPyramidTexture"); + private static readonly int inputScaleAndMaxIndexId = Shader.PropertyToID("_InputScaleAndMaxIndex"); + + private readonly Settings settings; + private ProfilingSampler profiler; + + private Vector2Int cachedHardwareTextureSize; + private bool cachedSkipThreeMip; + private Vector2Int mip0SizeNOP; + private Vector2Int depthPyramidTextureSize; + private int mipLevelCount; + private Vector2Int[] mipLevelOffsets; + private Vector2Int[] mipLevelSizes; + private Vector4[] mipOffsetAndSizes = new Vector4[32]; + + private RTHandle[] depthPyramidTexs = new RTHandle[3]; + private static string[] depthPyramidNames = new string[3] { "_DepthPyramidTextureA", "_DepthPyramidTextureB", "_DepthPyramidTextureC" }; + + public HizPass(Settings settings) + { + renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing; + profiler = new("DepthPyramid"); + this.settings = settings; + mipLevelOffsets = new Vector2Int[32]; + mipLevelSizes = new Vector2Int[32]; + } + + public static int HizIndex { get; private set; } + + private int GetHizIndex() + { + if(settings.UseThreeFrameReadback) + { + HizIndex = Time.frameCount % 3; + } + else + { + HizIndex = 0; + } + + return HizIndex; + } + + public void ComputePackedMipChainInfo(Vector2Int viewportSize) + { + if (cachedHardwareTextureSize == viewportSize && cachedSkipThreeMip == settings.SkipThreeMip) + { + return; + } + + cachedHardwareTextureSize = viewportSize; + cachedSkipThreeMip = settings.SkipThreeMip; + + mip0SizeNOP = viewportSize; + int resizeX = Mathf.IsPowerOfTwo(viewportSize.x) ? viewportSize.x : Mathf.NextPowerOfTwo(viewportSize.x); + int resizeY = Mathf.IsPowerOfTwo(viewportSize.y) ? viewportSize.y : Mathf.NextPowerOfTwo(viewportSize.y); + Vector2Int hardwareTextureSize = new Vector2Int(resizeX, resizeY); + mipLevelOffsets[0] = Vector2Int.zero; + mipLevelSizes[0] = Vector2Int.zero; + int mipLevel = 0; + Vector2Int mipSize = hardwareTextureSize; + Vector2Int texSize = Vector2Int.zero; + do + { + mipLevel++; + + // Round up. + mipSize.x = System.Math.Max(1, (mipSize.x + 1) >> 1); + mipSize.y = System.Math.Max(1, (mipSize.y + 1) >> 1); + + mipLevelSizes[mipLevel] = mipSize; + + Vector2Int prevMipBegin = mipLevelOffsets[mipLevel - 1]; + Vector2Int prevMipEnd = prevMipBegin + mipLevelSizes[mipLevel - 1]; + + Vector2Int mipBegin = new Vector2Int(); + + if ((mipLevel & 1) != 0) + { + mipBegin.x = prevMipBegin.x; + mipBegin.y = prevMipEnd.y; + } + else + { + mipBegin.x = prevMipEnd.x; + mipBegin.y = prevMipBegin.y; + } + if (settings.SkipThreeMip && mipLevel == 4) //跳过前面3级的Mip,从第四级开始算 + { + mipBegin = Vector2Int.zero; + texSize = Vector2Int.zero; + } + + mipLevelOffsets[mipLevel] = mipBegin; + + texSize.x = System.Math.Max(texSize.x, mipBegin.x + mipSize.x); + texSize.y = System.Math.Max(texSize.y, mipBegin.y + mipSize.y); + } + while ((mipSize.x > 1) || (mipSize.y > 1)); + mipLevelSizes[0] = hardwareTextureSize; + //RT实际大小 + depthPyramidTextureSize = new Vector2Int((int)Mathf.Ceil((float)texSize.x), (int)Mathf.Ceil((float)texSize.y)); + mipLevelCount = mipLevel + 1; + } + + private static int[] depthMipId = null; + + private void DoCopyDepth(CommandBuffer cmd, Texture depthTex) + { + if (depthMipId == null) + { + depthMipId = new int[32]; + for (int i = 0; i < depthMipId.Length; i++) + { + depthMipId[i] = Shader.PropertyToID("_DepthMip" + i); + } + } + + var sampleName = "DepthDownSample"; + cmd.BeginSample(sampleName); + cmd.SetViewProjectionMatrices(Matrix4x4.identity, Matrix4x4.identity); + cmd.SetGlobalTexture(depthInputId, depthTex); + for (int i = 1; i < mipLevelCount; i++) + { + var mipSize = mipLevelSizes[i]; + var inputMipSize = i == 1 ? mip0SizeNOP : mipLevelSizes[i - 1]; + var texId = depthMipId[i]; + cmd.SetGlobalVector(inputScaleAndMaxIndexId, new Vector4(inputMipSize.x / (float)mipSize.x, inputMipSize.y / (float)mipSize.y, inputMipSize.x - 1, inputMipSize.y - 1)); + cmd.GetTemporaryRT(texId, mipSize.x, mipSize.y, 0, FilterMode.Point, RenderTextureFormat.RFloat); + cmd.SetRenderTarget(texId, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store); + cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, settings.CopyDepth, 0, 0); + cmd.SetGlobalTexture(depthInputId, texId); + } + + cmd.EndSample(sampleName); + + sampleName = "DepthCombine"; + cmd.BeginSample(sampleName); + var hizIndex = GetHizIndex(); + RTHandle hizRt = depthPyramidTexs[hizIndex]; + + RenderingUtils.ReAllocateIfNeeded(ref hizRt, new RenderTextureDescriptor() + { + width = depthPyramidTextureSize.x, + height = depthPyramidTextureSize.y, + dimension = TextureDimension.Tex2D, + colorFormat = RenderTextureFormat.RFloat, + msaaSamples = 1, + }, filterMode : FilterMode.Point, name: depthPyramidNames[hizIndex]); + depthPyramidTexs[hizIndex] = hizRt; + + cmd.SetRenderTarget(hizRt, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store); + for (int i = 1; i < mipLevelCount; i++) + { + var texId = depthMipId[i]; + cmd.SetGlobalTexture(depthInputId, texId); + var mipSize = mipLevelSizes[i]; + var mipOffset = mipLevelOffsets[i]; + mipOffsetAndSizes[i] = new (mipOffset.x, mipOffset.y, mipSize.x, mipSize.y); + cmd.SetViewport(new Rect(mipOffset.x, mipOffset.y, mipSize.x, mipSize.y)); + cmd.DrawMesh(RenderingUtils.fullscreenMesh, Matrix4x4.identity, settings.CopyDepth, 0, 1); + } + + cmd.SetGlobalTexture(depthPyramidTexId, hizRt); + cmd.EndSample(sampleName); + + for (int i = 0; i < depthMipId.Length; i++) + { + var texId = depthMipId[i]; + cmd.ReleaseTemporaryRT(texId); + } + } + + private void DoComputeDepth(CommandBuffer cmd, Texture depthTex) + { + var hizIndex = GetHizIndex(); + RTHandle hizBuffer = depthPyramidTexs[hizIndex]; + + RenderingUtils.ReAllocateIfNeeded(ref hizBuffer, new RenderTextureDescriptor() + { + width = depthPyramidTextureSize.x, + height = depthPyramidTextureSize.y, + dimension = TextureDimension.Tex2D, + colorFormat = RenderTextureFormat.RFloat, + msaaSamples = 1, + enableRandomWrite = true, + }, filterMode: FilterMode.Point, name: depthPyramidNames[hizIndex]); + depthPyramidTexs[hizIndex] = hizBuffer; + + int outputMipCnt = mipLevelCount - 1; + int dispatchCnt = Mathf.CeilToInt(outputMipCnt / 4f); + int mipCnt = outputMipCnt; + Matrix4x4 matrix4X4 = new Matrix4x4(); + for (int i = 0; i <= dispatchCnt; i++) + { + int startMip = i * 4; + int mip1 = startMip + 1; + int mip2 = startMip + 2; + int mip3 = startMip + 3; + int mip4 = startMip + 4; + var outputMipSize = mipLevelSizes[mip1]; + if(outputMipSize.x == 0 || outputMipSize.y == 0) + { + break; + } + int kernelId = 0; + if (i == 0) + { + kernelId = 1; + if (settings.SkipThreeMip) + { + kernelId = 2; + } + } + + cmd.SetComputeTextureParam(settings.ComputeShader, kernelId, depthInputId, i == 0 ? depthTex : hizBuffer); + cmd.SetComputeTextureParam(settings.ComputeShader, kernelId, "_DepthMipChain", hizBuffer); + + int inputMipIndex = startMip; + var inputMipOffset = mipLevelOffsets[inputMipIndex]; + var inputMipSize = inputMipIndex == 0 ? mip0SizeNOP : mipLevelSizes[inputMipIndex]; + + cmd.SetComputeVectorParam(settings.ComputeShader, "_InputMipOffsetAndSize", new Vector4(inputMipOffset.x, inputMipOffset.y, inputMipSize.x, inputMipSize.y)); + cmd.SetComputeIntParam(settings.ComputeShader, "_MipCount", Mathf.Min(mipCnt, 4)); + + ref var mipOffset = ref mipLevelOffsets[mip1]; + ref var mipSize = ref mipLevelSizes[mip1]; + matrix4X4.SetRow(0, new Vector4(mipOffset.x, mipOffset.y, mipSize.x, mipSize.y)); + mipOffset = ref mipLevelOffsets[mip2]; + mipSize = ref mipLevelSizes[mip2]; + matrix4X4.SetRow(1, new Vector4(mipOffset.x, mipOffset.y, mipSize.x, mipSize.y)); + mipOffset = ref mipLevelOffsets[mip3]; + mipSize = ref mipLevelSizes[mip3]; + matrix4X4.SetRow(2, new Vector4(mipOffset.x, mipOffset.y, mipSize.x, mipSize.y)); + mipOffset = ref mipLevelOffsets[mip4]; + mipSize = ref mipLevelSizes[mip4]; + matrix4X4.SetRow(3, new Vector4(mipOffset.x, mipOffset.y, mipSize.x, mipSize.y)); + + cmd.SetComputeMatrixParam(settings.ComputeShader, "_MipOffsetAndSizeArray", matrix4X4); + + // XXX: 可以测试是否有正面作用 + // cmd.SetExecutionFlags(CommandBufferExecutionFlags.AsyncCompute); + cmd.DispatchCompute(settings.ComputeShader, kernelId, Mathf.CeilToInt(outputMipSize.x / 8f), Mathf.CeilToInt(outputMipSize.y / 8f), 1); + mipCnt = mipCnt - 4; + } + cmd.SetGlobalTexture(depthPyramidTexId, hizBuffer); + } + + private void DoSpdDepth(CommandBuffer cmd, Texture depthTex) + { + + } + + public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) + { + var cmd = renderingData.commandBuffer; + using var soc = new ProfilingScope(cmd, profiler); + Texture depthTex = Shader.GetGlobalTexture(depthTextureId); + if(depthTex == null) + { + return; + } + + ComputePackedMipChainInfo(new Vector2Int(depthTex.width, depthTex.height)); + + switch (settings.PyramidFunc) + { + case EDepthPyramidFunc.CopyDepth: + DoCopyDepth(cmd, depthTex); + break; + case EDepthPyramidFunc.Compute: + DoComputeDepth(cmd, depthTex); + break; + case EDepthPyramidFunc.SPD: + DoSpdDepth(cmd, depthTex); + break; + default: + break; + } + } + + public void Dispose() + { + for (int i = 0; i < depthPyramidTexs.Length; i++) + { + var rt = depthPyramidTexs[i]; + rt?.Release(); + } + } + } + } +} diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HierarchicalZFeature.cs.meta b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HierarchicalZFeature.cs.meta new file mode 100644 index 0000000..9bf249c --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HierarchicalZFeature.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9f7bf3c01c632d044877a67f9e9abb21 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HziCullingFeature.cs b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HziCullingFeature.cs new file mode 100644 index 0000000..d3b147f --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HziCullingFeature.cs @@ -0,0 +1,54 @@ +using System; +using UnityEngine; +using UnityEngine.Rendering; +using UnityEngine.Rendering.Universal; + +namespace X.Rendering.Feature +{ + public class HziCullingFeature : ScriptableRendererFeature + { + [Serializable] + public class Settings + { + //TODO: 通过使用上一帧的摄像机位置(包括矩阵)和上一帧的深度图做剔除,储存已经被剔除的物体和未被剔除的物体,然后绘制未被剔除的物体到GBuffer(包含深度图), + //再二次生成HiZ DepthTexture,并对已经被剔除的物体使用一遍新的深度和当前摄像机的位置做一次剔除判断 + public bool UseTowCullPass; + } + + [SerializeField] + private Settings settings; + + private CullPass cullPass; + public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) + { + if (renderingData.cameraData.cameraType == CameraType.Game) + { + renderer.EnqueuePass(cullPass); + } + } + + public override void Create() + { + cullPass = new(settings); + } + + internal class CullPass : ScriptableRenderPass + { + private Settings settings; + private ProfilingSampler profiler; + + public CullPass(Settings settings) + { + profiler = new("Hi-Z Culling"); + this.settings = settings; + } + + public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) + { + var cmd = renderingData.commandBuffer; + using var soc = new ProfilingScope(cmd, profiler); + + } + } + } +} diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HziCullingFeature.cs.meta b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HziCullingFeature.cs.meta new file mode 100644 index 0000000..dddfd52 --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/HziCullingFeature.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a0b8751ae563c82438124306d98fffd5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders.meta b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders.meta new file mode 100644 index 0000000..bd7e7a9 --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d52a54cc0a95d6c4c83efcba0b275bba +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/CopyDepth.shader b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/CopyDepth.shader new file mode 100644 index 0000000..6c7b408 --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/CopyDepth.shader @@ -0,0 +1,106 @@ +Shader "Hidden/CopyDepth" +{ + SubShader + { + Pass + { + HLSLPROGRAM + #pragma vertex Vertex + #pragma fragment DownsampleDepthFrag + + #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; + } + + #if UNITY_REVERSED_Z + # define MIN_DEPTH(l, r) min(l, r) + #else + # define MIN_DEPTH(l, r) max(l, r) + #endif + + TEXTURE2D_FLOAT(_InputDepth); + SAMPLER(sampler_InputDepth); + float4 _InputScaleAndMaxIndex;//xy: inputeTexsize/outputTextureSize , zw:textureSize - 1 + + half4 DownsampleDepthFrag(Varyings input) : SV_Target + { + int2 texCrood = int2(input.positionCS.xy) * _InputScaleAndMaxIndex.xy; + uint2 maxIndex = _InputScaleAndMaxIndex.zw; + int2 texCrood00 = min(texCrood + uint2(0, 0), maxIndex); + int2 texCrood10 = min(texCrood + uint2(1, 0), maxIndex); + int2 texCrood01 = min(texCrood + uint2(0, 1), maxIndex); + int2 texCrood11 = min(texCrood + uint2(1, 1), maxIndex); + float p00 = LOAD_TEXTURE2D_LOD(_InputDepth,texCrood00,0); + float p01 = LOAD_TEXTURE2D_LOD(_InputDepth,texCrood10,0); + float p10 = LOAD_TEXTURE2D_LOD(_InputDepth,texCrood01,0); + float p11 = LOAD_TEXTURE2D_LOD(_InputDepth,texCrood11,0); + return MIN_DEPTH(MIN_DEPTH(p00 ,p01), MIN_DEPTH(p10, p11)); + } + + ENDHLSL + } + + Pass + { + HLSLPROGRAM + #pragma vertex Vertex + #pragma fragment CopyDepthFrag + + #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; + } + + #if UNITY_REVERSED_Z + # define MIN_DEPTH(l, r) min(l, r) + #else + # define MIN_DEPTH(l, r) max(l, r) + #endif + + TEXTURE2D_FLOAT(_InputDepth); + SAMPLER(sampler_InputDepth); + + half4 CopyDepthFrag(Varyings input) : SV_Target + { + return SAMPLE_TEXTURE2D(_InputDepth, sampler_InputDepth, input.uv); + } + + ENDHLSL + } + } +} diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/CopyDepth.shader.meta b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/CopyDepth.shader.meta new file mode 100644 index 0000000..797c033 --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/CopyDepth.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 7f9d51c52061c72418245bdd5c8e83be +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/DepthPyramid.compute b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/DepthPyramid.compute new file mode 100644 index 0000000..e554b83 --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/DepthPyramid.compute @@ -0,0 +1,145 @@ +// Each #kernel tells which function to compile; you can have many kernels +#pragma kernel CSMainMipmapGroup0 +#pragma kernel CSMainMipmapGroup0 _INPUTE_DEPTH_TEXTURE +#pragma kernel CSMainMipmapGroup0 _INPUTE_DEPTH_TEXTURE _SKIP_3_MIP + +Texture2D _InputDepth; + +RWTexture2D _DepthMipChain; + +#if UNITY_REVERSED_Z +#define MIN_DEPTH(l, r) min(l, r) +#else +#define MIN_DEPTH(l, r) max(l, r) +#endif + +#define GROUP_TILE_SIZE 8 +float4x4 _MipOffsetAndSizeArray; +float4 _InputMipOffsetAndSize; +float _MipCount; +groupshared float _LDSDepths[GROUP_TILE_SIZE * GROUP_TILE_SIZE]; + +[numthreads(GROUP_TILE_SIZE, GROUP_TILE_SIZE, 1)] +void CSMainMipmapGroup0(uint3 dispatchThreadId : SV_DispatchThreadID, uint groupThreadIndex : SV_GroupIndex, uint2 groupId : SV_GroupID, uint3 groupThreadID : SV_GroupThreadID) +{ + uint2 curMipSize = _MipOffsetAndSizeArray[0].zw; + //Mip0从InputeTexture贴图下采样 + float2 uv = dispatchThreadId.xy / float2(curMipSize); + uv = clamp(uv, 0, 1); + int2 texCrood = _InputMipOffsetAndSize.xy + uv * (_InputMipOffsetAndSize.zw); + uint2 maxIndex = _InputMipOffsetAndSize.xy + _InputMipOffsetAndSize.zw - 1; +#ifdef _INPUTE_DEPTH_TEXTURE //第一次Dispath使用Depth Texture + float p00 = _InputDepth[min(texCrood + uint2(0, 0), maxIndex)]; + float p01 = _InputDepth[min(texCrood + uint2(1, 0), maxIndex)]; + float p10 = _InputDepth[min(texCrood + uint2(0, 1), maxIndex)]; + float p11 = _InputDepth[min(texCrood + uint2(1, 1), maxIndex)]; +#else + float p00 = _DepthMipChain[min(texCrood + uint2(0, 0), maxIndex)]; + float p01 = _DepthMipChain[min(texCrood + uint2(1, 0), maxIndex)]; + float p10 = _DepthMipChain[min(texCrood + uint2(0, 1), maxIndex)]; + float p11 = _DepthMipChain[min(texCrood + uint2(1, 1), maxIndex)]; +#endif + float4 depths = float4(p00, p10, p01, p11); + float minDepth = MIN_DEPTH(MIN_DEPTH(depths.x, depths.y), MIN_DEPTH(depths.z, depths.w)); + + if (all(dispatchThreadId.xy < curMipSize.xy)) + { +#ifndef _SKIP_3_MIP //跳过前3级,不输出到RT + _DepthMipChain[_MipOffsetAndSizeArray[0].xy + dispatchThreadId.xy] = minDepth; +#endif + _LDSDepths[groupThreadIndex] = minDepth; + } + GroupMemoryBarrierWithGroupSync(); + //Mip1 + curMipSize = curMipSize >> 1; + uint preMipTileSize = GROUP_TILE_SIZE; + uint TileSize = GROUP_TILE_SIZE / 2; //线程数减半 + float4 parentFurthestDeviceZ; + uint2 xy = min(groupThreadID.xy, TileSize - 1); + uint2 xy2 = xy * 2; //间隔索引:[0,2,4,6] + uint index0 = xy2.x + xy2.y * preMipTileSize; + uint index1 = (xy2.x + 1) + xy2.y * preMipTileSize; + uint index2 = xy2.x + (xy2.y + 1) * preMipTileSize; + uint index3 = (xy2.x + 1) + (xy2.y + 1) * preMipTileSize; + + parentFurthestDeviceZ.x = _LDSDepths[index0]; + parentFurthestDeviceZ.y = _LDSDepths[index1]; + parentFurthestDeviceZ.z = _LDSDepths[index2]; + parentFurthestDeviceZ.w = _LDSDepths[index3]; + + float furthestDeviceZ = MIN_DEPTH(MIN_DEPTH(parentFurthestDeviceZ.x, parentFurthestDeviceZ.y), MIN_DEPTH(parentFurthestDeviceZ.z, parentFurthestDeviceZ.w)); + uint2 localIndex = dispatchThreadId.xy - (groupId.xy * (GROUP_TILE_SIZE - TileSize)); //因为过滤了3/4的线程组,所以线程索引需要往前补上 + + if (all(localIndex < curMipSize.xy) //索引在贴图范围内的 + && all(groupThreadID.xy < TileSize) //每次每个线程组保留1/4的线程 + ) + { +#ifndef _SKIP_3_MIP //跳过前3级,不输出到RT + _DepthMipChain[_MipOffsetAndSizeArray[1].xy + localIndex] = furthestDeviceZ; +#endif + int threadIndex = xy.x + xy.y * TileSize; + _LDSDepths[threadIndex] = furthestDeviceZ; + } + + //Mip2 + GroupMemoryBarrierWithGroupSync(); + + curMipSize = curMipSize >> 1; + preMipTileSize = TileSize; + TileSize = TileSize / 2; //线程数减半 + xy = min(groupThreadID.xy, TileSize - 1); + xy2 = xy * 2; //间隔索引:[0,2,4,6] + index0 = xy2.x + xy2.y * preMipTileSize; + index1 = (xy2.x + 1) + xy2.y * preMipTileSize; + index2 = xy2.x + (xy2.y + 1) * preMipTileSize; + index3 = (xy2.x + 1) + (xy2.y + 1) * preMipTileSize; + + parentFurthestDeviceZ.x = _LDSDepths[index0]; + parentFurthestDeviceZ.y = _LDSDepths[index1]; + parentFurthestDeviceZ.z = _LDSDepths[index2]; + parentFurthestDeviceZ.w = _LDSDepths[index3]; + + GroupMemoryBarrierWithGroupSync(); + furthestDeviceZ = MIN_DEPTH(MIN_DEPTH(parentFurthestDeviceZ.x, parentFurthestDeviceZ.y), MIN_DEPTH(parentFurthestDeviceZ.z, parentFurthestDeviceZ.w)); + localIndex = dispatchThreadId.xy - (groupId.xy * (GROUP_TILE_SIZE - TileSize)); //因为过滤了3/4的线程组,所以线程索引需要往前补上 + + if (all(localIndex < curMipSize.xy) //索引在贴图范围内的 + && all(groupThreadID.xy < TileSize) //每次每个线程组保留1/4的线程 + ) + { +#ifndef _SKIP_3_MIP //跳过前3级,不输出到RT + _DepthMipChain[_MipOffsetAndSizeArray[2].xy + localIndex] = furthestDeviceZ; +#endif + int threadIndex = xy.x + xy.y * TileSize; + _LDSDepths[threadIndex] = furthestDeviceZ; + } + + //Mip3 + GroupMemoryBarrierWithGroupSync(); + + curMipSize = curMipSize >> 1; + preMipTileSize = TileSize; + TileSize = TileSize / 2; //线程数减半 + xy = min(groupThreadID.xy, TileSize - 1); + xy2 = xy * 2; //间隔索引:[0,2,4,6] + index0 = xy2.x + xy2.y * preMipTileSize; + index1 = (xy2.x + 1) + xy2.y * preMipTileSize; + index2 = xy2.x + (xy2.y + 1) * preMipTileSize; + index3 = (xy2.x + 1) + (xy2.y + 1) * preMipTileSize; + + parentFurthestDeviceZ.x = _LDSDepths[index0]; + parentFurthestDeviceZ.y = _LDSDepths[index1]; + parentFurthestDeviceZ.z = _LDSDepths[index2]; + parentFurthestDeviceZ.w = _LDSDepths[index3]; + + GroupMemoryBarrierWithGroupSync(); + furthestDeviceZ = MIN_DEPTH(MIN_DEPTH(parentFurthestDeviceZ.x, parentFurthestDeviceZ.y), MIN_DEPTH(parentFurthestDeviceZ.z, parentFurthestDeviceZ.w)); + localIndex = dispatchThreadId.xy - (groupId.xy * (GROUP_TILE_SIZE - TileSize)); //因为过滤了3/4的线程组,所以线程索引需要往前补上 + + if (all(localIndex < curMipSize.xy) //索引在贴图范围内的 + && all(groupThreadID.xy < TileSize) //每次每个线程组保留1/4的线程 + ) + { + _DepthMipChain[_MipOffsetAndSizeArray[3].xy + localIndex] = furthestDeviceZ; + } +} \ No newline at end of file diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/DepthPyramid.compute.meta b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/DepthPyramid.compute.meta new file mode 100644 index 0000000..420aeb5 --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/DepthPyramid.compute.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b10c09f63c5a5864ca12e07b1b361d56 +ComputeShaderImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/Hidden_CopyDepth.mat b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/Hidden_CopyDepth.mat new file mode 100644 index 0000000..44d543f --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/Hidden_CopyDepth.mat @@ -0,0 +1,29 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Hidden_CopyDepth + m_Shader: {fileID: 4800000, guid: 7f9d51c52061c72418245bdd5c8e83be, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: [] + m_Ints: [] + m_Floats: [] + m_Colors: [] + m_BuildTextureStacks: [] diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/Hidden_CopyDepth.mat.meta b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/Hidden_CopyDepth.mat.meta new file mode 100644 index 0000000..94271cc --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/Hidden_CopyDepth.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5f8ec7ea87b60a1448091fade6a0e68f +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/SPD.compute b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/SPD.compute new file mode 100644 index 0000000..ad8fcb5 --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/SPD.compute @@ -0,0 +1,14 @@ +// Each #kernel tells which function to compile; you can have many kernels +#pragma kernel CSMain + +// Create a RenderTexture with enableRandomWrite flag and set it +// with cs.SetTexture +RWTexture2D Result; + +[numthreads(8,8,1)] +void CSMain (uint3 id : SV_DispatchThreadID) +{ + // TODO: insert actual code here! + + Result[id.xy] = float4(id.x & id.y, (id.x & 15)/15.0, (id.y & 15)/15.0, 0.0); +} diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/SPD.compute.meta b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/SPD.compute.meta new file mode 100644 index 0000000..bdde789 --- /dev/null +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/Runtime/OcclusionCulling/Shaders/SPD.compute.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2c0519b45f80f5c47b4ee3edb2e7931b +ComputeShaderImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: