Untitled
unknown
csharp
4 years ago
11 kB
14
Indexable
Shader "/Grass"
{
Properties
{
[Header(Shading)]
_TopColor("Top Color", Color) = (1,1,1,1)
_BottomColor("Bottom Color", Color) = (1,1,1,1)
_DepositColor("Deposit Color", Color) = (1,1,1,1)
_DepositTex("Deposit Texture", 2D) = "defaulttexture" {}
_GrassMask("Grass Mask Texture", 2D) = "defaulttexture" {}
_GrassBladeTex("Grass Blade Texture", 2D) = "defaulttexture" {}
_CutOff("Cut off", float) = 0.1
_ColorVariationRandom("Color Variation Random", Range(0,128)) = 5
_TranslucentGain("Translucent Gain", Range(0,1)) = 0.5
_BendRotationRandom("Bend Rotation Random", Range(0, 1)) = 0.2
_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
_TessellationUniform("Tessellation Uniform", Range(1, 64)) = 1
_WindDistortionMap("Wind Distortion Map", 2D) = "white" {}
_RotationSpeed ("Rotation Speed", Float) = 2.0
_WindFrequency("Wind Frequency", Vector) = (0.05, 0.05, 0, 0)
_WindStrength("Wind Strength", Float) = 1
_BladeForward("Blade Forward Amount", Float) = 0.38
_BladeCurve("Blade Curvature Amount", Range(1, 4)) = 2
_maxDist("Max Distance", Float) = 100
_UseTextureColors("Use Texture Colors", Range(0, 1)) = 0
[Header(Bending)]
_YOffset("Y offset", float) = 0.0// y offset, below this is no animation
_MaxWidth("Max Displacement Width", Range(0, 2)) = 0.1 // width of the line around the dissolve
_Radius("Radius", Range(0,5)) = 1 // width of the line around the dissolve
_CutRadius("Cut Radius", Range(0,5)) = 1 // width of the line around the dissolve (for cutting)
_Positions("Positions", Vector) = (0,0,0,0)
_PositionArray("PositionArray", Float) = 0
_CutPositions("Cut Positions", Vector) = (0,0,0,0)
_CutPositionArray("Cut PositionArray", Float) = 0
}
CGINCLUDE
#include "UnityCG.cginc"
#include "Autolight.cginc"
#include "./CustomTessellation.cginc"
#define BLADE_SEGMENTS 2
float _BendRotationRandom;
float _BladeHeight;
float _BladeHeightRandom;
float _BladeWidth;
float _BladeWidthRandom;
float _BladeForward;
float _BladeCurve;
uniform float3 _Positions[100];
uniform float _PositionArray;
uniform float3 _CutPositions[100];
uniform float _CutPositionArray;
sampler2D _WindDistortionMap;
float4 _WindDistortionMap_ST;
float2 _WindFrequency;
float _WindStrength;
float _RotationSpeed;
float _UseTextureColors;
//limits
float _SlopeLimit;
float _BeachLimit;
float _HeightLimit;
float _maxDist;
sampler2D _DepositTex;
//sampler2D _GrassMask;
float4 _GrassMask_ST;
float4 _DepositTex_ST;
sampler2D _GrassBladeTex;
uniform float _CutOff;
//bending
float _Radius;
float _MaxWidth;
float _YOffset;
//cutting
float _CutRadius;
struct geometryOutput
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
float deposit : DEPOSIT;
unityShadowCoord4 _ShadowCoord : TEXCOORD1;
};
geometryOutput VertexOutput(float3 pos, float2 uv, float3 normal, float deposit)
{
geometryOutput o;
o.pos = UnityObjectToClipPos(pos);
o.uv = uv;
o._ShadowCoord = ComputeScreenPos(o.pos);
o.normal = UnityObjectToWorldNormal(normal);
o.deposit = deposit;
#if UNITY_PASS_SHADOWCASTER
// Applying the bias prevents artifacts from appearing on the surface. i.e. self-shadowing
o.pos = UnityApplyLinearShadowBias(o.pos);
#endif
return o;
}
// 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 GenerateGrassVertex(float3 vertexPosition, float width, float height, float forward, float2 uv, float3x3 transformMatrix, float depositSample)
{
float3 tangentPoint = float3(width, forward, height);
float3 tangentNormal = normalize(float3(0, -1, forward));
float3 localNormal = mul(transformMatrix, tangentNormal);
float3 localPosition = vertexPosition + mul(transformMatrix, tangentPoint);
return VertexOutput(localPosition, uv, localNormal, depositSample);
}
[maxvertexcount(BLADE_SEGMENTS * 2 + 1)]
void geo(triangle vertexOutput IN[3], inout TriangleStream<geometryOutput> triStream)
{
float3 pos = IN[0].vertex;
float3 wpos = mul(unity_ObjectToWorld, pos).xyz;// world position
float _size = 1000;
//float3 worldPos = mul(unity_ObjectToWorld, IN[0].vertex.xyz);
float3 worldNormal = mul( unity_ObjectToWorld, float4( IN[0].normal, 0.0 ) ).xyz;
float slope = worldNormal.y;
float dist = distance(_WorldSpaceCameraPos, mul(unity_ObjectToWorld, IN[0].vertex).xyz);
float grassMask = tex2Dlod(_GrassMask, float4(pos.xz / _GrassMask_ST.xy+_GrassMask_ST.zw,0,0));
int shouldCreateGrass = sign(slope-0.9) + sign(180-dist) + sign(1 - grassMask);
if(shouldCreateGrass==3){
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
);
float3x3 facingRotationMatrix = AngleAxis3x3(rand(pos) * UNITY_TWO_PI, float3(0, 0, 1));
float3x3 bendRotationMatrix = AngleAxis3x3(rand(pos.zzx) * _BendRotationRandom * UNITY_PI * 0.5, float3(-1, 0, 0));
float depositSample = tex2Dlod(_DepositTex, float4(pos.xz / _DepositTex_ST.xy+_DepositTex_ST.zw,0,0));
float height = (rand(pos.zyx) * 2 - 1) * _BladeHeightRandom - (depositSample*3) + _BladeHeight;
height = height > 0 ? height : 0.2f; // hack to keep the height from going negative
float width = (rand(pos.xzy) * 2 - 1) * _BladeWidthRandom + _BladeWidth;
float forward = rand(pos.yyz) * _BladeForward;
//bend grass radially away from xyz coords
float windStrength = _WindStrength;
for (int x = 0; x < _PositionArray; x++){
float3 dis = distance(_Positions[x], wpos); // distance for radius
float3 radius = 1 - saturate(dis /_Radius); // in world radius based on objects interaction radius
float3 sphereDisp = wpos - _Positions[x]; // position comparison
sphereDisp *= radius; // position multiplied by radius for falloff
float2 bendArea = abs(clamp(sphereDisp.xz * step(_YOffset, pos.y), -_MaxWidth,_MaxWidth));
pos.xz += bendArea*2;// vertex movement based on falloff
height -= bendArea*5;
forward += bendArea*10;
}
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);
float3x3 transformationMatrix = mul(mul(mul(tangentToLocal, windRotation), facingRotationMatrix), bendRotationMatrix);
float3x3 transformationMatrixFacing = mul(tangentToLocal, facingRotationMatrix);
//pos = 1;
for (int i = 0; i < BLADE_SEGMENTS; i++)
{
float t = i / (float)BLADE_SEGMENTS;
float segmentHeight = height * t;
float segmentWidth = i == 0 ? width/4 : width * (1 - t); //slimmer bottom segments
float segmentForward = pow(t, _BladeCurve) * forward;
float3x3 transformMatrix = i == 0 ? transformationMatrixFacing : transformationMatrix;
triStream.Append(GenerateGrassVertex(pos, segmentWidth, segmentHeight, segmentForward, float2(0, t), transformMatrix, depositSample));
triStream.Append(GenerateGrassVertex(pos, -segmentWidth, segmentHeight, segmentForward, float2(1, t), transformMatrix, depositSample));
}
//for cutting
bool inArea = false;
for (int j = 0; j < _CutPositionArray; j++){
float3 dis = distance(_CutPositions[j], wpos); // distance for radius
float3 radius = 1 - saturate(dis /_CutRadius); // in world radius based on objects interaction radius
float3 sphereDisp = wpos - _CutPositions[j]; // position comparison
sphereDisp *= radius; // position multiplied by radius for falloff
float2 area = abs(clamp(sphereDisp.xz * step(_YOffset, pos.y), -_MaxWidth,_MaxWidth));
height -= area*10;
if(height > 0)
{
//height = 0;
inArea = true;
}
}
if(inArea)
{
triStream.Append(GenerateGrassVertex(pos, 0, height, forward, float2(0.5, 1), transformationMatrix, depositSample));
}
triStream.Append(GenerateGrassVertex(pos, 0, height, forward, float2(0.5, 1), transformationMatrix, depositSample));
}
}
ENDCG
SubShader
{
Cull Off
Pass
{
Tags
{
"RenderType" = "Opaque"
"LightMode" = "ForwardBase"
"DisableBatching" = "True"//possibly needed for bending?
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma geometry geo
#pragma hull hull
#pragma domain domain
#pragma target 4.6
#pragma multi_compile_fwdbase
#include "Lighting.cginc"
float4 _TopColor;
float4 _BottomColor;
float4 _DepositColor;
float4 _ColorVariationRandom;
float _TranslucentGain;
float4 frag (geometryOutput i, 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);
float4 tex = tex2Dlod (_GrassBladeTex, float4(i.uv.xy,0,0));
float deposit = i.deposit;
float4 col = lerp(_BottomColor + (deposit * _DepositColor), (_TopColor + (deposit * _DepositColor)) * lightIntensity, i.uv.y) * tex.r * 2;
if(tex.a < _CutOff) discard;
return _UseTextureColors ? tex : 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
}
}
}Editor is loading...