Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
- Shader "Roystan/Grass"
- {
- Properties
- {
- [Header(Shading)]
- _TopColor("Top Color", Color) = (1,1,1,1)
- _BottomColor("Bottom Color", Color) = (1,1,1,1)
- _ColorMap("Color Map", 2D) = "white" {}
- _TranslucentGain("Translucent Gain", Range(0,1)) = 0.5
- [Space]
- _TessellationUniform ("Tessellation Uniform", Range(1, 64)) = 1
- [Header(Blades)]
- _BladeWidth("Blade Width", Float) = 0.05
- _BladeWidthRandom("Blade Width Random", Float) = 0.02
- _BladeHeight("Blade Height", Float) = 0.5
- _BladeHeightRandom("Blade Height Random", Float) = 0.3
- _BladeForward("Blade Forward Amount", Float) = 0.38
- _BladeCurve("Blade Curvature Amount", Range(1, 4)) = 2
- _BendRotationRandom("Bend Rotation Random", Range(0, 1)) = 0.2
- [Header(Wind)]
- _WindDistortionMap("Wind Distortion Map", 2D) = "white" {}
- _WindStrength("Wind Strength", Float) = 1
- _WindFrequency("Wind Frequency", Vector) = (0.05, 0.05, 0, 0)
- }
- CGINCLUDE
- #include "UnityCG.cginc"
- #include "Autolight.cginc"
- #include "CustomTessellation.cginc"
- struct geometryOutput
- {
- float4 pos : SV_POSITION;
- #if UNITY_PASS_FORWARDBASE
- float3 normal : NORMAL;
- float2 uv : TEXCOORD0;
- // unityShadowCoord4 is defined as a float4 in UnityShadowLibrary.cginc.
- unityShadowCoord4 _ShadowCoord : TEXCOORD1;
- #endif
- };
- struct secondGeometryOutput {
- float4 wPos : POSITION2;
- };
- // Simple noise function, sourced from http://answers.unity.com/answers/624136/view.html
- // Extended discussion on this function can be found at the following link:
- // https://forum.unity.com/threads/am-i-over-complicating-this-random-function.454887/#post-2949326
- // Returns a number in the 0...1 range.
- float rand(float3 co)
- {
- return frac(sin(dot(co.xyz, float3(12.9898, 78.233, 53.539))) * 43758.5453);
- }
- // Construct a rotation matrix that rotates around the provided axis, sourced from:
- // https://gist.github.com/keijiro/ee439d5e7388f3aafc5296005c8c3f33
- float3x3 AngleAxis3x3(float angle, float3 axis)
- {
- float c, s;
- sincos(angle, s, c);
- float t = 1 - c;
- float x = axis.x;
- float y = axis.y;
- float z = axis.z;
- return float3x3(
- t * x * x + c, t * x * y - s * z, t * x * z + s * y,
- t * x * y + s * z, t * y * y + c, t * y * z - s * x,
- t * x * z - s * y, t * y * z + s * x, t * z * z + c
- );
- }
- geometryOutput VertexOutput(float3 pos, float3 normal, float2 uv)
- {
- geometryOutput o;
- o.pos = UnityObjectToClipPos(pos);
- #if UNITY_PASS_FORWARDBASE
- o.normal = UnityObjectToWorldNormal(normal);
- o.uv = uv;
- // Shadows are sampled from a screen-space shadow map texture.
- o._ShadowCoord = ComputeScreenPos(o.pos);
- #elif UNITY_PASS_SHADOWCASTER
- // Applying the bias prevents artifacts from appearing on the surface.
- o.pos = UnityApplyLinearShadowBias(o.pos);
- #endif
- return o;
- }
- geometryOutput GenerateGrassVertex(float3 vertexPosition, float width, float height, float forward, float2 uv, float3x3 transformMatrix)
- {
- float3 tangentPoint = float3(width, forward, height);
- float3 tangentNormal = normalize(float3(0, -1, forward));
- float3 localPosition = vertexPosition + mul(transformMatrix, tangentPoint);
- float3 localNormal = mul(transformMatrix, tangentNormal);
- return VertexOutput(localPosition, localNormal, uv);
- }
- secondGeometryOutput GetVertexPositionInFrag(float3 vertexPosition) {
- secondGeometryOutput o;
- o.wPos = float4(vertexPosition, 0);
- return o;
- }
- float _BladeHeight;
- float _BladeHeightRandom;
- float _BladeWidthRandom;
- float _BladeWidth;
- float _BladeForward;
- float _BladeCurve;
- float _BendRotationRandom;
- sampler2D _WindDistortionMap;
- float4 _WindDistortionMap_ST;
- float _WindStrength;
- float2 _WindFrequency;
- #define BLADE_SEGMENTS 3
- // Geometry program that takes in a single vertex and outputs a blade
- // of grass at that vertex's position, aligned to the vertex's normal.
- [maxvertexcount(BLADE_SEGMENTS * 2 + 1)]
- void geo(point vertexOutput IN[1], inout TriangleStream<geometryOutput> triStream)
- {
- float3 pos = IN[0].vertex.xyz;
- // Each blade of grass is constructed in tangent space with respect
- // to the emitting vertex's normal and tangent vectors, where the width
- // lies along the X axis and the height along Z.
- // Construct random rotations to point the blade in a direction.
- float3x3 facingRotationMatrix = AngleAxis3x3(rand(pos) * UNITY_TWO_PI, float3(0, 0, 1));
- // Matrix to bend the blade in the direction it's facing.
- float3x3 bendRotationMatrix = AngleAxis3x3(rand(pos.zzx) * _BendRotationRandom * UNITY_PI * 0.5, float3(-1, 0, 0));
- // Sample the wind distortion map, and construct a normalized vector of its direction.
- float2 uv = pos.xz * _WindDistortionMap_ST.xy + _WindDistortionMap_ST.zw + _WindFrequency * _Time.y;
- float2 windSample = (tex2Dlod(_WindDistortionMap, float4(uv, 0, 0)).xy * 2 - 1) * _WindStrength;
- float3 wind = normalize(float3(windSample.x, windSample.y, 0));
- float3x3 windRotation = AngleAxis3x3(UNITY_PI * windSample, wind);
- // Construct a matrix to transform our blade from tangent space
- // to local space; this is the same process used when sampling normal maps.
- float3 vNormal = IN[0].normal;
- float4 vTangent = IN[0].tangent;
- float3 vBinormal = cross(vNormal, vTangent) * vTangent.w;
- float3x3 tangentToLocal = float3x3(
- vTangent.x, vBinormal.x, vNormal.x,
- vTangent.y, vBinormal.y, vNormal.y,
- vTangent.z, vBinormal.z, vNormal.z
- );
- // Construct full tangent to local matrix, including our rotations.
- // Construct a second matrix with only the facing rotation; this will be used
- // for the root of the blade, to ensure it always faces the correct direction.
- float3x3 transformationMatrix = mul(mul(mul(tangentToLocal, windRotation), facingRotationMatrix), bendRotationMatrix);
- float3x3 transformationMatrixFacing = mul(tangentToLocal, facingRotationMatrix);
- float height = (rand(pos.zyx) * 2 - 1) * _BladeHeightRandom + _BladeHeight;
- float width = (rand(pos.xzy) * 2 - 1) * _BladeWidthRandom + _BladeWidth;
- float forward = rand(pos.yyz) * _BladeForward;
- for (int i = 0; i < BLADE_SEGMENTS; i++)
- {
- float t = i / (float)BLADE_SEGMENTS;
- float segmentHeight = height * t;
- float segmentWidth = width * (1 - t);
- float segmentForward = pow(t, _BladeCurve) * forward;
- // Select the facing-only transformation matrix for the root of the blade.
- float3x3 transformMatrix = i == 0 ? transformationMatrixFacing : transformationMatrix;
- triStream.Append(GenerateGrassVertex(pos, segmentWidth, segmentHeight, segmentForward, float2(0, t), transformMatrix));
- triStream.Append(GenerateGrassVertex(pos, -segmentWidth, segmentHeight, segmentForward, float2(1, t), transformMatrix));
- GetVertexPositionInFrag(IN[0].vertex.xyz);
- }
- // Add the final vertex as the tip.
- triStream.Append(GenerateGrassVertex(pos, 0, height, forward, float2(0.5, 1), transformationMatrix));
- }
- ENDCG
- SubShader
- {
- Cull Off
- Pass
- {
- Tags
- {
- "RenderType" = "Opaque"
- "LightMode" = "ForwardBase"
- }
- CGPROGRAM
- #pragma vertex vert
- #pragma geometry geo
- #pragma fragment frag
- #pragma hull hull
- #pragma domain domain
- #pragma target 4.6
- #pragma multi_compile_fwdbase
- #include "Lighting.cginc"
- float4 _TopColor;
- float4 _BottomColor;
- float _TranslucentGain;
- sampler2D _ColorMap;
- uniform float4 _ColorMap_ST;
- float4 frag (geometryOutput i, secondGeometryOutput o, fixed facing : VFACE) : SV_Target
- {
- float3 normal = facing > 0 ? i.normal : -i.normal;
- float shadow = SHADOW_ATTENUATION(i);
- float NdotL = saturate(saturate(dot(normal, _WorldSpaceLightPos0)) + _TranslucentGain) * shadow;
- float3 ambient = ShadeSH9(float4(normal, 1));
- float4 lightIntensity = NdotL * _LightColor0 + float4(ambient, 1);
- float3 verPos = mul (unity_ObjectToWorld, o.wPos).xyz;
- //float4 col = lerp(_BottomColor, _TopColor * lightIntensity, i.uv.y) * tex2D(_ColorMap, verPos.xz/_ColorMap_ST.xy);
- float4 col = lerp(_BottomColor, _TopColor * lightIntensity, i.uv.y) * tex2D(_ColorMap, float2(fmod(verPos.x * _ColorMap_ST.x, 1), fmod(verPos.z * _ColorMap_ST.y, 1)));
- return col;
- }
- ENDCG
- }
- Pass
- {
- Tags
- {
- "LightMode" = "ShadowCaster"
- }
- CGPROGRAM
- #pragma vertex vert
- #pragma geometry geo
- #pragma fragment frag
- #pragma hull hull
- #pragma domain domain
- #pragma target 4.6
- #pragma multi_compile_shadowcaster
- float4 frag(geometryOutput i) : SV_Target
- {
- SHADOW_CASTER_FRAGMENT(i)
- }
- ENDCG
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement