Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

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

Discussion in 'Shaders' started by Kusras, May 14, 2016.

  1. Kusras

    Kusras

    Joined:
    Jul 9, 2015
    Posts:
    129
    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 :) but fortunately my game is not much underwater... these flags are more crucial...

    Thanks
    Jakub index.png index2.png
    Code (CSharp):
    1. Shader "Custom/2 Sided" {
    2.      Properties {
    3.          _Color ("Color", Color) = (1,1,1,1)
    4.          _MainTex ("Albedo (RGB)", 2D) = "white" {}
    5.          _Glossiness ("Smoothness", Range(0,1)) = 0.5
    6.          _Metallic ("Metallic", Range(0,1)) = 0.0
    7.          _BumpMap("Normal Map", 2D) = "bump" {}
    8.          _BumpScale("Scale", Float) = 1.0
    9. //         _Parallax ("Height Scale", Range (0.005, 0.08)) = 0.02
    10. //        _ParallaxMap ("Height Map", 2D) = "black" {}
    11.      }
    12.      SubShader {
    13.          Tags { "RenderType"="Opaque" }
    14.          LOD 300
    15.          Cull Back
    16.       // Fog {Mode Off}
    17.         // ZWrite On
    18.           //usePass"Custom/TransparentShadowReceiver"
    19.  
    20.           CGPROGRAM
    21.              // Physically based Standard lighting model, and enable shadows on all light types
    22.  
    23.          #pragma surface surf Standard fullforwardshadows // alpha
    24.          #pragma target 3.0
    25.          sampler2D _MainTex;
    26.          sampler2D _BumpMap;
    27.          struct Input {
    28.              float2 uv_MainTex;
    29.          };
    30.          half _Glossiness;
    31.          half _Metallic;
    32.          half _BumpScale;
    33.          fixed4 _Color;
    34.          void surf (Input IN, inout SurfaceOutputStandard o) {
    35.  
    36.              // Albedo comes from a texture tinted by color
    37.              fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    38.              o.Albedo = c.rgb;
    39.              // Metallic and smoothness come from slider variables
    40.              o.Normal=UnpackScaleNormal(tex2D(_BumpMap, IN.uv_MainTex),_BumpScale);
    41.              o.Metallic = _Metallic;
    42.              o.Smoothness = _Glossiness;
    43.              o.Alpha = c.a;
    44.          }
    45.  
    46.  
    47.          ENDCG
    48.    //       Tags { "LightMode"="Vertex" }
    49.         Ztest LEqual
    50.          Cull Front
    51.        //  Fog {Mode Off}
    52.          CGPROGRAM
    53.  
    54.          #pragma surface surf Standard fullforwardshadows approxview //alpha
    55.          //   #pragma multi_compile_fwdbase
    56.          #pragma target 3.0
    57.          #pragma vertex vert
    58.          sampler2D _MainTex;
    59.          sampler2D _BumpMap;
    60.  
    61.          struct Input {
    62.              float2 uv_MainTex;
    63.              fixed facing :VFACE;
    64.          };
    65.          half _Glossiness;
    66.          half _Metallic;
    67.          fixed4 _Color;
    68.          half _BumpScale;
    69.          void vert (inout appdata_full v) {
    70.         //     v.normal *= -1;
    71.              v.tangent*=-1;
    72.          }
    73.          void surf (Input IN, inout SurfaceOutputStandard o) {
    74.              // Albedo comes from a texture tinted by color
    75.              fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    76.              o.Albedo = c.rgb;
    77.              // Metallic and smoothness come from slider variables
    78.              o.Metallic = _Metallic;
    79.              o.Smoothness = _Glossiness;
    80.              o.Alpha = c.a;
    81.             o.Normal=UnpackScaleNormal(tex2D(_BumpMap, IN.uv_MainTex),_BumpScale);
    82.             o.Normal.z*=IN.facing;
    83.  
    84.          }
    85.          ENDCG
    86.          //
    87.  
    88.      }
    89.  
    90.  
    91.      FallBack "Diffuse"
    92. }
     
    Last edited: May 14, 2016
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    7,480
    Try
    #pragma surface ... addshadow
     
    Flavelius likes this.
  3. Kusras

    Kusras

    Joined:
    Jul 9, 2015
    Posts:
    129
    It Works! Thanks a lot! :)
     
  4. Kusras

    Kusras

    Joined:
    Jul 9, 2015
    Posts:
    129
    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
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    7,480
    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:
    http://docs.unity3d.com/Manual/SL-VertexFragmentShaderExamples.html

    Code (CSharp):
    1.         Pass
    2.         {
    3.             Tags {"LightMode"="ShadowCaster"}
    4.             Cull Off
    5.  
    6.             CGPROGRAM
    7.             #pragma vertex vert
    8.             #pragma fragment frag
    9.             #pragma multi_compile_shadowcaster
    10.             #include "UnityCG.cginc"
    11.  
    12.             struct v2f {
    13.                 V2F_SHADOW_CASTER;
    14.             };
    15.  
    16.             v2f vert(appdata_base v)
    17.             {
    18.                 v2f o;
    19.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
    20.                 return o;
    21.             }
    22.  
    23.             float4 frag(v2f i) : SV_Target
    24.             {
    25.                 SHADOW_CASTER_FRAGMENT(i)
    26.             }
    27.             ENDCG
    28.         }
    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.
     
    Kusras likes this.
  6. Kusras

    Kusras

    Joined:
    Jul 9, 2015
    Posts:
    129
    Thanks Bgolus. It works at single pass! :) Now only SSAO is visible through, but it is way much better and nearly invisible :) Marking this as solved.
     
  7. mizaelmontenegro

    mizaelmontenegro

    Joined:
    Sep 5, 2017
    Posts:
    1
    Could you post the complete shader with the solution?
     
  8. Kusras

    Kusras

    Joined:
    Jul 9, 2015
    Posts:
    129
    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.