Search Unity

Getting depth of semitransparent object with HDRP Custom Post Process Volume shader.

Discussion in 'Shaders' started by sand_lantern, May 13, 2021.

  1. sand_lantern

    sand_lantern

    Joined:
    Sep 15, 2017
    Posts:
    210
    I have a custom shader that I call "SimpleZFog" for a 2.5D game I'm working on. Basically, this shader adds a hazy look to objects as it goes farther away from a specified Z distance. I use it both to give a foggy look, as well as to help isolate the foreground from the background.

    upload_2021-5-13_10-27-7.png

    Here is a little sample of what it looks like. It works pretty well, except in the situation with some VFX that I have.

    Here is what the VFX looks like w/o the post process.
    upload_2021-5-13_10-30-6.png

    However, with it on I get something more like this:
    upload_2021-5-13_10-26-10.png


    The thing about this, is that my shader only effects things with a depth greather than a certain Z value, which is more than my VFX in the third image. I think what is happening is that, when my shader is polling depth, it is getting the depth of whatever is behind my VFX object and then applying it to it. I can 'fix' the issue by moving my custom post process from `Before Post Process` to `After Opaque and Sky`, however this has the unfortunate problem of not applying SimpleZFog to water that I have because it's part of the Transparent Order
    upload_2021-5-13_10-34-23.png
    *Note here that, while the walls in the background are faded out, the water color remains static regardless of depth.

    I'm pretty new to shader programming, so any criticisms or style suggestions I'm happy to take also. Here is my shader:
    Code (CSharp):
    1. Shader "Hidden/Shader/SimpleZFog"
    2. {
    3.     HLSLINCLUDE
    4.  
    5.     #pragma target 4.5
    6.     //#pragma only_renderers d3d11 ps4 xboxone vulkan metal switch
    7.  
    8.     #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
    9.     #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
    10.     #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
    11.     #include "Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/FXAA.hlsl"
    12.     #include "Packages/com.unity.render-pipelines.high-definition/Runtime/PostProcessing/Shaders/RTUpscale.hlsl"
    13.     #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/SpaceTransforms.hlsl"
    14.  
    15.     struct Attributes
    16.     {
    17.         uint vertexID   : SV_VertexID;
    18.         UNITY_VERTEX_INPUT_INSTANCE_ID
    19.     };
    20.  
    21.     struct Varyings
    22.     {
    23.         float4 position : POSITION;
    24.         float2 texcoord : TEXCOORD0;
    25.         UNITY_VERTEX_OUTPUT_STEREO
    26.     };
    27.  
    28.     Varyings Vert(Attributes input)
    29.     {
    30.         Varyings output;
    31.         UNITY_SETUP_INSTANCE_ID(input);
    32.         UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
    33.         output.position = GetFullScreenTriangleVertexPosition(input.vertexID);
    34.         //output.zPos = input.vertex;
    35.         output.texcoord = GetFullScreenTriangleTexCoord(input.vertexID);
    36.         return output;
    37.     }
    38.  
    39.     // List of properties to control your post process effect
    40.     TEXTURE2D_X(_InputTexture);
    41.     float _Intensity;
    42.     float _MinZDistance;
    43.     float _MaxZDistance;
    44.     float _InfinityDistance;
    45.     float _MinDensity;
    46.     float _MaxDensity;
    47.     float _ImmediateDensity;
    48.     float _InfinityDensity;
    49.     float4 _ZFogColor;
    50.  
    51.     float4 CustomPostProcess(Varyings input) : SV_Target
    52.     {
    53.         UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
    54.  
    55.         uint2 positionSS = input.texcoord * _ScreenSize.xy;
    56.         float4 baseColor = LOAD_TEXTURE2D_X(_InputTexture, positionSS);
    57.         float3 outColor = baseColor.rgb;
    58.         float3 correctedColor = Gamma22ToLinear(_ZFogColor.rgb);
    59.  
    60.         float2 positionNDC = positionSS * _ScreenSize.zw + (0.5 * _ScreenSize.zw);
    61.         float  deviceDepth = LoadCameraDepth(positionSS);
    62.         float3 positionWS = ComputeWorldSpacePosition(positionNDC, deviceDepth, UNITY_MATRIX_I_VP);
    63.         positionWS = GetAbsolutePositionWS(positionWS);
    64.  
    65.         float z = positionWS.z;//GetAbsolutePositionWS(input.position.xyz).z;
    66.  
    67.  
    68.         if (z < _MinZDistance) {
    69.             if (_ImmediateDensity != 0) {
    70.                 outColor = lerp(outColor, correctedColor, _ImmediateDensity * _Intensity);
    71.             }
    72.         }
    73.         else if (z <= _MaxZDistance) {
    74.             float scale = (z - _MinZDistance) / (_MaxZDistance - _MinZDistance);
    75.             outColor = lerp(outColor, correctedColor, lerp(_MinDensity, _MaxDensity, scale) * _Intensity);
    76.         }
    77.         else if (z <= _InfinityDistance) {
    78.             outColor = lerp(outColor, correctedColor, _MaxDensity * _Intensity);
    79.         }
    80.         else {
    81.             outColor = lerp(outColor, correctedColor, _InfinityDensity * _Intensity);
    82.         }
    83.  
    84.         return float4(outColor, baseColor.a);
    85.     }
    86.  
    87.     ENDHLSL
    88.  
    89.     SubShader
    90.     {
    91.         Pass
    92.         {
    93.             Name "SimpleZFog"
    94.  
    95.             ZWrite Off
    96.             ZTest Always
    97.             Blend Off
    98.             Cull Off
    99.  
    100.             HLSLPROGRAM
    101.                 #pragma fragment CustomPostProcess
    102.                 #pragma vertex Vert
    103.             ENDHLSL
    104.         }
    105.     }
    106.     Fallback Off
    107. }
     

    Attached Files:

    Last edited: May 13, 2021
  2. three-ms-creative

    three-ms-creative

    Joined:
    May 5, 2021
    Posts:
    10
    Late to the party, but did you ever figure this out? I’m trying to solve this problem now and it seems almost impossible to do without modifying the HDRP source in some manner.
     
  3. sand_lantern

    sand_lantern

    Joined:
    Sep 15, 2017
    Posts:
    210
    We ended up changing our vfx to accommodate our shader. I think it may be possible still, but don't really have the time to go all in on a solution. It seems like Post Processing shaders are limited and not all options work with them or something.

    Would love for someone who knows better to give some input though!
     
  4. antoinel_unity

    antoinel_unity

    Unity Technologies

    Joined:
    Jan 7, 2019
    Posts:
    265
    Hello,

    have you tried to enable the depth post-pass option on the transparent materials you want to be affected by the fog?
    https://docs.unity3d.com/Packages/c...n@12.0/manual/Lit-Shader.html#surface-options

    The transparent depth post-pass option will render your transparent object in the depth buffer so the post-processes that require depth are correctly applied (for example depth of field).

    This solution really depends on the content of your scene, but it may work for you. Note that there is also an alpha clip threshold especially for the depth post-pass, so you can control when to write depth based on the transparency of the object.
     
  5. three-ms-creative

    three-ms-creative

    Joined:
    May 5, 2021
    Posts:
    10
    This is interesting, I'll have to give this a try. I came up with an alternate solution that involved making a slightly modified copy of the standard Lit shader that correctly receives fog. I like this strategy because it'll composite the fog correctly over an arbitrary number of layered transparent objects.

    Still I'll give this strategy a go, it might be easier to use in some cases. I have a hunch it won't work though, since my fog is composited in the sky pass, which takes place before transparent objects are even rendered.