Search Unity

  1. If you have experience with import & exporting custom (.unitypackage) packages, please help complete a survey (open until May 15, 2024).
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice

[Free] Grass shader

Discussion in 'Assets and Asset Store' started by aubergine, Jan 23, 2012.

  1. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,880
    Here is an old trick that extrudes mesh vertices in vertex fragment to simulate moving grass, i found it dying in my old codebase.


    How to use:
    Create a material with the below "Grass.shader" and put your terrain's splatmap as the mask texture.
    Make an empty game object in your scene at the same position as your Terrain and attach the "DrawPlane.cs" script to it with the above created material.

    If you dont want SM3.0, you can reduce the passes in the shader accordingly, or add some more if you are happy with it.

    EDIT: IT does consider your terrains base texture as the grass itself. So, you must arrange the textures accordingly.

    Grass.shader:
    Code (csharp):
    1. Shader "Custom/Grass" {
    2.     Properties {
    3.         _MainTex ("Base (RGB)", 2D) = "white" {}
    4.         _GrassMask ("Mask", 2D) = "white" {}
    5.     }
    6.     SubShader {
    7.         Tags { "RenderType"="Transparent" }
    8.         LOD 600
    9.        
    10.         CGINCLUDE
    11.             #include "UnityCG.cginc"
    12.             #pragma target 3.0
    13.            
    14.             struct v2f {
    15.                 float4 pos : SV_POSITION;
    16.                 half2 uv0 : TEXCOORD0;
    17.                 half2 uv1 : TEXCOORD1;
    18.             };
    19.            
    20.             uniform sampler2D _MainTex, _GrassMask;
    21.             float4 _MainTex_ST;
    22.  
    23.             half4 frag (v2f i) : COLOR {
    24.                 half4 col = tex2D(_MainTex, i.uv0);
    25.                 half4 mask = tex2D(_GrassMask, i.uv1);
    26.                 return float4(col.rgb, mask);
    27.             }
    28.         ENDCG
    29.        
    30.         Pass {
    31.             Blend SrcColor OneMinusSrcColor
    32.             AlphaTest Greater 0.9
    33.             CGPROGRAM
    34.                 #pragma vertex vert
    35.                 #pragma fragment frag
    36.                
    37.                 v2f vert(appdata_base v) {
    38.                     v2f o;
    39.                     float4 p = v.vertex;
    40.                     p.y += .01;
    41.                     p.x += sin(_Time.y + p.x * 0.1) * 0.01;
    42.                     p.z += cos(_Time.y + p.z * 0.1) * 0.01;
    43.                     o.pos = mul(UNITY_MATRIX_MVP, p);
    44.                     o.uv0 = TRANSFORM_TEX(v.texcoord, _MainTex);
    45.                     o.uv1 = v.texcoord;
    46.                     return o;
    47.                 }
    48.             ENDCG
    49.         }
    50.         Pass {
    51.             Blend SrcColor OneMinusSrcColor
    52.             //Blend SrcAlpha OneMinusSrcAlpha
    53.             AlphaTest Greater 0.9
    54.             CGPROGRAM
    55.                 #pragma vertex vert
    56.                 #pragma fragment frag
    57.                
    58.                 v2f vert(appdata_base v) {
    59.                     v2f o;
    60.                     float4 p = v.vertex;
    61.                     p.y += .02;
    62.                     p.x += sin(_Time.y + p.x * 0.1) * 0.02;
    63.                     p.z += cos(_Time.y + p.z * 0.1) * 0.02;
    64.                     o.pos = mul(UNITY_MATRIX_MVP, p);
    65.                     o.uv0 = TRANSFORM_TEX(v.texcoord, _MainTex);
    66.                     o.uv1 = v.texcoord;
    67.                     return o;
    68.                 }
    69.             ENDCG
    70.         }
    71.         Pass {
    72.             Blend SrcColor OneMinusSrcColor
    73.             //Blend SrcAlpha OneMinusSrcAlpha
    74.             AlphaTest Greater 0.9
    75.             CGPROGRAM
    76.                 #pragma vertex vert
    77.                 #pragma fragment frag
    78.                
    79.                 v2f vert(appdata_base v) {
    80.                     v2f o;
    81.                     float4 p = v.vertex;
    82.                     p.y += .03;
    83.                     p.x += sin(_Time.y + p.x * 0.1) * 0.03;
    84.                     p.z += cos(_Time.y + p.z * 0.1) * 0.03;
    85.                     o.pos = mul(UNITY_MATRIX_MVP, p);
    86.                     o.uv0 = TRANSFORM_TEX(v.texcoord, _MainTex);
    87.                     o.uv1 = v.texcoord;
    88.                     return o;
    89.                 }
    90.             ENDCG
    91.         }
    92.         Pass {
    93.             Blend SrcColor OneMinusSrcColor
    94.             //Blend SrcAlpha OneMinusSrcAlpha
    95.             AlphaTest Greater 0.9
    96.             CGPROGRAM
    97.                 #pragma vertex vert
    98.                 #pragma fragment frag
    99.                
    100.                 v2f vert(appdata_base v) {
    101.                     v2f o;
    102.                     float4 p = v.vertex;
    103.                     p.y += .04;
    104.                     p.x += sin(_Time.y + p.x * 0.1) * 0.04;
    105.                     p.z += cos(_Time.y + p.z * 0.1) * 0.04;
    106.                     o.pos = mul(UNITY_MATRIX_MVP, p);
    107.                     o.uv0 = TRANSFORM_TEX(v.texcoord, _MainTex);
    108.                     o.uv1 = v.texcoord;
    109.                     return o;
    110.                 }
    111.             ENDCG
    112.         }
    113.         Pass {
    114.             Blend SrcColor OneMinusSrcColor
    115.             //Blend SrcAlpha OneMinusSrcAlpha
    116.             AlphaTest Greater 0.9
    117.             CGPROGRAM
    118.                 #pragma vertex vert
    119.                 #pragma fragment frag
    120.                
    121.                 v2f vert(appdata_base v) {
    122.                     v2f o;
    123.                     float4 p = v.vertex;
    124.                     p.y += .05;
    125.                     p.x += sin(_Time.y + p.x * 0.1) * 0.05;
    126.                     p.z += cos(_Time.y + p.z * 0.1) * 0.05;
    127.                     o.pos = mul(UNITY_MATRIX_MVP, p);
    128.                     o.uv0 = TRANSFORM_TEX(v.texcoord, _MainTex);
    129.                     o.uv1 = v.texcoord;
    130.                     return o;
    131.                 }
    132.             ENDCG
    133.         }
    134.         Pass {
    135.             Blend SrcColor OneMinusSrcColor
    136.             //Blend SrcAlpha OneMinusSrcAlpha
    137.             AlphaTest Greater 0.9
    138.             CGPROGRAM
    139.                 #pragma vertex vert
    140.                 #pragma fragment frag
    141.                
    142.                 v2f vert(appdata_base v) {
    143.                     v2f o;
    144.                     float4 p = v.vertex;
    145.                     p.y += .06;
    146.                     p.x += sin(_Time.y + p.x * 0.1) * 0.06;
    147.                     p.z += cos(_Time.y + p.z * 0.1) * 0.06;
    148.                     o.pos = mul(UNITY_MATRIX_MVP, p);
    149.                     o.uv0 = TRANSFORM_TEX(v.texcoord, _MainTex);
    150.                     o.uv1 = v.texcoord;
    151.                     return o;
    152.                 }
    153.             ENDCG
    154.         }
    155.         Pass {
    156.             Blend SrcColor OneMinusSrcColor
    157.             //Blend SrcAlpha OneMinusSrcAlpha
    158.             AlphaTest Greater 0.9
    159.             CGPROGRAM
    160.                 #pragma vertex vert
    161.                 #pragma fragment frag
    162.                
    163.                 v2f vert(appdata_base v) {
    164.                     v2f o;
    165.                     float4 p = v.vertex;
    166.                     p.y += .07;
    167.                     p.x += sin(_Time.y + p.x * 0.1) * 0.07;
    168.                     p.z += cos(_Time.y + p.z * 0.1) * 0.07;
    169.                     o.pos = mul(UNITY_MATRIX_MVP, p);
    170.                     o.uv0 = TRANSFORM_TEX(v.texcoord, _MainTex);
    171.                     o.uv1 = v.texcoord;
    172.                     return o;
    173.                 }
    174.             ENDCG
    175.         }
    176.     }
    177. }
    DrawPlane.cs:
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class DrawPlane : MonoBehaviour {
    5.  
    6.     internal Mesh mesh;
    7.     public Material mat;
    8.    
    9.     void Start () {
    10.         gameObject.AddComponent("MeshFilter");
    11.         gameObject.AddComponent("MeshRenderer");
    12.         mesh = GetComponent<MeshFilter>().mesh;
    13.         mesh.Clear();
    14.        
    15.         TerrainData terData = Terrain.activeTerrain.terrainData;
    16.         int count = terData.heightmapResolution;
    17.        
    18.         Vector3[] vert = new Vector3[count*count];
    19.         Vector2[] uvs = new Vector2[count*count];
    20.         int[] tri = new int[(count-1)*(count-1)*6];
    21.  
    22.         for(int z=0; z<count; z++) {
    23.             for(int x=0; x<count; x++) {
    24.                 vert[z+x*count] = new Vector3(x*2f, 0, z*2f);
    25.                 vert[z+x*count].y = terData.GetHeight(x, z);
    26.                 uvs[z+x*count] = new Vector2((float)x/count, (float)z/count);
    27.             }
    28.         }
    29.  
    30.         for(int z=0; z<count-1; z++) {
    31.             for(int x=0; x<count-1; x++) {
    32.                 //if (z > 1  z < 10  x > 1  x < 10) continue;
    33.                 //if (Random.value > 0.5) continue;
    34.                 tri[(z+x*(count-1))*6] = (x+1) + (z+1) * count;
    35.                 tri[(z+x*(count-1))*6+1] = x + z * count;
    36.                 tri[(z+x*(count-1))*6+2] = (x+1) + z * count;
    37.                
    38.                 tri[(z+x*(count-1))*6+3] = (x+1) + (z+1) * count;
    39.                 tri[(z+x*(count-1))*6+4] = x + (z+1) * count;
    40.                 tri[(z+x*(count-1))*6+5] = x + z * count;
    41.             }
    42.         }
    43.  
    44.         mesh.vertices = vert;
    45.         mesh.uv = uvs;
    46.         mesh.triangles = tri;
    47.  
    48.         //mesh.Optimize();
    49.         mesh.RecalculateBounds();
    50.        
    51.         renderer.material = mat;
    52.     }
    53. }
     

    Attached Files:

    Last edited: Jan 27, 2012
  2. ResidentPm

    ResidentPm

    Joined:
    Jul 19, 2010
    Posts:
    25
    Can you make a demo package?
    I did not get to run :(
     
    Last edited: Jan 26, 2012
  3. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,880
    Added sample package to first post.
     
  4. Xellinus

    Xellinus

    Joined:
    Jan 28, 2012
    Posts:
    44
    I've not looked at it but couldn't this also work for "hair" on animals? looks kinda like that in the pic.
     
  5. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,880
    Sure it would work, but you would have to change the shaders animation to work with its uv rather than the vertices for spherical shapes or anything with large curves. Also you must extrude the vertices according to vertex normals rather than vertex.y
    Thats how fur shaders work.
     
  6. Renofox

    Renofox

    Joined:
    Jan 14, 2015
    Posts:
    10
    I'd love to use this for a fur shader, but the shader gives the error "incorrect number of arguments to numeric-type constructor".
     
  7. Duende

    Duende

    Joined:
    Oct 11, 2014
    Posts:
    200
    The error is in line 26:

    Code (CSharp):
    1.                 return float4(col.rgb, mask);
     
    undyingwill likes this.