[SOLVED] Double sided Material Depth fix for shadows and fogs (shader included)

Hello,

I tried to make a double sided cloth I partially downloaded and partially wrote shader for double sided material. Also tried thin box, double faced mesh, two separated cloths. But all lead to bad cloth physics, normal issues, or separated simulation for both cloths… The best solution is this shader at this moment. But it has one issue as unity render depth separately, it just ignore backfaces of the mesh. And then shadows behind the cloth appears onto the flag (like shadows of the building behind the flag, which should not appear, because it is behind the flag). It also shows fog, SSAO and all other things that uses depth… Partial sollution is to turn off shadows on renderer. But it has 2 problems. 1st there are no shadows, and still other depth based things will stay incorrect.

Do you have any solution, how to tell depth render to not cull backface? Or how to do simple double sided cloth for flags? I tried at least 8 approaches and all fails even more… Also with Depth render I found that almost every water in unity has problem to correctly draw underwater fog. It ignores end of the water and ray stops on the mountains… So if anyone has solution also for this problem I would be happy :slight_smile: but fortunately my game is not much underwater… these flags are more crucial…

Thanks
Jakub

Shader "Custom/2 Sided" {
     Properties {
         _Color ("Color", Color) = (1,1,1,1)
         _MainTex ("Albedo (RGB)", 2D) = "white" {}
         _Glossiness ("Smoothness", Range(0,1)) = 0.5
         _Metallic ("Metallic", Range(0,1)) = 0.0
         _BumpMap("Normal Map", 2D) = "bump" {}
         _BumpScale("Scale", Float) = 1.0
//         _Parallax ("Height Scale", Range (0.005, 0.08)) = 0.02
//        _ParallaxMap ("Height Map", 2D) = "black" {}
     }
     SubShader {
         Tags { "RenderType"="Opaque" }
         LOD 300
         Cull Back
      // Fog {Mode Off}
        // ZWrite On
          //usePass"Custom/TransparentShadowReceiver"

          CGPROGRAM
             // Physically based Standard lighting model, and enable shadows on all light types

         #pragma surface surf Standard fullforwardshadows // alpha
         #pragma target 3.0
         sampler2D _MainTex;
         sampler2D _BumpMap;
         struct Input {
             float2 uv_MainTex;
         };
         half _Glossiness;
         half _Metallic;
         half _BumpScale;
         fixed4 _Color;
         void surf (Input IN, inout SurfaceOutputStandard o) {

             // Albedo comes from a texture tinted by color
             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
             o.Albedo = c.rgb;
             // Metallic and smoothness come from slider variables
             o.Normal=UnpackScaleNormal(tex2D(_BumpMap, IN.uv_MainTex),_BumpScale);
             o.Metallic = _Metallic;
             o.Smoothness = _Glossiness;
             o.Alpha = c.a;
         }


         ENDCG
   //       Tags { "LightMode"="Vertex" }
        Ztest LEqual
         Cull Front
       //  Fog {Mode Off}
         CGPROGRAM

         #pragma surface surf Standard fullforwardshadows approxview //alpha
         //   #pragma multi_compile_fwdbase
         #pragma target 3.0
         #pragma vertex vert
         sampler2D _MainTex;
         sampler2D _BumpMap;

         struct Input {
             float2 uv_MainTex;
             fixed facing :VFACE;
         };
         half _Glossiness;
         half _Metallic;
         fixed4 _Color;
         half _BumpScale;
         void vert (inout appdata_full v) {
        //     v.normal *= -1;
             v.tangent*=-1;
         }
         void surf (Input IN, inout SurfaceOutputStandard o) {
             // Albedo comes from a texture tinted by color
             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
             o.Albedo = c.rgb;
             // Metallic and smoothness come from slider variables
             o.Metallic = _Metallic;
             o.Smoothness = _Glossiness;
             o.Alpha = c.a;
            o.Normal=UnpackScaleNormal(tex2D(_BumpMap, IN.uv_MainTex),_BumpScale);
            o.Normal.z*=IN.facing;

         }
         ENDCG
         //

     }


     FallBack "Diffuse"
}

Try
#pragma surface … addshadow

2 Likes

It Works! Thanks a lot! :slight_smile:

Well it did not work, it just turned same problem on front side, but back side now works…

What would fix is something like this, but it absolutely ignores any try to if statement…
CGPROGRAM

#if VFACE>0//IN.facing!=0
#pragmasurfacesurfStandard
#else
#pragmasurfacesurfStandardaddshadow
#endif

Ah, right. I didn’t read the whole shader file before (posted from my phone).

The problem comes down to you doing the two sided shader as two passes. I much prefer the single pass method using VFACE to flip sides. Then you could use Cull Off and addshadow and it’d work. The reason why your attempt to use VFACE for switching the pragma doesn’t work is the pragma happens at compile time and VFACE isn’t known until it’s rendering the pixel on screen. You can’t use those kinds of semantics for compile time #if blocks.

Alternatively you can add your own shadow pass. You should be able to copy the shadow pass code from this page to the end of your shader and add Cull Off:

        Pass
        {
            Tags {"LightMode"="ShadowCaster"}
            Cull Off

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_shadowcaster
            #include "UnityCG.cginc"

            struct v2f {
                V2F_SHADOW_CASTER;
            };

            v2f vert(appdata_base v)
            {
                v2f o;
                TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
                return o;
            }

            float4 frag(v2f i) : SV_Target
            {
                SHADOW_CASTER_FRAGMENT(i)
            }
            ENDCG
        }

Sadly one disadvantage is the biasing will potentially cause some shadow problems for one side of the flag. Because there really is only one set of geometry the offset can’t be pushed in both directions. This is a problem for thin geometry too though. It’s possible it could be fixed by writing out a fully custom shadow pass that uses VFACE, or disabling offset.

1 Like

Thanks Bgolus. It works at single pass! :slight_smile: Now only SSAO is visible through, but it is way much better and nearly invisible :slight_smile: Marking this as solved.

Could you post the complete shader with the solution?

Ah sorry, it was in unity 5.0 or so… I am not sure now which shader it was and if it is still actual. But the goal to fix depth issues was to add custom depth pass in depth_normal built-in shader and replace the original one. With adding VFace also to that built-in shader. So only changes in shader itself did not help.