New weird behavior of the particleSystem since the last 12h

Good morning,

I quickly wanted to inform you about my latest issue with #particleSystem. I was using the preview version of 'babylon.js’ in my project as of yesterday evening (12h ago). But this morning, I had to roll back to cdn because of this new weird behavior of my particles (see screenshot - to the left the actual preview, to the right the actual cdn).

My particles are now sort of ‘constrained’ in some undetermined manner. At first, I thought there might have been a change in measurements (of the emitter, of lifetime or anything like that) but for whatever input/property I tried to change in the inspector, got just about no result. I don’t really have time to investigate on this (nor would I have the skills probably;) but I’d rather have the actual (cdn) version persist/'hold-‘on’ for the release of my project. I wouldn’t be very happy if I had to redo all my handling of #particleSystem… Thanks for taking a look at it and eventually inform me about the new constraints/evolution for this part.

particles-issue_11262020

I have performed some testings in the Playground by creating a particle system with sphere emitter and it does work for me.

Is it possible for you to make a repro with a particle system that would not work?

In the meantime, you can test a couple of things:

  • try to put engine.getCaps().instancedArrays = false; very early in your code and see if it helps. It disables instancing support, so the particle system will use another code path than the standard one
  • put back engine.getCaps().instancedArrays = true; (or better, remove it) and add this code in your project:
BABYLON.ParticleSystem.prototype._createVertexBuffers = function () {
    this._vertexBufferSize = this._useInstancing ? 10 : 12;
    if (this._isAnimationSheetEnabled) {
        this._vertexBufferSize += 1;
    }

    if (!this._isBillboardBased || this.billboardMode === BABYLON.ParticleSystem.BILLBOARDMODE_STRETCHED) {
        this._vertexBufferSize += 3;
    }

    if (this._useRampGradients) {
        this._vertexBufferSize += 4;
    }

    let engine = this._engine;
    this._vertexData = new Float32Array(this._capacity * this._vertexBufferSize * (this._useInstancing ? 1 : 4));
    this._vertexBuffer = new BABYLON.Buffer(engine, this._vertexData, true, this._vertexBufferSize);

    let dataOffset = 0;
    var positions = this._vertexBuffer.createVertexBuffer(BABYLON.VertexBuffer.PositionKind, dataOffset, 3, this._vertexBufferSize, this._useInstancing);
    this._vertexBuffers[BABYLON.VertexBuffer.PositionKind] = positions;
    dataOffset += 3;

    var colors = this._vertexBuffer.createVertexBuffer(BABYLON.VertexBuffer.ColorKind, dataOffset, 4, this._vertexBufferSize, this._useInstancing);
    this._vertexBuffers[BABYLON.VertexBuffer.ColorKind] = colors;
    dataOffset += 4;

    var options = this._vertexBuffer.createVertexBuffer("angle", dataOffset, 1, this._vertexBufferSize, this._useInstancing);
    this._vertexBuffers["angle"] = options;
    dataOffset += 1;

    var size = this._vertexBuffer.createVertexBuffer("size", dataOffset, 2, this._vertexBufferSize, this._useInstancing);
    this._vertexBuffers["size"] = size;
    dataOffset += 2;

    if (this._isAnimationSheetEnabled) {
        var cellIndexBuffer = this._vertexBuffer.createVertexBuffer("cellIndex", dataOffset, 1, this._vertexBufferSize, this._useInstancing);
        this._vertexBuffers["cellIndex"] = cellIndexBuffer;
        dataOffset += 1;
    }

    if (!this._isBillboardBased || this.billboardMode === BABYLON.ParticleSystem.BILLBOARDMODE_STRETCHED) {
        var directionBuffer = this._vertexBuffer.createVertexBuffer("direction", dataOffset, 3, this._vertexBufferSize, this._useInstancing);
        this._vertexBuffers["direction"] = directionBuffer;
        dataOffset += 3;
    }

    if (this._useRampGradients) {
        var rampDataBuffer = this._vertexBuffer.createVertexBuffer("remapData", dataOffset, 4, this._vertexBufferSize, this._useInstancing);
        this._vertexBuffers["remapData"] = rampDataBuffer;
        dataOffset += 4;
    }

    var offsets;
    if (this._useInstancing) {
        //var spriteData = new Float32Array([0, 0, 1, 0, 0, 1, 1, 1]);
        var spriteData = new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]);
        this._spriteBuffer = new BABYLON.Buffer(engine, spriteData, false, 2);
        offsets = this._spriteBuffer.createVertexBuffer("offset", 0, 2);
    } else {
        offsets = this._vertexBuffer.createVertexBuffer("offset", dataOffset, 2, this._vertexBufferSize, this._useInstancing);
        dataOffset += 2;
    }
    this._vertexBuffers["offset"] = offsets;

}

BABYLON.ParticleSystem.prototype._render = function (blendMode) {
    var effect = this._getEffect(blendMode);

    var engine = this._engine;

    // Render
    engine.enableEffect(effect);

    var viewMatrix = this.defaultViewMatrix ? this.defaultViewMatrix : this._scene.getViewMatrix();
    effect.setTexture("diffuseSampler", this.particleTexture);
    effect.setMatrix("view", viewMatrix);
    effect.setMatrix("projection", this.defaultProjectionMatrix ? this.defaultProjectionMatrix : this._scene.getProjectionMatrix());

    if (this._isAnimationSheetEnabled && this.particleTexture) {
        var baseSize = this.particleTexture.getBaseSize();
        effect.setFloat3("particlesInfos", this.spriteCellWidth / baseSize.width, this.spriteCellHeight / baseSize.height, this.spriteCellWidth / baseSize.width);
    }

    effect.setVector2("translationPivot", this.translationPivot);
    effect.setFloat4("textureMask", this.textureMask.r, this.textureMask.g, this.textureMask.b, this.textureMask.a);

    if (this._isBillboardBased && this._scene) {
        var camera = this._scene.activeCamera;
        effect.setVector3("eyePosition", camera.globalPosition);
    }

    if (this._rampGradientsTexture) {
        if (!this._rampGradients || !this._rampGradients.length) {
            this._rampGradientsTexture.dispose();
            this._rampGradientsTexture = null;
        }
        effect.setTexture("rampSampler", this._rampGradientsTexture);
    }

    const defines = effect.defines;

    if (this._scene) {
        if (this._scene.clipPlane || this._scene.clipPlane2 || this._scene.clipPlane3 || this._scene.clipPlane4 || this._scene.clipPlane5 || this._scene.clipPlane6) {
            BABYLON.ThinMaterialHelper.BindClipPlane(effect, this._scene);
        }
    }

    if (defines.indexOf("#define BILLBOARDMODE_ALL") >= 0) {
        viewMatrix.invertToRef(BABYLON.TmpVectors.Matrix[0]);
        effect.setMatrix("invView", BABYLON.TmpVectors.Matrix[0]);
    }

    engine.bindBuffers(this._vertexBuffers, this._indexBuffer, effect);

    // image processing
    if (this._imageProcessingConfiguration && !this._imageProcessingConfiguration.applyByPostProcess) {
        this._imageProcessingConfiguration.bind(effect);
    }

    // Draw order
    switch (blendMode) {
        case BABYLON.ParticleSystem.BLENDMODE_ADD:
            engine.setAlphaMode(BABYLON.Constants.ALPHA_ADD);
            break;
        case BABYLON.ParticleSystem.BLENDMODE_ONEONE:
            engine.setAlphaMode(BABYLON.Constants.ALPHA_ONEONE);
            break;
        case BABYLON.ParticleSystem.BLENDMODE_STANDARD:
            engine.setAlphaMode(BABYLON.Constants.ALPHA_COMBINE);
            break;
        case BABYLON.ParticleSystem.BLENDMODE_MULTIPLY:
            engine.setAlphaMode(BABYLON.Constants.ALPHA_MULTIPLY);
            break;
    }

    if (this._onBeforeDrawParticlesObservable) {
        this._onBeforeDrawParticlesObservable.notifyObservers(effect);
    }

    if (this._useInstancing) {
        //engine.drawArraysType(BABYLON.Constants.MATERIAL_TriangleStripDrawMode, 0, 4, this._particles.length);
        engine.drawArraysType(BABYLON.Constants.MATERIAL_TriangleFanDrawMode, 0, 4, this._particles.length);
    } else {
        engine.drawElementsType(BABYLON.Constants.MATERIAL_TriangleFillMode, 0, this._particles.length * 6);
    }

    return this._particles.length;
}

It will put back the usage of triangle fans instead of triangle strips, which has been a late change to the particle system. I checked on the playground that the new and old way does still work, but…

Thank you for this prompt answer. I shall try this shortly.
The code for this part is an old version (and an early version from my learning) from March/April. I needed to eventually go back to it, since the ’snow effect’ is a main part of the project.
The code is likely to be a bit mess (or overcrowded;), so I shall have a look at it and will also try set up a playground example reproducing this behavior/error. In any case, thanks a late for the info about the late change(s); it sure gives me a clue about the possible source of the problem (or my error).

quickly checked both solution as early as after

«

var delayCreateScene = function () {
engine.displayLoadingUI();
var scene = new BABYLON.Scene(engine);
engine.getCaps().instancedArrays = true;
«

Either, it’s not early enough, too early or simply not working with my faen code:(
None of these options change anything. They do not throw an error, but they don’t change anything.
I believe I will have to try’n set up a playground reproducing this. And while doing this, there’s still a chance I might find my error or my ‘unhanded’ twist;)
Will be back on it anyway (for now, I’m struggling with another topic for #spritesheet animation and #babylon GUI (2d GUI). I was actually investigating this problem with my handling of an animated 2D GUI spreadsheet for buttons when I bumped into this new issue with #particles. A sad day;)…
Thanks again,

@mawa we did a big merge yesterday and I am afraid we might have introduced a regression.

Is it possible for you to share your code with us (in private messages) ? and if not, could you in the playground only copy your particle system setup ?

I will see what I can do to quickly set up a playground repro. I’m not really willing to share the code at this stage of the project because for now it’s mostly just a ‘pilling-up’ from a large variety of babylon’s features;) I’d like to clean it at least a little bit before sharing. But I will definitely try to set up something. Just had some other things I needed to focus on…
Thanks again,

no rush and thanks a lot, isolating the particle system issue would be way better for us anyway :slight_smile:

Also are you using pointsCloudSystem, GpuParticles or regular particles, which can help narrowing our search until we get your repro ?

no pointsCloud, but I’m using GPU (currently on just one of my particleSystems). The snowball snow effect. I was running some tests also with the warm-up feature… As I said, I need to quickly go back to it and will try to set up something (after dinner;). Thanks,

I’m making some tests while trying to set-up the playground repro and it looks like it could have something to do with the ‘update speed’. Does this ring a bell?
It’s the only parameter I can change where I can actually see a real difference. For now, I’ve remove ‘animated cells’(animationSheet) and returned to just the simple ‘flare.png’ image, I’ve also removed lifetime- and velocity-gradients & GPU particles,I did extend the lifetime of particles, removed all of ‘warm-up’ or ‘delay’ and rendering group in case of an issue with the blend/alpha. I’m still getting the same result.
I’ll keep you posted…

Ok, so here’s my repro in the playground, based on the ‘emit particles from a box’ from the intro to the particle system (https://playground.babylonjs.com/#0K3AQ2#5)

This is my version (somewhat simplified but still featuring the problem):
https://playground.babylonjs.com/#0K3AQ2#5

Change the ‘preview/*’ with ’cdn.babylonjs.com/babylon.js’ and you shall clearly see the difference.

Let me know when you get an input on this. I’m eager to understand just where I messed it up again;)
Thanks a lot,

@mawa are you sure you shared the right one ??? you have shared 2 times the same url
and for me locally both versions do the exact same ???

Ok found it https://playground.babylonjs.com/#0K3AQ2#81 is acting differently !!!

thanks alot

sorry wrong link (getting tired;)
here’s the repro:

https://playground.babylonjs.com/#0K3AQ2#81

NP. sry for spamming. As I said, getting tired. I’m gonna go for a rest now and will return on it tomorrow morning.
GL with the topic.

Nah all goood have a good rest the bug is definitely on our side we ll fix it ASAP probably in the next nightly.

Fix is in and will be available in the next nightly in about 1 hour Fix WebGPU Particles NoiseTexture by sebavan · Pull Request #9491 · BabylonJS/Babylon.js · GitHub

Thank you for this quick reaction,
For whatever you did, your magic worked. :mage:
I hope you manage to also get a rest from time to time :relieved: