Search Unity

How to convert grass shader into URP?

Discussion in 'Universal Render Pipeline' started by thieum, Aug 27, 2020.

  1. thieum

    thieum

    Joined:
    Apr 8, 2011
    Posts:
    61
    GrassShader.jpg
    Hi there,

    I'm trying to port a custom CG shader into URP.
    The current shader generates billboards from a mesh at runtime and uses two UV sets: the generated quad UVs to display a cut-out texture + the mesh UVs for scattering and additional shading. Extra functions in the cginc are not really essential (waving).

    From what I learned so far, this shader should not work with SRP, but we can observe in the screenshot that billboards are correctly drawn by the current Vertex function. When the shader is faulty, no quad is drawn at all. It gives me hope since we just have to render a cut-out map in the quads...

    It could work with Unlit shader variant as the lighting can be faked here (but I'd like it to receive shadows,such as with the old atten variable).

    I went through @phil_lira examples on Github, but I don't know where to start to comply with urp semantics.

    Code (CSharp):
    1. Shader "Nature/ParticleGrassCOL" {
    2.  
    3. Properties {
    4.     _BaseColor ("Main Color", Color) = (1, 1, 1, 0)
    5.     _BaseMap ("Base (RGB) Alpha (A)", 2D) = "white" {}
    6.     _DetailTex ("DetailTex", 2D) = "white" {}
    7.     _waveStrength ("Wind Strength", Range (0,50)) = 30
    8.     _waveSpeed ("Wind speed", Range (0,30)) = 30
    9.     _fadeDistance ("_fadeDistance", float) = 250
    10.     _fadeLength ("_fadeLength", float) = 50  
    11.     _sunTrick ("_sun", float) = 0                            
    12.     _Cutoff ("Cutoff", float) = 0.2
    13. }
    14.  
    15. SubShader {
    16.         Tags { "Queue" = "Geometry" "RenderType" = "Geometry" "RenderPipeline" = "UniversalPipeline" }
    17.         LOD 200
    18.  
    19.         CGPROGRAM
    20.         #pragma surface surf SimpleLambert vertex:vert
    21.         #include "ParticleGrass.cginc"
    22.  
    23.         half4 LightingSimpleLambert (SurfaceOutput s, half3 lightDir, half atten) {
    24.             lightDir = normalize(lightDir);
    25.             half NdotL = saturate(dot(abs(lightDir), s.Normal)); // fully exposed at zenith
    26.             half diff = exp(NdotL);
    27.             half4 c;
    28.             if (_WorldSpaceLightPos0.w == 0)
    29.                 c.rgb = saturate(s.Albedo * _LightColor0 * min(atten, 0.66));
    30.             else
    31.                 c.rgb = saturate(s.Albedo * diff * _LightColor0 * min(atten, 0.5));
    32.             c.a = s.Alpha;
    33.             return c;
    34.         }
    35.      
    36.         struct Input {
    37.             float2 uv_BaseMap;
    38.             float2 uv2_DetailTex;
    39.             fixed4 color : COLOR;
    40.         };
    41.      
    42.         sampler2D _BaseMap;
    43.         sampler2D _DetailTex;
    44.         fixed _Cutoff;
    45.         half _sunTrick;
    46.  
    47.         v2f vert (inout appdata_full v) {
    48.             v2f o;
    49.             UNITY_INITIALIZE_OUTPUT(v2f,o);  
    50.             UNITY_SETUP_INSTANCE_ID(v);
    51.             UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);                        
    52.          
    53.             o.color = v.color;
    54.             float4 vertex = v.vertex;
    55.             float2 xyOffset = v.color.rg;
    56.             float distance = length(UnityObjectToClipPos(vertex).xyz);
    57.             // Fade out amount when beyond fade distance
    58.             // When faded out make them zero size to save on fillrate
    59.             float fadeAmount =  saturate((1 / _fadeDistance) * distance) ;
    60.          
    61.             if ( distance < (_fadeDistance - _fadeLength) )
    62.                 fadeAmount = 1;
    63.  
    64.             else if (distance < _fadeDistance)
    65.             {
    66.                 float nearDistance = _fadeDistance - _fadeLength;
    67.                 fadeAmount = 1-saturate((1/nearDistance) * (distance - nearDistance));
    68.             }
    69.             else
    70.             {
    71.                 xyOffset = float2(0, 0);
    72.             }
    73.             // Apply billboard extrusion
    74.             v.vertex.xyz += (xyOffset.x-0.5) * -_CameraRight.xyz;
    75.             v.vertex.xyz += xyOffset.y * _CameraUp.xyz;
    76.             float4 pos = UnityObjectToClipPos (vertex);
    77.             o.pos = pos;
    78.             o.uv[0] = v.texcoord;
    79.             o.uv[1] = v.texcoord1;
    80.             v.color.a = fadeAmount;
    81.             return o;
    82.         }
    83.  
    84.         void surf (Input IN, inout SurfaceOutput o) {
    85.             fixed4 c = tex2D(_BaseMap, IN.uv_BaseMap);
    86.             fixed4 main = tex2D(_BaseMap, IN.uv_BaseMap);
    87.             fixed4 detail = tex2D(_DetailTex, IN.uv2_DetailTex);  
    88.             c *= IN.color;
    89.             main.rgb *= detail.rgb;
    90.             o.Albedo =  main.rgb *(0.4 +(0.6*saturate(_sunTrick))) ;
    91.             o.Alpha = main.a ;
    92.             clip (o.Alpha - (_Cutoff*IN.color.a));
    93.         }
    94.         ENDCG
    95.     }
    96.     Fallback "UniversalRenderPipeline/Unlit"
    97. }