computeShaderParticleSystem.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import { StorageBuffer } from "../Buffers/storageBuffer.js";
  2. import { ComputeShader } from "../Compute/computeShader.js";
  3. import { UniformBuffer } from "../Materials/uniformBuffer.js";
  4. import { UniformBufferEffectCommonAccessor } from "../Materials/uniformBufferEffectCommonAccessor.js";
  5. import { RegisterClass } from "../Misc/typeStore.js";
  6. import "../ShadersWGSL/gpuUpdateParticles.compute.js";
  7. /** @internal */
  8. export class ComputeShaderParticleSystem {
  9. constructor(parent, engine) {
  10. this._bufferComputeShader = [];
  11. this._renderVertexBuffers = [];
  12. this.alignDataInBuffer = true;
  13. this._parent = parent;
  14. this._engine = engine;
  15. }
  16. contextLost() {
  17. this._updateComputeShader = undefined;
  18. this._bufferComputeShader.length = 0;
  19. this._renderVertexBuffers.length = 0;
  20. }
  21. isUpdateBufferCreated() {
  22. return !!this._updateComputeShader;
  23. }
  24. isUpdateBufferReady() {
  25. return this._updateComputeShader?.isReady() ?? false;
  26. }
  27. createUpdateBuffer(defines) {
  28. const bindingsMapping = {
  29. params: { group: 0, binding: 0 },
  30. particlesIn: { group: 0, binding: 1 },
  31. particlesOut: { group: 0, binding: 2 },
  32. randomTexture: { group: 0, binding: 3 },
  33. randomTexture2: { group: 0, binding: 4 },
  34. };
  35. if (this._parent._sizeGradientsTexture) {
  36. bindingsMapping["sizeGradientTexture"] = { group: 1, binding: 1 };
  37. }
  38. if (this._parent._angularSpeedGradientsTexture) {
  39. bindingsMapping["angularSpeedGradientTexture"] = { group: 1, binding: 3 };
  40. }
  41. if (this._parent._velocityGradientsTexture) {
  42. bindingsMapping["velocityGradientTexture"] = { group: 1, binding: 5 };
  43. }
  44. if (this._parent._limitVelocityGradientsTexture) {
  45. bindingsMapping["limitVelocityGradientTexture"] = { group: 1, binding: 7 };
  46. }
  47. if (this._parent._dragGradientsTexture) {
  48. bindingsMapping["dragGradientTexture"] = { group: 1, binding: 9 };
  49. }
  50. if (this._parent.noiseTexture) {
  51. bindingsMapping["noiseTexture"] = { group: 1, binding: 11 };
  52. }
  53. this._updateComputeShader = new ComputeShader("updateParticles", this._engine, "gpuUpdateParticles", { bindingsMapping, defines: defines.split("\n") });
  54. this._simParamsComputeShader?.dispose();
  55. this._simParamsComputeShader = new UniformBuffer(this._engine, undefined, undefined, "ComputeShaderParticleSystemUBO");
  56. this._simParamsComputeShader.addUniform("currentCount", 1);
  57. this._simParamsComputeShader.addUniform("timeDelta", 1);
  58. this._simParamsComputeShader.addUniform("stopFactor", 1);
  59. this._simParamsComputeShader.addUniform("randomTextureSize", 1);
  60. this._simParamsComputeShader.addUniform("lifeTime", 2);
  61. this._simParamsComputeShader.addUniform("emitPower", 2);
  62. if (!this._parent._colorGradientsTexture) {
  63. this._simParamsComputeShader.addUniform("color1", 4);
  64. this._simParamsComputeShader.addUniform("color2", 4);
  65. }
  66. this._simParamsComputeShader.addUniform("sizeRange", 2);
  67. this._simParamsComputeShader.addUniform("scaleRange", 4);
  68. this._simParamsComputeShader.addUniform("angleRange", 4);
  69. this._simParamsComputeShader.addUniform("gravity", 3);
  70. if (this._parent._limitVelocityGradientsTexture) {
  71. this._simParamsComputeShader.addUniform("limitVelocityDamping", 1);
  72. }
  73. if (this._parent.isAnimationSheetEnabled) {
  74. this._simParamsComputeShader.addUniform("cellInfos", 4);
  75. }
  76. if (this._parent.noiseTexture) {
  77. this._simParamsComputeShader.addUniform("noiseStrength", 3);
  78. }
  79. if (!this._parent.isLocal) {
  80. this._simParamsComputeShader.addUniform("emitterWM", 16);
  81. }
  82. if (this._parent.particleEmitterType) {
  83. this._parent.particleEmitterType.buildUniformLayout(this._simParamsComputeShader);
  84. }
  85. this._updateComputeShader.setUniformBuffer("params", this._simParamsComputeShader);
  86. return new UniformBufferEffectCommonAccessor(this._simParamsComputeShader);
  87. }
  88. createVertexBuffers(updateBuffer, renderVertexBuffers) {
  89. this._renderVertexBuffers.push(renderVertexBuffers);
  90. }
  91. createParticleBuffer(data) {
  92. const buffer = new StorageBuffer(this._engine, data.length * 4, 3 | 8, "ComputeShaderParticleSystemBuffer");
  93. buffer.update(data);
  94. this._bufferComputeShader.push(buffer);
  95. return buffer.getBuffer();
  96. }
  97. bindDrawBuffers(index, effect, indexBuffer) {
  98. this._engine.bindBuffers(this._renderVertexBuffers[index], indexBuffer, effect);
  99. }
  100. preUpdateParticleBuffer() { }
  101. updateParticleBuffer(index, targetBuffer, currentActiveCount) {
  102. this._simParamsComputeShader.update();
  103. this._updateComputeShader.setTexture("randomTexture", this._parent._randomTexture, false);
  104. this._updateComputeShader.setTexture("randomTexture2", this._parent._randomTexture2, false);
  105. if (this._parent._sizeGradientsTexture) {
  106. this._updateComputeShader.setTexture("sizeGradientTexture", this._parent._sizeGradientsTexture);
  107. }
  108. if (this._parent._angularSpeedGradientsTexture) {
  109. this._updateComputeShader.setTexture("angularSpeedGradientTexture", this._parent._angularSpeedGradientsTexture);
  110. }
  111. if (this._parent._velocityGradientsTexture) {
  112. this._updateComputeShader.setTexture("velocityGradientTexture", this._parent._velocityGradientsTexture);
  113. }
  114. if (this._parent._limitVelocityGradientsTexture) {
  115. this._updateComputeShader.setTexture("limitVelocityGradientTexture", this._parent._limitVelocityGradientsTexture);
  116. }
  117. if (this._parent._dragGradientsTexture) {
  118. this._updateComputeShader.setTexture("dragGradientTexture", this._parent._dragGradientsTexture);
  119. }
  120. if (this._parent.noiseTexture) {
  121. this._updateComputeShader.setTexture("noiseTexture", this._parent.noiseTexture);
  122. }
  123. this._updateComputeShader.setStorageBuffer("particlesIn", this._bufferComputeShader[index]);
  124. this._updateComputeShader.setStorageBuffer("particlesOut", this._bufferComputeShader[index ^ 1]);
  125. this._updateComputeShader.dispatch(Math.ceil(currentActiveCount / 64));
  126. }
  127. releaseBuffers() {
  128. for (let i = 0; i < this._bufferComputeShader.length; ++i) {
  129. this._bufferComputeShader[i].dispose();
  130. }
  131. this._bufferComputeShader.length = 0;
  132. this._simParamsComputeShader?.dispose();
  133. this._simParamsComputeShader = null;
  134. this._updateComputeShader = null;
  135. }
  136. releaseVertexBuffers() {
  137. this._renderVertexBuffers.length = 0;
  138. }
  139. }
  140. RegisterClass("BABYLON.ComputeShaderParticleSystem", ComputeShaderParticleSystem);
  141. //# sourceMappingURL=computeShaderParticleSystem.js.map