Search Unity

Question HDRP in 2020.2.0f1 vs 2020.2.1f1 - what broke my shader?

Discussion in 'High Definition Render Pipeline' started by KYL3R, Jan 12, 2021.

  1. KYL3R

    KYL3R

    Joined:
    Nov 16, 2012
    Posts:
    135
    I have a custom handwritten HDRP Shader. It has 2 Passes, "DepthOnly" and "GBuffer". It was working nicely.
    Now I upgraded from 2020.2 "0f1" to "1f1" and it doesn't work properly: depth not clearing so it looks glitchy.

    0f1:

    1f1 (gray grass on the left is HDRP/Lit)



    Depth seems ok (DepthPrepass - Depth)


    But in DepthPrepass - RT0, it looks off:


    So what am I missing?


    Simplified code to reproduce:

    Code (CSharp):
    1. Shader "Custom/GrassBroken" {
    2.     Properties{
    3.         _TintColor1("Tint Color 1", Color) = (1, 1, 1)
    4.         _TintColor2("Tint Color 2", Color) = (1, 1, 1)
    5.         _ColorHeight("Color Height", Range(0, 1)) = .3
    6.  
    7.         _StencilRef("Stencil Ref Value", Range(0, 100)) = 10
    8.         _StencilWriteMask("Stencil WriteMask Value", Range(0, 100)) = 14
    9.         _StencilRefDepth("Stencil Ref Value Depth", Range(0, 100)) = 8
    10.         _StencilWriteMaskDepth("Stencil WriteMask Value Depth", Range(0, 100)) = 14
    11.  
    12.         _AlphaToMask("AlphaToMask", Range(0, 100)) = 0
    13.  
    14.         _SpecularRGB("Specular Color", Color) = (1, 1, 1)
    15.         _RoughnessValue("Roughness Value", Range(0,1)) = 0.5
    16.         _SpecularOcclusion("Specular Occlusion", Range(0,1)) = 0.5
    17.  
    18.         _NoiseScale("Noise Scale", Range(0, .5)) = .1
    19.         _Height("Grass Height", Range(0, 2)) = 1
    20.         _Amount("Amount", Range(-1.0, 1.0)) = 1
    21.         _CollisionBending("Collision Bending (instanced)", Color) = (0, 0, 0, 0)
    22.     }
    23.  
    24.  
    25.     SubShader{
    26.        
    27.        
    28.         Pass {
    29.             Name "GBuffer"
    30.             Tags { "LightMode" = "GBuffer" }
    31.             ZWrite On
    32.  
    33.  
    34.             Stencil {
    35.                 Ref [_StencilRef]
    36.                 WriteMask [_StencilWriteMask]
    37.                 Comp Always
    38.                 Pass Replace
    39.             }
    40.  
    41.             HLSLPROGRAM
    42.  
    43.             #pragma target 3.5
    44.  
    45.         #include "UnityCG.cginc"
    46.             #pragma multi_compile_instancing
    47.  
    48.             float hash(float n) {
    49.                 return frac(sin(n) * 43758.5453);
    50.             }
    51.  
    52.             float _Height;
    53.             float _Amount;
    54.  
    55.             UNITY_INSTANCING_BUFFER_START(Props)
    56.             UNITY_DEFINE_INSTANCED_PROP(fixed4, _CollisionBending)
    57.             UNITY_INSTANCING_BUFFER_END(Props)
    58.  
    59.             #pragma vertex GBufferVertex
    60.             #pragma fragment GBufferFragment
    61.  
    62.             struct VertexInput {
    63.                 float4 vertex : POSITION;
    64.                 float3 normal : NORMAL;
    65.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    66.             };
    67.  
    68.             struct VertexOutput {
    69.                 float4 clipPos : SV_POSITION;
    70.                 float localPosY : TEXCOORD0;
    71.                 float3 worldNormal : TEXCOORD1;
    72.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    73.             };
    74.  
    75.             float4 _TintColor1;
    76.             float4 _TintColor2;
    77.             float _ColorHeight;
    78.  
    79.             float3 _SpecularRGB;
    80.             float _RoughnessValue;
    81.             float _SpecularOcclusion;
    82.  
    83.             VertexOutput GBufferVertex(VertexInput input) {
    84.                 VertexOutput output;
    85.                 UNITY_SETUP_INSTANCE_ID(input);
    86.                 UNITY_TRANSFER_INSTANCE_ID(input, output);
    87.  
    88.                 output.localPosY = input.vertex.y;
    89.                 fixed4 collisionBend = UNITY_ACCESS_INSTANCED_PROP(Props, _CollisionBending);
    90.                
    91.                 float4 worldPos2 = mul(UNITY_MATRIX_M, float4(input.vertex.xyz, 1.0));
    92.                 output.clipPos = mul(unity_MatrixVP, worldPos2);
    93.                 return output;
    94.             }
    95.  
    96.             //FeatureName   Standard
    97.             //GBuffer0      baseColor.r,    baseColor.g,    baseColor.b,    specularOcclusion
    98.             //GBuffer1      normal.xy (1212),   perceptualRoughness
    99.             //GBuffer2      f0.r,   f0.g,   f0.b,   featureID(3) / coatMask(5)
    100.             //GBuffer3      bakedDiffuseLighting.rgb
    101.             struct FragmentOutput {
    102.                 float4 gBuffer0 : SV_Target0;
    103.                 float4 gBuffer1 : SV_Target1;
    104.                 float4 gBuffer2 : SV_Target2;
    105.                 float4 gBuffer3 : SV_Target3;
    106.             };          
    107.            
    108.             struct NormalData // from "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/NormalBuffer.hlsl"
    109.             {
    110.                 float3 normalWS;
    111.                 float  perceptualRoughness;
    112.             };
    113.             // Inserts the bits indicated by 'mask' from 'src' into 'dst'.
    114.             uint BitFieldInsert(uint mask, uint src, uint dst)
    115.             {
    116.                 return (src & mask) | (dst & ~mask);
    117.             }
    118.             // Composes a floating point value with the magnitude of 'x' and the sign of 's'.
    119.             // See the comment about FastSign() below.
    120.             float CopySign(float x, float s, bool ignoreNegZero = true)
    121.             {
    122. #if !defined(SHADER_API_GLES)
    123.                 if (ignoreNegZero)
    124.                 {
    125.                     return (s >= 0) ? abs(x) : -abs(x);
    126.                 }
    127.                 else
    128.                 {
    129.                     uint negZero = 0x80000000u;
    130.                     uint signBit = negZero & asuint(s);
    131.                     return asfloat(BitFieldInsert(negZero, signBit, asuint(x)));
    132.                 }
    133. #else
    134.                 return (s >= 0) ? abs(x) : -abs(x);
    135. #endif
    136.             }
    137.             // Ref: http://jcgt.org/published/0003/02/01/paper.pdf "A Survey of Efficient Representations for Independent Unit Vectors"
    138.             // Encode with Oct, this function work with any size of output
    139.             // return float between [-1, 1]
    140.             float2 PackNormalOctQuadEncode(float3 n)
    141.             {
    142.                 //float l1norm    = dot(abs(n), 1.0);
    143.                 //float2 res0     = n.xy * (1.0 / l1norm);
    144.  
    145.                 //float2 val      = 1.0 - abs(res0.yx);
    146.                 //return (n.zz < float2(0.0, 0.0) ? (res0 >= 0.0 ? val : -val) : res0);
    147.  
    148.                 // Optimized version of above code:
    149.                 n *= rcp(dot(abs(n), 1.0));
    150.                 float t = saturate(-n.z);
    151.                 return n.xy + (n.xy >= 0.0 ? t : -t);
    152.             }
    153.             // Pack float2 (each of 12 bit) in 888
    154.             float3 PackFloat2To888(float2 f)
    155.             {
    156.                 uint2 i = (uint2)(f * 4095.5);
    157.                 uint2 hi = i >> 8;
    158.                 uint2 lo = i & 255;
    159.                 // 8 bit in lo, 4 bit in hi
    160.                 uint3 cb = uint3(lo, hi.x | (hi.y << 4));
    161.  
    162.                 return cb / 255.0;
    163.             }
    164.             void EncodeIntoNormalBuffer(NormalData normalData, out float4 outNormalBuffer0)
    165.             {
    166.                 // The sign of the Z component of the normal MUST round-trip through the G-Buffer, otherwise
    167.                 // the reconstruction of the tangent frame for anisotropic GGX creates a seam along the Z axis.
    168.                 // The constant was eye-balled to not cause artifacts.
    169.                 // TODO: find a proper solution. E.g. we could re-shuffle the faces of the octahedron
    170.                 // s.t. the sign of the Z component round-trips.
    171.                 const float seamThreshold = 1.0 / 1024.0;
    172.                 normalData.normalWS.z = CopySign(max(seamThreshold, abs(normalData.normalWS.z)), normalData.normalWS.z);
    173.  
    174.                 // RT1 - 8:8:8:8
    175.                 // Our tangent encoding is based on our normal.
    176.                 float2 octNormalWS = PackNormalOctQuadEncode(normalData.normalWS);
    177.                 float3 packNormalWS = PackFloat2To888(saturate(octNormalWS * 0.5 + 0.5));
    178.                 // We store perceptualRoughness instead of roughness because it is perceptually linear.
    179.                 outNormalBuffer0 = float4(packNormalWS, normalData.perceptualRoughness);
    180.             }
    181.  
    182.             FragmentOutput GBufferFragment(VertexOutput input) : SV_TARGET{
    183.                 UNITY_SETUP_INSTANCE_ID(input);
    184.                 FragmentOutput output;
    185.                 fixed4 col = lerp(_TintColor1, _TintColor2, dot(_ColorHeight, input.localPosY)); // local x pos is height
    186.                 float3 albedo = col;
    187.                 float4 specular_roughness = float4(_SpecularRGB.r, _SpecularRGB.g, _SpecularRGB.b, _RoughnessValue);
    188.  
    189.                 NormalData normalData;
    190.                 normalData.normalWS = input.worldNormal.xyz;
    191.                 normalData.perceptualRoughness = 1;
    192.  
    193.                 EncodeIntoNormalBuffer(normalData, output.gBuffer1);
    194.  
    195.                 output.gBuffer0.rgba = float4(albedo.rgb, _SpecularOcclusion); // Diffuse (RGB), specularOcclusion (A)
    196.                 float3 shadow_color = albedo.rgb * 0.8f;
    197.                 shadow_color.r += 0.2f;
    198.                 shadow_color.b += 0.2f;
    199.                 saturate(shadow_color);
    200.                 output.gBuffer2.rgba = float4(shadow_color, 0); // f0.r, f0.g, f0.b, featureID(3) / coatMask(5)
    201.                 output.gBuffer3.rgba = float4(.0, .0, .0, 0); // bakedDiffuseLighting.rgb
    202.  
    203.                 return output;
    204.             }
    205.  
    206.             ENDHLSL
    207.         }
    208.        
    209.         Pass {
    210.             Name "DepthOnly"
    211.             Tags { "LightMode" = "DepthOnly" "Queue" = "Geometry+0" "RenderType" = "Opaque" "RenderPipeline" = "HDRenderPipeline" }
    212.             ColorMask 0
    213.             ZWrite On
    214.  
    215.             Stencil {
    216.                 Ref[_StencilRefDepth]
    217.                 WriteMask[_StencilWriteMaskDepth]
    218.                 Comp Always
    219.                 Pass Replace
    220.             }
    221.             AlphaToMask[_AlphaToMask]
    222.  
    223.             HLSLPROGRAM
    224.  
    225.             #pragma target 3.5
    226.  
    227.             #pragma multi_compile_instancing
    228.             #include "UnityCG.cginc"
    229.  
    230.  
    231.             float _Height;
    232.             float _Amount;
    233.  
    234.             UNITY_INSTANCING_BUFFER_START(Props)
    235.             UNITY_DEFINE_INSTANCED_PROP(fixed4, _CollisionBending)
    236.             UNITY_INSTANCING_BUFFER_END(Props)
    237.  
    238.             #pragma vertex DepthOnlyPassVertex
    239.             #pragma fragment DepthOnlyPassFragment
    240.  
    241.             struct VertexInput {
    242.                 float4 vertex : POSITION;
    243.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    244.             };
    245.  
    246.             struct VertexOutput {
    247.                 float4 clipPos : SV_POSITION;
    248.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    249.             };
    250.  
    251.             VertexOutput DepthOnlyPassVertex(VertexInput input) {
    252.                 VertexOutput output;
    253.                 UNITY_SETUP_INSTANCE_ID(input);
    254.                 UNITY_TRANSFER_INSTANCE_ID(input, output);
    255.  
    256.                 float4 worldPos = mul(UNITY_MATRIX_M, float4(input.vertex.xyz, 1.0));
    257.                 output.clipPos = mul(unity_MatrixVP, worldPos);
    258.                 return output;
    259.             }
    260.  
    261.             float4 DepthOnlyPassFragment(VertexOutput input) : SV_TARGET{
    262.                 UNITY_SETUP_INSTANCE_ID(input);
    263.                 return 0;
    264.             }
    265.  
    266.             ENDHLSL
    267.         }
    268.            
    269.     }
    270.     FallBack "HDRP/Lit"
    271. }
     
  2. zeropointblack

    zeropointblack

    Joined:
    Jun 8, 2020
    Posts:
    197
    this is why i like upgrading.
     
  3. KYL3R

    KYL3R

    Joined:
    Nov 16, 2012
    Posts:
    135
    Grass is back!


    So what broke my shader? Shader seems fine, I didn't even update the RenderPipeline in that update. Only updated the editor.

    After debugging for some hours, I noticed "msaa" in the Frame Debugger as RenderTarget:


    So I started to wonder if I enabled that on some point.
    I was looking at the Lit.hlsl and Lit.shader code to understand what they are doing with all the "#ifdef WRITE_MSAA_DEPTH" Stuff, as I figured my problem had to do with Depth and/or MSAA.

    So to disable it, I opened the HDRP Asset:



    So, I saw "MSAA 8x" enabled. And setting it to "None" didn't do any on fixing my problem. But then I noticed "Forward Only" and got suspicious. I was working with Deferred all the way, I thought.

    So, setting it to "Deferred Only" grayed out the MSAA option and my shader is working again! So either the Unity Update flipped that switch or I misclicked at some point.

    That took me wayy to long to figure out.
     
    VOTRUBEC likes this.