NMWind.cginc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. #define FLT_EPSILON 1.192092896e-07
  2. #include "NMWindTouchRect.cginc"
  3. sampler2D WIND_SETTINGS_TexNoise;
  4. sampler2D WIND_SETTINGS_TexGust;
  5. float _InitialBend;
  6. float _Stiffness;
  7. float _Drag;
  8. float _ShiverDrag;
  9. float _ShiverDirectionality;
  10. float _WindNormalInfluence;
  11. float4 _NewNormal;
  12. float4 WIND_SETTINGS_WorldDirectionAndSpeed;
  13. float WIND_SETTINGS_FlexNoiseScale;
  14. float WIND_SETTINGS_ShiverNoiseScale;
  15. float WIND_SETTINGS_Turbulence;
  16. float WIND_SETTINGS_GustSpeed;
  17. float WIND_SETTINGS_GustScale;
  18. float WIND_SETTINGS_GustWorldScale;
  19. float4x4 WIND_SETTINGS_Points;
  20. float4 WIND_SETTINGS_Points_Radius;
  21. uniform half _CullFarStart = -1;
  22. uniform half _CullFarDistance = -1;
  23. float PositivePow(float base, float power)
  24. {
  25. return pow(max(abs(base), float(FLT_EPSILON)), power);
  26. }
  27. float AttenuateTrunk(float x, float s)
  28. {
  29. float r = (x / s);
  30. return PositivePow(r, 1 / s);
  31. }
  32. float3 Rotate(float3 pivot, float3 position, float3 rotationAxis, float angle)
  33. {
  34. rotationAxis = normalize(rotationAxis);
  35. float3 cpa = pivot + rotationAxis * dot(rotationAxis, position - pivot);
  36. return cpa + ((position - cpa) * cos(angle) + cross(rotationAxis, (position - cpa)) * sin(angle));
  37. }
  38. struct WindData
  39. {
  40. float3 Direction;
  41. float Strength;
  42. float3 ShiverStrength;
  43. float3 ShiverDirection;
  44. float Gust;
  45. };
  46. float3 texNoise(float3 worldPos, float LOD)
  47. {
  48. return tex2Dlod(WIND_SETTINGS_TexNoise, float4(worldPos.xz, 0, LOD)).xyz - 0.5;
  49. }
  50. float texGust(float3 worldPos, float LOD)
  51. {
  52. return tex2Dlod(WIND_SETTINGS_TexGust, float4(worldPos.xz, 0, LOD)).x;
  53. }
  54. float4 PointDirection(float4 collumn, float radius)
  55. {
  56. float3 position = UNITY_MATRIX_M._m03_m13_m23;
  57. float3 direction = position - collumn.rgb;
  58. float3 norm = normalize(direction);
  59. float leng = length(direction);
  60. leng = clamp(leng / radius, 0, 1);
  61. leng = lerp(collumn.a, 0, leng);
  62. norm = norm * leng;
  63. return float4(norm.rgb, leng);
  64. }
  65. float4 MatrixSplit(float4x4 mat, float column)
  66. {
  67. return float4(mat[0][column], mat[1][column], mat[2][column], mat[3][column]);
  68. }
  69. WindData GetAnalyticalWind(float3 WorldPosition, float3 PivotPosition, float drag, float shiverDrag, float initialBend, float4 time)
  70. {
  71. WindData result;
  72. float4 newDirection = PointDirection(MatrixSplit(WIND_SETTINGS_Points, 0), WIND_SETTINGS_Points_Radius[0]);
  73. newDirection += PointDirection(MatrixSplit(WIND_SETTINGS_Points, 1), WIND_SETTINGS_Points_Radius[1]);
  74. newDirection += PointDirection(MatrixSplit(WIND_SETTINGS_Points, 2), WIND_SETTINGS_Points_Radius[2]);
  75. newDirection += PointDirection(MatrixSplit(WIND_SETTINGS_Points, 3), WIND_SETTINGS_Points_Radius[3]);
  76. float4 WIND_SETTINGS_WorldDirectionAndSpeednew = WIND_SETTINGS_WorldDirectionAndSpeed + newDirection;
  77. float3 normalizedDir = normalize(WIND_SETTINGS_WorldDirectionAndSpeednew.xyz);
  78. float3 worldOffset = float3(1, 0, 0) * WIND_SETTINGS_WorldDirectionAndSpeednew.w * time.y;
  79. float3 gustWorldOffset = float3(1, 0, 0) * WIND_SETTINGS_GustSpeed * time.y;
  80. // Trunk noise is base wind + gusts + noise
  81. float3 trunk = float3(0, 0, 0);
  82. if (WIND_SETTINGS_WorldDirectionAndSpeednew.w > 0.0 || WIND_SETTINGS_Turbulence > 0.0)
  83. {
  84. trunk = texNoise((PivotPosition - worldOffset) * WIND_SETTINGS_FlexNoiseScale, 3);
  85. }
  86. float gust = 0.0;
  87. if (WIND_SETTINGS_GustSpeed > 0.0)
  88. {
  89. gust = texGust((PivotPosition - gustWorldOffset) * WIND_SETTINGS_GustWorldScale, 3);
  90. gust = pow(gust, 2) * WIND_SETTINGS_GustScale;
  91. }
  92. float3 trunkNoise =
  93. (
  94. (normalizedDir * WIND_SETTINGS_WorldDirectionAndSpeednew.w)
  95. + (gust * normalizedDir * WIND_SETTINGS_GustSpeed)
  96. + (trunk * WIND_SETTINGS_Turbulence)
  97. ) * drag;
  98. // Shiver Noise
  99. float3 shiverNoise = texNoise((WorldPosition - worldOffset) * WIND_SETTINGS_ShiverNoiseScale, 0) * shiverDrag * WIND_SETTINGS_Turbulence;
  100. float3 dir = trunkNoise;
  101. float flex = length(trunkNoise) + initialBend;
  102. float shiver = length(shiverNoise);
  103. result.Direction = dir;
  104. result.ShiverDirection = shiverNoise;
  105. result.Strength = flex;
  106. result.ShiverStrength = shiver + shiver * gust;
  107. result.Gust = (gust * normalizedDir * WIND_SETTINGS_GustSpeed)
  108. + (trunk * WIND_SETTINGS_Turbulence);
  109. return result;
  110. }
  111. void ApplyWindDisplacement(inout float3 positionWS,
  112. inout WindData windData,
  113. float3 normalWS,
  114. float3 rootWP,
  115. float stiffness,
  116. float drag,
  117. float shiverDrag,
  118. float shiverDirectionality,
  119. float initialBend,
  120. float shiverMask,
  121. float4 time)
  122. {
  123. WindData wind = GetAnalyticalWind(positionWS, rootWP, drag, shiverDrag, initialBend, time);
  124. if (wind.Strength > 0.0)
  125. {
  126. float att = AttenuateTrunk(distance(positionWS, rootWP), stiffness);
  127. float3 rotAxis = cross(float3(0, 1, 0), wind.Direction);
  128. positionWS = Rotate(rootWP, positionWS, rotAxis, (wind.Strength) * 0.001 * att);
  129. float3 shiverDirection = normalize(lerp(normalWS, normalize(wind.Direction + wind.ShiverDirection), shiverDirectionality));
  130. positionWS += wind.ShiverStrength * shiverDirection * shiverMask;
  131. }
  132. windData = wind;
  133. }
  134. float4x4 GetObjectToWorldMatrix()
  135. {
  136. return unity_ObjectToWorld;
  137. }
  138. float4x4 GetWorldToObjectMatrix()
  139. {
  140. return unity_WorldToObject;
  141. }
  142. float3 TransformObjectToWorld(float3 positionOS)
  143. {
  144. return mul(GetObjectToWorldMatrix(), float4(positionOS, 1.0)).xyz;
  145. }
  146. float3 TransformObjectToWorldNormal(float3 normalOS)
  147. {
  148. #ifdef UNITY_ASSUME_UNIFORM_SCALING
  149. return UnityObjectToWorldDir(normalOS);
  150. #else
  151. // Normal need to be multiply by inverse transpose
  152. // mul(IT_M, norm) => mul(norm, I_M) => {dot(norm, I_M.col0), dot(norm, I_M.col1), dot(norm, I_M.col2)}
  153. return normalize(mul(normalOS, (float3x3) GetWorldToObjectMatrix()));
  154. #endif
  155. }
  156. float3 TransformWorldToObject(float3 positionWS)
  157. {
  158. return mul(GetWorldToObjectMatrix(), float4(positionWS, 1.0)).xyz;
  159. }
  160. void vert(inout appdata_full v)
  161. {
  162. float3 positionWS = TransformObjectToWorld(v.vertex.xyz);
  163. float distanceToCamera = length(positionWS - _WorldSpaceCameraPos.xyz);
  164. float cull = 1;
  165. if(_CullFarStart>0)
  166. cull = 1 - saturate((distanceToCamera -_CullFarStart) / _CullFarDistance);
  167. float3 rootWP = mul(GetObjectToWorldMatrix(), float4(0, 0, 0, 1)).xyz;
  168. float3 normalWS = TransformObjectToWorldNormal(v.normal);
  169. WindData windData;
  170. ApplyWindDisplacement(positionWS, windData, normalWS, rootWP, _Stiffness, _Drag, _ShiverDrag, _ShiverDirectionality, _InitialBend, v.color.a, _Time);
  171. v.vertex.xyz = TransformWorldToObject(positionWS).xyz * cull;
  172. if (_NewNormal.x != 0 || _NewNormal.y != 0 || _NewNormal.z != 0)
  173. v.normal *= _NewNormal;
  174. if (_WindNormalInfluence != 0)
  175. v.normal.y += -_WindNormalInfluence + windData.ShiverStrength * (_WindNormalInfluence + _WindNormalInfluence);
  176. v.color.r = windData.ShiverStrength;
  177. //v.color.g = cull;
  178. if (_TouchReactActive > 0)
  179. v.vertex.xyz += TouchReactAdjustVertex(half4(v.vertex.xyz, 0.0).xyz);
  180. }
  181. void AdditionalWind(inout appdata_full v)
  182. {
  183. vert(v);
  184. }