BEGIN_OPTIONS ShaderName "AwesomeTechnologies/Development/Trees/VertexWind" Stackable "True" END_OPTIONS BEGIN_PROPERTIES _InitialBend("Wind Initial Bend", Float) = 1 _Stiffness("Wind Stiffness", Float) = 1 _Drag("Wind Drag", Float) = 1 _ShiverDrag("Wind Shiver Drag", Float) = 0.05 _WindNormalInfluence("Wind Normal Influence", Float) = 0 END_PROPERTIES BEGIN_DEFINES #define FLT_EPSILON 1.192092896e-07 END_DEFINES BEGIN_CODE sampler2D WIND_SETTINGS_TexNoise; sampler2D WIND_SETTINGS_TexGust; float _InitialBend; float _Stiffness; float _Drag; float _ShiverDrag; float _ShiverDirectionality; float _WindNormalInfluence; float4 _NewNormal; float4 WIND_SETTINGS_WorldDirectionAndSpeed; float WIND_SETTINGS_FlexNoiseScale; float WIND_SETTINGS_ShiverNoiseScale; float WIND_SETTINGS_Turbulence; float WIND_SETTINGS_GustSpeed; float WIND_SETTINGS_GustScale; float WIND_SETTINGS_GustWorldScale; float PositivePow_(float base, float power) { return pow(max(abs(base), float(FLT_EPSILON)), power); } float AttenuateTrunk_(float x, float s) { float r = (x / s); return PositivePow_(r,1/s); } float3 Rotate_(float3 pivot, float3 position, float3 rotationAxis, float angle) { rotationAxis = normalize(rotationAxis); float3 cpa = pivot + rotationAxis * dot(rotationAxis, position - pivot); return cpa + ((position - cpa) * cos(angle) + cross(rotationAxis, (position - cpa)) * sin(angle)); } struct WindData_ { float3 Direction; float Strength; float3 ShiverStrength; float3 ShiverDirection; float Gust; }; float3 texNoise_(float3 worldPos, float LOD) { return tex2Dlod(WIND_SETTINGS_TexNoise,float4(worldPos.xz,0,LOD)).xyz -0.5; } float texGust_(float3 worldPos, float LOD) { return tex2Dlod(WIND_SETTINGS_TexGust, float4(worldPos.xz,0, LOD)).x; } WindData_ GetAnalyticalWind(float3 WorldPosition, float3 PivotPosition, float drag, float shiverDrag, float initialBend, float4 time) { WindData_ result; float3 normalizedDir = normalize(WIND_SETTINGS_WorldDirectionAndSpeed.xyz); float3 worldOffset = normalizedDir * WIND_SETTINGS_WorldDirectionAndSpeed.w * time.y; float3 gustWorldOffset = normalizedDir * WIND_SETTINGS_GustSpeed * time.y; // Trunk noise is base wind + gusts + noise float3 trunk = float3(0,0,0); if(WIND_SETTINGS_WorldDirectionAndSpeed.w > 0.0 || WIND_SETTINGS_Turbulence > 0.0) { trunk = texNoise_((PivotPosition - worldOffset)*WIND_SETTINGS_FlexNoiseScale,3); } float gust = 0.0; if(WIND_SETTINGS_GustSpeed > 0.0) { gust = texGust_((PivotPosition - gustWorldOffset)*WIND_SETTINGS_GustWorldScale,3); gust = pow(gust, 2) * WIND_SETTINGS_GustScale; } float3 trunkNoise = ( (normalizedDir * WIND_SETTINGS_WorldDirectionAndSpeed.w) + (gust * normalizedDir * WIND_SETTINGS_GustSpeed) + (trunk * WIND_SETTINGS_Turbulence) ) * drag; // Shiver Noise float3 shiverNoise = texNoise_((WorldPosition - worldOffset)*WIND_SETTINGS_ShiverNoiseScale,0) * shiverDrag * WIND_SETTINGS_Turbulence; float3 dir = trunkNoise; float flex = length(trunkNoise) + initialBend; float shiver = length(shiverNoise); result.Direction = dir; result.ShiverDirection = shiverNoise; result.Strength = flex; result.ShiverStrength = shiver + shiver * gust; result.Gust = (gust * normalizedDir * WIND_SETTINGS_GustSpeed) + (trunk * WIND_SETTINGS_Turbulence); return result; } void ApplyWindDisplacement_( inout float3 positionWS, inout WindData_ windData, float3 normalWS, float3 rootWP, float stiffness, float drag, float shiverDrag, float shiverDirectionality, float initialBend, float shiverMask, float4 time) { WindData_ wind = GetAnalyticalWind(positionWS, rootWP, drag, shiverDrag, initialBend, time); if (wind.Strength > 0.0) { float att = AttenuateTrunk_(distance(positionWS, rootWP), stiffness); float3 rotAxis = cross(float3(0, 1, 0), wind.Direction); positionWS = Rotate_(rootWP, positionWS, rotAxis, (wind.Strength) * 0.001 * att); float3 shiverDirection = normalize(lerp(normalWS, normalize(wind.Direction + wind.ShiverDirection), shiverDirectionality)); positionWS += wind.ShiverStrength * shiverDirection * shiverMask; } windData = wind; } float3 TransformObjectToWorldNormal_(float3 normalOS) { #ifdef UNITY_ASSUME_UNIFORM_SCALING return UnityObjectToWorldDir(normalOS); #else return normalize(mul(normalOS, (float3x3)GetWorldToObjectMatrix())); #endif } void ModifyVertex(inout VertexData v, inout ExtraV2F d) { float3 positionWS = TransformObjectToWorld(v.vertex.xyz); float3 rootWP = TransformObjectToWorld(float3(0,0,0)); if (positionWS.y > rootWP.y) { float3 normalWS = TransformObjectToWorldNormal_(v.normal); WindData_ windData; ApplyWindDisplacement_(positionWS, windData, normalWS, rootWP, _Stiffness, _Drag, _ShiverDrag, _ShiverDirectionality, _InitialBend, v.vertexColor.a, _Time); v.vertex.xyz = TransformWorldToObject(positionWS).xyz; } } void SurfaceFunction(inout Surface o, ShaderData d) { } END_CODE