@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.
261 lines (260 loc) • 11 kB
JavaScript
import { CustomParticleEmitter } from "./EmitterTypes/customParticleEmitter.js";
import { UniformBufferEffectCommonAccessor } from "../Materials/uniformBufferEffectCommonAccessor.js";
import { RegisterClass } from "../Misc/typeStore.js";
import "../Shaders/gpuUpdateParticles.fragment.js";
import "../Shaders/gpuUpdateParticles.vertex.js";
/** @internal */
export class WebGL2ParticleSystem {
/** @internal */
constructor(parent, engine) {
this._renderVAO = [];
this._updateVAO = [];
/** @internal */
this.alignDataInBuffer = false;
this._parent = parent;
this._engine = engine;
this._updateEffectOptions = {
attributes: [
"position",
"initialPosition",
"age",
"life",
"seed",
"size",
"color",
"direction",
"initialDirection",
"angle",
"cellIndex",
"cellStartOffset",
"noiseCoordinates1",
"noiseCoordinates2",
],
uniformsNames: [
"currentCount",
"timeDelta",
"emitterWM",
"lifeTime",
"color1",
"color2",
"sizeRange",
"scaleRange",
"gravity",
"emitPower",
"direction1",
"direction2",
"minEmitBox",
"maxEmitBox",
"radius",
"directionRandomizer",
"height",
"coneAngle",
"stopFactor",
"angleRange",
"radiusRange",
"cellInfos",
"noiseStrength",
"limitVelocityDamping",
"flowMapProjection",
"flowMapStrength",
],
uniformBuffersNames: [],
samplers: [
"randomSampler",
"randomSampler2",
"sizeGradientSampler",
"angularSpeedGradientSampler",
"velocityGradientSampler",
"limitVelocityGradientSampler",
"noiseSampler",
"dragGradientSampler",
"flowMapSampler",
],
defines: "",
fallbacks: null,
onCompiled: null,
onError: null,
indexParameters: null,
maxSimultaneousLights: 0,
transformFeedbackVaryings: [],
};
}
/** @internal */
contextLost() {
this._updateEffect = undefined;
this._renderVAO.length = 0;
this._updateVAO.length = 0;
}
/** @internal */
isUpdateBufferCreated() {
return !!this._updateEffect;
}
/** @internal */
isUpdateBufferReady() {
return this._updateEffect?.isReady() ?? false;
}
/** @internal */
createUpdateBuffer(defines) {
this._updateEffectOptions.transformFeedbackVaryings = ["outPosition"];
this._updateEffectOptions.transformFeedbackVaryings.push("outAge");
this._updateEffectOptions.transformFeedbackVaryings.push("outSize");
this._updateEffectOptions.transformFeedbackVaryings.push("outLife");
this._updateEffectOptions.transformFeedbackVaryings.push("outSeed");
this._updateEffectOptions.transformFeedbackVaryings.push("outDirection");
if (this._parent.particleEmitterType instanceof CustomParticleEmitter) {
this._updateEffectOptions.transformFeedbackVaryings.push("outInitialPosition");
}
if (!this._parent._colorGradientsTexture) {
this._updateEffectOptions.transformFeedbackVaryings.push("outColor");
}
if (!this._parent._isBillboardBased) {
this._updateEffectOptions.transformFeedbackVaryings.push("outInitialDirection");
}
if (this._parent.noiseTexture) {
this._updateEffectOptions.transformFeedbackVaryings.push("outNoiseCoordinates1");
this._updateEffectOptions.transformFeedbackVaryings.push("outNoiseCoordinates2");
}
this._updateEffectOptions.transformFeedbackVaryings.push("outAngle");
if (this._parent.isAnimationSheetEnabled) {
this._updateEffectOptions.transformFeedbackVaryings.push("outCellIndex");
if (this._parent.spriteRandomStartCell) {
this._updateEffectOptions.transformFeedbackVaryings.push("outCellStartOffset");
}
}
this._updateEffectOptions.defines = defines;
this._updateEffect = this._engine.createEffect("gpuUpdateParticles", this._updateEffectOptions, this._engine);
return new UniformBufferEffectCommonAccessor(this._updateEffect);
}
/** @internal */
createVertexBuffers(updateBuffer, renderVertexBuffers) {
this._updateVAO.push(this._createUpdateVAO(updateBuffer));
this._renderVAO.push(this._engine.recordVertexArrayObject(renderVertexBuffers, null, this._parent._getWrapper(this._parent.blendMode).effect));
this._engine.bindArrayBuffer(null);
this._renderVertexBuffers = renderVertexBuffers;
}
/** @internal */
createParticleBuffer(data) {
return data;
}
/** @internal */
bindDrawBuffers(index, effect, indexBuffer) {
if (indexBuffer) {
this._engine.bindBuffers(this._renderVertexBuffers, indexBuffer, effect);
}
else {
this._engine.bindVertexArrayObject(this._renderVAO[index], null);
}
}
/** @internal */
preUpdateParticleBuffer() {
const engine = this._engine;
this._engine.enableEffect(this._updateEffect);
if (!engine.setState) {
throw new Error("GPU particles cannot work without a full Engine. ThinEngine is not supported");
}
}
/** @internal */
updateParticleBuffer(index, targetBuffer, currentActiveCount) {
this._updateEffect.setTexture("randomSampler", this._parent._randomTexture);
this._updateEffect.setTexture("randomSampler2", this._parent._randomTexture2);
if (this._parent._flowMap) {
this._updateEffect.setTexture("flowMapSampler", this._parent._flowMap);
}
if (this._parent._sizeGradientsTexture) {
this._updateEffect.setTexture("sizeGradientSampler", this._parent._sizeGradientsTexture);
}
if (this._parent._angularSpeedGradientsTexture) {
this._updateEffect.setTexture("angularSpeedGradientSampler", this._parent._angularSpeedGradientsTexture);
}
if (this._parent._velocityGradientsTexture) {
this._updateEffect.setTexture("velocityGradientSampler", this._parent._velocityGradientsTexture);
}
if (this._parent._limitVelocityGradientsTexture) {
this._updateEffect.setTexture("limitVelocityGradientSampler", this._parent._limitVelocityGradientsTexture);
}
if (this._parent._dragGradientsTexture) {
this._updateEffect.setTexture("dragGradientSampler", this._parent._dragGradientsTexture);
}
if (this._parent.noiseTexture) {
this._updateEffect.setTexture("noiseSampler", this._parent.noiseTexture);
}
// Bind source VAO
this._engine.bindVertexArrayObject(this._updateVAO[index], null);
// Update
const engine = this._engine;
engine.bindTransformFeedbackBuffer(targetBuffer.getBuffer());
engine.setRasterizerState(false);
engine.beginTransformFeedback(true);
engine.drawArraysType(3, 0, currentActiveCount);
engine.endTransformFeedback();
engine.setRasterizerState(true);
engine.bindTransformFeedbackBuffer(null);
}
/** @internal */
releaseBuffers() { }
/** @internal */
releaseVertexBuffers() {
for (let index = 0; index < this._updateVAO.length; index++) {
this._engine.releaseVertexArrayObject(this._updateVAO[index]);
}
this._updateVAO.length = 0;
for (let index = 0; index < this._renderVAO.length; index++) {
this._engine.releaseVertexArrayObject(this._renderVAO[index]);
}
this._renderVAO.length = 0;
}
_createUpdateVAO(source) {
const updateVertexBuffers = {};
updateVertexBuffers["position"] = source.createVertexBuffer("position", 0, 3);
let offset = 3;
updateVertexBuffers["age"] = source.createVertexBuffer("age", offset, 1);
offset += 1;
updateVertexBuffers["size"] = source.createVertexBuffer("size", offset, 3);
offset += 3;
updateVertexBuffers["life"] = source.createVertexBuffer("life", offset, 1);
offset += 1;
updateVertexBuffers["seed"] = source.createVertexBuffer("seed", offset, 4);
offset += 4;
updateVertexBuffers["direction"] = source.createVertexBuffer("direction", offset, 3);
offset += 3;
if (this._parent.particleEmitterType instanceof CustomParticleEmitter) {
updateVertexBuffers["initialPosition"] = source.createVertexBuffer("initialPosition", offset, 3);
offset += 3;
}
if (!this._parent._colorGradientsTexture) {
updateVertexBuffers["color"] = source.createVertexBuffer("color", offset, 4);
offset += 4;
}
if (!this._parent._isBillboardBased) {
updateVertexBuffers["initialDirection"] = source.createVertexBuffer("initialDirection", offset, 3);
offset += 3;
}
if (this._parent.noiseTexture) {
updateVertexBuffers["noiseCoordinates1"] = source.createVertexBuffer("noiseCoordinates1", offset, 3);
offset += 3;
updateVertexBuffers["noiseCoordinates2"] = source.createVertexBuffer("noiseCoordinates2", offset, 3);
offset += 3;
}
if (this._parent._angularSpeedGradientsTexture) {
updateVertexBuffers["angle"] = source.createVertexBuffer("angle", offset, 1);
offset += 1;
}
else {
updateVertexBuffers["angle"] = source.createVertexBuffer("angle", offset, 2);
offset += 2;
}
if (this._parent._isAnimationSheetEnabled) {
updateVertexBuffers["cellIndex"] = source.createVertexBuffer("cellIndex", offset, 1);
offset += 1;
if (this._parent.spriteRandomStartCell) {
updateVertexBuffers["cellStartOffset"] = source.createVertexBuffer("cellStartOffset", offset, 1);
offset += 1;
}
}
const vao = this._engine.recordVertexArrayObject(updateVertexBuffers, null, this._updateEffect);
this._engine.bindArrayBuffer(null);
return vao;
}
}
RegisterClass("BABYLON.WebGL2ParticleSystem", WebGL2ParticleSystem);
//# sourceMappingURL=webgl2ParticleSystem.js.map