NMWindNoShiver.cginc 5.8 KB

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