Search Unity

U3: Add 2 sided to AlphaTest-Bumped.shader?

Discussion in 'Shaders' started by bigkahuna, Sep 29, 2010.

  1. bigkahuna

    bigkahuna

    Joined:
    Apr 30, 2006
    Posts:
    5,434
    I need a 2-sided cut-out transparent, diffuse bumped shader. I looked at some of the other 2-sided shaders posted here in the forums, but they don't seem to work in Unity 3.0. Any ideas? Here is the original shader:

    Code (csharp):
    1. Shader "Transparent/Cutout/Bumped Diffuse" {
    2. Properties {
    3.     _Color ("Main Color", Color) = (1,1,1,1)
    4.     _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
    5.     _BumpMap ("Normalmap", 2D) = "bump" {}
    6.     _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    7. }
    8.  
    9. SubShader {
    10.     Tags {"IgnoreProjector"="True" "RenderType"="TransparentCutout"}
    11.     LOD 300
    12.    
    13. CGPROGRAM
    14. #pragma surface surf Lambert alphatest:_Cutoff
    15.  
    16. sampler2D _MainTex;
    17. sampler2D _BumpMap;
    18. float4 _Color;
    19.  
    20. struct Input {
    21.     float2 uv_MainTex;
    22.     float2 uv_BumpMap;
    23. };
    24.  
    25. void surf (Input IN, inout SurfaceOutput o) {
    26.     half4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    27.     o.Albedo = c.rgb;
    28.     o.Alpha = c.a;
    29.     o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    30. }
    31. ENDCG
    32. }
    33.  
    34. FallBack "Transparent/Cutout/Diffuse"
    35. }
    36.  
     
  2. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    Have you considered doubling your geometry? It's way easier and usually performs better.
     
  3. bigkahuna

    bigkahuna

    Joined:
    Apr 30, 2006
    Posts:
    5,434
    I want to use it on an interactive cloth object.
     
  4. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    Ah. That's a good reason to do it in a shader.

    Unfortunately, I think might be pretty horrible to do. I would approach it by compiling the above shader with #pragma debug. This will give you the passes generated by the surface shader translator. Then you need to duplicate all of those passes and negate the normals in the duplicates.

    I'm not actually sure how that will work with lighting passes.
     
  5. bigkahuna

    bigkahuna

    Joined:
    Apr 30, 2006
    Posts:
    5,434
    I'm about as far from a shader coder as you can get. I think I modified a grand total of one shader without breaking it. ;) Maybe one of those new visual shader editors might be easier for me to work with...
     
  6. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    Ok wait I figured out a far easier way to do it. It requires two materials: the built-in one and this, slightly modified one:
    Code (csharp):
    1. Shader "Transparent/Cutout/Bumped Diffuse Backwards" {
    2. Properties {
    3.     _Color ("Main Color", Color) = (1,1,1,1)
    4.     _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
    5.     _BumpMap ("Normalmap", 2D) = "bump" {}
    6.     _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    7. }
    8.  
    9. SubShader {
    10.     Tags {"IgnoreProjector"="True" "RenderType"="TransparentCutout"}
    11.     LOD 300
    12.     Cull Front
    13.    
    14. CGPROGRAM
    15. #pragma surface surf Lambert alphatest:_Cutoff
    16.  
    17. sampler2D _MainTex;
    18. sampler2D _BumpMap;
    19. float4 _Color;
    20.  
    21. struct Input {
    22.     float2 uv_MainTex;
    23.     float2 uv_BumpMap;
    24. };
    25.  
    26. void surf (Input IN, inout SurfaceOutput o) {
    27.     half4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    28.     o.Albedo = c.rgb;
    29.     o.Alpha = c.a;
    30.     o.Normal = -UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    31. }
    32. ENDCG
    33. }
    34.  
    35. FallBack "Transparent/Cutout/Diffuse"
    36. }
    Then, on your cloth, make the Materials array have a length of 2 instead of 1. Use the built-in shader for the first one, and the fancy new backwards shader for the second one.

    Note that all I did was add Cull Front before the CGPROGRAM block, and a minus sign in front of UnpackNormal().
     
  7. bigkahuna

    bigkahuna

    Joined:
    Apr 30, 2006
    Posts:
    5,434
    Thank you so much Daniel, this is working absolutely perfectly! :)
     
  8. BIG-BUG

    BIG-BUG

    Joined:
    Mar 29, 2009
    Posts:
    457
    A simple CULL OFF would disable backface culling the simple way. Daniels solution however has the charme of correctly aligned normals. But wouldn't it be faster to do all the stuff in a second pass as only one draw call would be required?
     
  9. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    Cull Off produces reversed lighting. The second material is the only way to use the normals correctly, although both approaches break shadows in forward rendering.
    What do you mean by "all the stuff"?
     
  10. bigkahuna

    bigkahuna

    Joined:
    Apr 30, 2006
    Posts:
    5,434
    Actually, I'm quite happy with Daniel's solution. Works great and I haven't seen any appreciable performance lost (although I haven't really done any super accurate performance tests).
     
  11. SQR

    SQR

    Joined:
    Jun 29, 2010
    Posts:
    10
    Hi, I'm sorry to jump in like this, I've been in need of a shader like this for cloth precisely and this sounds great, but I have a question, I'm really no programmer so could someone please explain the part where Daniel, says
    I would really appreciate it. Thx!

    Ok nevermind that, I figured it out. Still thx for the shader!
     
    Last edited: Oct 1, 2010
  12. arbbot

    arbbot

    Joined:
    May 2, 2010
    Posts:
    74
    Daniel,

    Thanks so much for your shader solution and help on the forums. It's a shame that the Unity team hasn't posted an AAA tutorial about the Interactive Cloth features and possibilities, but through the community I have been able to figure out most of the details to mae it work. Anyway, your shader works perfectly and looks good. I hope to be able to upload some screenshots of the prototypes I'm working on soon. Thanks again for the help and the shader code.

    Cheers!
    -arbbot
     
  13. battou

    battou

    Joined:
    Jan 25, 2011
    Posts:
    222
    I have a problem with above shader. It's working great on meshes, but on Cloth objects it's just flipping normals and front side become invisible.( Any way to fix this?
     
  14. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    Did you follow the instructions given with the shader?
     
  15. golgauth

    golgauth

    Joined:
    Sep 11, 2009
    Posts:
    21
    Ok guys,

    Thanks a lot for this very usefull Thread.
    Starting from this, I went a little bit further with a case study (a waving flag shader).

    Full documentation here :
    http://klakos.com/en/advanced-waving-flag-shader-for-unity-double-sided-alpha-shadow-support-3/

    It covers the following points :

    * * Flag vertices animation via a shader (trigo. way)
    * * Advanced ShaderLab surface shading for transparency management
    * * Adding a shadow Pass (with alpha support)
    * * Double-sided surfaces methods (methods 1, 2 and 3)
    * * Provided Double-sided Materials Configuration Wizard (for 3rd method)


    >>> Downloads [from the address bellow]

    * - PDF version of the article : WavingFlag.pdf
    * - Configuration Wizard : BackwardMaterialBuilder.cs
    * - Unity 3.3 Package : WavingFlagDemo.unitypackage | WavingFlagDemo.rar

    Here is my shader code :

    The "FlagWaveCG.cginc" file :
    Code (csharp):
    1. // Upgrade NOTE: replaced 'glstate.matrix.mvp' with 'UNITY_MATRIX_MVP'
    2.  
    3. // Original shader by cboe - Mar, 23, 2009
    4. // Enhanced to 3 axis movement by Seon - Jan, 21, 2010
    5. // Added _WaveSpeed by Eric5h5 - Jan, 26, 2010
    6. // CHANGE LOG - Gauthier BOAGLIO (golgauth) / Klakos - May, 07, 2011 :
    7. //      - Added Transparency support
    8. //      - Added Spec and Normal mapping support
    9. //      - Added Shadow casting support (+ Shadow Alpha and Shadow Alpha cutoff support)
    10. //              [Done in the "ShadowCaster" additional Pass]
    11. //      - Added advanced double-sided rendering support
    12. //      - Added _WaveStrength param
    13. //
    14. // Requirements: assumes you are using a subdivided plane created with X (width) * Z (height) where Y is flat.
    15. // Requirements: assumes UV as: left X (U0) is attatched to pole, and Top Z (V1) is at top of pole.  
    16. //
    17. // [url]http://klakos.com/en/advanced-waving-flag-shader-for-unity-double-sided-alpha-shadow-support-3/[/url] ] for
    18. // visuals and more informations
    19.  
    20.  
    21. #include "UnityCG.cginc"
    22.  
    23. float4 _Color;
    24. sampler2D _MainTex;
    25. fixed _Cutoff;
    26. float _WaveSpeed;
    27. float _WaveStrength;
    28.  
    29.  
    30. struct v2f {
    31.     V2F_SHADOW_CASTER;
    32.     float2 uv : TEXCOORD1;
    33. };
    34.  
    35.  
    36. void computeWave (inout appdata_full v, inout v2f o)
    37. {
    38.     float sinOff=(v.vertex.x+v.vertex.y+v.vertex.z) * _WaveStrength;
    39.     float t=-_Time*_WaveSpeed;
    40.     float fx=v.texcoord.x;
    41.     float fy=v.texcoord.x*v.texcoord.y;
    42.  
    43.     v.vertex.x+=sin(t*1.45+sinOff)*fx*0.5;
    44.     v.vertex.y=(sin(t*3.12+sinOff)*fx*0.5-fy*0.9);
    45.     v.vertex.z-=(sin(t*2.2+sinOff)*fx*0.2);
    46.     o.pos = mul( UNITY_MATRIX_MVP, v.vertex );
    47.     o.uv = v.texcoord;
    48. }

    The "FlagWave-Advanced.shader" file :
    Code (csharp):
    1. // Upgrade NOTE: replaced 'glstate.matrix.mvp' with 'UNITY_MATRIX_MVP'
    2.  
    3. // Original shader by cboe - Mar, 23, 2009
    4. // Enhanced to 3 axis movement by Seon - Jan, 21, 2010
    5. // Added _WaveSpeed by Eric5h5 - Jan, 26, 2010
    6. // CHANGE LOG - Gauthier BOAGLIO (golgauth) / Klakos - May, 07, 2011 :
    7. //      - Added Transparency support
    8. //      - Added Spec and Normal mapping support
    9. //      - Added Shadow casting support (+ Shadow Alpha and Shadow Alpha cutoff support)
    10. //              [Done in the "ShadowCaster" additional Pass]
    11. //      - Added advanced double-sided rendering support
    12. //      - Added _WaveStrength param
    13. //
    14. // Requirements: assumes you are using a subdivided plane created with X (width) * Z (height) where Y is flat.
    15. // Requirements: assumes UV as: left X (U0) is attatched to pole, and Top Z (V1) is at top of pole.  
    16. //
    17. // See [ http://klakos.com/en/advanced-waving-flag-shader-for-unity-double-sided-alpha-shadow-support-3/ ] for
    18. // visuals and more informations
    19.  
    20.  
    21. Shader "Selfmade/for-2sided/FlagWave Advanced Regular"
    22. {
    23.  
    24. Properties
    25. {
    26.     // Ususal stuffs
    27.     _Color ("Main Color", Color) = (1,1,1,1)
    28.     _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 0)
    29.     _Shininess ("Shininess", Range (0.01, 1)) = 0.078125
    30.     _MainTex ("Base (RGB) TransGloss (A)", 2D) = "white" {}
    31.  
    32.     // Bump stuffs
    33.     //_Parallax ("Height", Range (0.005, 0.08)) = 0.02
    34.     _BumpMap ("Normalmap", 2D) = "bump" {}
    35.     //_ParallaxMap ("Heightmap (A)", 2D) = "black" {}
    36.    
    37.     // Shadow Stuff
    38.     _Cutoff ("Shadow Alpha cutoff", Range(0.25,0.9)) = 1.0
    39.  
    40.     // Flag Stuffs
    41.     _WaveSpeed ("Wave Speed", Range(0.0, 300.0)) = 50.0
    42.     _WaveStrength ("Wave Strength", Range(0.0, 5.0)) = 1.0
    43. }
    44.  
    45.  
    46. SubShader
    47. {
    48.     Tags {
    49.     "Queue"="Geometry"
    50.     "IgnoreProjector"="True"
    51.     "RenderType"="Transparent"}
    52.  
    53.     LOD 300
    54.  
    55.  
    56.  
    57.     Pass
    58.     {
    59.             Name "ShadowCaster"
    60.             Tags { "LightMode" = "ShadowCaster" }
    61.            
    62.             Fog {Mode Off}
    63.             ZWrite On ZTest Less Cull Off
    64.             Offset 1, 1
    65.  
    66.             CGPROGRAM
    67. // Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it does not contain a surface program or both vertex and fragment programs.
    68. #pragma exclude_renderers gles
    69.             #pragma vertex vert
    70.             #pragma fragment frag
    71.             #pragma fragmentoption ARB_precision_hint_fastest
    72.             #pragma multi_compile_shadowcaster
    73.             #include "FlagWaveCG.cginc"
    74.            
    75.            
    76.             v2f vert( appdata_full v )
    77.             {
    78.                 v2f o;
    79.                 computeWave(v, o);
    80.                 TRANSFER_SHADOW_CASTER(o)
    81.    
    82.               return o;
    83.             }
    84.            
    85.             //sampler2D _MainTex;
    86.                    
    87.             float4 frag( v2f i ) : COLOR
    88.             {
    89.                 fixed4 texcol = tex2D( _MainTex, i.uv );
    90.                 clip( texcol.a - _Cutoff );
    91.                 SHADOW_CASTER_FRAGMENT(i)
    92.             }
    93.             ENDCG
    94.  
    95.  
    96.       //SetTexture [_MainTex] {combine texture}
    97.     }
    98.  
    99. //CULL Front
    100.  
    101. CGPROGRAM
    102.         #pragma surface surf BlinnPhong alpha vertex:vert fullforwardshadows approxview
    103.         #include "FlagWaveCG.cginc"
    104.  
    105.  
    106.         half _Shininess;
    107.  
    108.         sampler2D _BumpMap;
    109.         //sampler2D _ParallaxMap;
    110.         float _Parallax;
    111.  
    112.         struct Input {
    113.             float2 uv_MainTex;
    114.             float2 uv_BumpMap;
    115.             //float3 viewDir;
    116.         };
    117.  
    118.         v2f vert (inout appdata_full v) {
    119.             v2f o;
    120.             computeWave(v, o);
    121.             return o;
    122.         }
    123.  
    124.         void surf (Input IN, inout SurfaceOutput o) {
    125.             // Comment the next 4 following lines to get a standard bumped rendering
    126.             // [Without Parallax usage, which can cause strange result on the back side of the plane]
    127.             /*half h = tex2D (_ParallaxMap, IN.uv_BumpMap).w;
    128.             float2 offset = ParallaxOffset (h, _Parallax, IN.viewDir);
    129.             IN.uv_MainTex += offset;
    130.             IN.uv_BumpMap += offset;*/
    131.  
    132.             fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
    133.             o.Albedo = tex.rgb * _Color.rgb;
    134.             o.Gloss = tex.a;
    135.             o.Alpha = tex.a * _Color.a;
    136.             //clip(o.Alpha - _Cutoff);
    137.             o.Specular = _Shininess;
    138.             o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    139.         }
    140. ENDCG
    141. }
    142.    
    143. Fallback "Transparent/VertexLit"
    144. }

    Hope this will help...
     
    Last edited: May 14, 2011
  16. michael bricout

    michael bricout

    Joined:
    Aug 26, 2010
    Posts:
    59
    Hi !

    I try your SHADER "Selfmade/TransparentShadowCaster", but it dosen't work :confused:

    Can you help me to see the shadows on my plane with an alpha texture ?

    Many thanks for yout help ! ;)
     
    Last edited: Oct 10, 2011
  17. golgauth

    golgauth

    Joined:
    Sep 11, 2009
    Posts:
    21
    Hello,

    I made some tests and it appears that it works with Point and Spot Lights, but no satisfying result with a "Directional Light".
    Does anyone has an idea about this issue ?
    Thanks

    NB : Here is what I get with a "Spot Light" dedicated to the "alpha plane" layer >>

     
    Last edited: Sep 20, 2011
  18. golgauth

    golgauth

    Joined:
    Sep 11, 2009
    Posts:
    21
    A workaround to all of this could be :

    Apply 2 materials to the Plane >>

    1. One as described above (TransparentShadowCaster)
    2. A second one to obtain the shadow working with "Directional Light" (using "Transparent/Cutout/Diffuse" built-in shader, which can handle shadows receiving)

    Illustration [Not very satisfying because of the aliasing at the shadow border] :



    Obtained with the following settings :



    But well, I don't have any better simple solution right now... And what about you, guys ?
     
    Last edited: Sep 21, 2011
  19. Chickenlord

    Chickenlord

    Joined:
    May 13, 2011
    Posts:
    381
    Try adding addshadow to the pragma line.
     
  20. golgauth

    golgauth

    Joined:
    Sep 11, 2009
    Posts:
    21
    Already tested with no result
    Thanks
     
  21. Chickenlord

    Chickenlord

    Joined:
    May 13, 2011
    Posts:
    381
    Ah okay, i'm sorry. Just read through the code. The receiving part is alpha, not alpha testing so it will never ever receive shadows. If you can switch it to cutoff, you could get shadows otherwise it won't work.
     
  22. golgauth

    golgauth

    Joined:
    Sep 11, 2009
    Posts:
    21
    Ok, we went to the same conclusion : "Cutoff" is the only way. But what I would really like to know is the big difference between Spot/Point lights and Directional ones (just for Unity knowledge purpose). Why can I get a perfect result with the first ones and nothing at all with the second ones ?

    NB : A little amelioration for the "cutout/cutoff solution" : using the AntiAliasing Post Effect (DLAA technique) given with the "Image Effects (Pro Only)" package. But we still have un-shadowed (white) edges - of course.



    (And of course, it is costly, real-time computing speaking ! But can be OK for small scenes...)
     
    Last edited: Sep 22, 2011
  23. golgauth

    golgauth

    Joined:
    Sep 11, 2009
    Posts:
    21
    So, I went a little further and found the LightMode" = "ForwardBase" Pass Tag.
    This does : "Used in Forward rendering, ambient, main directional light and vertex/SH lights are applied".
    http://unity3d.com/support/documentation/Components/SL-PassTags.html

    With this tag added to our shader, then only the main directional light is used, taking ride of the others.
    Here comes the modified shader [FlagWave Advanced Regular - ForwardBase] :
    Code (csharp):
    1.  
    2. // Upgrade NOTE: replaced 'glstate.matrix.mvp' with 'UNITY_MATRIX_MVP'
    3.  
    4. // Original shader by cboe - Mar, 23, 2009
    5. // Enhanced to 3 axis movement by Seon - Jan, 21, 2010
    6. // Added _WaveSpeed by Eric5h5 - Jan, 26, 2010
    7. // CHANGE LOG - Gauthier BOAGLIO (golgauth) / Klakos - May, 07, 2011 :
    8. //      - Added Transparency support
    9. //      - Added Spec and Normal mapping support
    10. //      - Added Shadow casting support (+ Shadow Alpha and Shadow Alpha cutoff support)
    11. //              [Done in the "ShadowCaster" additional Pass]
    12. //      - Added advanced double-sided rendering support
    13. //      - Added _WaveStrength param
    14. //
    15. // Requirements: assumes you are using a subdivided plane created with X (width) * Z (height) where Y is flat.
    16. // Requirements: assumes UV as: left X (U0) is attatched to pole, and Top Z (V1) is at top of pole.  
    17. //
    18. // See [ http://klakos.com/en/advanced-waving-flag-shader-for-unity-double-sided-alpha-shadow-support-3/ ] for
    19. // visuals and more informations
    20.  
    21.  
    22. Shader "Selfmade/for-2sided/FlagWave Advanced Regular - ForwardBase"
    23. {
    24.  
    25. Properties
    26. {
    27.     // Usual stuffs
    28.     _Color ("Main Color", Color) = (1,1,1,1)
    29.     _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 0)
    30.     _Shininess ("Shininess", Range (0.01, 1)) = 0.078125
    31.     _MainTex ("Base (RGB) TransGloss (A)", 2D) = "white" {}
    32.  
    33.     // Bump stuffs
    34.     //_Parallax ("Height", Range (0.005, 0.08)) = 0.02
    35.     _BumpMap ("Normalmap", 2D) = "bump" {}
    36.     //_ParallaxMap ("Heightmap (A)", 2D) = "black" {}
    37.    
    38.     // Shadow Stuff
    39.     _Cutoff ("Shadow Alpha cutoff", Range(0.25,0.9)) = 1.0
    40.  
    41.     // Flag Stuffs
    42.     _WaveSpeed ("Wave Speed", Range(0.0, 300.0)) = 50.0
    43.     _WaveStrength ("Wave Strength", Range(0.0, 5.0)) = 1.0
    44. }
    45.  
    46.  
    47. SubShader
    48. {
    49.     Tags {
    50.     "Queue"="Geometry"
    51.     "IgnoreProjector"="True"
    52.     "RenderType"="Transparent"
    53.     "LightMode" = "ForwardBase" }
    54.  
    55.     LOD 300
    56.  
    57.  
    58.     // Removed
    59.     /*
    60.     Pass
    61.         {
    62.             Name "ShadowCaster"
    63.             .
    64.             .
    65.             .
    66.     }
    67.     */
    68.  
    69. //CULL Front
    70.  
    71. CGPROGRAM
    72.         #pragma surface surf BlinnPhong alpha vertex:vert fullforwardshadows approxview
    73.         #include "FlagWaveCG.cginc"
    74.  
    75.  
    76.         half _Shininess;
    77.  
    78.         sampler2D _BumpMap;
    79.         //sampler2D _ParallaxMap;
    80.         float _Parallax;
    81.  
    82.         struct Input {
    83.             float2 uv_MainTex;
    84.             float2 uv_BumpMap;
    85.             //float3 viewDir;
    86.         };
    87.  
    88.         v2f vert (inout appdata_full v) {
    89.             v2f o;
    90.             //computeWave(v, o);
    91.             return o;
    92.         }
    93.  
    94.         void surf (Input IN, inout SurfaceOutput o) {
    95.             // Comment the next 4 following lines to get a standard bumped rendering
    96.             // [Without Parallax usage, which can cause strange result on the back side of the plane]
    97.             /*half h = tex2D (_ParallaxMap, IN.uv_BumpMap).w;
    98.             float2 offset = ParallaxOffset (h, _Parallax, IN.viewDir);
    99.             IN.uv_MainTex += offset;
    100.             IN.uv_BumpMap += offset;*/
    101.  
    102.             fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
    103.             o.Albedo = tex.rgb * _Color.rgb;
    104.             o.Gloss = tex.a;
    105.             o.Alpha = tex.a * _Color.a;
    106.             //clip(o.Alpha - _Cutoff);
    107.             o.Specular = _Shininess;
    108.             o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    109.         }
    110. ENDCG
    111. }
    112.    
    113. //Fallback "Transparent/VertexLit"
    114. FallBack "Diffuse"
    115. }
    116.  
    117.  
    Starting from that point, we can then combine both Directional and Spot/Point lights :



    Here come the materials settings :



    Any comment or nicer solution (using one single Surface Shader, by example) are welcome.
    Thanks
     
    Last edited: Sep 23, 2011
  24. golgauth

    golgauth

    Joined:
    Sep 11, 2009
    Posts:
    21
    Last edited: Sep 24, 2011
  25. golgauth

    golgauth

    Joined:
    Sep 11, 2009
    Posts:
    21
    Here is the shader code for a first attempt to get rendered both Spot/Point light and Directional shodows :
    [It consists in adding the shadows generated by the Directional light by blending the light attenuation over the rest...]

    Code (csharp):
    1. // Upgrade NOTE: replaced 'glstate.matrix.mvp' with 'UNITY_MATRIX_MVP'
    2.  
    3. // Original shader by cboe - Mar, 23, 2009
    4. // Enhanced to 3 axis movement by Seon - Jan, 21, 2010
    5. // Added _WaveSpeed by Eric5h5 - Jan, 26, 2010
    6. // CHANGE LOG - Gauthier BOAGLIO (golgauth) / Klakos - May, 07, 2011 :
    7. //      - Added Transparency support
    8. //      - Added Spec and Normal mapping support
    9. //      - Added Shadow casting support (+ Shadow Alpha and Shadow Alpha cutoff support)
    10. //              [Done in the "ShadowCaster" additional Pass]
    11. //      - Added advanced double-sided rendering support
    12. //      - Added _WaveStrength param
    13. //
    14. // Requirements: assumes you are using a subdivided plane created with X (width) * Z (height) where Y is flat.
    15. // Requirements: assumes UV as: left X (U0) is attatched to pole, and Top Z (V1) is at top of pole.  
    16. //
    17. // See [ http://klakos.com/en/advanced-waving-flag-shader-for-unity-double-sided-alpha-shadow-support-3/ ] for
    18. // visuals and more informations
    19.  
    20.  
    21. Shader "Selfmade/for-2sided/FlagWave Advanced Regular - ForwardBase - Single"
    22. {
    23.  
    24. Properties
    25. {
    26.     // Usual stuffs
    27.     _Color ("Main Color", Color) = (1,1,1,1)
    28.     _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 0)
    29.     _Shininess ("Shininess", Range (0.01, 1)) = 0.078125
    30.     _MainTex ("Base (RGB) TransGloss (A)", 2D) = "white" {}
    31.  
    32.     // Bump stuffs
    33.     //_Parallax ("Height", Range (0.005, 0.08)) = 0.02
    34.     _BumpMap ("Normalmap", 2D) = "bump" {}
    35.     //_ParallaxMap ("Heightmap (A)", 2D) = "black" {}
    36.    
    37.     // Shadow Stuff
    38.     _Cutoff ("Shadow Alpha cutoff", Range(0.25,0.9)) = 1.0
    39.     _ShadowIntensity ("Shadow Intensity", Range (0, 2)) = 0.6
    40.  
    41.     // Flag Stuffs
    42.     _WaveSpeed ("Wave Speed", Range(0.0, 300.0)) = 50.0
    43.     _WaveStrength ("Wave Strength", Range(0.0, 5.0)) = 1.0
    44. }
    45.  
    46.  
    47. SubShader
    48. {
    49.     Tags {
    50.     "Queue"="Geometry"
    51.     "IgnoreProjector"="True"
    52.     "RenderType"="Transparent"
    53.     }
    54.  
    55.     LOD 300
    56.  
    57.     //Lighting On
    58.  
    59. /*  Pass
    60.     {
    61.             Name "ShadowCaster"
    62.             Tags { "LightMode" = "ShadowCaster" }
    63.            
    64.             Fog {Mode Off}
    65.             ZWrite On ZTest Less Cull Off
    66.             Offset 1, 1
    67.  
    68.             CGPROGRAM
    69. // Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it does not contain a surface program or both vertex and fragment programs.
    70. #pragma exclude_renderers gles
    71.             #pragma vertex vert
    72.             #pragma fragment frag
    73.             #pragma fragmentoption ARB_precision_hint_fastest
    74.             #pragma multi_compile_shadowcaster
    75.             #include "FlagWaveCG.cginc"
    76.            
    77.            
    78.             v2f vert( appdata_full v )
    79.             {
    80.                 v2f o;
    81.                 ///computeWave(v, o);
    82.                 TRANSFER_SHADOW_CASTER(o)
    83.    
    84.               return o;
    85.             }
    86.            
    87.             //sampler2D _MainTex;
    88.                    
    89.             float4 frag( v2f i ) : COLOR
    90.             {
    91.                 fixed4 texcol = tex2D( _MainTex, i.uv );
    92.                 clip( texcol.a - _Cutoff );
    93.                 SHADOW_CASTER_FRAGMENT(i)
    94.             }
    95.             ENDCG
    96.  
    97.  
    98.       //SetTexture [_MainTex] {combine texture}
    99.     } */
    100.  
    101. //CULL Front
    102.  
    103. CGPROGRAM
    104.         #pragma surface surf BlinnPhong alpha vertex:vert fullforwardshadows approxview
    105.         #include "FlagWaveCG.cginc"
    106.  
    107.  
    108.         half _Shininess;
    109.  
    110.         sampler2D _BumpMap;
    111.         //sampler2D _ParallaxMap;
    112.         float _Parallax;
    113.  
    114.         struct Input {
    115.             float2 uv_MainTex;
    116.             float2 uv_BumpMap;
    117.             //float3 viewDir;
    118.         };
    119.  
    120.         v2f vert (inout appdata_full v) {
    121.             v2f o;
    122.             //computeWave(v, o);
    123.             return o;
    124.         }
    125.  
    126.         void surf (Input IN, inout SurfaceOutput o) {
    127.             // Comment the next 4 following lines to get a standard bumped rendering
    128.             // [Without Parallax usage, which can cause strange result on the back side of the plane]
    129.             /*half h = tex2D (_ParallaxMap, IN.uv_BumpMap).w;
    130.             float2 offset = ParallaxOffset (h, _Parallax, IN.viewDir);
    131.             IN.uv_MainTex += offset;
    132.             IN.uv_BumpMap += offset;*/
    133.  
    134.             fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
    135.             o.Albedo = tex.rgb * _Color.rgb;
    136.             o.Gloss = tex.a;
    137.             o.Alpha = tex.a * _Color.a;
    138.             //clip(o.Alpha - _Cutoff);
    139.             o.Specular = _Shininess;
    140.             o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    141.         }
    142. ENDCG
    143.  
    144.  
    145.  
    146.         // We "add" the shadows by blending the light attenuation
    147.         Pass {
    148.             Blend SrcAlpha OneMinusSrcAlpha
    149.             Name "ShadowPass"
    150.             Tags {"LightMode" = "ForwardBase"}
    151.              
    152.             CGPROGRAM
    153.             #pragma exclude_renderers xbox360
    154.             #pragma debug
    155.             #pragma vertex vert
    156.             #pragma fragment frag
    157.             #pragma multi_compile_fwdbase
    158.             #pragma fragmentoption ARB_fog_exp2
    159.             #pragma fragmentoption ARB_precision_hint_fastest
    160.             #include "UnityCG.cginc"
    161.             #include "AutoLight.cginc"
    162.  
    163.             struct v2f {
    164.                 float2 uv_MainTex : TEXCOORD1;
    165.                 float4 pos : SV_POSITION;
    166.                 LIGHTING_COORDS(3,4)
    167.                 float3  lightDir;
    168.             };
    169.  
    170.             uniform float4 _MainTex_ST;
    171.  
    172.             uniform sampler2D _MainTex;
    173.             uniform float4 _Color;
    174.             uniform float _ShadowIntensity;
    175.  
    176.             v2f vert (appdata_full v)
    177.             {
    178.                 v2f o;
    179.                 o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    180.                 o.lightDir = ObjSpaceLightDir( v.vertex );
    181.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    182.                 return o;
    183.             }
    184.  
    185.             float4 frag (v2f i) : COLOR
    186.             {
    187.                 float atten = LIGHT_ATTENUATION(i);
    188.                
    189.                 half4 c;
    190.                 c.rgb =  0;
    191.                 c.a = (1-atten) * _ShadowIntensity * tex2D(_MainTex, i.uv_MainTex).a;
    192.                 return c;
    193.             }
    194.             ENDCG
    195.         }
    196.    
    197.    
    198. }
    199.    
    200. //Fallback "Transparent/VertexLit"
    201. FallBack "Diffuse"
    202. }
    203.  
    204.  
    205.  
    It gives :



    Well, I'm unsatisfied because of the darkening all over the holes in the main texture.
    (It was not the case with the method explained bellow : http://forum.unity3d.com/threads/61882-U3-Add-2-sided-to-AlphaTest-Bumped.shader?p=696649&viewfull=1#post696649).

    I tried to get ride of it by doing :
    Code (csharp):
    1. c.a = (1-atten) * _ShadowIntensity * tex2D(_MainTex, i.uv_MainTex).a;
    2.  
    But it seems that the tex2D(_MainTex, i.uv_MainTex).a doesn't reduce the intensity of the shadow even where pixels are fully transparent from the main texture (I think that I don't get the right alpha informations from the texture).

    Any idea ?
    Thanks again.
     
    Last edited: Sep 24, 2011
  26. golgauth

    golgauth

    Joined:
    Sep 11, 2009
    Posts:
    21
    Well, I found out something. And yes I didn't get the right alpha informations from the main texture :
    Just added this line in the "vert" function :
    Code (csharp):
    1. o.uv_MainTex = TRANSFORM_TEX(v.texcoord, _MainTex);
    2.  
    "TRANSFORM_TEX" calculates the uv coordinates for the tiling and offset set up for the texture...
    Shame on me !

    It looks quite good now :



    Full final shader file :
    Code (csharp):
    1. // Upgrade NOTE: replaced 'glstate.matrix.mvp' with 'UNITY_MATRIX_MVP'
    2.  
    3. // Original shader by cboe - Mar, 23, 2009
    4. // Enhanced to 3 axis movement by Seon - Jan, 21, 2010
    5. // Added _WaveSpeed by Eric5h5 - Jan, 26, 2010
    6. // CHANGE LOG - Gauthier BOAGLIO (golgauth) / Klakos - May, 07, 2011 :
    7. //      - Added Transparency support
    8. //      - Added Spec and Normal mapping support
    9. //      - Added Shadow casting support (+ Shadow Alpha and Shadow Alpha cutoff support)
    10. //              [Done in the "ShadowCaster" additional Pass]
    11. //      - Added advanced double-sided rendering support
    12. //      - Added _WaveStrength param
    13. //      - Added full support for Shadow receiving
    14. //              [Done in the "ShadowPass" additional "ForwardBase" Pass]
    15. //
    16. // Requirements: assumes you are using a subdivided plane created with X (width) * Z (height) where Y is flat.
    17. // Requirements: assumes UV as: left X (U0) is attatched to pole, and Top Z (V1) is at top of pole.  
    18. //
    19. // See [ http://klakos.com/en/advanced-waving-flag-shader-for-unity-double-sided-alpha-shadow-support-3/ ] for
    20. // visuals and more informations
    21.  
    22.  
    23. Shader "Selfmade/for-2sided/FlagWave Advanced Regular - ForwardBase - Single"
    24. {
    25.  
    26. Properties
    27. {
    28.     // Usual stuffs
    29.     _Color ("Main Color", Color) = (1,1,1,1)
    30.     _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 0)
    31.     _Shininess ("Shininess", Range (0.01, 1)) = 0.078125
    32.     _MainTex ("Base (RGB) TransGloss (A)", 2D) = "white" {}
    33.  
    34.     // Bump stuffs
    35.     //_Parallax ("Height", Range (0.005, 0.08)) = 0.02
    36.     _BumpMap ("Normalmap", 2D) = "bump" {}
    37.     //_ParallaxMap ("Heightmap (A)", 2D) = "black" {}
    38.    
    39.     // Shadow Stuff
    40.     _Cutoff ("Shadow Alpha cutoff", Range(0.25,0.9)) = 1.0
    41.     _ShadowIntensity ("Shadow Intensity", Range (0, 2)) = 0.6
    42.  
    43.     // Flag Stuffs
    44.     _WaveSpeed ("Wave Speed", Range(0.0, 300.0)) = 50.0
    45.     _WaveStrength ("Wave Strength", Range(0.0, 5.0)) = 1.0
    46. }
    47.  
    48.  
    49. SubShader
    50. {
    51.     Tags {
    52.     "Queue"="Geometry"
    53.     "IgnoreProjector"="True"
    54.     "RenderType"="Transparent"
    55.     }
    56.  
    57.     LOD 300
    58.  
    59.     //Lighting On
    60.  
    61. /*  Pass
    62.     {
    63.             Name "ShadowCaster"
    64.             Tags { "LightMode" = "ShadowCaster" }
    65.            
    66.             Fog {Mode Off}
    67.             ZWrite On ZTest Less Cull Off
    68.             Offset 1, 1
    69.  
    70.             CGPROGRAM
    71. // Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it does not contain a surface program or both vertex and fragment programs.
    72. #pragma exclude_renderers gles
    73.             #pragma vertex vert
    74.             #pragma fragment frag
    75.             #pragma fragmentoption ARB_precision_hint_fastest
    76.             #pragma multi_compile_shadowcaster
    77.             #include "FlagWaveCG.cginc"
    78.            
    79.            
    80.             v2f vert( appdata_full v )
    81.             {
    82.                 v2f o;
    83.                 ///computeWave(v, o);
    84.                 TRANSFER_SHADOW_CASTER(o)
    85.    
    86.               return o;
    87.             }
    88.            
    89.             //sampler2D _MainTex;
    90.                    
    91.             float4 frag( v2f i ) : COLOR
    92.             {
    93.                 fixed4 texcol = tex2D( _MainTex, i.uv );
    94.                 clip( texcol.a - _Cutoff );
    95.                 SHADOW_CASTER_FRAGMENT(i)
    96.             }
    97.             ENDCG
    98.  
    99.  
    100.       //SetTexture [_MainTex] {combine texture}
    101.     } */
    102.  
    103. //CULL Front
    104.  
    105. CGPROGRAM
    106.         #pragma surface surf BlinnPhong alpha vertex:vert fullforwardshadows approxview
    107.         #include "FlagWaveCG.cginc"
    108.  
    109.  
    110.         half _Shininess;
    111.  
    112.         sampler2D _BumpMap;
    113.         //sampler2D _ParallaxMap;
    114.         float _Parallax;
    115.  
    116.         struct Input {
    117.             float2 uv_MainTex;
    118.             float2 uv_BumpMap;
    119.             //float3 viewDir;
    120.         };
    121.  
    122.         v2f vert (inout appdata_full v) {
    123.             v2f o;
    124.             //computeWave(v, o);
    125.             return o;
    126.         }
    127.  
    128.         void surf (Input IN, inout SurfaceOutput o) {
    129.             // Comment the next 4 following lines to get a standard bumped rendering
    130.             // [Without Parallax usage, which can cause strange result on the back side of the plane]
    131.             /*half h = tex2D (_ParallaxMap, IN.uv_BumpMap).w;
    132.             float2 offset = ParallaxOffset (h, _Parallax, IN.viewDir);
    133.             IN.uv_MainTex += offset;
    134.             IN.uv_BumpMap += offset;*/
    135.  
    136.             fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
    137.             o.Albedo = tex.rgb * _Color.rgb;
    138.             o.Gloss = tex.a;
    139.             o.Alpha = tex.a * _Color.a;
    140.             //clip(o.Alpha - _Cutoff);
    141.             o.Specular = _Shininess;
    142.             o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    143.         }
    144. ENDCG
    145.  
    146.  
    147.  
    148.         // Adding the shadows (from Directional Light)
    149.         // by blending the light attenuation
    150.         Pass {
    151.             Blend SrcAlpha OneMinusSrcAlpha
    152.             Name "ShadowPass"
    153.             Tags {"LightMode" = "ForwardBase"}
    154.              
    155.             CGPROGRAM
    156.             #pragma exclude_renderers xbox360
    157.             #pragma debug
    158.             #pragma vertex vert
    159.             #pragma fragment frag
    160.             #pragma multi_compile_fwdbase
    161.             #pragma fragmentoption ARB_fog_exp2
    162.             #pragma fragmentoption ARB_precision_hint_fastest
    163.             #include "UnityCG.cginc"
    164.             #include "AutoLight.cginc"
    165.  
    166.             struct v2f {
    167.                 float2 uv_MainTex : TEXCOORD1;
    168.                 float4 pos : SV_POSITION;
    169.                 LIGHTING_COORDS(3,4)
    170.                 float3  lightDir;
    171.             };
    172.  
    173.             float4 _MainTex_ST;
    174.  
    175.             sampler2D _MainTex;
    176.             float4 _Color;
    177.             float _ShadowIntensity;
    178.  
    179.             v2f vert (appdata_full v)
    180.             {
    181.                 v2f o;
    182.                 o.uv_MainTex = TRANSFORM_TEX(v.texcoord, _MainTex);
    183.                 o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
    184.                 o.lightDir = ObjSpaceLightDir( v.vertex );
    185.                 TRANSFER_VERTEX_TO_FRAGMENT(o);
    186.                 return o;
    187.             }
    188.  
    189.             float4 frag (v2f i) : COLOR
    190.             {
    191.                 float atten = LIGHT_ATTENUATION(i);
    192.                
    193.                 half4 c;
    194.                 c.rgb =  0;
    195.                 c.a = (1-atten) * _ShadowIntensity * (tex2D(_MainTex, i.uv_MainTex).a);
    196.                 return c;
    197.             }
    198.             ENDCG
    199.         }
    200.    
    201.    
    202. }
    203.    
    204. //Fallback "Transparent/VertexLit"
    205. FallBack "Diffuse"
    206. }
    207.  
    208.  
    209.  
     
    Last edited: Sep 24, 2011
  27. golgauth

    golgauth

    Joined:
    Sep 11, 2009
    Posts:
    21
    Well, I agree with it. And my final solution is only available for "Forward" rendering path (this can be a constraint for many different reasons - and a benefit for some others).

    What ever your needs are : here is the document I produced covering what we've been talking about until now : http://klakos.com/en/fully-shadowed-transparent-shader-for-unity-shadows-receiving-support-from-spotpoint-and-directional-lights/

    Guess this will be useful for some of you !
     
  28. Chickenlord

    Chickenlord

    Joined:
    May 13, 2011
    Posts:
    381
    Hi. Cool stuff, i'll read through all of that later. Maybe quite useful, so thanks for it.
    Regarding the "only in forward path"-thing, it looks like there's a bug in unity itself, preventing things from casting/receiving full shadows in deferred rendering, when they are drawn in forward mode (which is the case for transparent objects and all shaders using a modified lighting function). Already reported this, but sadly haven't got any replies or info on that.
     
  29. golgauth

    golgauth

    Joined:
    Sep 11, 2009
    Posts:
    21
    Ok, good to know. Very interesting informations [Coming from a "Shader lord" : I had a look to your Shader Bundle, and they're impressive (specially the skin ones are so awesome).]
    Thanks a lot.
     
  30. golgauth

    golgauth

    Joined:
    Sep 11, 2009
    Posts:
    21
    Well, to make sure that I fully understood what you said : Do you mean that everything that works and is drawn in forward mode should also theoretically work (cast/receive shadows) in deferred ? Is it the way it works in the others game engines ?

    Edit : I saw that you forced all your shaders (from the Chicken Bundle) in forward mode... What kind of differences can we get with them by switching the rendering path from forward to deferred ?
     
    Last edited: Sep 28, 2011
  31. Chickenlord

    Chickenlord

    Joined:
    May 13, 2011
    Posts:
    381
    Despite transparent objects: Yes. Transparent objects don't cast or receive shadows because they do not write to the depth buffer.

    It's not me who forces them to be drawn in forward mode but the engine itself. Here's how it works.
    In deferred lighting all the lighting stuff is done in screen space. But it has a major disadvantage, which is that all objects are using the same lighting function (usually Blinn-Phong). While is performance wise a good choice, it obviously prevents you from using a different lighting function for some objects (as long as it's not just a slightly changed one).
    Then you have three ways to solve this issue. You could either use deferred shading, which is way more powerful but also needs way more performance. Lately there are more and more papers on how to implement deferred shading efficiently etc, so it will probably become the standard in next few years (as long as no other incredible technique shows up).
    Another way would be to extend the G-Buffer, in order to allow all the different lighting things. This kills one of the main benefits of deferred lighting though, the small G-Buffer, and in addition you'd have to compute all the lighting for all the objects regardless of what kind of light they use. So, for example, you'd calculate the light traveling inside an object to render translucency although the objects isn't translucent at all. (I may be mistaken with this one, so if i am and your reading this, please correct me)
    The last possibility, which unity actually uses, is to draw everything in deferred mode, that can be drawn in deferred mode. So in a usual case, all that stuff that isn't transparent (cut-off should work if i'm correct) and uses a deferred lighting compatible light model, so Blinn-Phong or slightly changed Blinn-Phong. Everything else is drawn in forward mode. Regarding the fact how unity solves the mixing of those two renderers, i don't know.

    So the issue here is, that all my shaders use a completely different lighting function. So they are drawn in forward mode. And they do receive/cast shadows in deferred rendering. But they only receive shadows from the most important light of a type in a scene. So if there are for example three directional lights, all three are taken into account for the model lighting itself but only the most important one (usually the brightest one) does cast shadows onto the custom shader material.
    I don't know, what the issue for this really is, but this doesn't happen in forward mode. So yeah, i don't know if this is a general Unity bug, if it does only happen for me, or if this is done on purpose.

    And now that i'm finished writing i have the feeling i forgot something and said a whole bunch of stupid nonsense :D (but i guess it's not that bad)
     
  32. golgauth

    golgauth

    Joined:
    Sep 11, 2009
    Posts:
    21
    Ok "Chickenlord",

    First of all, thank you so much for having taken so much time to explain all of this. And don't worry : Everything you said makes definitely sense to me and is an excellent starting point for me to pick up more informations by googling, concerning some of the points you've been talking about. So thank you so very much !

    Yes you are correct.

    So do I ! For example I've been able to get this in Deferred Lighting by heavily tricky tricky way and it does probably make sense to Unity programmers but definitely not to me ( (using 2 cameras - one [CullingMask = Everything, Depth Only] for the transparent plane, another one [CullingMask = exclude transparent plane layer, Skybox]) + (playing with Queue and RenderType Tags) - and 2 lights : spot + directional [directional blended using ForwardBase like explained earlier] ) :


    Both Cameras turned into Deferred L

    Anyway it is not exploitable... And it seems to make the renderer a bit crazy in the Game view, even if it works perfectly in play mode.
    But now, I think I have a better understanding about how Unity behaves, renderly and shaderly speaking ;-) .
     
    Last edited: Sep 29, 2011
  33. argosy_ops

    argosy_ops

    Joined:
    Dec 27, 2012
    Posts:
    49
    Interesting solution, but I'm wondering how I could use that on a multi-material model? I have two materials on that model, one of which is supposed to have a two-sided material with flipped normals on the backside. In Blender, the two materials are assigned to their respective faces and correctly show up in Unity. However, if I simply add another material slot to the mesh renderer, how will Unity know what faces to assign the new material to?
     
  34. Ravel

    Ravel

    Joined:
    Nov 21, 2010
    Posts:
    605
    Can anyone get this to work with Unity5 ?