|
@@ -30,18 +30,18 @@
|
|
public layerMask: number = 0x0FFFFFFF; // TODO
|
|
public layerMask: number = 0x0FFFFFFF; // TODO
|
|
|
|
|
|
private _capacity: number;
|
|
private _capacity: number;
|
|
|
|
+ private _activeCount: number;
|
|
|
|
+ private _currentActiveCount: number;
|
|
private _renderEffect: Effect;
|
|
private _renderEffect: Effect;
|
|
private _updateEffect: Effect;
|
|
private _updateEffect: Effect;
|
|
|
|
|
|
- private _updateBuffer: Buffer;
|
|
|
|
- private _updateVAO: WebGLVertexArrayObject;
|
|
|
|
- private _updateVertexBuffers: {[key: string]: VertexBuffer} = {};
|
|
|
|
- private _renderBuffer: Buffer;
|
|
|
|
- private _renderVAO: WebGLVertexArrayObject;
|
|
|
|
- private _renderVertexBuffers: {[key: string]: VertexBuffer} = {};
|
|
|
|
|
|
+ private _buffer0: Buffer;
|
|
|
|
+ private _buffer1: Buffer;
|
|
|
|
+ private _spriteBuffer: Buffer;
|
|
|
|
+ private _updateVAO = new Array<WebGLVertexArrayObject>();
|
|
|
|
+ private _renderVAO = new Array<WebGLVertexArrayObject>()
|
|
|
|
|
|
- private _sourceVAO: WebGLVertexArrayObject;
|
|
|
|
- private _targetVAO: WebGLVertexArrayObject;
|
|
|
|
|
|
+ private _targetIndex = 0;
|
|
private _sourceBuffer: Buffer;
|
|
private _sourceBuffer: Buffer;
|
|
private _targetBuffer: Buffer;
|
|
private _targetBuffer: Buffer;
|
|
|
|
|
|
@@ -49,7 +49,13 @@
|
|
private _engine: Engine;
|
|
private _engine: Engine;
|
|
|
|
|
|
private _currentRenderId = -1;
|
|
private _currentRenderId = -1;
|
|
- private _started = true;
|
|
|
|
|
|
+ private _started = false;
|
|
|
|
+
|
|
|
|
+ private _timeDelta = 0;
|
|
|
|
+
|
|
|
|
+ private _randomTexture: RawTexture;
|
|
|
|
+
|
|
|
|
+ private readonly _attributesStrideSize = 14;
|
|
|
|
|
|
/**
|
|
/**
|
|
* An event triggered when the system is disposed.
|
|
* An event triggered when the system is disposed.
|
|
@@ -57,6 +63,81 @@
|
|
public onDisposeObservable = new Observable<GPUParticleSystem>();
|
|
public onDisposeObservable = new Observable<GPUParticleSystem>();
|
|
|
|
|
|
/**
|
|
/**
|
|
|
|
+ * The overall motion speed (0.01 is default update speed, faster updates = faster animation)
|
|
|
|
+ */
|
|
|
|
+ public updateSpeed = 0.01;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * The texture used to render each particle. (this can be a spritesheet)
|
|
|
|
+ */
|
|
|
|
+ public particleTexture: Nullable<Texture>;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Blend mode use to render the particle, it can be either ParticleSystem.BLENDMODE_ONEONE or ParticleSystem.BLENDMODE_STANDARD.
|
|
|
|
+ */
|
|
|
|
+ public blendMode = ParticleSystem.BLENDMODE_ONEONE;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Minimum life time of emitting particles.
|
|
|
|
+ */
|
|
|
|
+ public minLifeTime = 1;
|
|
|
|
+ /**
|
|
|
|
+ * Maximum life time of emitting particles.
|
|
|
|
+ */
|
|
|
|
+ public maxLifeTime = 1;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Minimum Size of emitting particles.
|
|
|
|
+ */
|
|
|
|
+ public minSize = 1;
|
|
|
|
+ /**
|
|
|
|
+ * Maximum Size of emitting particles.
|
|
|
|
+ */
|
|
|
|
+ public maxSize = 1;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Random color of each particle after it has been emitted, between color1 and color2 vectors.
|
|
|
|
+ */
|
|
|
|
+ public color1 = new Color4(1.0, 1.0, 1.0, 1.0);
|
|
|
|
+ /**
|
|
|
|
+ * Random color of each particle after it has been emitted, between color1 and color2 vectors.
|
|
|
|
+ */
|
|
|
|
+ public color2 = new Color4(1.0, 1.0, 1.0, 1.0);
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Color the particle will have at the end of its lifetime.
|
|
|
|
+ */
|
|
|
|
+ public colorDead = new Color4(0, 0, 0, 0);
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * The maximum number of particles to emit per frame until we reach the activeParticleCount value
|
|
|
|
+ */
|
|
|
|
+ public emitRate = 100;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * You can use gravity if you want to give an orientation to your particles.
|
|
|
|
+ */
|
|
|
|
+ public gravity = Vector3.Zero();
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Gets the maximum number of particles supported by this system
|
|
|
|
+ */
|
|
|
|
+ public get capacity(): number {
|
|
|
|
+ return this._capacity;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Gets or set the number of active particles
|
|
|
|
+ */
|
|
|
|
+ public get activeParticleCount(): number {
|
|
|
|
+ return this._activeCount;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public set activeParticleCount(value: number) {
|
|
|
|
+ this._activeCount = Math.min(value, this._capacity);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
* Gets Wether the system has been started.
|
|
* Gets Wether the system has been started.
|
|
* @returns True if it has been started, otherwise false.
|
|
* @returns True if it has been started, otherwise false.
|
|
*/
|
|
*/
|
|
@@ -90,86 +171,147 @@
|
|
this.name = name;
|
|
this.name = name;
|
|
this._scene = scene || Engine.LastCreatedScene;
|
|
this._scene = scene || Engine.LastCreatedScene;
|
|
this._capacity = capacity;
|
|
this._capacity = capacity;
|
|
|
|
+ this._activeCount = capacity;
|
|
|
|
+ this._currentActiveCount = 0;
|
|
this._engine = this._scene.getEngine();
|
|
this._engine = this._scene.getEngine();
|
|
|
|
|
|
this._scene.particleSystems.push(this);
|
|
this._scene.particleSystems.push(this);
|
|
|
|
|
|
- this._renderEffect = new Effect("gpuRenderParticles", ["position", "age", "life", "velocity"], [], [], this._scene.getEngine());
|
|
|
|
-
|
|
|
|
let updateEffectOptions: EffectCreationOptions = {
|
|
let updateEffectOptions: EffectCreationOptions = {
|
|
- attributes: ["position", "age", "life", "velocity"],
|
|
|
|
- uniformsNames: [],
|
|
|
|
|
|
+ attributes: ["position", "age", "life", "seed", "size", "color", "direction"],
|
|
|
|
+ uniformsNames: ["currentCount", "timeDelta", "generalRandom", "emitterWM", "lifeTime", "color1", "color2", "sizeRange", "gravity"],
|
|
uniformBuffersNames: [],
|
|
uniformBuffersNames: [],
|
|
- samplers:[],
|
|
|
|
|
|
+ samplers:["randomSampler"],
|
|
defines: "",
|
|
defines: "",
|
|
fallbacks: null,
|
|
fallbacks: null,
|
|
onCompiled: null,
|
|
onCompiled: null,
|
|
onError: null,
|
|
onError: null,
|
|
indexParameters: null,
|
|
indexParameters: null,
|
|
maxSimultaneousLights: 0,
|
|
maxSimultaneousLights: 0,
|
|
- transformFeedbackVaryings: ["outPosition", "outAge", "outLife", "outVelocity"]
|
|
|
|
|
|
+ transformFeedbackVaryings: ["outPosition", "outAge", "outLife", "outSeed", "outSize", "outColor", "outDirection"]
|
|
};
|
|
};
|
|
|
|
|
|
this._updateEffect = new Effect("gpuUpdateParticles", updateEffectOptions, this._scene.getEngine());
|
|
this._updateEffect = new Effect("gpuUpdateParticles", updateEffectOptions, this._scene.getEngine());
|
|
|
|
+
|
|
|
|
+ this._renderEffect = new Effect("gpuRenderParticles", ["position", "age", "life", "size", "color", "offset", "uv"], ["view", "projection", "colorDead"], ["textureSampler"], this._scene.getEngine());
|
|
|
|
+
|
|
|
|
+ // Random data
|
|
|
|
+ var maxTextureSize = this._engine.getCaps().maxTextureSize;
|
|
|
|
+ var d = [];
|
|
|
|
+ for (var i = 0; i < maxTextureSize; ++i) {
|
|
|
|
+ d.push(Math.random());
|
|
|
|
+ d.push(Math.random());
|
|
|
|
+ d.push(Math.random());
|
|
|
|
+ }
|
|
|
|
+ this._randomTexture = new RawTexture(new Float32Array(d), maxTextureSize, 1, Engine.TEXTUREFORMAT_RGB32F, this._scene, false, false, Texture.NEAREST_SAMPLINGMODE, Engine.TEXTURETYPE_FLOAT)
|
|
|
|
+ this._randomTexture.wrapU = Texture.WRAP_ADDRESSMODE;
|
|
|
|
+ this._randomTexture.wrapV = Texture.WRAP_ADDRESSMODE;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
* Animates the particle system for the current frame by emitting new particles and or animating the living ones.
|
|
* Animates the particle system for the current frame by emitting new particles and or animating the living ones.
|
|
*/
|
|
*/
|
|
public animate(): void {
|
|
public animate(): void {
|
|
- // Do nothing
|
|
|
|
|
|
+ if (this._currentRenderId === this._scene.getRenderId()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this._currentRenderId = this._scene.getRenderId();
|
|
|
|
+ this._timeDelta = this.updateSpeed * this._scene.getAnimationRatio();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private _createUpdateVAO(source: Buffer): WebGLVertexArrayObject {
|
|
|
|
+ let updateVertexBuffers: {[key: string]: VertexBuffer} = {};
|
|
|
|
+ updateVertexBuffers["position"] = source.createVertexBuffer("position", 0, 3);
|
|
|
|
+ updateVertexBuffers["age"] = source.createVertexBuffer("age", 3, 1);
|
|
|
|
+ updateVertexBuffers["life"] = source.createVertexBuffer("life", 4, 1);
|
|
|
|
+ updateVertexBuffers["seed"] = source.createVertexBuffer("seed", 5, 1);
|
|
|
|
+ updateVertexBuffers["size"] = source.createVertexBuffer("size", 6, 1);
|
|
|
|
+ updateVertexBuffers["color"] = source.createVertexBuffer("color", 7, 4);
|
|
|
|
+ updateVertexBuffers["direction"] = source.createVertexBuffer("direction", 11, 3);
|
|
|
|
+
|
|
|
|
+ let vao = this._engine.recordVertexArrayObject(updateVertexBuffers, null, this._updateEffect);
|
|
|
|
+ this._engine.bindArrayBuffer(null);
|
|
|
|
+
|
|
|
|
+ return vao;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ private _createRenderVAO(source: Buffer, spriteSource: Buffer): WebGLVertexArrayObject {
|
|
|
|
+ let renderVertexBuffers: {[key: string]: VertexBuffer} = {};
|
|
|
|
+ renderVertexBuffers["position"] = source.createVertexBuffer("position", 0, 3, this._attributesStrideSize, true);
|
|
|
|
+ renderVertexBuffers["age"] = source.createVertexBuffer("age", 3, 1, this._attributesStrideSize, true);
|
|
|
|
+ renderVertexBuffers["life"] = source.createVertexBuffer("life", 4, 1, this._attributesStrideSize, true);
|
|
|
|
+ renderVertexBuffers["size"] = source.createVertexBuffer("size", 6, 1, this._attributesStrideSize, true);
|
|
|
|
+ renderVertexBuffers["color"] = source.createVertexBuffer("color", 7, 4, this._attributesStrideSize, true);
|
|
|
|
+
|
|
|
|
+ renderVertexBuffers["offset"] = spriteSource.createVertexBuffer("offset", 0, 2);
|
|
|
|
+ renderVertexBuffers["uv"] = spriteSource.createVertexBuffer("uv", 2, 2);
|
|
|
|
+
|
|
|
|
+ let vao = this._engine.recordVertexArrayObject(renderVertexBuffers, null, this._renderEffect);
|
|
|
|
+ this._engine.bindArrayBuffer(null);
|
|
|
|
+
|
|
|
|
+ return vao;
|
|
|
|
+ }
|
|
|
|
|
|
private _initialize(): void {
|
|
private _initialize(): void {
|
|
- if (this._renderVAO) {
|
|
|
|
|
|
+ if (this._buffer0) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ let engine = this._scene.getEngine();
|
|
var data = new Array<float>();
|
|
var data = new Array<float>();
|
|
for (var particleIndex = 0; particleIndex < this._capacity; particleIndex++) {
|
|
for (var particleIndex = 0; particleIndex < this._capacity; particleIndex++) {
|
|
// position
|
|
// position
|
|
data.push(0.0);
|
|
data.push(0.0);
|
|
data.push(0.0);
|
|
data.push(0.0);
|
|
data.push(0.0);
|
|
data.push(0.0);
|
|
-
|
|
|
|
- var life = 1 + Math.random() * 10; // TODO: var
|
|
|
|
- data.push(life + 1); // create the particle as a dead one to create a new one at start
|
|
|
|
- data.push(life);
|
|
|
|
-
|
|
|
|
- // velocity
|
|
|
|
|
|
+
|
|
|
|
+ // Age and life
|
|
|
|
+ data.push(0.0); // create the particle as a dead one to create a new one at start
|
|
|
|
+ data.push(0.0);
|
|
|
|
+
|
|
|
|
+ // Seed
|
|
|
|
+ data.push(Math.random());
|
|
|
|
+
|
|
|
|
+ // Size
|
|
|
|
+ data.push(0.0);
|
|
|
|
+
|
|
|
|
+ // color
|
|
data.push(0.0);
|
|
data.push(0.0);
|
|
data.push(0.0);
|
|
data.push(0.0);
|
|
|
|
+ data.push(0.0);
|
|
|
|
+ data.push(0.0);
|
|
|
|
+
|
|
|
|
+ // direction
|
|
data.push(0.0);
|
|
data.push(0.0);
|
|
|
|
+ data.push(0.0);
|
|
|
|
+ data.push(0.0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // Sprite data
|
|
|
|
+ var spriteData = new Float32Array([1, 1, 1, 1,
|
|
|
|
+ -1, 1, 0, 1,
|
|
|
|
+ -1, -1, 0, 0,
|
|
|
|
+ 1, -1, 1, 0]);
|
|
|
|
+
|
|
|
|
+ // Buffers
|
|
|
|
+ this._buffer0 = new Buffer(engine, data, false, this._attributesStrideSize);
|
|
|
|
+ this._buffer1 = new Buffer(engine, data, false, this._attributesStrideSize);
|
|
|
|
+ this._spriteBuffer = new Buffer(engine, spriteData, false, 4);
|
|
|
|
+
|
|
// Update VAO
|
|
// Update VAO
|
|
- this._updateBuffer = new Buffer(this._scene.getEngine(), data, false, 0);
|
|
|
|
- this._updateVertexBuffers["position"] = this._updateBuffer.createVertexBuffer("position", 0, 3, 3);
|
|
|
|
- this._updateVertexBuffers["age"] = this._updateBuffer.createVertexBuffer("age", 3, 1, 1);
|
|
|
|
- this._updateVertexBuffers["life"] = this._updateBuffer.createVertexBuffer("life", 4, 1, 1);
|
|
|
|
- this._updateVertexBuffers["velocity"] = this._updateBuffer.createVertexBuffer("velocity", 5, 3, 3);
|
|
|
|
-
|
|
|
|
- this._updateVAO = this._engine.recordVertexArrayObject(this._updateVertexBuffers, null, this._updateEffect);
|
|
|
|
- this._engine.bindArrayBuffer(null);
|
|
|
|
|
|
+ this._updateVAO.push(this._createUpdateVAO(this._buffer0));
|
|
|
|
+ this._updateVAO.push(this._createUpdateVAO(this._buffer1));
|
|
|
|
|
|
// Render VAO
|
|
// Render VAO
|
|
- this._renderBuffer = new Buffer(this._scene.getEngine(), data, false, 0);
|
|
|
|
- this._renderVertexBuffers["position"] = this._renderBuffer.createVertexBuffer("position", 0, 3, 3);
|
|
|
|
- this._renderVertexBuffers["age"] = this._renderBuffer.createVertexBuffer("age", 3, 1, 1);
|
|
|
|
- this._renderVertexBuffers["life"] = this._renderBuffer.createVertexBuffer("life", 4, 1, 1);
|
|
|
|
- this._renderVertexBuffers["velocity"] = this._renderBuffer.createVertexBuffer("velocity", 5, 3, 3);
|
|
|
|
-
|
|
|
|
- this._renderVAO = this._engine.recordVertexArrayObject(this._renderVertexBuffers, null, this._renderEffect);
|
|
|
|
- this._engine.bindArrayBuffer(null);
|
|
|
|
|
|
+ this._renderVAO.push(this._createRenderVAO(this._buffer1, this._spriteBuffer));
|
|
|
|
+ this._renderVAO.push(this._createRenderVAO(this._buffer0, this._spriteBuffer));
|
|
|
|
|
|
// Links
|
|
// Links
|
|
- this._sourceVAO = this._updateVAO;
|
|
|
|
- this._targetVAO = this._renderVAO;
|
|
|
|
|
|
+ this._sourceBuffer = this._buffer0;
|
|
|
|
+ this._targetBuffer = this._buffer1;
|
|
|
|
|
|
- this._sourceBuffer = this._updateBuffer;
|
|
|
|
- this._targetBuffer = this._renderBuffer;
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
/**
|
|
/**
|
|
* Renders the particle system in its current state.
|
|
* Renders the particle system in its current state.
|
|
* @returns the current number of particles.
|
|
* @returns the current number of particles.
|
|
@@ -181,42 +323,71 @@
|
|
|
|
|
|
// Get everything ready to render
|
|
// Get everything ready to render
|
|
this. _initialize();
|
|
this. _initialize();
|
|
-
|
|
|
|
- if (this._currentRenderId === this._scene.getRenderId()) {
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- this._currentRenderId = this._scene.getRenderId();
|
|
|
|
|
|
|
|
|
|
+ this._currentActiveCount = Math.min(this._activeCount, this._currentActiveCount + this.emitRate);
|
|
|
|
+
|
|
// Enable update effect
|
|
// Enable update effect
|
|
this._engine.enableEffect(this._updateEffect);
|
|
this._engine.enableEffect(this._updateEffect);
|
|
- this._engine.setState(false);
|
|
|
|
|
|
+ this._engine.setState(false);
|
|
|
|
+
|
|
|
|
+ this._updateEffect.setFloat("currentCount", this._currentActiveCount);
|
|
|
|
+ this._updateEffect.setFloat("timeDelta", this._timeDelta);
|
|
|
|
+ this._updateEffect.setFloat("generalRandom", Math.random());
|
|
|
|
+ this._updateEffect.setTexture("randomSampler", this._randomTexture);
|
|
|
|
+ this._updateEffect.setFloat2("lifeTime", this.minLifeTime, this.maxLifeTime);
|
|
|
|
+ this._updateEffect.setDirectColor4("color1", this.color1);
|
|
|
|
+ this._updateEffect.setDirectColor4("color2", this.color2);
|
|
|
|
+ this._updateEffect.setFloat2("sizeRange", this.minSize, this.maxSize);
|
|
|
|
+ this._updateEffect.setVector3("gravity", this.gravity);
|
|
|
|
+
|
|
|
|
+ let emitterWM: Matrix;
|
|
|
|
+ if ((<AbstractMesh>this.emitter).position) {
|
|
|
|
+ var emitterMesh = (<AbstractMesh>this.emitter);
|
|
|
|
+ emitterWM = emitterMesh.getWorldMatrix();
|
|
|
|
+ } else {
|
|
|
|
+ var emitterPosition = (<Vector3>this.emitter);
|
|
|
|
+ emitterWM = Matrix.Translation(emitterPosition.x, emitterPosition.y, emitterPosition.z);
|
|
|
|
+ }
|
|
|
|
+ this._updateEffect.setMatrix("emitterWM", emitterWM);
|
|
|
|
|
|
// Bind source VAO
|
|
// Bind source VAO
|
|
- this._engine.bindVertexArrayObject(this._sourceVAO, null);
|
|
|
|
|
|
+ this._engine.bindVertexArrayObject(this._updateVAO[this._targetIndex], null);
|
|
|
|
|
|
// Update
|
|
// Update
|
|
this._engine.bindTransformFeedbackBuffer(this._targetBuffer.getBuffer());
|
|
this._engine.bindTransformFeedbackBuffer(this._targetBuffer.getBuffer());
|
|
this._engine.setRasterizerState(false);
|
|
this._engine.setRasterizerState(false);
|
|
this._engine.beginTransformFeedback();
|
|
this._engine.beginTransformFeedback();
|
|
- this._engine.drawArraysType(Material.PointListDrawMode, 0, this._capacity);
|
|
|
|
|
|
+ this._engine.drawArraysType(Material.PointListDrawMode, 0, this._currentActiveCount);
|
|
this._engine.endTransformFeedback();
|
|
this._engine.endTransformFeedback();
|
|
this._engine.setRasterizerState(true);
|
|
this._engine.setRasterizerState(true);
|
|
this._engine.bindTransformFeedbackBuffer(null);
|
|
this._engine.bindTransformFeedbackBuffer(null);
|
|
|
|
|
|
// Enable render effect
|
|
// Enable render effect
|
|
this._engine.enableEffect(this._renderEffect);
|
|
this._engine.enableEffect(this._renderEffect);
|
|
|
|
+ this._renderEffect.setMatrix("view", this._scene.getViewMatrix());
|
|
|
|
+ this._renderEffect.setMatrix("projection", this._scene.getProjectionMatrix());
|
|
|
|
+ this._renderEffect.setTexture("textureSampler", this.particleTexture);
|
|
|
|
+ this._renderEffect.setDirectColor4("colorDead", this.colorDead);
|
|
|
|
+
|
|
|
|
+ // Draw order
|
|
|
|
+ if (this.blendMode === ParticleSystem.BLENDMODE_ONEONE) {
|
|
|
|
+ this._engine.setAlphaMode(Engine.ALPHA_ONEONE);
|
|
|
|
+ } else {
|
|
|
|
+ this._engine.setAlphaMode(Engine.ALPHA_COMBINE);
|
|
|
|
+ }
|
|
|
|
|
|
// Bind source VAO
|
|
// Bind source VAO
|
|
- this._engine.bindVertexArrayObject(this._targetVAO, null);
|
|
|
|
|
|
+ this._engine.bindVertexArrayObject(this._renderVAO[this._targetIndex], null);
|
|
|
|
|
|
// Render
|
|
// Render
|
|
- this._engine.drawArraysType(Material.PointListDrawMode, 0, this._capacity);
|
|
|
|
|
|
+ this._engine.drawArraysType(Material.TriangleFanDrawMode, 0, 4, this._currentActiveCount);
|
|
|
|
+ this._engine.setAlphaMode(Engine.ALPHA_DISABLE);
|
|
|
|
|
|
// Switch VAOs
|
|
// Switch VAOs
|
|
- let tmpVAO = this._sourceVAO;
|
|
|
|
- this._sourceVAO = this._targetVAO;
|
|
|
|
- this._targetVAO = tmpVAO;
|
|
|
|
|
|
+ this._targetIndex++;
|
|
|
|
+ if (this._targetIndex === 2) {
|
|
|
|
+ this._targetIndex = 0;
|
|
|
|
+ }
|
|
|
|
|
|
// Switch buffers
|
|
// Switch buffers
|
|
let tmpBuffer = this._sourceBuffer;
|
|
let tmpBuffer = this._sourceBuffer;
|
|
@@ -242,7 +413,29 @@
|
|
this._scene.particleSystems.splice(index, 1);
|
|
this._scene.particleSystems.splice(index, 1);
|
|
}
|
|
}
|
|
|
|
|
|
- //TODO: this._dataBuffer.dispose();
|
|
|
|
|
|
+ if (this._buffer0) {
|
|
|
|
+ this._buffer0.dispose();
|
|
|
|
+ (<any>this._buffer0) = null;
|
|
|
|
+ }
|
|
|
|
+ if (this._buffer1) {
|
|
|
|
+ this._buffer1.dispose();
|
|
|
|
+ (<any>this._buffer1) = null;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (var index = 0; index < this._updateVAO.length; index++) {
|
|
|
|
+ this._engine.releaseVertexArrayObject(this._updateVAO[index]);
|
|
|
|
+ }
|
|
|
|
+ this._updateVAO = [];
|
|
|
|
+
|
|
|
|
+ for (var index = 0; index < this._renderVAO.length; index++) {
|
|
|
|
+ this._engine.releaseVertexArrayObject(this._renderVAO[index]);
|
|
|
|
+ }
|
|
|
|
+ this._renderVAO = [];
|
|
|
|
+
|
|
|
|
+ if (this._randomTexture) {
|
|
|
|
+ this._randomTexture.dispose();
|
|
|
|
+ (<any>this._randomTexture) = null;
|
|
|
|
+ }
|
|
|
|
|
|
// Callback
|
|
// Callback
|
|
this.onDisposeObservable.notifyObservers(this);
|
|
this.onDisposeObservable.notifyObservers(this);
|