Search Unity

Question What's the correct way to draw into a custom depth buffer in CustomPass

Discussion in 'High Definition Render Pipeline' started by ryanflees, Jan 4, 2023.

  1. ryanflees

    ryanflees

    Joined:
    Nov 15, 2014
    Posts:
    59
    Unity 2022.2 + HDRP

    I need to draw objects depth of a certain layer into a custom depth texture in CustomPass.
    I've tried CustomPass's custom depth buffer, and create my only buffer , neither of them works.
    CustomPassUtils.RenderDepthFromCamera,
    CustomPassUtils.RenderFromCamera,
    CoreUtils.DrawRendererList
    none of these APIs works either.
    I tried to blit the buffer into a RenderTexture, the render texture shows the scene depth.
    Tried to draw a fullscreen with the custom buffer , and the result shows all black.
    So what would be the correct way to draw a custom depth? I've search through the offical CustomPass examples from github(in unity 2022), searched in google and can't find any effective result.

    Here's one of the code I use, which is a mixed of the DrawRenderersCustomPass of HDRP and CopyPass from the CustomPass examples.

    Code (CSharp):
    1.  
    2. using System.Collections.Generic;
    3. using UnityEngine.Rendering;
    4. using UnityEngine.Experimental.Rendering;
    5. using System;
    6. using UnityEngine;
    7. using UnityEngine.Rendering.HighDefinition;
    8.  
    9. namespace CR
    10. {
    11.     /// <summary>
    12.     /// DrawRenderers Custom Pass
    13.     /// </summary>
    14.     [System.Serializable]
    15.     public class TestDrawRenderer : CustomPass
    16.     {
    17.         /// <summary>
    18.         /// HDRP Shader passes
    19.         /// </summary>
    20.         public enum ShaderPass
    21.         {
    22.             // Ordered by frame time in HDRP
    23.             ///<summary>Object Depth pre-pass, only the depth of the object will be rendered.</summary>
    24.             DepthPrepass = 1,
    25.             ///<summary>Forward pass, render the object color.</summary>
    26.             Forward = 0,
    27.         }
    28.  
    29.         // Used only for the UI to keep track of the toggle state
    30.         [SerializeField] internal bool filterFoldout;
    31.         [SerializeField] internal bool rendererFoldout;
    32.  
    33.         //Filter settings
    34.         /// <summary>
    35.         /// Render Queue filter to select which kind of object to render.
    36.         /// </summary>
    37.         public RenderQueueType renderQueueType = RenderQueueType.AllOpaque;
    38.         /// <summary>
    39.         /// Layer Mask filter, select which layer to render.
    40.         /// </summary>
    41.         public LayerMask layerMask = 1; // Layer mask Default enabled
    42.         /// <summary>
    43.         /// Sorting flags of the objects to render.
    44.         /// </summary>
    45.         public SortingCriteria sortingCriteria = SortingCriteria.CommonOpaque;
    46.  
    47.         /// <summary>
    48.         /// Select which type of override to apply on the DrawRenderers pass.
    49.         /// </summary>
    50.         public enum OverrideMaterialMode
    51.         {
    52.             /// <summary> Disable the material override </summary>
    53.             None,
    54.             /// <summary> Override the material for all renderers </summary>
    55.             Material,
    56.             /// <summary> Override the shader for all renderers. This option keeps the material properties of the renderer and can be used like a replacement shader. </summary>
    57.             Shader
    58.         };
    59.  
    60.         /// <summary>
    61.         /// Controls how the material on each renderer will be replaced. Material mode uses overrideMaterial. Shader mode uses overrideShader.
    62.         /// </summary>
    63.         public OverrideMaterialMode overrideMode = OverrideMaterialMode.Material; //default to Material as this was previously the only option
    64.  
    65.         // Override material
    66.         /// <summary>
    67.         /// Replaces the material of selected renders by this one, be sure to also set overrideMaterialPassName to a good value when using this property.
    68.         /// </summary>
    69.         public Material overrideMaterial = null;
    70.         [SerializeField]
    71.         int overrideMaterialPassIndex = 0;
    72.         /// <summary>
    73.         /// Select which pass will be used to render objects when using an override material.
    74.         /// </summary>
    75.         public string overrideMaterialPassName = "Forward";
    76.  
    77.         // Override shader
    78.         /// <summary>
    79.         /// Replaces the shader of selected renderers while using the current material properties.
    80.         /// </summary>
    81.         public Shader overrideShader = null;
    82.         [SerializeField]
    83.         int overrideShaderPassIndex = 0;
    84.         ///<summary>
    85.         /// Select whih pass will be used to render objects when using an override material.
    86.         /// </summary>
    87.         public string overrideShaderPassName = "Forward";
    88.  
    89.         /// <summary>
    90.         /// When true, overrides the depth state of the objects.
    91.         /// </summary>
    92.         public bool overrideDepthState = false;
    93.         /// <summary>
    94.         /// Overrides the Depth comparison function, only used when overrideDepthState is true.
    95.         /// </summary>
    96.         public CompareFunction depthCompareFunction = CompareFunction.LessEqual;
    97.         /// <summary>
    98.         /// Overrides the Depth write, only used when overrideDepthState is true.
    99.         /// </summary>
    100.         public bool depthWrite = true;
    101.  
    102.         /// <summary>
    103.         /// Override the stencil state of the objects.
    104.         /// </summary>
    105.         public bool overrideStencil = false;
    106.  
    107.         /// <summary>
    108.         /// Stencil reference value. Be careful when using this value to write in the stencil buffer to not overwrite HDRP stencil bits.
    109.         /// </summary>
    110.         public int stencilReferenceValue = (int)UserStencilUsage.UserBit0;
    111.  
    112.         /// <summary>
    113.         /// Write mask of the stencil.
    114.         /// </summary>
    115.         public int stencilWriteMask = (int)(UserStencilUsage.AllUserBits);
    116.  
    117.         /// <summary>
    118.         /// Read mask of the stencil
    119.         /// </summary>
    120.         public int stencilReadMask = (int)(UserStencilUsage.AllUserBits);
    121.  
    122.         /// <summary>
    123.         /// Comparison operation between the stencil buffer and the reference value.
    124.         /// </summary>
    125.         public CompareFunction stencilCompareFunction = CompareFunction.Always;
    126.  
    127.         /// <summary>
    128.         /// Operation to execute if the stencil test passes.
    129.         /// </summary>
    130.         public StencilOp stencilPassOperation;
    131.  
    132.         /// <summary>
    133.         /// Operation to execute if the stencil test fails.
    134.         /// </summary>
    135.         public StencilOp stencilFailOperation;
    136.  
    137.         /// <summary>
    138.         /// Operation to execute if the depth test fails.
    139.         /// </summary>
    140.         public StencilOp stencilDepthFailOperation;
    141.  
    142.         /// <summary>
    143.         /// Set the shader pass to use when the override material is null
    144.         /// </summary>
    145.         public ShaderPass shaderPass = ShaderPass.Forward;
    146.  
    147.         int fadeValueId;
    148.  
    149.         static ShaderTagId[] forwardShaderTags;
    150.         static ShaderTagId[] depthShaderTags;
    151.  
    152.         // Cache the shaderTagIds so we don't allocate a new array each frame
    153.         ShaderTagId[] cachedShaderTagIDs;
    154.  
    155.         //public RenderTexture depthTexture = null;
    156.         public enum BufferType
    157.         {
    158.             Color,
    159.             Normal,
    160.             Roughness,
    161.             Depth,
    162.             CustomDepth,
    163.             MotionVectors,
    164.         }
    165.  
    166.         public RenderTexture outputRenderTexture;
    167.  
    168.         [SerializeField, HideInInspector]
    169.         Shader customCopyShader;
    170.         Material customCopyMaterial;
    171.  
    172.         public BufferType bufferType;
    173.  
    174.         protected override bool executeInSceneView => false;
    175.  
    176.         int normalPass;
    177.         int roughnessPass;
    178.         int depthPass;
    179.        
    180.        
    181.         //RTHandle fpsDepthBuffer;
    182.         /// <summary>
    183.         /// Called before the first execution of the pass occurs.
    184.         /// Allow you to allocate custom buffers.
    185.         /// </summary>
    186.         /// <param name="renderContext">The render context</param>
    187.         /// <param name="cmd">Current command buffer of the frame</param>
    188.         protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
    189.         {
    190.             fadeValueId = Shader.PropertyToID("_FadeValue");
    191.  
    192.             // In case there was a pass index assigned, we retrieve the name of this pass
    193.             if (String.IsNullOrEmpty(overrideMaterialPassName) && overrideMaterial != null)
    194.                 overrideMaterialPassName = overrideMaterial.GetPassName(overrideMaterialPassIndex);
    195.             if (String.IsNullOrEmpty(overrideShaderPassName) && overrideShader != null)
    196.                 overrideShaderPassName = new Material(overrideShader).GetPassName(overrideShaderPassIndex);
    197.  
    198.             forwardShaderTags = new ShaderTagId[]
    199.             {
    200.                 HDShaderPassNames.s_ForwardName,            // HD Lit shader
    201.                 HDShaderPassNames.s_ForwardOnlyName,        // HD Unlit shader
    202.                 HDShaderPassNames.s_SRPDefaultUnlitName,    // Cross SRP Unlit shader
    203.                 HDShaderPassNames.s_EmptyName,              // Add an empty slot for the override material
    204.             };
    205.  
    206.             depthShaderTags = new ShaderTagId[]
    207.             {
    208.                 HDShaderPassNames.s_DepthForwardOnlyName,
    209.                 HDShaderPassNames.s_DepthOnlyName,
    210.                 HDShaderPassNames.s_EmptyName,              // Add an empty slot for the override material
    211.             };
    212.            
    213.             if (customCopyShader == null)
    214.                 customCopyShader = Shader.Find("Hidden/FullScreen/CustomCopy");
    215.             customCopyMaterial = CoreUtils.CreateEngineMaterial(customCopyShader);
    216.  
    217.             normalPass = customCopyMaterial.FindPass("Normal");
    218.             roughnessPass = customCopyMaterial.FindPass("Roughness");
    219.             depthPass = customCopyMaterial.FindPass("Depth");
    220.            
    221.             //
    222.             // fpsDepthBuffer = RTHandles.Alloc(
    223.             //     Vector2.one,
    224.             //     TextureXR.slices,
    225.             //     dimension: TextureXR.dimension,
    226.             //     useDynamicScale: true,
    227.             //     name: "Test Depth",
    228.             //     enableRandomWrite: true
    229.             // );
    230.         }
    231.  
    232.         protected override void Cleanup()
    233.         {
    234.             CoreUtils.Destroy(customCopyMaterial);
    235.             //fpsDepthBuffer.Release();
    236.         }
    237.  
    238.         /// <summary>
    239.         /// Use this method if you want to draw objects that are not visible in the camera.
    240.         /// For example if you disable a layer in the camera and add it in the culling parameters, then the culling result will contains your layer.
    241.         /// </summary>
    242.         /// <param name="cullingParameters">Aggregate the parameters in this property (use |= for masks fields, etc.)</param>
    243.         /// <param name="hdCamera">The camera where the culling is being done</param>
    244.         protected override void AggregateCullingParameters(ref ScriptableCullingParameters cullingParameters, HDCamera hdCamera)
    245.         {
    246.             cullingParameters.cullingMask |= (uint)(int)layerMask;
    247.         }
    248.  
    249.         ShaderTagId[] GetShaderTagIds()
    250.         {
    251.             if (shaderPass == ShaderPass.DepthPrepass)
    252.                 return depthShaderTags;
    253.             else
    254.                 return forwardShaderTags;
    255.         }
    256.  
    257.         /// <summary>
    258.         /// Execute the DrawRenderers with parameters setup from the editor
    259.         /// </summary>
    260.         /// <param name="ctx">The context of the custom pass. Contains command buffer, render context, buffer, etc.</param>
    261.         protected override void Execute(CustomPassContext ctx)
    262.         {
    263.             base.Execute(ctx);
    264.             var shaderPasses = GetShaderTagIds();
    265.             if (overrideMaterial != null)
    266.             {
    267.                 shaderPasses[shaderPasses.Length - 1] = new ShaderTagId(overrideMaterialPassName);
    268.                 overrideMaterial.SetFloat(fadeValueId, fadeValue);
    269.             }
    270.  
    271.             if (shaderPasses.Length == 0)
    272.             {
    273.                 Debug.LogWarning("Attempt to call DrawRenderers with an empty shader passes. Skipping the call to avoid errors");
    274.                 return;
    275.             }
    276.  
    277.             var mask = overrideDepthState ? RenderStateMask.Depth : 0;
    278.             mask |= overrideDepthState && !depthWrite ? RenderStateMask.Stencil : 0;
    279.             if (overrideStencil)
    280.                 mask |= RenderStateMask.Stencil;
    281.             var stateBlock = new RenderStateBlock(mask)
    282.             {
    283.                 depthState = new DepthState(depthWrite, depthCompareFunction),
    284.                 // We disable the stencil when the depth is overwritten but we don't write to it, to prevent writing to the stencil.
    285.                 stencilState = new StencilState(overrideStencil, (byte)stencilReadMask, (byte)stencilWriteMask, stencilCompareFunction, stencilPassOperation, stencilFailOperation, stencilDepthFailOperation),
    286.                 stencilReference = overrideStencil ? stencilReferenceValue : 0,
    287.             };
    288.  
    289.             PerObjectData renderConfig = ctx.hdCamera.frameSettings.IsEnabled(FrameSettingsField.Shadowmask) ? HDUtils.GetBakedLightingWithShadowMaskRenderConfig() : HDUtils.GetBakedLightingRenderConfig();
    290.             var overrideShaderMaterial = (overrideShader != null) ? new Material(overrideShader) : null;
    291.  
    292.             var result = new UnityEngine.Rendering.RendererUtils.RendererListDesc(shaderPasses, ctx.cullingResults, ctx.hdCamera.camera)
    293.             {
    294.                 rendererConfiguration = renderConfig,
    295.                 renderQueueRange = GetRenderQueueRange(renderQueueType),
    296.                 sortingCriteria = sortingCriteria,
    297.                 excludeObjectMotionVectors = false,
    298.                 overrideShader = overrideMode == OverrideMaterialMode.Shader ? overrideShader : null,
    299.                 overrideMaterial = overrideMode == OverrideMaterialMode.Material ? overrideMaterial : null,
    300.                 overrideMaterialPassIndex = (overrideMaterial != null) ? overrideMaterial.FindPass(overrideMaterialPassName) : 0,
    301.                 overrideShaderPassIndex = (overrideShader != null) ? overrideShaderMaterial.FindPass(overrideShaderPassName) : 0,
    302.                 stateBlock = stateBlock,
    303.                 layerMask = layerMask,
    304.             };
    305.  
    306.             UnityEngine.Object.DestroyImmediate(overrideShaderMaterial);
    307.             var renderCtx = ctx.renderContext;
    308.            
    309.             //CoreUtils.SetRenderTarget(ctx.cmd, ctx.cameraColorBuffer, fpsDepthBuffer, ClearFlag.Depth);
    310.             CoreUtils.DrawRendererList(ctx.renderContext, ctx.cmd, renderCtx.CreateRendererList(result));
    311.  
    312.             ExecuteCopyPass(ctx);
    313.         }
    314.  
    315.         protected void ExecuteCopyPass(CustomPassContext ctx)
    316.         {
    317.             if (outputRenderTexture == null || customCopyMaterial == null)
    318.                 return;
    319.  
    320.             SyncRenderTextureAspect(outputRenderTexture, ctx.hdCamera.camera);
    321.  
    322.             var scale = RTHandles.rtHandleProperties.rtHandleScale;
    323.             customCopyMaterial.SetVector("_Scale", scale);
    324.  
    325.             switch (bufferType)
    326.             {
    327.                 default:
    328.                 case BufferType.Color:
    329.                     ctx.cmd.Blit(ctx.cameraColorBuffer, outputRenderTexture, new Vector2(scale.x, scale.y), Vector2.zero, 0, 0);
    330.                     break;
    331.                 case BufferType.Normal:
    332.                     ctx.cmd.Blit(ctx.cameraNormalBuffer, outputRenderTexture, customCopyMaterial, normalPass);
    333.                     break;
    334.                 case BufferType.Roughness:
    335.                     ctx.cmd.Blit(ctx.cameraNormalBuffer, outputRenderTexture, customCopyMaterial, roughnessPass);
    336.                     break;
    337.                 case BufferType.Depth:
    338.                     ctx.cmd.Blit(ctx.cameraNormalBuffer, outputRenderTexture, customCopyMaterial, depthPass);
    339.                     break;
    340.                 case BufferType.CustomDepth:
    341.                     {
    342.                         //ctx.cmd.Blit(fpsDepthBuffer, outputRenderTexture, customCopyMaterial, depthPass);
    343.                         ctx.cmd.Blit(ctx.customDepthBuffer.Value, outputRenderTexture, customCopyMaterial, depthPass);
    344.                     }
    345.                     break;
    346.                 case BufferType.MotionVectors:
    347.                     ctx.cmd.Blit(ctx.cameraMotionVectorsBuffer, outputRenderTexture, new Vector2(scale.x, scale.y), Vector2.zero, 0, 0);
    348.                     break;
    349.             }
    350.         }
    351.        
    352.         /// <summary>
    353.         /// List all the materials that need to be displayed at the bottom of the component.
    354.         /// All the materials gathered by this method will be used to create a Material Editor and then can be edited directly on the custom pass.
    355.         /// </summary>
    356.         /// <returns>An enumerable of materials to show in the inspector. These materials can be null, the list is cleaned afterwards</returns>
    357.         public override IEnumerable<Material> RegisterMaterialForInspector() { yield return overrideMaterial; }
    358.        
    359.         void SyncRenderTextureAspect(RenderTexture rt, Camera camera)
    360.         {
    361.             float aspect = rt.width / (float)rt.height;
    362.  
    363.             if (!Mathf.Approximately(aspect, camera.aspect))
    364.             {
    365.                 rt.Release();
    366.                 rt.width = camera.pixelWidth;
    367.                 rt.height = camera.pixelHeight;
    368.                 rt.Create();
    369.             }
    370.         }
    371.     }
    372. }
    373.  
    374.  
    QQ截图20230104205327.png
    The screenshot shows a background scene with a ball, the ball is of a special layer which's not renderer by the camera, but drawn in custom pass.I want to draw the depth of the ball in to the custom depth buffer, but the left-top result shows that the custom depth buffer is the scene depth, not the ball's depth.
    (shader pass changed to Depth Prepass doesn't work either)
     
  2. mathsive

    mathsive

    Joined:
    Jul 3, 2013
    Posts:
    3
    did you ever find a solution to this?