webgl2ParticleSystem.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. import { Effect } from "../Materials/effect.js";
  2. import { CustomParticleEmitter } from "./EmitterTypes/customParticleEmitter.js";
  3. import { UniformBufferEffectCommonAccessor } from "../Materials/uniformBufferEffectCommonAccessor.js";
  4. import { RegisterClass } from "../Misc/typeStore.js";
  5. import "../Shaders/gpuUpdateParticles.fragment.js";
  6. import "../Shaders/gpuUpdateParticles.vertex.js";
  7. /** @internal */
  8. export class WebGL2ParticleSystem {
  9. constructor(parent, engine) {
  10. this._renderVAO = [];
  11. this._updateVAO = [];
  12. this.alignDataInBuffer = false;
  13. this._parent = parent;
  14. this._engine = engine;
  15. this._updateEffectOptions = {
  16. attributes: [
  17. "position",
  18. "initialPosition",
  19. "age",
  20. "life",
  21. "seed",
  22. "size",
  23. "color",
  24. "direction",
  25. "initialDirection",
  26. "angle",
  27. "cellIndex",
  28. "cellStartOffset",
  29. "noiseCoordinates1",
  30. "noiseCoordinates2",
  31. ],
  32. uniformsNames: [
  33. "currentCount",
  34. "timeDelta",
  35. "emitterWM",
  36. "lifeTime",
  37. "color1",
  38. "color2",
  39. "sizeRange",
  40. "scaleRange",
  41. "gravity",
  42. "emitPower",
  43. "direction1",
  44. "direction2",
  45. "minEmitBox",
  46. "maxEmitBox",
  47. "radius",
  48. "directionRandomizer",
  49. "height",
  50. "coneAngle",
  51. "stopFactor",
  52. "angleRange",
  53. "radiusRange",
  54. "cellInfos",
  55. "noiseStrength",
  56. "limitVelocityDamping",
  57. ],
  58. uniformBuffersNames: [],
  59. samplers: [
  60. "randomSampler",
  61. "randomSampler2",
  62. "sizeGradientSampler",
  63. "angularSpeedGradientSampler",
  64. "velocityGradientSampler",
  65. "limitVelocityGradientSampler",
  66. "noiseSampler",
  67. "dragGradientSampler",
  68. ],
  69. defines: "",
  70. fallbacks: null,
  71. onCompiled: null,
  72. onError: null,
  73. indexParameters: null,
  74. maxSimultaneousLights: 0,
  75. transformFeedbackVaryings: [],
  76. };
  77. }
  78. contextLost() {
  79. this._updateEffect = undefined;
  80. this._renderVAO.length = 0;
  81. this._updateVAO.length = 0;
  82. }
  83. isUpdateBufferCreated() {
  84. return !!this._updateEffect;
  85. }
  86. isUpdateBufferReady() {
  87. return this._updateEffect?.isReady() ?? false;
  88. }
  89. createUpdateBuffer(defines) {
  90. this._updateEffectOptions.transformFeedbackVaryings = ["outPosition"];
  91. this._updateEffectOptions.transformFeedbackVaryings.push("outAge");
  92. this._updateEffectOptions.transformFeedbackVaryings.push("outSize");
  93. this._updateEffectOptions.transformFeedbackVaryings.push("outLife");
  94. this._updateEffectOptions.transformFeedbackVaryings.push("outSeed");
  95. this._updateEffectOptions.transformFeedbackVaryings.push("outDirection");
  96. if (this._parent.particleEmitterType instanceof CustomParticleEmitter) {
  97. this._updateEffectOptions.transformFeedbackVaryings.push("outInitialPosition");
  98. }
  99. if (!this._parent._colorGradientsTexture) {
  100. this._updateEffectOptions.transformFeedbackVaryings.push("outColor");
  101. }
  102. if (!this._parent._isBillboardBased) {
  103. this._updateEffectOptions.transformFeedbackVaryings.push("outInitialDirection");
  104. }
  105. if (this._parent.noiseTexture) {
  106. this._updateEffectOptions.transformFeedbackVaryings.push("outNoiseCoordinates1");
  107. this._updateEffectOptions.transformFeedbackVaryings.push("outNoiseCoordinates2");
  108. }
  109. this._updateEffectOptions.transformFeedbackVaryings.push("outAngle");
  110. if (this._parent.isAnimationSheetEnabled) {
  111. this._updateEffectOptions.transformFeedbackVaryings.push("outCellIndex");
  112. if (this._parent.spriteRandomStartCell) {
  113. this._updateEffectOptions.transformFeedbackVaryings.push("outCellStartOffset");
  114. }
  115. }
  116. this._updateEffectOptions.defines = defines;
  117. this._updateEffect = new Effect("gpuUpdateParticles", this._updateEffectOptions, this._engine);
  118. return new UniformBufferEffectCommonAccessor(this._updateEffect);
  119. }
  120. createVertexBuffers(updateBuffer, renderVertexBuffers) {
  121. this._updateVAO.push(this._createUpdateVAO(updateBuffer));
  122. this._renderVAO.push(this._engine.recordVertexArrayObject(renderVertexBuffers, null, this._parent._getWrapper(this._parent.blendMode).effect));
  123. this._engine.bindArrayBuffer(null);
  124. this._renderVertexBuffers = renderVertexBuffers;
  125. }
  126. createParticleBuffer(data) {
  127. return data;
  128. }
  129. bindDrawBuffers(index, effect, indexBuffer) {
  130. if (indexBuffer) {
  131. this._engine.bindBuffers(this._renderVertexBuffers, indexBuffer, effect);
  132. }
  133. else {
  134. this._engine.bindVertexArrayObject(this._renderVAO[index], null);
  135. }
  136. }
  137. preUpdateParticleBuffer() {
  138. const engine = this._engine;
  139. this._engine.enableEffect(this._updateEffect);
  140. if (!engine.setState) {
  141. throw new Error("GPU particles cannot work without a full Engine. ThinEngine is not supported");
  142. }
  143. }
  144. updateParticleBuffer(index, targetBuffer, currentActiveCount) {
  145. this._updateEffect.setTexture("randomSampler", this._parent._randomTexture);
  146. this._updateEffect.setTexture("randomSampler2", this._parent._randomTexture2);
  147. if (this._parent._sizeGradientsTexture) {
  148. this._updateEffect.setTexture("sizeGradientSampler", this._parent._sizeGradientsTexture);
  149. }
  150. if (this._parent._angularSpeedGradientsTexture) {
  151. this._updateEffect.setTexture("angularSpeedGradientSampler", this._parent._angularSpeedGradientsTexture);
  152. }
  153. if (this._parent._velocityGradientsTexture) {
  154. this._updateEffect.setTexture("velocityGradientSampler", this._parent._velocityGradientsTexture);
  155. }
  156. if (this._parent._limitVelocityGradientsTexture) {
  157. this._updateEffect.setTexture("limitVelocityGradientSampler", this._parent._limitVelocityGradientsTexture);
  158. }
  159. if (this._parent._dragGradientsTexture) {
  160. this._updateEffect.setTexture("dragGradientSampler", this._parent._dragGradientsTexture);
  161. }
  162. if (this._parent.noiseTexture) {
  163. this._updateEffect.setTexture("noiseSampler", this._parent.noiseTexture);
  164. }
  165. // Bind source VAO
  166. this._engine.bindVertexArrayObject(this._updateVAO[index], null);
  167. // Update
  168. const engine = this._engine;
  169. engine.bindTransformFeedbackBuffer(targetBuffer.getBuffer());
  170. engine.setRasterizerState(false);
  171. engine.beginTransformFeedback(true);
  172. engine.drawArraysType(3, 0, currentActiveCount);
  173. engine.endTransformFeedback();
  174. engine.setRasterizerState(true);
  175. engine.bindTransformFeedbackBuffer(null);
  176. }
  177. releaseBuffers() { }
  178. releaseVertexBuffers() {
  179. for (let index = 0; index < this._updateVAO.length; index++) {
  180. this._engine.releaseVertexArrayObject(this._updateVAO[index]);
  181. }
  182. this._updateVAO.length = 0;
  183. for (let index = 0; index < this._renderVAO.length; index++) {
  184. this._engine.releaseVertexArrayObject(this._renderVAO[index]);
  185. }
  186. this._renderVAO.length = 0;
  187. }
  188. _createUpdateVAO(source) {
  189. const updateVertexBuffers = {};
  190. updateVertexBuffers["position"] = source.createVertexBuffer("position", 0, 3);
  191. let offset = 3;
  192. updateVertexBuffers["age"] = source.createVertexBuffer("age", offset, 1);
  193. offset += 1;
  194. updateVertexBuffers["size"] = source.createVertexBuffer("size", offset, 3);
  195. offset += 3;
  196. updateVertexBuffers["life"] = source.createVertexBuffer("life", offset, 1);
  197. offset += 1;
  198. updateVertexBuffers["seed"] = source.createVertexBuffer("seed", offset, 4);
  199. offset += 4;
  200. updateVertexBuffers["direction"] = source.createVertexBuffer("direction", offset, 3);
  201. offset += 3;
  202. if (this._parent.particleEmitterType instanceof CustomParticleEmitter) {
  203. updateVertexBuffers["initialPosition"] = source.createVertexBuffer("initialPosition", offset, 3);
  204. offset += 3;
  205. }
  206. if (!this._parent._colorGradientsTexture) {
  207. updateVertexBuffers["color"] = source.createVertexBuffer("color", offset, 4);
  208. offset += 4;
  209. }
  210. if (!this._parent._isBillboardBased) {
  211. updateVertexBuffers["initialDirection"] = source.createVertexBuffer("initialDirection", offset, 3);
  212. offset += 3;
  213. }
  214. if (this._parent.noiseTexture) {
  215. updateVertexBuffers["noiseCoordinates1"] = source.createVertexBuffer("noiseCoordinates1", offset, 3);
  216. offset += 3;
  217. updateVertexBuffers["noiseCoordinates2"] = source.createVertexBuffer("noiseCoordinates2", offset, 3);
  218. offset += 3;
  219. }
  220. if (this._parent._angularSpeedGradientsTexture) {
  221. updateVertexBuffers["angle"] = source.createVertexBuffer("angle", offset, 1);
  222. offset += 1;
  223. }
  224. else {
  225. updateVertexBuffers["angle"] = source.createVertexBuffer("angle", offset, 2);
  226. offset += 2;
  227. }
  228. if (this._parent._isAnimationSheetEnabled) {
  229. updateVertexBuffers["cellIndex"] = source.createVertexBuffer("cellIndex", offset, 1);
  230. offset += 1;
  231. if (this._parent.spriteRandomStartCell) {
  232. updateVertexBuffers["cellStartOffset"] = source.createVertexBuffer("cellStartOffset", offset, 1);
  233. offset += 1;
  234. }
  235. }
  236. const vao = this._engine.recordVertexArrayObject(updateVertexBuffers, null, this._updateEffect);
  237. this._engine.bindArrayBuffer(null);
  238. return vao;
  239. }
  240. }
  241. RegisterClass("BABYLON.WebGL2ParticleSystem", WebGL2ParticleSystem);
  242. //# sourceMappingURL=webgl2ParticleSystem.js.map