NMWindNoShiver.cginc 4.7 KB

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