[Shader Graph] Alpha clip dither and keep original shadows

I’m applying a dithering effect to my object when the camera gets close, and use the alpha clip threshold to make those dithered pixels transparent. This causes the shadows to appear dithered as well whenever the object is dithered. Is it possible to keep the original shadow (not dithered) of the object?

For reference, I’m using a PBR graph, a surface of “Opaque”, and a blend of “Alpha”.

With shader graph? Not really. Not with out some other errors. Shader Graph doesn’t yet let you detect between shadowcaster pass and normal rendering pass, so you can’t modify the shader’s behavior for each.

There is a solution though. Use two mesh renderers. You can set one to no shadows (the one with your shader) and one set to shadows only using a default shader.

In my other thread in the Shader Graph forum, someone from Unity supplied a solution with a custom node that checks “#ifdef UNITY_PASS_SHADOWCASTER”, which works for this issue in Shader Graph.

Here’s the other thread for those that are curious: Alpha clip dither and keep original shadows

2 Likes

@bgolus I have a dithering transparency shader that will make a screen-door effect on a opaque object.
The reason is that I want to create a fading cealing when player enters a building.
However, the shader will not allow shadows behind the object to be rendered (picture attached). Besides that, I can’t dither the “received shadows” on the object with dithering.
What solution do you think would be most appropriate for this?

I’m using Unity 2018.4.14f1 standard 3D.

Shader "TEST/Dithering (Simple)"
{
    Properties
    {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _Transparency ("Transparency", Range(0,1)) = 1.0
    }
 
    SubShader
    {
        Tags
        {
            "RenderType"="Opaque"
        }

        CGPROGRAM
        #pragma surface surf Lambert noforwardadd
  
        sampler2D _MainTex;
  
        struct Input
        {
            float2 uv_MainTex;
            float4 screenPos;
        };
  
        half _Transparency;
  
        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
            // Screen-door transparency: Discard pixel if below threshold.
            float4x4 thresholdMatrix =
            {  1.0 / 17.0,  9.0 / 17.0,  3.0 / 17.0, 11.0 / 17.0,
            13.0 / 17.0,  5.0 / 17.0, 15.0 / 17.0,  7.0 / 17.0,
            4.0 / 17.0, 12.0 / 17.0,  2.0 / 17.0, 10.0 / 17.0,
            16.0 / 17.0,  8.0 / 17.0, 14.0 / 17.0,  6.0 / 17.0
            };
            float2 pos = IN.screenPos.xy / IN.screenPos.w;
            pos *= _ScreenParams.xy; // pixel position
            clip(_Transparency - thresholdMatrix[pos.x % 4] [pos.y % 4]);
        }
        ENDCG
    }
    Fallback "VertexLit"
}

This is the effect I’m looking for without Shader Graph:
- Dithering Transparency
- Dithering received shadow
- Rendering shadows behind the object