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): Shader "Hair/Unlit" { Properties { _MainTex ("Texture", 2D) = "white" {} _Color("Color", Color) = (1, 1, 1, 1) _Cutoff("AlphaCutout", Range(0.0, 1.0)) = 0.0 } SubShader { Tags {"RenderType" = "Transparent" "IgnoreProjector"="True" "Queue"="Transparent"} //Depth only prepass Pass { ZWrite On ColorMask 0 } //Main pass Pass { //Disable zwrite, disable cull, setup blending and make sure the color mask for this pass is correct ZWrite Off Cull Off Blend SrcAlpha OneMinusSrcAlpha ColorMask RGB CGPROGRAM //Define vertex and fragment function #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" //Basic input struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; //Basic fragment input struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; //Vars sampler2D _MainTex; float4 _MainTex_ST; float4 _Color; float _Cutoff; //Basic vertex function v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } //Alpha cutoff function void AlphaDiscard(half alpha, half cutoff) { clip(alpha - cutoff); } //Basic fragment function with alpha support fixed4 frag (v2f i) : SV_Target { fixed4 texColor = tex2D(_MainTex, i.uv); half3 color = texColor.rgb * _Color.rgb; half alpha = texColor.a * _Color.a; AlphaDiscard(alpha, _Cutoff); return half4(color, alpha); } ENDCG } } }
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): Shader "Unlit/Hair" { Properties { _MainTex ("Texture", 2D) = "white" {} _Color("Color", Color) = (1, 1, 1, 1) _Cutoff("AlphaCutout", Range(0.0, 1.0)) = 0.0 } SubShader { Tags {"RenderType" = "Opaque" "IgnoreProjector"="True" "RenderPipeline" = "LightweightPipeline"} Blend SrcAlpha OneMinusSrcAlpha ZWrite On Cull Off ColorMask RGB //Depth only prepass Pass { Name "DepthOnly" Tags{"LightMode" = "DepthOnly"} ZWrite On ColorMask 0 } //Main pass Pass { Name "StandardUnlit" ColorMask RGB Blend SrcAlpha OneMinusSrcAlpha ZWrite Off Cull Off CGPROGRAM //Define vertex and fragment function #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" //Basic input struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; //Basic fragment input struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; //Vars sampler2D _MainTex; float4 _MainTex_ST; float4 _Color; float _Cutoff; //Basic vertex function v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } //Alpha cutoff function void AlphaDiscard(half alpha, half cutoff, half offset = 0.0001h) { clip(alpha - cutoff + offset); } //Basic fragment function with alpha support fixed4 frag (v2f i) : SV_Target { half4 texColor = tex2D(_MainTex, i.uv); half3 color = texColor.rgb * _Color.rgb; AlphaDiscard(texColor.a, _Cutoff); return half4(color, texColor.a); } ENDCG } } }
FYI, I issued a bug report that shows a similar transparency problem using no custom shaders: 1099404
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): Shader "Lightweight MultPass Test" { Properties { [NoScaleOffset] _MainTex ("Texture", 2D) = "white" {} _Color ("Color", Color) = (1,1,1,1) } SubShader { Tags{ "RenderPipeline" = "LightweightPipeline" "Queue"="Transparent" } Pass { Name "Depth Fill" Tags{"LightMode" = "SRPDefaultUnlit"} Cull Off ZTest LEqual ZWrite On ColorMask 0 HLSLPROGRAM #pragma prefer_hlslcc gles #pragma exclude_renderers d3d11_9x #pragma target 2.0 #pragma multi_compile_instancing #pragma vertex vert #pragma fragment frag #include "LWRP/ShaderLibrary/Core.hlsl" struct VertexInput { float4 vertex : POSITION; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct VertexOutput { float4 position : POSITION; }; VertexOutput vert (VertexInput v) { VertexOutput o = (VertexOutput)0; UNITY_SETUP_INSTANCE_ID(v); o.position = TransformObjectToHClip(v.vertex.xyz); return o; } void frag (VertexOutput IN) {} ENDHLSL } Pass { Name "Color Fill" Tags{"LightMode" = "LightweightForward"} Blend SrcAlpha OneMinusSrcAlpha Cull Off ZTest LEqual ZWrite Off HLSLPROGRAM #pragma prefer_hlslcc gles #pragma exclude_renderers d3d11_9x #pragma target 2.0 #pragma multi_compile_fog #pragma multi_compile_instancing #pragma vertex vert #pragma fragment frag #include "LWRP/ShaderLibrary/Core.hlsl" TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); half4 _Color; struct VertexInput { float4 vertex : POSITION; float4 texcoord1 : TEXCOORD1; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct VertexOutput { float4 position : POSITION; float4 uv0AndFog : TEXCOORD8; UNITY_VERTEX_INPUT_INSTANCE_ID }; VertexOutput vert (VertexInput v) { VertexOutput o = (VertexOutput)0; UNITY_SETUP_INSTANCE_ID(v); UNITY_TRANSFER_INSTANCE_ID(v, o); float4 clipPos = TransformObjectToHClip(v.vertex.xyz); half fogFactor = ComputeFogFactor(clipPos.z); o.position = clipPos; o.uv0AndFog = float4(v.texcoord1.xy, fogFactor, 0.0); return o; } half4 frag (VertexOutput IN) : SV_Target { UNITY_SETUP_INSTANCE_ID(IN); float4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uv0AndFog.xy) * _Color; ApplyFog(color.rgb, IN.uv0AndFog.z); return color; } ENDHLSL } } }
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!
Likely the vertex position calculations in the pre-pass's vertex shader doesn't exactly match what the Shader Graph generated pass is doing.
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
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 ?
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.