Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question How to use CopyDepthPass in custom render feature to update depth texture

Discussion in 'Universal Render Pipeline' started by fragilecontinuum, Jul 12, 2023.

  1. fragilecontinuum

    fragilecontinuum

    Joined:
    Jan 12, 2020
    Posts:
    51
    I'm trying to update an old render feature that used to work fine in Unity 2021 LTS, but is no longer working in 2022 in large part due to the RTHandle change afaik. For context, what I'm actually trying to achieve is to add transparent objects to the camera depth texture just prior to another custom render feature using the depth buffer, which needs the position of the transparent objects added in order to look correct. This is what I've been trying to use, any thoughts? :

    Code (CSharp):
    1. public class CopyDepthRender : ScriptableRendererFeature
    2. {
    3.     CopyDepthPass _copyDepthPass;
    4.     RTHandle _depthDestHandle;
    5.     RTHandle _depthSourceHandle;
    6.  
    7.     public override void Create()
    8.     {
    9.         _copyDepthPass = new CopyDepthPass(RenderPassEvent.AfterRenderingTransparents, CoreUtils.CreateEngineMaterial("Hidden/Universal Render Pipeline/CopyDepth")); // This could be wrong in 2022 too ?
    10.     }
    11.  
    12.     public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    13.     {
    14.         renderer.EnqueuePass(_copyDepthPass);
    15.     }
    16.  
    17.     public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData)
    18.     {
    19.         _depthDestHandle = // WHAT GOES HERE ? -----Used to be _depthDestHandle.Init(new RenderTargetIdentifier("_CameraDepthTexture"));
    20.         _depthSourceHandle = renderer.cameraDepthTargetHandle; // Used to be _depthSourceHandle.Init("_CameraDepthAttachment");
    21.         _copyDepthPass.Setup(_depthSourceHandle, _depthDestHandle);
    22.     }
    23. }
     
  2. wwWwwwW1

    wwWwwwW1

    Joined:
    Oct 31, 2021
    Posts:
    637
    Hi, you can get the RTHandle of "_CameraDepthAttachment" with
    renderingData.cameraData.renderer.cameraDepthTarget
    .

    However, you have to use reflection to get the RTHandle of "_CameraDepthTexture" because it's an internal variable in UniversalRenderer (ScriptableRenderer).
     
    fragilecontinuum likes this.
  3. fragilecontinuum

    fragilecontinuum

    Joined:
    Jan 12, 2020
    Posts:
    51
    Aha, thank you, that worked! I did have the source handle correct (renderer.cameraDepthTargetHandle is equivalent to renderingData.cameraData.renderer.cameraDepthTarget it seems), but your reference to reflection helped out in a further forum search.

    To any future visitors still trying to figure this out, this post in Question - How to set _CameraDepthTexture as render target in URP 13? - Unity Forum helped me, though I doubt it's an optimal solution given I presume this is being called every frame:

    Code (CSharp):
    1. private readonly static FieldInfo depthTextureFieldInfo = typeof(UniversalRenderer).GetField("m_DepthTexture", BindingFlags.NonPublic | BindingFlags.Instance);
    2. public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
    3. {
    4. #if UNITY_2022_1_OR_NEWER
    5.     var renderer = renderingData.cameraData.renderer as UniversalRenderer;
    6.     var depthTextureHandle = depthTextureFieldInfo.GetValue(renderer) as RTHandle;
    7.     if (depthTextureHandle != null)
    8.     {
    9.         this.ConfigureTarget(depthTextureHandle, depthTextureHandle);
    10.     }
    11. #else
    12.     this.ConfigureTarget("_CameraDepthTexture", "_CameraDepthTexture");
    13. #endif
    14. }
    I suspect that something like:

    Code (CSharp):
    1. RenderTextureDescriptor depthDescriptor = new RenderTextureDescriptor();
    2. RenderingUtils.ReAllocateIfNeeded(ref _depthDestHandle, depthDescriptor, FilterMode.Point, TextureWrapMode.Clamp, name: "_CameraDepthTexture");
    is supposed to be the correct way to approach this, but reflection at least did work in my case. Cheers!
     
    wwWwwwW1 likes this.
  4. fragilecontinuum

    fragilecontinuum

    Joined:
    Jan 12, 2020
    Posts:
    51
    For the sake of completeness (and I couldn't find this anywhere else), what I ended up with is:

    Code (CSharp):
    1. using System.Reflection;
    2. using UnityEngine.Rendering;
    3. using UnityEngine.Rendering.Universal;
    4. using UnityEngine.Rendering.Universal.Internal;
    5.  
    6. public class CopyDepthRender : ScriptableRendererFeature
    7. {
    8.     CopyDepthPass _copyDepthPass;
    9.     RTHandle _depthDestHandle;
    10.     RTHandle _depthSourceHandle;
    11.     readonly static FieldInfo depthTextureFieldInfo = typeof(UniversalRenderer).GetField("m_DepthTexture", BindingFlags.NonPublic | BindingFlags.Instance);
    12.  
    13.     public override void Create()
    14.     {
    15.         _copyDepthPass = new CopyDepthPass(RenderPassEvent.AfterRenderingTransparents, CoreUtils.CreateEngineMaterial("Hidden/Universal Render Pipeline/CopyDepth"));
    16.     }
    17.  
    18.     public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    19.     {
    20.         renderer.EnqueuePass(_copyDepthPass);
    21.     }
    22.  
    23.     public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData)
    24.     {
    25. #if UNITY_2022_1_OR_NEWER
    26.         _depthDestHandle = depthTextureFieldInfo.GetValue(renderer) as RTHandle;
    27. //#else
    28. //There is no else, just don't use RTHandles -.-
    29. #endif
    30.  
    31.         _depthSourceHandle = renderer.cameraDepthTargetHandle;
    32.         _copyDepthPass.Setup(_depthSourceHandle, _depthDestHandle);
    33.     }
    34. }
     
    Last edited: Jul 12, 2023
  5. Gisle

    Gisle

    Joined:
    Mar 25, 2014
    Posts:
    26
    Hi, Ive been using this exact solution for this exact problem/use case, and I have now stumbled upon a situation where I need this to work on AOT platforms, which means I am unable to use reflection.

    Does anyone know if there are any other way to do this? A built in render feature for instance?
    Probably not the right place to ask, but maybe someone at Unity could pick up on this?

    Edit:
    I found this, and it looks like it may work after all. Still, not a great solution for something that could be easily supported.
    https://docs.unity3d.com/Manual/ScriptingRestrictions.html
     
    Last edited: Oct 16, 2023
  6. ManueleB

    ManueleB

    Unity Technologies

    Joined:
    Jul 6, 2020
    Posts:
    98
    hey! Not a direct question to your answer, but from 22 you can set the copyDepth pass to happen after the transparent pass in the RendererData options, which should do exactly what you need without using reflection or having to write a custom pass:

    upload_2023-10-17_9-24-17.png

    upload_2023-10-17_9-25-16.png

    https://docs.unity3d.com/Packages/c...ersal@17.0/manual/urp-universal-renderer.html

    NOTE: the new name for the setting is "Depth Texture Mode", the doc page needs updating
     
    Last edited: Oct 17, 2023
    ElliotB likes this.