using System.Collections.Generic; using UnityEditor; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; public class DepthRenderPassFeature : ScriptableRendererFeature { class DepthRenderPass : ScriptableRenderPass { public static Queue Requests; public static Queue Answers; ProfilingSampler m_ProfilingSampler = new ProfilingSampler("ColorBlit"); private Material material; private RTHandle rtHandle; private bool depth = false; private ComputeBuffer computeBuffer; public DepthRenderPass(Material material) { this.material = material; Requests = new Queue(); Answers = new Queue(); } public void SetTarget(RTHandle handle, bool depth) { rtHandle = handle; this.depth = depth; if (computeBuffer != null) DestroyComputeBuffer(); RenderTexture rt = rtHandle.rt; computeBuffer = new ComputeBuffer(rt.width * rt.height, 1 * sizeof(float)); if(material != null) { material.SetBuffer("distBuffer", computeBuffer); material.SetFloat("res", rt.height); } } public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) { ConfigureTarget(rtHandle); } // Here you can implement the rendering logic. // Use ScriptableRenderContext to issue drawing commands or execute command buffers // https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html // You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { if (!depth) return; CommandBuffer cmd = CommandBufferPool.Get(); //RTHandle rt = renderingData.cameraData.renderer.cameraColorTargetHandle; using (new ProfilingScope(cmd, m_ProfilingSampler)) { Blitter.BlitCameraTexture(cmd, rtHandle, rtHandle, material, 0); if(Requests.Count > 0) { Requests.Dequeue(); float[] resultArray = new float[computeBuffer.count]; computeBuffer.GetData(resultArray); Answers.Enqueue(resultArray); } } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); } // Cleanup any allocated resources that were created during the execution of this render pass. public override void OnCameraCleanup(CommandBuffer cmd) { } public void Dispose() { #if UNITY_EDITOR if (EditorApplication.isPlaying) { Destroy(material); } else { DestroyImmediate(material); } #else Destroy(material); #endif if (rtHandle != null) rtHandle.Release(); if (computeBuffer != null) { DestroyComputeBuffer(); } if (Requests != null) { Requests.Clear(); Requests = null; } if (Answers != null) { Answers.Clear(); Answers = null; } } public void DestroyComputeBuffer() { computeBuffer.Release(); computeBuffer = null; } } [SerializeField] Shader shader; [SerializeField] bool Depth = false; DepthRenderPass m_ScriptablePass; Material material; /// public override void Create() { if(shader == null) shader = TexturesSettings.Instance.DepthShader; material = CoreUtils.CreateEngineMaterial(shader); m_ScriptablePass = new DepthRenderPass(material); // Configures where the render pass should be injected. m_ScriptablePass.renderPassEvent = RenderPassEvent.AfterRenderingOpaques; } // Here you can inject one or multiple render passes in the renderer. // This method is called when setting up the renderer once per-camera. public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { if (renderingData.cameraData.camera.tag == "Eye") { renderer.EnqueuePass(m_ScriptablePass); } } public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData) { m_ScriptablePass.ConfigureInput(ScriptableRenderPassInput.Color); m_ScriptablePass.SetTarget(renderer.cameraColorTargetHandle, Depth); } protected override void Dispose(bool disposing) { base.Dispose(disposing); #if UNITY_EDITOR if (EditorApplication.isPlaying) { Destroy(material); } else { DestroyImmediate(material); } #else Destroy(material); #endif m_ScriptablePass.Dispose(); } }