Search Unity

How to render the depth of transparent objects to _CameraDepthTexture

Discussion in 'Universal Render Pipeline' started by JASONYJY, Apr 9, 2022.

  1. JASONYJY

    JASONYJY

    Joined:
    Oct 15, 2015
    Posts:
    4
    I want to write the depth information of the transparent object to _CameraDepthTexture,But I don't know what to do.
    I use DepthNormalsFeature to render depth:
    截屏2022-04-09 18.46.52.png
    The two balls in the middle are transparent and the others are opaque.

    and c#:

    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3. using UnityEngine.Rendering;
    4. using UnityEngine.Rendering.Universal;
    5.  
    6. public class DepthNormalsFeature : ScriptableRendererFeature {
    7.     class RenderPass : ScriptableRenderPass {
    8.  
    9.         private Material material;
    10.         private RenderTargetHandle destinationHandle;
    11.         private List<ShaderTagId> shaderTags;
    12.         private FilteringSettings filteringSettings;
    13.  
    14.         public RenderPass() : base() {
    15.             this.material = CoreUtils.CreateEngineMaterial("My/Internal-DepthNormalsTexture"); ;
    16.             this.shaderTags = new List<ShaderTagId>() {
    17.                 new ShaderTagId("DepthOnly"),
    18.                 // Render shader graph transparent materials
    19.                 new ShaderTagId("DepthNormalsOnly")
    20.             };
    21.             // RenderQueueRange.all: Render transparent materials
    22.             this.filteringSettings = new FilteringSettings(RenderQueueRange.all);
    23.             renderPassEvent = RenderPassEvent.AfterRenderingPrePasses;
    24.             destinationHandle.Init("_DepthNormalsTexture");
    25.         }
    26.  
    27.         public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) {
    28.             cmd.GetTemporaryRT(destinationHandle.id, cameraTextureDescriptor, FilterMode.Point);
    29.             ConfigureTarget(destinationHandle.Identifier());
    30.             ConfigureClear(ClearFlag.All, Color.black);
    31.         }
    32.  
    33.         public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) {
    34.             var drawSettings = CreateDrawingSettings(shaderTags, ref renderingData, renderingData.cameraData.defaultOpaqueSortFlags);
    35.  
    36.             drawSettings.overrideMaterial = material;
    37.             context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref filteringSettings);
    38.         }
    39.  
    40.         public override void FrameCleanup(CommandBuffer cmd) {
    41.             cmd.ReleaseTemporaryRT(destinationHandle.id);
    42.         }
    43.     }
    44.  
    45.     private RenderPass renderPass;
    46.  
    47.     public override void Create() {
    48.         this.renderPass = new RenderPass();
    49.     }
    50.  
    51.     public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) {
    52.         renderer.EnqueuePass(renderPass);
    53.     }
    54. }
    shader:

    Code (CSharp):
    1. Shader "My/Internal-DepthNormalsTexture"
    2. {
    3.     SubShader
    4.     {
    5.         Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
    6.        
    7.         Pass
    8.         {
    9.             Name "Depth-Normal"
    10.            
    11.             HLSLPROGRAM
    12.             HLSLcc by default
    13.             #pragma prefer_hlslcc gles
    14.             #pragma exclude_renderers d3d11_9x
    15.             #pragma target 2.0
    16.            
    17.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    18.            
    19.             #pragma vertex vert
    20.             #pragma fragment frag
    21.            
    22.             struct Attributes
    23.             {
    24.                 float4 positionOS: POSITION;
    25.                 float3 normalOS: NORMAL;
    26.             };
    27.            
    28.             struct Varyings
    29.             {
    30.                 float4 positionCS: SV_POSITION;
    31.                 float4 normal_depth: TEXCOORD0;
    32.             };
    33.            
    34.             // Encoding/decoding view space normals into 2D 0..1 vector
    35.             float2 EncodeViewNormalStereo(float3 n)
    36.             {
    37.                 float kScale = 1.7777;
    38.                 float2 enc;
    39.                 enc = n.xy / (n.z + 1);
    40.                 enc /= kScale;
    41.                 enc = enc * 0.5 + 0.5;
    42.                 return enc;
    43.             }
    44.            
    45.             // Encoding/decoding [0..1) floats into 8 bit/channel RG. Note that 1.0 will not be encoded properly.
    46.             float2 EncodeFloatRG(float v)
    47.             {
    48.                 float2 kEncodeMul = float2(1.0, 255.0);
    49.                 float kEncodeBit = 1.0 / 255.0;
    50.                 float2 enc = kEncodeMul * v;
    51.                 enc = frac(enc);
    52.                 enc.x -= enc.y * kEncodeBit;
    53.                 return enc;
    54.             }
    55.            
    56.             float4 EncodeDepthNormal(float depth, float3 normal)
    57.             {
    58.                 float4 enc;
    59.                 enc.xy = EncodeViewNormalStereo(normal);
    60.                 enc.zw = EncodeFloatRG(depth);
    61.                 //enc.zw = float2(0, 0);
    62.                 return enc;
    63.             }
    64.            
    65.             Varyings vert(Attributes input)
    66.             {
    67.                 Varyings output = (Varyings)0;
    68.                
    69.                 VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
    70.                
    71.                 output.positionCS = vertexInput.positionCS;
    72.                 output.normal_depth.xyz = mul((float3x3)UNITY_MATRIX_IT_MV, input.normalOS);
    73.                 output.normal_depth.w = - (vertexInput.positionVS.z * _ProjectionParams.w);
    74.                 return output;
    75.             }
    76.            
    77.             half4 frag(Varyings input): SV_Target
    78.             {
    79.                 return EncodeDepthNormal(input.normal_depth.w, input.normal_depth.xyz);
    80.             }
    81.             ENDHLSL
    82.            
    83.         }
    84.     }
    85. }
    Then in the copy depth stage, the two transparent balls disappeared

    截屏2022-04-09 18.56.06.png

    I want to use the with transparent material depth information later in the rednerobjects phase _Cameradepthtexture, but I can't get it

    2022-04-09 19.00.45.png

    How can I write transparent object depth information to _Cameradepthtexture?
     
  2. funkyCoty

    funkyCoty

    Joined:
    May 22, 2018
    Posts:
    727
    Instead of writing to it directly, do you just want to update _CameraDepthTexture again?

    _CameraDepthTexture
    is automatically handled by Unity based on various factors (what RenderFeatures you're using, if you have that toggle checked on, stuff like that). It's just a blit of the current working depth to a new texture, so you can read the results from that moment onward despite depth still being written to in upcoming draws. I believe the blit is always done either after Opaque geometry is rendered or maybe after the Skybox is rendered (either way, before transparency queue).

    If you want to 'update' _CameraDepthTexture's results, you'll need to do another blit. URP is written by people who don't make games, it seems, and so they don't provide any easy way to do this. Your best bet is to just have your own custom RenderFeature/RenderPass which does the same blit at whichever moment you need.
     
    forestrf and revolute like this.
  3. JASONYJY

    JASONYJY

    Joined:
    Oct 15, 2015
    Posts:
    4
    I want to render outlines for transparent objects, so I need to use SHADERGRAPH_SAMPLE_SCENE_DEPTH, but transparent shader do not render to by default _CameraDepthTexture

    Code (CSharp):
    1. // Weights for the x component
    2. static float sobelXMatrix[9] = {
    3.     1, 0, -1,
    4.     2, 0, -2,
    5.     1, 0, -1
    6. };
    7.  
    8. // Weights for the y component
    9. static float sobelYMatrix[9] = {
    10.     1, 2, 1,
    11.     0, 0, 0,
    12.     -1, -2, -1
    13. };
    14.  
    15. void DepthSobel_float(float2 UV, float Thickness, out float Out) {
    16.     float2 sobel = 0;
    17.     [unroll] for (int i = 0; i < 9; i++) {
    18.         float depth = SHADERGRAPH_SAMPLE_SCENE_DEPTH(UV + sobelSamplePoints[i] * Thickness);
    19.         sobel += depth * float2(sobelXMatrix[i], sobelYMatrix[i]);
    20.     }
    21.     Out = length(sobel);
    22. }
    23.  
     
  4. ManueleB

    ManueleB

    Unity Technologies

    Joined:
    Jul 6, 2020
    Posts:
    110
    In versions < 22.1, the CopyDepth pass happens always after the Opaque pass, so the copied depth will miss any transparent depth. The solution to that would be to write your own CopyDepthPass render feature (you can look at CopyDepthPass.cs as an implementation example).

    In 22.1 we added a new "Copy Depth Mode" option to the renderer that allows to copy the depth after the transparent pass instead of using the opaque one:

    upload_2022-4-11_13-48-42.png
     
  5. Graigy1337

    Graigy1337

    Joined:
    Oct 26, 2019
    Posts:
    9

    Hi there I have been trying to get this working but I have hit a wall.
    I set up a test environment with two opaque cubes and a transparent one.
    I placed them into a giant cube that has the test shader on it, basically it just highlights the object White if it detects its depth. As you can see in the picture only the Opaque cubes (the sides) show up. The middle ones just doesn't interact at all. I tired Depth Write Always and a million other things i could think of but nothing. Any ideas? Thanks

    DepthTest.png DepthTestShader.png RenderSettings.png