Search Unity

Transparency using the LWRP

Discussion in 'Shaders' started by Laex410, Sep 4, 2018.

  1. Laex410

    Laex410

    Joined:
    Mar 18, 2015
    Posts:
    51
    Hello everyone,

    I am currently working on a transparency shader for the lightweight render pipeline. However, I ran into some issues. I added a depth only pass to my shader to get rid of some sorting issues but that just ended in the object not being visible at all. According to the frame analyser just pass 0 is executed, the second pass is not executed at all. I hope you guys can help me here, thank you very much :)

    Code (CSharp):
    1. Shader "Hair/Unlit"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Texture", 2D) = "white" {}
    6.         _Color("Color", Color) = (1, 1, 1, 1)
    7.         _Cutoff("AlphaCutout", Range(0.0, 1.0)) = 0.0
    8.  
    9.     }
    10.     SubShader
    11.     {  
    12.         Tags {"RenderType" = "Transparent" "IgnoreProjector"="True" "Queue"="Transparent"}
    13.  
    14.         //Depth only prepass
    15.         Pass
    16.         {
    17.             ZWrite On
    18.             ColorMask 0
    19.         }
    20.  
    21.         //Main pass
    22.         Pass
    23.         {
    24.             //Disable zwrite, disable cull, setup blending and make sure the color mask for this pass is correct
    25.             ZWrite Off
    26.             Cull Off
    27.             Blend SrcAlpha OneMinusSrcAlpha
    28.             ColorMask RGB
    29.  
    30.             CGPROGRAM
    31.  
    32.             //Define vertex and fragment function
    33.             #pragma vertex vert
    34.             #pragma fragment frag
    35.             #include "UnityCG.cginc"
    36.  
    37.             //Basic input
    38.             struct appdata
    39.             {
    40.                 float4 vertex : POSITION;
    41.                 float2 uv : TEXCOORD0;
    42.             };
    43.  
    44.             //Basic fragment input
    45.             struct v2f
    46.             {
    47.                 float2 uv : TEXCOORD0;
    48.                 float4 vertex : SV_POSITION;
    49.             };
    50.  
    51.             //Vars
    52.             sampler2D _MainTex;
    53.             float4 _MainTex_ST;
    54.             float4 _Color;
    55.             float _Cutoff;
    56.            
    57.             //Basic vertex function
    58.             v2f vert (appdata v)
    59.             {
    60.                 v2f o;
    61.                 o.vertex = UnityObjectToClipPos(v.vertex);
    62.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    63.                 return o;
    64.             }
    65.  
    66.             //Alpha cutoff function
    67.             void AlphaDiscard(half alpha, half cutoff)
    68.             {
    69.                 clip(alpha - cutoff);
    70.             }
    71.            
    72.             //Basic fragment function with alpha support
    73.             fixed4 frag (v2f i) : SV_Target
    74.             {
    75.                 fixed4 texColor = tex2D(_MainTex, i.uv);
    76.                 half3 color = texColor.rgb * _Color.rgb;
    77.                 half alpha = texColor.a * _Color.a;
    78.                 AlphaDiscard(alpha, _Cutoff);
    79.  
    80.                 return half4(color, alpha);
    81.             }
    82.  
    83.             ENDCG
    84.         }
    85.     }
    86. }
     
  2. Laex410

    Laex410

    Joined:
    Mar 18, 2015
    Posts:
    51
    Quick update: My object is visible again, however I am still stuck with parts of my object being rendered in the wrong order. https://docs.unity3d.com/Manual/SL-CullAndDepth.html has a section ("Transparent shader with depth writes") about this issue, but adding this depth pass to my shader doesn't work. Parts of my mesh that are in the background are still being rendered in front of stuff in the foreground. Here is the current code:

    Code (CSharp):
    1. Shader "Unlit/Hair"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Texture", 2D) = "white" {}
    6.         _Color("Color", Color) = (1, 1, 1, 1)
    7.         _Cutoff("AlphaCutout", Range(0.0, 1.0)) = 0.0
    8.     }
    9.     SubShader
    10.     {  
    11.         Tags {"RenderType" = "Opaque" "IgnoreProjector"="True" "RenderPipeline" = "LightweightPipeline"}
    12.        
    13.         Blend SrcAlpha OneMinusSrcAlpha
    14.         ZWrite On
    15.         Cull Off
    16.         ColorMask RGB
    17.            
    18.         //Depth only prepass
    19.         Pass
    20.         {
    21.             Name "DepthOnly"
    22.             Tags{"LightMode" = "DepthOnly"}
    23.  
    24.             ZWrite On
    25.             ColorMask 0
    26.         }
    27.  
    28.         //Main pass
    29.         Pass
    30.         {
    31.             Name "StandardUnlit"
    32.  
    33.             ColorMask RGB
    34.             Blend SrcAlpha OneMinusSrcAlpha
    35.             ZWrite Off
    36.             Cull Off
    37.  
    38.             CGPROGRAM
    39.  
    40.             //Define vertex and fragment function
    41.             #pragma vertex vert
    42.             #pragma fragment frag
    43.             #include "UnityCG.cginc"
    44.  
    45.             //Basic input
    46.             struct appdata
    47.             {
    48.                 float4 vertex : POSITION;
    49.                 float2 uv : TEXCOORD0;
    50.             };
    51.  
    52.             //Basic fragment input
    53.             struct v2f
    54.             {
    55.                 float2 uv : TEXCOORD0;
    56.                 float4 vertex : SV_POSITION;
    57.             };
    58.  
    59.             //Vars
    60.             sampler2D _MainTex;
    61.             float4 _MainTex_ST;
    62.             float4 _Color;
    63.             float _Cutoff;
    64.            
    65.             //Basic vertex function
    66.             v2f vert (appdata v)
    67.             {
    68.                 v2f o;
    69.                 o.vertex = UnityObjectToClipPos(v.vertex);
    70.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    71.                 return o;
    72.             }
    73.  
    74.             //Alpha cutoff function
    75.             void AlphaDiscard(half alpha, half cutoff, half offset = 0.0001h)
    76.             {
    77.                 clip(alpha - cutoff + offset);
    78.             }
    79.            
    80.             //Basic fragment function with alpha support
    81.             fixed4 frag (v2f i) : SV_Target
    82.             {
    83.                 half4 texColor = tex2D(_MainTex, i.uv);
    84.                 half3 color = texColor.rgb * _Color.rgb;
    85.                 AlphaDiscard(texColor.a, _Cutoff);
    86.                 return half4(color, texColor.a);
    87.             }
    88.  
    89.             ENDCG
    90.         }  
    91.     }
    92. }
     
  3. fortgreeneVR

    fortgreeneVR

    Joined:
    Sep 5, 2018
    Posts:
    50
    FYI, I issued a bug report that shows a similar transparency problem using no custom shaders: 1099404
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Well, AFAIK the "DepthOnly" light mode pass is only used for the depth texture generation. I don't believe it pre-fills the depth buffer used for rendering the main view, so it won't help with the transparency issue.

    To do a multi pass shader in the Lightweight pipeline you have to have one pass have no lightmode defined (or be using the default, which is "LightMode" = "SRPDefaultUnlit"), and one pass use "LightMode" = "LightweightForward". The lightweight pipeline appears to only use the first pass it finds of each tag, so no more 3+ pass shaders. :(

    Code (CSharp):
    1. Shader "Lightweight MultPass Test"
    2. {
    3.     Properties
    4.     {
    5.         [NoScaleOffset] _MainTex ("Texture", 2D) = "white" {}
    6.         _Color ("Color", Color) = (1,1,1,1)
    7.     }
    8.     SubShader
    9.     {
    10.         Tags{ "RenderPipeline" = "LightweightPipeline" "Queue"="Transparent" }
    11.  
    12.         Pass
    13.         {
    14.             Name "Depth Fill"
    15.             Tags{"LightMode" = "SRPDefaultUnlit"}
    16.  
    17.             Cull Off
    18.             ZTest LEqual
    19.             ZWrite On
    20.             ColorMask 0
    21.  
    22.             HLSLPROGRAM
    23.             #pragma prefer_hlslcc gles
    24.             #pragma exclude_renderers d3d11_9x
    25.             #pragma target 2.0
    26.  
    27.             #pragma multi_compile_instancing
    28.            
    29.             #pragma vertex vert
    30.             #pragma fragment frag
    31.  
    32.             #include "LWRP/ShaderLibrary/Core.hlsl"
    33.  
    34.             struct VertexInput
    35.             {
    36.                 float4 vertex : POSITION;
    37.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    38.             };
    39.  
    40.             struct VertexOutput
    41.             {
    42.                 float4 position : POSITION;
    43.             };
    44.  
    45.             VertexOutput vert (VertexInput v)
    46.             {
    47.                 VertexOutput o = (VertexOutput)0;
    48.                 UNITY_SETUP_INSTANCE_ID(v);
    49.  
    50.                 o.position = TransformObjectToHClip(v.vertex.xyz);
    51.  
    52.                 return o;
    53.             }
    54.  
    55.             void frag (VertexOutput IN) {}
    56.             ENDHLSL
    57.         }
    58.  
    59.         Pass
    60.         {
    61.             Name "Color Fill"
    62.             Tags{"LightMode" = "LightweightForward"}
    63.  
    64.             Blend SrcAlpha OneMinusSrcAlpha
    65.             Cull Off
    66.             ZTest LEqual
    67.             ZWrite Off
    68.  
    69.             HLSLPROGRAM
    70.             #pragma prefer_hlslcc gles
    71.             #pragma exclude_renderers d3d11_9x
    72.             #pragma target 2.0
    73.  
    74.             #pragma multi_compile_fog
    75.  
    76.             #pragma multi_compile_instancing
    77.            
    78.             #pragma vertex vert
    79.             #pragma fragment frag
    80.  
    81.             #include "LWRP/ShaderLibrary/Core.hlsl"
    82.  
    83.             TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex);
    84.             half4 _Color;
    85.  
    86.             struct VertexInput
    87.             {
    88.                 float4 vertex : POSITION;
    89.                 float4 texcoord1 : TEXCOORD1;
    90.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    91.             };
    92.  
    93.             struct VertexOutput
    94.             {
    95.                 float4 position : POSITION;
    96.                 float4 uv0AndFog : TEXCOORD8;
    97.  
    98.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    99.             };
    100.  
    101.             VertexOutput vert (VertexInput v)
    102.             {
    103.                 VertexOutput o = (VertexOutput)0;
    104.  
    105.                 UNITY_SETUP_INSTANCE_ID(v);
    106.                 UNITY_TRANSFER_INSTANCE_ID(v, o);
    107.  
    108.                 float4 clipPos = TransformObjectToHClip(v.vertex.xyz);
    109.                 half fogFactor = ComputeFogFactor(clipPos.z);
    110.  
    111.                 o.position = clipPos;
    112.                 o.uv0AndFog = float4(v.texcoord1.xy, fogFactor, 0.0);
    113.  
    114.                 return o;
    115.             }
    116.  
    117.             half4 frag (VertexOutput IN) : SV_Target
    118.             {
    119.                 UNITY_SETUP_INSTANCE_ID(IN);
    120.  
    121.                 float4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uv0AndFog.xy) * _Color;
    122.                 ApplyFog(color.rgb, IN.uv0AndFog.z);
    123.                 return color;
    124.             }
    125.             ENDHLSL
    126.         }
    127.     }
    128. }
     
  5. NolwennB

    NolwennB

    Joined:
    Mar 4, 2014
    Posts:
    15
    Hello,
    Would you know how to do this Depth Only Pass on a PBR Shader ? I've created a simple transparent PBR shader in ShaderGraph with an albedo texture on it. I've generated the code, and pasted your pre-pass. I don't have sorting issue inside my mesh anymore, but I have a strange behaviour when I move my camera, like some kind of flicking on my mesh.
    Thanks!
     
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Likely the vertex position calculations in the pre-pass's vertex shader doesn't exactly match what the Shader Graph generated pass is doing.
     
  7. NolwennB

    NolwennB

    Joined:
    Mar 4, 2014
    Posts:
    15
    Yes, you're right ! I've replaced your pre-pass's vertex shader with the Shader Graph generated one, keeping only what's about vertex position, and it works.
    Thank you very much :)
     
  8. NolwennB

    NolwennB

    Joined:
    Mar 4, 2014
    Posts:
    15
    I've tried to apply the same method on a Fabric ShaderGraph in HDRP, but the result is not really good. Do you know if it is possible to do a proper depth only pre-pass in HDRP ?
     
  9. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    No idea. I'm not too familiar with the HDRP, so I have no idea if the HDRP even allows for multipass shaders using the hack I mentioned for the LWRP or otherwise.