Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Combining surface and vertex/fragment shader

Discussion in 'Shaders' started by Vade-Mecum, Jan 8, 2015.

  1. Vade-Mecum

    Vade-Mecum

    Joined:
    Dec 10, 2012
    Posts:
    17
    Hello!
    We use the nature pack trees in our project, but their shaders has no lighting and cast no shadow (and for some reason they use double polygons in all foliage, instead of turning off backface cull). So i thought it would be great to combine them with built in transparency diffuse cutout shader, since it looks much more juicy and gets illuminated by the lights. The main reason to combine them is the animation. Their trees is animated by vertex transformation in shader. I don't know economywise how efficient this solution is, but it works fine and since some maps already contain their trees i think correcting the shader is the right thing to do.
    I've deal with some simple shaders before, but this seems too complicated to me since these shaders works diffirently. I thought to mess up with passes and subshaders, but this is a mobile game and the solution got to be light and simple, si i'm asking for your help.
    First of all - i can't get which is the best - implement the animation cycle in surface shader, or try to use the lambent lighting model in 2-pass nature pack shader.
    Also there's one thing that disturbs me: i can't get adequate source of information for shader programming. I mean the scripting in that case is pretty obvious, you have the issue, you google it, read about it and it works. In shader code it just isn't, and i can't get any information source that would tell me why that happens and how to fix it. All i get is extensive advices to read books, but since i'm a all-in-one person, i'm gonna blow my head this way, so it would be great if you have some adequate shader manuals and command lists.

    So, the shader is
    Code (CSharp):
    1. // - Unlit
    2.  
    3. Shader "atsGrass-Unlit-Wind" {
    4. Properties {
    5.     _MainTex ("Base (RGB) Alpha (A)", 2D) = "white" {}
    6.     _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    7. }
    8.  
    9. SubShader {
    10.     Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "LightMode"="ForwardBase"}
    11.     LOD 100
    12.     Cull Off
    13.     ZWrite Off
    14.     Blend SrcAlpha OneMinusSrcAlpha
    15.    
    16.    
    17.     CGINCLUDE
    18.     #include "UnityCG.cginc"
    19.     sampler2D _MainTex;
    20.     half4 _MainTex_ST;
    21.    
    22.     float4 _GrassWind; //is not defined in terrainengine.cginc
    23.  
    24.     struct v2f {
    25.         float4 pos : SV_POSITION;
    26.         float2 uv : TEXCOORD0;
    27.     };
    28.  
    29. inline float4 AnimateGrass(float4 pos, float3 normal, float animParams)
    30. {  
    31.     // animParams stored in color
    32.     // animParams = primary factor = blue
    33.     // Primary bending
    34.     // Displace position
    35.     pos.xyz += animParams * _GrassWind.xyz * _GrassWind.w; // controlled by vertex color blue
    36.     return pos;
    37. }
    38.  
    39.  
    40.    
    41.     v2f vert (appdata_full v)
    42.     {
    43.         v2f o;
    44.         float4    windParams    = float(v.color.b);      
    45.         // call vertex animation
    46.         float4 mdlPos = AnimateGrass(v.vertex, v.normal, windParams);
    47.         o.pos = mul(UNITY_MATRIX_MVP,mdlPos);
    48.         o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    49.         return o;
    50.     }
    51.     ENDCG
    52.  
    53.     Pass {
    54.         CGPROGRAM
    55.         #pragma debug
    56.         #pragma vertex vert
    57.         #pragma fragment frag
    58.         #pragma fragmentoption ARB_precision_hint_fastest      
    59.         fixed4 frag (v2f i) : COLOR
    60.         {
    61.             fixed4 tex = tex2D (_MainTex, i.uv);
    62.            
    63.             fixed4 c;
    64.             c.rgb = tex.rgb;
    65.             c.a = tex.a;
    66.            
    67.             return c;
    68.         }
    69.         ENDCG
    70.     }  
    71. }
    72. }
    73.  
    74.  
    Thanks in advance!
     
  2. Vade-Mecum

    Vade-Mecum

    Joined:
    Dec 10, 2012
    Posts:
    17
    So, for now i've managed to get the assets lighted correctly, cast and recieve shadows. But there's a problem with blending and the shadows won't move with the leaves, There's temporary version. Still will appreciate any possible help.
    Code (CSharp):
    1. Shader "Wind Trees" {
    2. Properties {
    3.          _MainTex ("Base (RGB) Alpha (A)", 2D) = "white" {}
    4.          _Color ("Main Color", Color) = (1,1,1,1)
    5.          _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    6. }
    7. SubShader {
    8.          Pass {
    9.          Tags {"Queue"="Transparent+1" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
    10.     LOD 200
    11.     Cull Off
    12.         CGPROGRAM
    13.         #pragma vertex vert
    14.         #pragma fragment frag
    15.         #pragma multi_compile_fwdbase
    16.         #pragma fragmentoption ARB_precision_hint_fastest
    17.         #include "UnityCG.cginc"
    18.         #include "AutoLight.cginc"
    19.     sampler2D _MainTex;
    20.     float4 _Color;
    21.     float4 _LightColor0;
    22.     half4 _MainTex_ST;
    23.     float4 _GrassWind; //is not defined in terrainengine.cginc
    24.     struct v2f {
    25.                  float4 pos : SV_POSITION;
    26.                  float3 lightDir : TEXCOORD0;
    27.                  float3 normal : TEXCOORD1;
    28.                  float2 uv : TEXCOORD2;
    29.                  LIGHTING_COORDS(3, 4)
    30.     };
    31. inline float4 AnimateGrass(float4 pos, float3 normal, float animParams)
    32. {
    33.     pos.xyz += animParams * _GrassWind.xyz * _GrassWind.w; // controlled by vertex color blue
    34.     return pos;
    35. }
    36.     v2f vert (appdata_full v)
    37.     {
    38.         v2f o;
    39.         float4    windParams    = float(v.color.b);
    40.         float4 mdlPos = AnimateGrass(v.vertex, v.normal, windParams);
    41.         o.pos = mul(UNITY_MATRIX_MVP,mdlPos);
    42.                  o.uv = v.texcoord;
    43.                  o.lightDir = normalize(ObjSpaceLightDir(v.vertex));
    44.                  o.normal = normalize(v.normal).xyz;
    45.         TRANSFER_VERTEX_TO_FRAGMENT(o);
    46.         return o;
    47.     }
    48.         fixed4 frag (v2f i) : COLOR
    49.         {
    50.                  float3 L = normalize(i.lightDir);
    51.                  float3 N = normalize(i.normal);    
    52.                  float attenuation = LIGHT_ATTENUATION(i) * 2;
    53.                  float4 ambient = UNITY_LIGHTMODEL_AMBIENT * 2;
    54.                  float NdotL = saturate(dot(N, L));
    55.                  float4 diffuseTerm = NdotL * _LightColor0 * _Color * attenuation;
    56.                  fixed4 tex = tex2D(_MainTex, i.uv);
    57.                  fixed4 c = ((ambient + diffuseTerm) * tex.rgba) * _Color;
    58.                  return c;
    59.         }
    60.         ENDCG    
    61. }
    62.  
    63.     // Pass to render object as a shadow caster
    64.     Pass {
    65.         Name "Caster"
    66.         Tags { "LightMode" = "ShadowCaster" }
    67.         Offset 1, 1
    68.         Fog {Mode Off}
    69.         ZWrite On ZTest LEqual Cull Off
    70. CGPROGRAM
    71. #pragma vertex vert
    72. #pragma fragment frag
    73. #pragma fragmentoption ARB_precision_hint_fastest
    74. #include "UnityCG.cginc"
    75. struct v2f {
    76.     V2F_SHADOW_CASTER;
    77.     float2  uv : TEXCOORD1;
    78. };
    79. uniform float4 _MainTex_ST;
    80. v2f vert( appdata_base v )
    81. {
    82.     v2f o;
    83.     TRANSFER_SHADOW_CASTER(o)
    84.     o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    85.     return o;
    86. }
    87. uniform sampler2D _MainTex;
    88. uniform fixed _Cutoff;
    89. uniform fixed4 _Color;
    90. float4 frag( v2f i ) : COLOR
    91. {
    92.     fixed4 texcol = tex2D( _MainTex, i.uv );
    93.     clip( texcol.a*_Color.a - _Cutoff );
    94.     SHADOW_CASTER_FRAGMENT(i)
    95. }
    96. ENDCG
    97.     }
    98.         // Pass to render object as a shadow collector
    99.     Pass {
    100.         Name "ShadowCollector"
    101.         Tags { "LightMode" = "ShadowCollector" }
    102.         Fog {Mode Off}
    103.         ZWrite On ZTest LEqual
    104. CGPROGRAM
    105. #pragma vertex vert
    106. #pragma fragment frag
    107. #pragma fragmentoption ARB_precision_hint_fastest
    108. #define SHADOW_COLLECTOR_PASS
    109. #include "UnityCG.cginc"
    110. struct v2f {
    111.     V2F_SHADOW_COLLECTOR;
    112.     float2  uv : TEXCOORD5;
    113. };
    114. uniform float4 _MainTex_ST;
    115. v2f vert (appdata_base v)
    116. {
    117.     v2f o;
    118.     TRANSFER_SHADOW_COLLECTOR(o)
    119.     o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    120.     return o;
    121. }
    122. uniform sampler2D _MainTex;
    123. uniform fixed _Cutoff;
    124. uniform fixed4 _Color;
    125. fixed4 frag (v2f i) : COLOR
    126. {
    127.     fixed4 texcol = tex2D( _MainTex, i.uv );
    128.     clip( texcol.a*_Color.a - _Cutoff );
    129.     SHADOW_COLLECTOR_FRAGMENT(i)
    130. }
    131. ENDCG
    132.     }
    133.  
    134. }
    135. }
     
  3. Vade-Mecum

    Vade-Mecum

    Joined:
    Dec 10, 2012
    Posts:
    17
    So, after some experiments i came up with this - surface shader that well lit, animated, casts and recieves shadow. HOWEVER.. the shadows is not animated with the leaves. I still don't know how to solve this. Should i modify the shadow caster(no need to tweak the shadow reciever, it works fine with the non-animated shadows saving some performance) or the main pass. Here's the code:
    Code (CSharp):
    1. Shader "Wind Trees2" {
    2. Properties {
    3.     _Color ("Main Color", Color) = (1,1,1,1)
    4.     _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
    5.     _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    6. }
    7.  
    8. SubShader {
    9.     Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
    10.     LOD 200
    11.     Cull Off
    12.    
    13. CGPROGRAM
    14. #pragma surface surf Lambert alphatest:_Cutoff vertex:vert
    15. #pragma addshadow
    16. sampler2D _MainTex;
    17. fixed4 _Color;
    18. float4 _GrassWind; //is not defined in terrainengine.cginc
    19.  
    20.  
    21. struct Input {
    22.     float2 uv_MainTex;
    23.     float4 pos : SV_POSITION;
    24. };
    25.  
    26. inline float4 AnimateGrass(float4 pos, float3 normal, float animParams)
    27. {
    28.     pos.xyz += animParams * _GrassWind.xyz * _GrassWind.w; // controlled by vertex color blue
    29.     return pos;
    30. }
    31.  
    32. void vert (inout appdata_full v, out Input o) {
    33.         UNITY_INITIALIZE_OUTPUT(Input,o);
    34.         float4    windParams    = float(v.color.b);
    35.         float4 mdlPos = AnimateGrass(v.vertex, v.normal, windParams);
    36.     //    o.pos = mul(UNITY_MATRIX_MVP,mdlPos);
    37.         v.vertex = mdlPos;
    38.     //    v.vertex.xyz += v.normal * v.vertex.xyz * _Cutoff ;
    39.           }
    40.  
    41. void surf (Input IN, inout SurfaceOutput o) {
    42.     fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    43.     o.Albedo = c.rgb;
    44.     o.Alpha = c.a;
    45. }
    46. ENDCG
    47.  
    48.  
    49.     }
    50.  
    51. Fallback "Transparent/Cutout/VertexLit"
    52. }
    53.  
    If you want some custom shadow caster/reciever you should add after the final ENDCG this:
    Code (CSharp):
    1.     // Pass to render object as a shadow caster
    2.     Pass {
    3.         Name "Caster"
    4.         Tags { "LightMode" = "ShadowCaster" }
    5.         Offset 1, 1
    6.         Fog {Mode Off}
    7.         ZWrite On ZTest LEqual Cull Off
    8. CGPROGRAM
    9. #pragma vertex vert
    10. #pragma fragment frag
    11. #pragma fragmentoption ARB_precision_hint_fastest
    12. #include "UnityCG.cginc"
    13. struct v2f {
    14.     V2F_SHADOW_CASTER;
    15.     float2  uv : TEXCOORD1;
    16. };
    17. uniform float4 _MainTex_ST;
    18. v2f vert( appdata_base v )
    19. {
    20.     v2f o;
    21.     TRANSFER_SHADOW_CASTER(o)
    22.     o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    23.     return o;
    24. }
    25. uniform sampler2D _MainTex;
    26. uniform fixed _Cutoff;
    27. uniform fixed4 _Color;
    28. float4 frag( v2f i ) : COLOR
    29. {
    30.     fixed4 texcol = tex2D( _MainTex, i.uv );
    31.     clip( texcol.a*_Color.a - _Cutoff );
    32.     SHADOW_CASTER_FRAGMENT(i)
    33. }
    34. ENDCG
    35.     }
    36.         // Pass to render object as a shadow collector
    37.     Pass {
    38.         Name "ShadowCollector"
    39.         Tags { "LightMode" = "ShadowCollector" }
    40.         Fog {Mode Off}
    41.         ZWrite On ZTest LEqual
    42. CGPROGRAM
    43. #pragma vertex vert
    44. #pragma fragment frag
    45. #pragma fragmentoption ARB_precision_hint_fastest
    46. #define SHADOW_COLLECTOR_PASS
    47. #include "UnityCG.cginc"
    48. struct v2f {
    49.     V2F_SHADOW_COLLECTOR;
    50.     float2  uv : TEXCOORD5;
    51. };
    52. uniform float4 _MainTex_ST;
    53. v2f vert (appdata_base v)
    54. {
    55.     v2f o;
    56.     TRANSFER_SHADOW_COLLECTOR(o)
    57.     o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    58.     return o;
    59. }
    60. uniform sampler2D _MainTex;
    61. uniform fixed _Cutoff;
    62. uniform fixed4 _Color;
    63. fixed4 frag (v2f i) : COLOR
    64. {
    65.     fixed4 texcol = tex2D( _MainTex, i.uv );
    66.     clip( texcol.a*_Color.a - _Cutoff );
    67.     SHADOW_COLLECTOR_FRAGMENT(i)
    68. }
    69. ENDCG
    70.     }
    and delete the Fallback line at the end.
    Still hope someone can help me find the solution.