@babylonjs/core
Version:
Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.
165 lines (164 loc) • 7.8 kB
JavaScript
import { StorageBuffer } from "../Buffers/storageBuffer.js";
import { ComputeShader } from "../Compute/computeShader.js";
import { UniformBuffer } from "../Materials/uniformBuffer.js";
import { UniformBufferEffectCommonAccessor } from "../Materials/uniformBufferEffectCommonAccessor.js";
import { RegisterClass } from "../Misc/typeStore.js";
import "../ShadersWGSL/gpuUpdateParticles.compute.js";
/** @internal */
export class ComputeShaderParticleSystem {
/** @internal */
constructor(parent, engine) {
this._bufferComputeShader = [];
this._renderVertexBuffers = [];
/** @internal */
this.alignDataInBuffer = true;
this._parent = parent;
this._engine = engine;
}
/** @internal */
contextLost() {
this._updateComputeShader = undefined;
this._bufferComputeShader.length = 0;
this._renderVertexBuffers.length = 0;
}
/** @internal */
isUpdateBufferCreated() {
return !!this._updateComputeShader;
}
/** @internal */
isUpdateBufferReady() {
return this._updateComputeShader?.isReady() ?? false;
}
/** @internal */
createUpdateBuffer(defines) {
const bindingsMapping = {
params: { group: 0, binding: 0 },
particlesIn: { group: 0, binding: 1 },
particlesOut: { group: 0, binding: 2 },
randomTexture: { group: 0, binding: 3 },
randomTexture2: { group: 0, binding: 4 },
};
if (this._parent._sizeGradientsTexture) {
bindingsMapping["sizeGradientTexture"] = { group: 1, binding: 1 };
}
if (this._parent._angularSpeedGradientsTexture) {
bindingsMapping["angularSpeedGradientTexture"] = { group: 1, binding: 3 };
}
if (this._parent._velocityGradientsTexture) {
bindingsMapping["velocityGradientTexture"] = { group: 1, binding: 5 };
}
if (this._parent._limitVelocityGradientsTexture) {
bindingsMapping["limitVelocityGradientTexture"] = { group: 1, binding: 7 };
}
if (this._parent._dragGradientsTexture) {
bindingsMapping["dragGradientTexture"] = { group: 1, binding: 9 };
}
if (this._parent.noiseTexture) {
bindingsMapping["noiseTexture"] = { group: 1, binding: 11 };
}
if (this._parent.flowMap) {
bindingsMapping["flowMapTexture"] = { group: 1, binding: 13 };
}
this._updateComputeShader = new ComputeShader("updateParticles", this._engine, "gpuUpdateParticles", { bindingsMapping, defines: defines.split("\n") });
this._simParamsComputeShader?.dispose();
this._simParamsComputeShader = new UniformBuffer(this._engine, undefined, undefined, "ComputeShaderParticleSystemUBO");
this._simParamsComputeShader.addUniform("currentCount", 1);
this._simParamsComputeShader.addUniform("timeDelta", 1);
this._simParamsComputeShader.addUniform("stopFactor", 1);
this._simParamsComputeShader.addUniform("randomTextureSize", 1);
this._simParamsComputeShader.addUniform("lifeTime", 2);
this._simParamsComputeShader.addUniform("emitPower", 2);
if (!this._parent._colorGradientsTexture) {
this._simParamsComputeShader.addUniform("color1", 4);
this._simParamsComputeShader.addUniform("color2", 4);
}
this._simParamsComputeShader.addUniform("sizeRange", 2);
this._simParamsComputeShader.addUniform("scaleRange", 4);
this._simParamsComputeShader.addUniform("angleRange", 4);
this._simParamsComputeShader.addUniform("gravity", 3);
if (this._parent._limitVelocityGradientsTexture) {
this._simParamsComputeShader.addUniform("limitVelocityDamping", 1);
}
if (this._parent.isAnimationSheetEnabled) {
this._simParamsComputeShader.addUniform("cellInfos", 4);
}
if (this._parent.noiseTexture) {
this._simParamsComputeShader.addUniform("noiseStrength", 3);
}
if (this._parent.flowMap) {
this._simParamsComputeShader.addUniform("flowMapProjection", 16);
this._simParamsComputeShader.addUniform("flowMapStrength", 1);
}
if (!this._parent.isLocal) {
this._simParamsComputeShader.addUniform("emitterWM", 16);
}
if (this._parent.particleEmitterType) {
this._parent.particleEmitterType.buildUniformLayout(this._simParamsComputeShader);
}
this._updateComputeShader.setUniformBuffer("params", this._simParamsComputeShader);
return new UniformBufferEffectCommonAccessor(this._simParamsComputeShader);
}
/** @internal */
createVertexBuffers(updateBuffer, renderVertexBuffers) {
this._renderVertexBuffers.push(renderVertexBuffers);
}
/** @internal */
createParticleBuffer(data) {
const buffer = new StorageBuffer(this._engine, data.length * 4, 3 | 8, "ComputeShaderParticleSystemBuffer");
buffer.update(data);
this._bufferComputeShader.push(buffer);
return buffer.getBuffer();
}
/** @internal */
bindDrawBuffers(index, effect, indexBuffer) {
this._engine.bindBuffers(this._renderVertexBuffers[index], indexBuffer, effect);
}
/** @internal */
preUpdateParticleBuffer() { }
/** @internal */
updateParticleBuffer(index, targetBuffer, currentActiveCount) {
this._simParamsComputeShader.update();
this._updateComputeShader.setTexture("randomTexture", this._parent._randomTexture, false);
this._updateComputeShader.setTexture("randomTexture2", this._parent._randomTexture2, false);
if (this._parent._sizeGradientsTexture) {
this._updateComputeShader.setTexture("sizeGradientTexture", this._parent._sizeGradientsTexture);
}
if (this._parent._angularSpeedGradientsTexture) {
this._updateComputeShader.setTexture("angularSpeedGradientTexture", this._parent._angularSpeedGradientsTexture);
}
if (this._parent._velocityGradientsTexture) {
this._updateComputeShader.setTexture("velocityGradientTexture", this._parent._velocityGradientsTexture);
}
if (this._parent._limitVelocityGradientsTexture) {
this._updateComputeShader.setTexture("limitVelocityGradientTexture", this._parent._limitVelocityGradientsTexture);
}
if (this._parent._dragGradientsTexture) {
this._updateComputeShader.setTexture("dragGradientTexture", this._parent._dragGradientsTexture);
}
if (this._parent.noiseTexture) {
this._updateComputeShader.setTexture("noiseTexture", this._parent.noiseTexture);
}
if (this._parent.flowMap) {
this._updateComputeShader.setTexture("flowMapTexture", this._parent.flowMap);
}
this._updateComputeShader.setStorageBuffer("particlesIn", this._bufferComputeShader[index]);
this._updateComputeShader.setStorageBuffer("particlesOut", this._bufferComputeShader[index ^ 1]);
this._updateComputeShader.dispatch(Math.ceil(currentActiveCount / 64));
}
/** @internal */
releaseBuffers() {
for (let i = 0; i < this._bufferComputeShader.length; ++i) {
this._bufferComputeShader[i].dispose();
}
this._bufferComputeShader.length = 0;
this._simParamsComputeShader?.dispose();
this._simParamsComputeShader = null;
this._updateComputeShader = null;
}
/** @internal */
releaseVertexBuffers() {
this._renderVertexBuffers.length = 0;
}
}
RegisterClass("BABYLON.ComputeShaderParticleSystem", ComputeShaderParticleSystem);
//# sourceMappingURL=computeShaderParticleSystem.js.map