FlowFieldCS.usf 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // Copyright 2023 ZSttt, Inc. All Rights Reserved.
  2. #include "/Engine/Public/Platform.ush"
  3. #include "/Engine/Private/Common.ush"
  4. RWStructuredBuffer<float2> RWParticles;
  5. Texture2D FlowFieldMap;
  6. SamplerState FlowFieldMapSampler;
  7. uint2 FlowFieldMapResolution;
  8. uint NumParticles;
  9. float RandomSeed;
  10. uint NumParticlesSqrt;
  11. float4 SpeedRange;
  12. float SpeedFactor;
  13. float RandomRate;
  14. float DropRate;
  15. float Spherical;
  16. static const float3 rand_constants = float3(12.9898, 78.233, 4375.85453);
  17. float rand(float2 uv)
  18. {
  19. float t = dot(rand_constants.xy, uv);
  20. return frac(sin(t) * (rand_constants.z + t));
  21. }
  22. float4 GetFlowFieldValue(float2 UV)
  23. {
  24. //UE Transform
  25. float2 pos = float2(UV.x,1.0 - UV.y);
  26. return Texture2DSample(FlowFieldMap, FlowFieldMapSampler, pos);
  27. }
  28. float2 lookup(float2 uv)
  29. {
  30. float2 px = 1.0 / (float) FlowFieldMapResolution;
  31. float2 vc = (floor(uv * (float) FlowFieldMapResolution)) * px;
  32. float2 f = frac(uv * (float) FlowFieldMapResolution);
  33. float2 tl = GetFlowFieldValue(vc).xy;
  34. float2 tr = GetFlowFieldValue(vc + float2(px.x, 0)).xy;
  35. float2 bl = GetFlowFieldValue(vc + float2(0, px.y)).xy;
  36. float2 br = GetFlowFieldValue(vc + px).xy;
  37. return lerp(lerp(tl, tr, f.x), lerp(bl, br, f.x), f.y);
  38. }
  39. [numthreads(256, 1, 1)]
  40. void UpdateParticles
  41. (
  42. uint3 GroupID : SV_GroupID,
  43. uint3 ThreadId : SV_DispatchThreadID,
  44. uint3 GroupThreadID : SV_GroupThreadID
  45. )
  46. {
  47. uint Index = ThreadId.x + ThreadId.y * 256;
  48. if (Index < NumParticles)
  49. {
  50. float2 particle = RWParticles[Index];
  51. float4 color = GetFlowFieldValue(particle);
  52. if (color.a == 0.0)
  53. {
  54. particle = frac(1.0 + particle + (RandomSeed * particle));
  55. float Row = Index / NumParticlesSqrt;
  56. float Column = Index % NumParticlesSqrt;
  57. float2 seed = (particle + (float2(Column, Row) / (float) NumParticlesSqrt)) * RandomSeed;
  58. particle = float2(rand(seed + 1.3), rand(seed + 2.1));
  59. }
  60. else
  61. {
  62. float2 velocity = lerp(SpeedRange.xy, SpeedRange.zw, lookup(particle));
  63. float speed = length(velocity) / length(SpeedRange.ba);
  64. float2 offset = 0.f;
  65. if (Spherical > 0.f)
  66. {
  67. float distortion = cos(radians(particle.y * 180.0 - 90.0));
  68. offset = float2(velocity.x / distortion, velocity.y) * 0.0001 * SpeedFactor;
  69. }
  70. else
  71. {
  72. offset = float2(velocity.x, velocity.y) * 0.0001 * SpeedFactor;
  73. }
  74. particle = frac(1.0 + particle + offset);
  75. float Row = Index / NumParticlesSqrt;
  76. float Column = Index % NumParticlesSqrt;
  77. float2 seed = (particle + (float2(Column, Row) / (float) NumParticlesSqrt)) * RandomSeed;
  78. float drop_rate = RandomRate + speed * DropRate;
  79. float drop = step(1.0 - drop_rate, rand(seed));
  80. float2 random_pos = float2(rand(seed + 1.3), rand(seed + 2.1));
  81. particle = lerp(particle, random_pos, drop);
  82. }
  83. RWParticles[Index].xy = particle;
  84. }
  85. }