Search Unity

Pixel world position recreation from depth buffer in URP

Discussion in 'Universal Render Pipeline' started by ko0zi, Oct 23, 2020.

  1. ko0zi

    ko0zi

    Joined:
    Feb 27, 2017
    Posts:
    15
    Hello! I have been trying to implement a shader effect for quite some time now, but I am currently stuck and need your help.

    I have been following this tutorial which demonstrates the effect I'm going for


    The tutorial is however for the built in render pipeline, and I'm trying to convert it for usage with the URP.

    For easy reference, here is the unmodified shader ( https://github.com/Broxxar/NoMansScanner/blob/master/Assets/Scanner Effect/ScannerEffect.shader )

    Code (CSharp):
    1. Shader "Hidden/ScannerEffect"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex("Texture", 2D) = "white" {}
    6.         _DetailTex("Texture", 2D) = "white" {}
    7.         _ScanDistance("Scan Distance", float) = 0
    8.         _ScanWidth("Scan Width", float) = 10
    9.         _LeadSharp("Leading Edge Sharpness", float) = 10
    10.         _LeadColor("Leading Edge Color", Color) = (1, 1, 1, 0)
    11.         _MidColor("Mid Color", Color) = (1, 1, 1, 0)
    12.         _TrailColor("Trail Color", Color) = (1, 1, 1, 0)
    13.         _HBarColor("Horizontal Bar Color", Color) = (0.5, 0.5, 0.5, 0)
    14.     }
    15.     SubShader
    16.     {
    17.         // No culling or depth
    18.         Cull Off ZWrite Off ZTest Always
    19.  
    20.         Pass
    21.         {
    22.             CGPROGRAM
    23.             #pragma vertex vert
    24.             #pragma fragment frag
    25.          
    26.             #include "UnityCG.cginc"
    27.  
    28.             struct VertIn
    29.             {
    30.                 float4 vertex : POSITION;
    31.                 float2 uv : TEXCOORD0;
    32.                 float4 ray : TEXCOORD1;
    33.             };
    34.  
    35.             struct VertOut
    36.             {
    37.                 float4 vertex : SV_POSITION;
    38.                 float2 uv : TEXCOORD0;
    39.                 float2 uv_depth : TEXCOORD1;
    40.                 float4 interpolatedRay : TEXCOORD2;
    41.             };
    42.  
    43.             float4 _MainTex_TexelSize;
    44.             float4 _CameraWS;
    45.  
    46.             VertOut vert(VertIn v)
    47.             {
    48.                 VertOut o;
    49.                 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    50.                 o.uv = v.uv.xy;
    51.                 o.uv_depth = v.uv.xy;
    52.  
    53.                 #if UNITY_UV_STARTS_AT_TOP
    54.                 if (_MainTex_TexelSize.y < 0)
    55.                     o.uv.y = 1 - o.uv.y;
    56.                 #endif              
    57.  
    58.                 o.interpolatedRay = v.ray;
    59.  
    60.                 return o;
    61.             }
    62.  
    63.             sampler2D _MainTex;
    64.             sampler2D _DetailTex;
    65.             sampler2D_float _CameraDepthTexture;
    66.             float4 _WorldSpaceScannerPos;
    67.             float _ScanDistance;
    68.             float _ScanWidth;
    69.             float _LeadSharp;
    70.             float4 _LeadColor;
    71.             float4 _MidColor;
    72.             float4 _TrailColor;
    73.             float4 _HBarColor;
    74.  
    75.             float4 horizBars(float2 p)
    76.             {
    77.                 return 1 - saturate(round(abs(frac(p.y * 100) * 2)));
    78.             }
    79.  
    80.             float4 horizTex(float2 p)
    81.             {
    82.                 return tex2D(_DetailTex, float2(p.x * 30, p.y * 40));
    83.             }
    84.  
    85.             half4 frag (VertOut i) : SV_Target
    86.             {
    87.                 half4 col = tex2D(_MainTex, i.uv);
    88.  
    89.                 float rawDepth = DecodeFloatRG(tex2D(_CameraDepthTexture, i.uv_depth));
    90.                 float linearDepth = Linear01Depth(rawDepth);
    91.                 float4 wsDir = linearDepth * i.interpolatedRay;
    92.                 float3 wsPos = _WorldSpaceCameraPos + wsDir;
    93.                 half4 scannerCol = half4(0, 0, 0, 0);
    94.  
    95.                 float dist = distance(wsPos, _WorldSpaceScannerPos);
    96.  
    97.                 if (dist < _ScanDistance && dist > _ScanDistance - _ScanWidth && linearDepth < 1)
    98.                 {
    99.                     float diff = 1 - (_ScanDistance - dist) / (_ScanWidth);
    100.                     half4 edge = lerp(_MidColor, _LeadColor, pow(diff, _LeadSharp));
    101.                     scannerCol = lerp(_TrailColor, edge, diff) + horizBars(i.uv) * _HBarColor;
    102.                     scannerCol *= diff;
    103.                 }
    104.  
    105.                 return col + scannerCol;
    106.             }
    107.             ENDCG
    108.         }
    109.     }
    110. }
    And here is the logic script for giving the shader the essential data using built in renderer. (https://github.com/Broxxar/NoMansScanner/blob/master/Assets/Scanner Effect/ScannerEffectDemo.cs)
    Code (CSharp):
    1. [ImageEffectOpaque]
    2.     void OnRenderImage(RenderTexture src, RenderTexture dst)
    3.     {
    4.         EffectMaterial.SetVector("_WorldSpaceScannerPos",
    5.                                ScannerOrigin.position);
    6.         EffectMaterial.SetFloat("_ScanDistance", ScanDistance);
    7.         RaycastCornerBlit(src, dst, EffectMaterial);
    8.     }
    9.  
    10.     void RaycastCornerBlit(RenderTexture source,
    11.                             RenderTexture dest,
    12.                             Material mat)
    13.     {
    14.         // Compute Frustum Corners
    15.         float camFar = _camera.farClipPlane;
    16.         float camFov = _camera.fieldOfView;
    17.         float camAspect = _camera.aspect;
    18.  
    19.         float fovWHalf = camFov * 0.5f;
    20.  
    21.         Vector3 toRight = _camera.transform.right
    22.                                * Mathf.Tan(fovWHalf
    23.                                * Mathf.Deg2Rad)
    24.                                * camAspect;
    25.         Vector3 toTop = _camera.transform.up
    26.                                * Mathf.Tan(fovWHalf
    27.                                * Mathf.Deg2Rad);
    28.  
    29.         Vector3 topLeft = (_camera.transform.forward - toRight + toTop);
    30.         float camScale = topLeft.magnitude * camFar;
    31.  
    32.         topLeft.Normalize();
    33.         topLeft *= camScale;
    34.  
    35.         Vector3 topRight = (_camera.transform.forward + toRight + toTop);
    36.         topRight.Normalize();
    37.         topRight *= camScale;
    38.  
    39.         Vector3 bottomRight = (_camera.transform.forward + toRight - toTop);
    40.         bottomRight.Normalize();
    41.         bottomRight *= camScale;
    42.  
    43.         Vector3 bottomLeft = (_camera.transform.forward - toRight - toTop);
    44.         bottomLeft.Normalize();
    45.         bottomLeft *= camScale;
    46.  
    47.         // Custom Blit, encoding Frustum Corners as
    48.         // additional Texture Coordinates
    49.         RenderTexture.active = dest;
    50.  
    51.         mat.SetTexture("_MainTex", source);
    52.  
    53.         GL.PushMatrix();
    54.         GL.LoadOrtho();
    55.  
    56.         mat.SetPass(0);
    57.  
    58.         GL.Begin(GL.QUADS);
    59.  
    60.         GL.MultiTexCoord2(0, 0.0f, 0.0f);
    61.         GL.MultiTexCoord(1, bottomLeft);
    62.         GL.Vertex3(0.0f, 0.0f, 0.0f);
    63.  
    64.         GL.MultiTexCoord2(0, 1.0f, 0.0f);
    65.         GL.MultiTexCoord(1, bottomRight);
    66.         GL.Vertex3(1.0f, 0.0f, 0.0f);
    67.  
    68.         GL.MultiTexCoord2(0, 1.0f, 1.0f);
    69.         GL.MultiTexCoord(1, topRight);
    70.         GL.Vertex3(1.0f, 1.0f, 0.0f);
    71.  
    72.         GL.MultiTexCoord2(0, 0.0f, 1.0f);
    73.         GL.MultiTexCoord(1, topLeft);
    74.         GL.Vertex3(0.0f, 1.0f, 0.0f);
    75.  
    76.         GL.End();
    77.         GL.PopMatrix();
    78.     }
    The first issue I encountered was that there are no "OnRenderImage" callback in the URP so I tried to implement a custom [ScriptableRendererFeature] and [ScriptableRenderPass]



    I have "Depth Texture" and "Opaque Texture" enabled in the "UniversalRenderPipelineAsset" options.

    This is my current implementation in the Execute function of the [ScriptableRenderPass]


    Code (CSharp):
    1. public override void Execute(ScriptableRenderContext context,
    2.                                         ref RenderingData renderingData)
    3.             {
    4.             CommandBuffer cmd = CommandBufferPool.Get(m_ProfilerTag);
    5.  
    6.             Camera _camera = renderingData.cameraData.camera;
    7.             cmd.SetGlobalVector("_WorldSpaceScannerPos",
    8.                                 _camera.transform.position);
    9.          
    10.             // Compute Frustum Corners
    11.             float camFar = _camera.farClipPlane;
    12.             float camFov = _camera.fieldOfView;
    13.             float camAspect = _camera.aspect;
    14.             float fovWHalf = camFov * 0.5f;
    15.  
    16.             Vector3 toRight = _camera.transform.right
    17.                             * Mathf.Tan(fovWHalf
    18.                             * Mathf.Deg2Rad)
    19.                             * camAspect;
    20.             Vector3 toTop = _camera.transform.up
    21.                             * Mathf.Tan(fovWHalf
    22.                             * Mathf.Deg2Rad);
    23.             Vector3 topLeft = (_camera.transform.forward - toRight + toTop);
    24.             float camScale = topLeft.magnitude * camFar;
    25.             topLeft.Normalize();
    26.             topLeft *= camScale;
    27.  
    28.             Vector3 topRight = (_camera.transform.forward + toRight + toTop);
    29.             topRight.Normalize();
    30.             topRight *= camScale;
    31.  
    32.             Vector3 bottomRight = (_camera.transform.forward + toRight - toTop);
    33.             bottomRight.Normalize();
    34.             bottomRight *= camScale;
    35.  
    36.             Vector3 bottomLeft = (_camera.transform.forward - toRight - toTop);
    37.             bottomLeft.Normalize();
    38.             bottomLeft *= camScale;
    39.  
    40.             RenderTextureDescriptor opaqueDesc =
    41.                     renderingData.cameraData.cameraTargetDescriptor;
    42.  
    43.             opaqueDesc.depthBufferBits = 16;
    44.  
    45.             cmd.GetTemporaryRT(m_TemporaryColorTexture.id,
    46.                                 opaqueDesc,
    47.                                 filterMode);
    48.             Blit(cmd, source, m_TemporaryColorTexture.id,
    49.                                 blitMaterial,
    50.                                 blitShaderPassIndex);
    51.          
    52.             // Custom Blit, encoding Frustum Corners
    53.             // as additional Texture Coordinates
    54.             cmd.SetRenderTarget(m_TemporaryColorTexture.id);
    55.             cmd.SetGlobalTexture("_MainTex", source);
    56.  
    57.             GL.PushMatrix();
    58.             GL.LoadOrtho();
    59.  
    60.             blitMaterial.SetPass(0);
    61.  
    62.             GL.Begin(GL.QUADS);
    63.  
    64.             GL.MultiTexCoord2(0, 0.0f, 0.0f);
    65.             GL.MultiTexCoord(1, bottomLeft);
    66.             GL.Vertex3(0.0f, 0.0f, 0.0f);
    67.  
    68.             GL.MultiTexCoord2(0, 1.0f, 0.0f);
    69.             GL.MultiTexCoord(1, bottomRight);
    70.             GL.Vertex3(1.0f, 0.0f, 0.0f);
    71.  
    72.             GL.MultiTexCoord2(0, 1.0f, 1.0f);
    73.             GL.MultiTexCoord(1, topRight);
    74.             GL.Vertex3(1.0f, 1.0f, 0.0f);
    75.  
    76.             GL.MultiTexCoord2(0, 0.0f, 1.0f);
    77.             GL.MultiTexCoord(1, topLeft);
    78.             GL.Vertex3(0.0f, 1.0f, 0.0f);
    79.  
    80.             GL.End();
    81.             GL.PopMatrix();
    82.  
    83.             Blit(cmd, m_TemporaryColorTexture.id, source);
    84.  
    85.             context.ExecuteCommandBuffer(cmd);
    86.             CommandBufferPool.Release(cmd);
    87.         }
    It seems like, the "TEXCOORD1" in the VertIn struct that "ray" get assigned to in the shader is not correct, which leads me to believe that I do something wrong in the Execute function..

    The shader is drawing the scan effect, however only when _WorldSpaceScannerPos is exactly that of the cameras, which leads me to believe that the pixel to world position is incorrect. We can see that the effect expands from the lower left corner of the view which also suggests that something fishy is going on..
     
  2. lvcoc

    lvcoc

    Joined:
    Jul 26, 2018
    Posts:
    9
    Did you fixed it,I am trying this shader in URP too,and lots of bugs made me crazy
     
  3. weiping-toh

    weiping-toh

    Joined:
    Sep 8, 2015
    Posts:
    192
    Are you mixing GL codes and commandbuffer codes together?
    GL calls are executed almost immediate upon calling but command buffers stack commands and do not execute until the you call for execution, which would explain why you would have lost all your vertex info during the execution because the context where you attempted to blit, do not contain the GL info.

    Hint: Try rewriting the GL parts in command buffer terms.
     
  4. ko0zi

    ko0zi

    Joined:
    Feb 27, 2017
    Posts:
    15
    Hi, sorry late answer.. I rewrote the shader from scratch and just like weiping-toh is suggesting above this comment is that we can't use GL commands with command buffer render feature!
     
    junhaowanggg likes this.
  5. junhaowanggg

    junhaowanggg

    Joined:
    Nov 14, 2015
    Posts:
    2
    Hi ko0Zi, I had the same problem. Any update on how to pass the UV value to the shader?
     
  6. junhaowanggg

    junhaowanggg

    Joined:
    Nov 14, 2015
    Posts:
    2
    ko0zi likes this.