Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Shader "Custom/GrassShader"
- {
- Properties
- {
- size("Width", Float) = 0.1
- [Header(Height)]
- amplitude (" Amplitude", Range(0, 1)) = 0.25
- height(" Height", Float) = 1
- [Header(Frequency)]
- chance(" Spawn chance", Range(0, 1)) = 0.75
- subdivisions(" Subdivisions", Int) = 1
- [Header(Wind)]
- flexibility(" Flexibitity", Range(0, 1)) = 0.5
- wind (" Wind direction", Vector) = (0, 0, 0)
- col ("Color", Color) = (1, 1, 1, 1)
- }
- SubShader
- {
- Tags { "LightMode" = "ForwardBase" }
- LOD 100
- Pass
- {
- CGPROGRAM
- #pragma target 4.6
- #pragma vertex vert
- #pragma geometry geom
- #pragma fragment frag
- #pragma hull hull
- #pragma domain domain
- #define LEVELS 4
- #define E 2.71828182845904523536
- #include "UnityCG.cginc"
- #include "UnityLightingCommon.cginc"
- #include "Subsurf.cginc"
- struct appdata
- {
- float4 vertex : POSITION;
- float2 uv : TEXCOORD0;
- float3 normal : NORMAL;
- };
- struct g2f
- {
- float2 uv : TEXCOORD0;
- float4 vertex : SV_POSITION;
- float4 light : COLOR0;
- };
- v2h vert(appdata v)
- {
- v2h o;
- o.vertex = v.vertex;
- o.uv = v.uv;
- o.normal = v.normal;
- return o;
- }
- float fract(float n) {
- return n - floor(n);
- }
- g2f toG2F(v2h inp, float3 pos, float4 diffuse) {
- g2f o;
- o.uv = inp.uv;
- o.vertex = UnityObjectToClipPos(pos);
- o.light = diffuse;
- return o;
- }
- float size;
- float height;
- float3 wind;
- float chance;
- float flexibility;
- float amplitude;
- float4 col;
- float4 diffuse(float3 a, float3 b, float3 c) {
- float3 normal = UnityObjectToWorldNormal(normalize(cross(b - a, c - a)));
- float4 o = max(0, dot(normal, _WorldSpaceLightPos0.xyz)) * _LightColor0;
- return o;
- }
- float th(float x) {
- float a = pow(E, 2 * x);
- return (a - 1) / (a + 1);
- }
- float rand(float2 co) {
- return abs(fract(sin(dot(co.xy, float2(12.9898, 78.233))) * 43758.5453));
- }
- float rand2(float rnd) {
- return fract(sin(rnd)*100000.0);
- }
- [maxvertexcount(18*LEVELS)]
- void geom(point v2h inp[1], inout TriangleStream<g2f> tristream) {
- float rnd = rand(inp[0].vertex.xz);
- if(rnd > chance)
- return;
- rnd /= chance;
- float3 vec = inp[0].normal;
- //Ambient calculation. Always returns the same value!
- float3 ambient = ShadeSH9(float4(UnityObjectToWorldNormal(vec), 1));
- height = (height+height*(rnd-0.5)*2*amplitude) / (LEVELS - 1);
- float3 base = inp[0].vertex;
- float3 root[3] = {
- float3(0, 0, 0),
- float3(0, 0, 0),
- float3(0, 0, 0)
- };
- float2 troff[3] = { float2(0, 0), float2(0, 0), float2(0,0) };
- {
- float sqr = sqrt(0.75);
- troff[0] = float2(1, 0);
- troff[1] = normalize(float2(-0.5, -sqr));
- troff[2] = normalize(float2(-0.5, sqr));
- }
- {
- rnd = rand2(rnd);
- float alpha = rnd*UNITY_PI*2;
- float sina = sin(alpha);
- float cosa = cos(alpha);
- float3x3 rotation = {
- cosa, -sina, 0,
- sina, cosa, 0,
- 0, 0, 1
- };
- for (int i = 0; i < 3; i++)
- troff[i] = mul(troff[i], rotation);
- rnd = rand2(rnd);
- wind = normalize(lerp(vec, wind + mul(float3(rnd, 0, 0), rotation), flexibility));
- }
- for (int i = 0; i < LEVELS; i++) {
- float prog = (i+.5)/LEVELS;
- float TH = th((prog - 0.5)*2.5) / 2;
- float3 dir = lerp(vec, wind, prog);
- float3 nbase = 0;
- float3 tr[3] = {
- float3(0, 0, 0),
- float3(0, 0, 0),
- float3(0, 0, 0)
- };
- bool last = i + 1 == LEVELS;
- if (last)
- for(int j = 0; j < 3; j++)
- tr[j] = base;
- else {
- for (int j = 0; j < 3; j++) {
- float3 vert = float3(
- troff[j].x,
- -((dir.x*troff[j].x + dir.z*troff[j].y) / dir.y),
- troff[j].y
- )* size * (0.5-TH) + base;
- nbase += vert;
- tr[j] = vert;
- }
- }
- if (i > 0) {
- for (uint j = 0; j < 3; j++) {
- int id = (j + 1) % 3;
- float4 diff = diffuse(tr[j], root[j], root[id]);
- diff.rgb = ambient; // += ambient
- tristream.Append(toG2F(inp[0], tr[j], diff));
- tristream.Append(toG2F(inp[0], root[j], diff));
- tristream.Append(toG2F(inp[0], root[id], diff));
- tristream.RestartStrip();
- id = (j + 2) % 3;
- diff = diffuse(tr[j], tr[id], root[j]);
- diff.rgb = ambient; // += ambient
- tristream.Append(toG2F(inp[0], tr[j], diff));
- tristream.Append(toG2F(inp[0], tr[id], diff));
- tristream.Append(toG2F(inp[0], root[j], diff));
- tristream.RestartStrip();
- }
- }
- root = tr;
- base = nbase / 3 + dir * height * (pow(prog * 2 - 1, 2) * 0.5 + 0.5);
- }
- }
- fixed4 frag (g2f i) : SV_Target
- {
- return i.light;// *col;
- }
- ENDCG
- }
- }
- }
Add Comment
Please, Sign In to add comment