1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
| Shader "Grass/Grass_GeometryShader" { Properties { _Height("Grass Height", range(0, 10)) = 3 _Width("Grass Width", range(0, 5)) = 0.1 _Color("Color",Color) = (0,1,0,1) _NormalSmooth("Normal Smooth", range(0, 1)) = 0.5 } SubShader { Cull off Tags { "Queue" = "AlphaTest" "RenderType" = "TransparentCutout" "IgnoreProjector" = "True" }
Pass { Cull OFF Tags { "LightMode" = "ForwardBase" } AlphaToMask On
CGPROGRAM #include "UnityCG.cginc" #pragma vertex vert #pragma fragment frag #pragma geometry geom #include "UnityLightingCommon.cginc"
#pragma target 4.0
struct v2g { float4 pos : SV_POSITION; half3 norm : NORMAL; half2 uv : TEXCOORD0; };
struct g2f { float4 pos : SV_POSITION; half3 norm : NORMAL; half2 uv : TEXCOORD0; };
v2g vert(appdata_full v) { v2g o; o.pos = v.vertex; o.norm = v.normal; o.uv = v.texcoord; return o; }
float _Height; float _Width; half4 _Color; half _NormalSmooth;
float rand(float2 uv) { return frac(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453); }
float remap(float x, float oldMin, float oldMax, float newMin, float newMax) { return lerp(newMin, newMax, x / (oldMax - oldMin)); }
float remap01(float x, float min, float max) { return lerp(min, max, x); } [maxvertexcount(30)] void geom(point v2g points[1], inout TriangleStream<g2f> triStream) { const float4 root = points[0].pos; const int vertexCount = 12;
half random = rand(root.xz);
float angle = random * UNITY_PI * 2; float faceNormalAngle = angle + UNITY_PI / 2;
half2 direction = half2(cos(angle), sin(angle)); half3 faceNormal = half3(cos(faceNormalAngle), 0, sin(faceNormalAngle)); faceNormal = normalize(lerp(faceNormal, half3(0, 1, 0), _NormalSmooth));
g2f v[vertexCount]; UNITY_UNROLL for (int i = 0; i < vertexCount; i++) { const uint h = (uint)i / 2;
const float length = (1 - h / ((vertexCount - 2) / 2.0)) * _Width / 2; half2 dir = (fmod(i, 2) == 0) ? direction : -direction; dir *= length;
const float3 pos = root + float3(dir.x, h * _Height, dir.y) * remap01(random, 0.3, 1.2);
g2f gPoint; gPoint.pos = UnityObjectToClipPos(pos); gPoint.norm = faceNormal; gPoint.uv = half2(i, 0); v[i] = gPoint; }
UNITY_UNROLL for (int p = 0; p < (vertexCount - 2); p++) { triStream.Append(v[p]); triStream.Append(v[p + 2]); triStream.Append(v[p + 1]); } }
half4 frag(g2f IN,fixed facing : VFACE) : COLOR { half3 worldNormal = UnityObjectToWorldNormal(IN.norm); fixed3 light; fixed3 ambient = ShadeSH9(half4(worldNormal, 1)); fixed3 diffuseLight = saturate(dot(worldNormal, UnityWorldSpaceLightDir(IN.pos))) * _LightColor0; fixed3 halfVector = normalize(UnityWorldSpaceLightDir(IN.pos) + WorldSpaceViewDir(IN.pos)); fixed3 specularLight = pow(saturate(dot(worldNormal, halfVector)), 15) * _LightColor0;
light = ambient + diffuseLight + specularLight; return half4(light, 1) * _Color; } ENDCG } } }
|