229 lines
8.1 KiB
HLSL
229 lines
8.1 KiB
HLSL
|
||
// Vertex Functions
|
||
|
||
float2 _WindMultiplier;
|
||
|
||
// Simple random function
|
||
inline float nrand(float2 pos) {
|
||
return frac(sin(dot(pos, half2(12.9898f, 78.233f))) * 43758.5453f);
|
||
//return frac((dot(pos, half2(12.9898f, 78.233f))) );
|
||
}
|
||
|
||
// Our vertex function which handles wind and culling
|
||
|
||
#if defined(DEPTHNORMAL)
|
||
void vertgrass(inout appdata_full v, in float3 terrainNormal, in float InstanceScale) {
|
||
#elif defined(DEPTHONLY)
|
||
void vertgrass(inout appdata_grassinstanced_depth v, in float3 terrainNormal, in float InstanceScale) {
|
||
#else
|
||
void vertgrass(inout appdata_grassinstanced v, out Input o) {
|
||
UNITY_INITIALIZE_OUTPUT(Input, o);
|
||
#endif
|
||
|
||
// Scale contains some perlin noise – so we use it to add any perlin noise based variation
|
||
//float3 unitvec = mul( (float3x3 )unity_ObjectToWorld, float3(1,0,0)); // float4 would be 0,1,0, 0 !!!!!
|
||
//float scale = length( unitvec );
|
||
|
||
float scale = InstanceScale;
|
||
const float3 pivot = float3(unity_ObjectToWorld[0].w, unity_ObjectToWorld[1].w, unity_ObjectToWorld[2].w);
|
||
const float3 dist = pivot
|
||
//+ scale.xxx * 4 // lets break up the boring distance - skipped as it might break smooth fading.
|
||
#if defined(DONOTUSE_ATGSETUP)
|
||
- _WorldSpaceCameraPos.xyz; // vs shader version
|
||
#elif !defined(UNITY_PROCEDURAL_INSTANCING_ENABLED)
|
||
- _WorldSpaceCameraPos.xyz; // for wind setup
|
||
#else
|
||
- _AtgSurfaceCameraPosition.xyz; // atg original shader: we have to use a custom cam pos to make it match compute.
|
||
#endif
|
||
const float SqrDist = dot(dist, dist);
|
||
|
||
// Calculate far fade factor
|
||
#if defined (UNITY_PASS_SHADOWCASTER)
|
||
float fade = 1;
|
||
// Depth Pass
|
||
if (unity_LightShadowBias.z == 0.0) {
|
||
fade = saturate(( _AtgGrassFadeProps.x - SqrDist) * _AtgGrassFadeProps.y);
|
||
}
|
||
// Shadow Pass
|
||
else {
|
||
// TODO: Check why i can't revert this as well? Clip?
|
||
fade = 1.0f - saturate((SqrDist - _AtgGrassShadowFadeProps.x) * _AtgGrassShadowFadeProps.y);
|
||
}
|
||
#else
|
||
float fade = saturate(( _AtgGrassFadeProps.x - SqrDist) * _AtgGrassFadeProps.y);
|
||
#endif
|
||
// Cull based on far culling distance
|
||
if (fade == 0.0f) {
|
||
v.vertex = 0.0f;
|
||
return;
|
||
}
|
||
|
||
// Get some random value per instance
|
||
// random = nrand(randPivot); // Due to compute and floating origin issues we use the baked scale:
|
||
fixed random = nrand( float2(scale, 1.0 - scale) );
|
||
//random = nrand(float2(unity_ObjectToWorld[0].x, unity_ObjectToWorld[1].y));
|
||
|
||
// Calculate near fade factor / reversed!
|
||
const float smallScaleClipping = saturate(( SqrDist - _AtgGrassFadeProps.z) * _AtgGrassFadeProps.w);
|
||
float clip = (random < _Clip)? 1 : 0;
|
||
// Debug: Colorize instances which would be culled early on
|
||
fixed4 color = 1;
|
||
#if defined(_PARALLAXMAP)
|
||
color.rgb = lerp(o.color.rgb, _DebugColor, clip);
|
||
#endif
|
||
clip = 1.0f - smallScaleClipping * clip;
|
||
|
||
half farNear = (clip < 1) ? 1 : 0;
|
||
|
||
// Cull based on near culling distance
|
||
if (clip == 0.0f) {
|
||
v.vertex = 0.0f;
|
||
return;
|
||
}
|
||
fade *= clip;
|
||
|
||
// Set color variation
|
||
float normalizedScale = (scale - _MinMaxScales.x) * _MinMaxScales.y;
|
||
normalizedScale = saturate(normalizedScale);
|
||
|
||
#if defined(GRASSUSESTEXTUREARRAYS) && defined(_MIXMODE_RANDOM)
|
||
color *= lerp(_HealthyColor, _DryColor, nrand(pivot.zx).xxxx); // PS4 lerp
|
||
#else
|
||
color *= lerp(_HealthyColor, _DryColor, normalizedScale.xxxx); // PS4 lerp
|
||
#endif
|
||
|
||
// Set random bend strength
|
||
const float mainBending = v.color.a * color.a;
|
||
|
||
// Apply fading
|
||
// Always use xyz at far distances
|
||
float3 targetPos = (_ScaleMode + farNear == 2) ? float3(0, v.vertex.y, 0) : float3(0,0,0);
|
||
v.vertex.xyz = lerp(v.vertex.xyz, targetPos, (1.0 - fade).xxx); // PS4 lerp
|
||
|
||
// ---------------------
|
||
// Wind
|
||
#if defined(_METALLICGLOSSMAP)
|
||
// Read wind at pivot
|
||
float4 wind = tex2Dlod(_AtgWindRT, float4( pivot.xz * _AtgWindDirSize.w + (1 - v.color.r).xx + scale * 0.025, 0, _WindLOD) );
|
||
#else
|
||
// Read wind texture at vertex world position
|
||
float3 wPos = mul(unity_ObjectToWorld, v.vertex).xyz;
|
||
float4 wind = tex2Dlod(_AtgWindRT, float4( wPos.xz * _AtgWindDirSize.w + (1 - v.color.r).xx + scale * 0.025, 0, _WindLOD) );
|
||
#endif
|
||
|
||
wind.r = wind.r * (wind.g * 2.0f - 0.24376f /* not a "real" normal as we want to keep the base direction*/);
|
||
|
||
// If not procedural instanced drawn swap direction as we have a proper WorldToObject matrix
|
||
#if !defined (UNITY_PROCEDURAL_INSTANCING_ENABLED)
|
||
wind.r *= -1;
|
||
#endif
|
||
|
||
// Add bending from wind
|
||
const float windStrength = wind.r * _AtgWindStrengthMultipliers.x * _WindMultiplier.x * mainBending;
|
||
|
||
float3 bend = UnityWorldToObjectDir(_AtgWindDirSize.xyz) * windStrength;
|
||
#if !defined(DEPTHNORMAL)
|
||
v.vertex.xz -= bend.xz;
|
||
#else
|
||
v.vertex.xz += bend.xz;
|
||
#endif
|
||
|
||
// Add none directional "jitter" – this helps to hide the quantized wind from the texture lookup.
|
||
float2 jitter = lerp( float2 (_AtgSinTime.x, 0), _AtgSinTime.yz, float2(random, windStrength) ); // PS4 lerp - already
|
||
#if !defined(DEPTHNORMAL)
|
||
v.vertex.xz +=
|
||
(jitter.x + jitter.y * _WindMultiplier.y)
|
||
* (0.075 + _AtgSinTime.w) * saturate(windStrength)
|
||
;
|
||
#else
|
||
// Crazy?!
|
||
float jitterFactor = (0.075 + _AtgSinTime.w) * saturate(windStrength);
|
||
v.vertex.zx += jitter.y * _WindMultiplier.y * jitterFactor;
|
||
v.vertex.xz -= jitter.x * jitterFactor;
|
||
#endif
|
||
|
||
// Get/set normal
|
||
#if !defined(DEPTHONLY)
|
||
#if defined(_NORMAL)
|
||
v.normal = terrainNormal;
|
||
#else
|
||
v.normal = half3(0,1,0);
|
||
#endif
|
||
// Bend normal
|
||
v.normal.xz -= (bend.xz * UNITY_PI) * _NormalBend;
|
||
// per pixel normalize is applied in lighting function // v.normal = normalize(v.normal);
|
||
#endif
|
||
|
||
// Derive ambient occlusion from baked bending
|
||
#if !defined(DEPTHNORMAL) && !defined(DEPTHONLY)
|
||
o.occ = saturate( 0.85 + v.color.a);
|
||
#endif
|
||
|
||
// Calcualte texture array layer based on a new random value
|
||
#if defined(GRASSUSESTEXTUREARRAYS)
|
||
#if defined(_MIXMODE_BYSIZE)
|
||
#if defined(DEPTHONLY)
|
||
v.texcoord.x = floor(normalizedScale * _Layers + _SizeThreshold);
|
||
#else
|
||
o.layer = floor(normalizedScale * _Layers + _SizeThreshold);
|
||
#endif
|
||
#elif defined(_MIXMODE_RANDOM)
|
||
// We must not use the same random value here as for the culling! -> nope: floating origin...
|
||
random = nrand( float2(1.0 - scale, scale) ); // nrand(pivot.zx); //
|
||
#if defined(DEPTHONLY)
|
||
v.texcoord.x = floor(random * _Layers + 0.5 );
|
||
#else
|
||
o.layer = floor(random * _Layers + 0.5 );
|
||
#endif
|
||
// here middle texture wins most of the time...
|
||
// o.layer = floor( (random + normalizedScale) * 0.5 * _Layers + 0.5);
|
||
#endif
|
||
#endif
|
||
|
||
// Store smoothness variation
|
||
scale = lerp(0.6, 1.0, random);
|
||
color.a = v.color.a;
|
||
|
||
// Set outputs needed by the Surface shaders
|
||
#if !defined(DEPTHNORMAL) && !defined(DEPTHONLY)
|
||
o.scale = scale;
|
||
o.color = color;
|
||
#endif
|
||
}
|
||
|
||
// ----------------------------------------------
|
||
// Currently unsused functions
|
||
|
||
void rotate2D(inout float2 v, float r) {
|
||
float s, c;
|
||
sincos(r, s, c);
|
||
v = float2(v.x * c - v.y * s, v.x * s + v.y * c);
|
||
}
|
||
|
||
// http://answers.unity3d.com/questions/218333/shader-inversefloat4x4-function.html
|
||
inline float4x4 inverseMat(float4x4 input) {
|
||
#define minor(a,b,c) determinant(float3x3(input.a, input.b, input.c))
|
||
float4x4 cofactors = float4x4(
|
||
minor(_22_23_24, _32_33_34, _42_43_44),
|
||
-minor(_21_23_24, _31_33_34, _41_43_44),
|
||
minor(_21_22_24, _31_32_34, _41_42_44),
|
||
-minor(_21_22_23, _31_32_33, _41_42_43),
|
||
|
||
-minor(_12_13_14, _32_33_34, _42_43_44),
|
||
minor(_11_13_14, _31_33_34, _41_43_44),
|
||
-minor(_11_12_14, _31_32_34, _41_42_44),
|
||
minor(_11_12_13, _31_32_33, _41_42_43),
|
||
|
||
minor(_12_13_14, _22_23_24, _42_43_44),
|
||
-minor(_11_13_14, _21_23_24, _41_43_44),
|
||
minor(_11_12_14, _21_22_24, _41_42_44),
|
||
-minor(_11_12_13, _21_22_23, _41_42_43),
|
||
|
||
-minor(_12_13_14, _22_23_24, _32_33_34),
|
||
minor(_11_13_14, _21_23_24, _31_33_34),
|
||
-minor(_11_12_14, _21_22_24, _31_32_34),
|
||
minor(_11_12_13, _21_22_23, _31_32_33)
|
||
);
|
||
#undef minor
|
||
return transpose(cofactors) / determinant(input);
|
||
} |