GpuParticlesSparks.ankiprog 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. // This shader does a particle simulation for spart-like particles
  6. #pragma anki mutator ANKI_WAVE_SIZE 16 32 64
  7. #pragma anki technique comp
  8. #include <AnKi/Shaders/GpuParticlesCommon.hlsl>
  9. #include <AnKi/Shaders/ImportanceSampling.hlsl>
  10. // clang-format off
  11. #pragma anki struct AnKiParticleEmitterProperties
  12. # pragma anki member F32 m_minParticleLife 1.0
  13. # pragma anki member F32 m_maxParticleLife 1.0
  14. # pragma anki member F32 m_minMass 0.5
  15. # pragma anki member F32 m_maxMass 0.5
  16. # pragma anki member Vec2 m_size 1.0 1.0
  17. # pragma anki member Vec3 m_minStartingPosition 0.0 0.0 0.0
  18. # pragma anki member Vec3 m_maxStartingPosition 0.0 0.0 0.0
  19. # pragma anki member Vec3 m_forceDir 0 1 0
  20. # pragma anki member F32 m_forceAngle 1.2
  21. # pragma anki member F32 m_minForce 1
  22. # pragma anki member F32 m_maxForce 2
  23. # pragma anki member F32 m_coefOfRestitution 0.1
  24. # pragma anki member F32 m_coefFriction 0.1
  25. #pragma anki struct_end
  26. // clang-format on
  27. struct ParticleInterface
  28. {
  29. AnKiParticleEmitterProperties m_props;
  30. void initAnKiParticleEmitterProperties(GpuSceneParticleEmitter2 emitter)
  31. {
  32. const AnKiParticleEmitterProperties props = loadAnKiParticleEmitterProperties(g_gpuScene, emitter.m_particleEmitterPropertiesOffset);
  33. m_props = props;
  34. }
  35. void initializeParticle(GpuSceneParticleEmitter2 emitter, Mat3x4 emitterTrf, Bool makeAlive, out Vec3 particlePosition, out F32 particleScale)
  36. {
  37. const F32 m = getRandomRange(m_props.m_minMass, m_props.m_maxMass);
  38. // Compute the force
  39. const F32 randAng = getRandomRange(0.0, m_props.m_forceAngle);
  40. const F32 adj = 10.0; // In meters. Something big
  41. const F32 opposite = tan(randAng / 2.0) * adj; // Compute the opposite in the orthogonal triangle. tan(phi) = opposite/adj
  42. const Vec3 sphereCenter = m_props.m_forceDir * adj;
  43. const F32 sphereRadius = opposite;
  44. const Vec3 randomPointInSphere = sphereCenter + normalize(getRandomRange((Vec3)-1.0, (Vec3)1.0)) * sphereRadius;
  45. const Vec3 forceDir = normalize(randomPointInSphere);
  46. const Vec3 F = getRandomRange(m_props.m_minForce, m_props.m_maxForce) * forceDir;
  47. // Initial stuff
  48. const Vec3 g = Vec3(0.0, -9.8, 0.0);
  49. const Vec3 a = F / m + g;
  50. const F32 dt = 1.0 / 60.0;
  51. const Vec3 v = a * dt;
  52. const Vec3 x = getRandomRange(m_props.m_minStartingPosition, m_props.m_maxStartingPosition) + emitterTrf.getTranslationPart().xyz;
  53. // Store
  54. writeProp(emitter, ParticleProperty::kVelocity, v);
  55. writeProp(emitter, ParticleProperty::kLifeFactor, makeAlive ? 0.0 : 1.0);
  56. writeProp(emitter, ParticleProperty::kMaxLife, getRandomRange(m_props.m_minParticleLife, m_props.m_maxParticleLife));
  57. writeProp(emitter, ParticleProperty::kPosition, x);
  58. writeProp(emitter, ParticleProperty::kPreviousPosition, x);
  59. writeProp(emitter, ParticleProperty::kMass, m);
  60. writeProp(emitter, ParticleProperty::kScale, Vec3(m_props.m_size, 1.0));
  61. particlePosition = x;
  62. particleScale = max2(m_props.m_size);
  63. }
  64. void simulateParticle(GpuSceneParticleEmitter2 emitter, F32 lifeFactor, out Vec3 particlePosition, out F32 particleScale)
  65. {
  66. const F32 m = readProp<F32>(emitter, ParticleProperty::kMass);
  67. const Vec3 g = Vec3(0.0, -9.8, 0.0);
  68. const Vec3 F = m * g;
  69. Vec3 v = readProp<Vec3>(emitter, ParticleProperty::kVelocity);
  70. Vec3 x = readProp<Vec3>(emitter, ParticleProperty::kPosition);
  71. const Vec3 prevX = x;
  72. SimulationArgs args;
  73. args.init();
  74. args.m_checkCollision = true;
  75. args.m_penetrationDistance = 0.4;
  76. args.m_iterationCount = 2;
  77. args.m_e = saturate(m_props.m_coefOfRestitution);
  78. args.m_mu = clamp(m_props.m_coefFriction, 0.1, 1.0);
  79. simulatePhysics(F, m, g_consts.m_dt, v, x, args);
  80. // Write
  81. writeProp(emitter, ParticleProperty::kVelocity, v);
  82. const F32 maxLife = readProp<F32>(emitter, ParticleProperty::kMaxLife);
  83. writeProp(emitter, ParticleProperty::kLifeFactor, lifeFactor + g_consts.m_dt / maxLife);
  84. writeProp(emitter, ParticleProperty::kPosition, x);
  85. writeProp(emitter, ParticleProperty::kPreviousPosition, prevX);
  86. writeProp(emitter, ParticleProperty::kScale, Vec3(m_props.m_size, 1.0));
  87. particlePosition = x;
  88. particleScale = max2(m_props.m_size);
  89. }
  90. };
  91. [numthreads(ANKI_WAVE_SIZE, 1, 1)] void main(COMPUTE_ARGS)
  92. {
  93. ParticleInterface iface;
  94. particleMain(svDispatchThreadId.x, svGroupIndex, iface);
  95. }