181 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			181 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | 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 | ||
|  | 
 |