Zwiększenie wydajności w czasie rzeczywistym na efektach płótna

Próbuję użyć następującego efektu w grze HTML5:http://somethinghitme.com/projects/metaballs/

Ale ponieważ jest to gra (w przeciwieństwie do demonstracji graficznej), mam ściślejsze wymagania FPS, potrzebuję czasu na obliczenie fizyki i kilku innych rzeczy, a moim największym wąskim gardłem jest kod metaballów.

Poniższy kod jest tym, co dostałem po usunięciu oryginalnego kodu dla wydajności, nie jest tak ładny, ale wystarcza do moich celów:

ParticleSpawner.prototype.metabilize = function(ctx) {
    var imageData = this._tempCtx.getImageData(0,0,900,675),
    pix = imageData.data;
    this._tempCtx.putImageData(imageData,0,0);

    for (var i = 0, n = pix.length; i <n; i += 4) {
        if(pix[i+3]<210){
            pix[i+3] = 0;
        }
    }

    //ctx.clearRect(0,0,900,675);
    //ctx.drawImage(this._tempCanvas,0,0);
    ctx.putImageData(imageData, 0, 0);
}

Miałem kolejną pętlę na moim kodzie i udało mi się zwiększyć jej wydajność, używając techniki opisanej w poniższym linkuhttp://www.fatagnus.com/unrolling-your-loop-for-better-performance-in-javascript/ ale używanie tego samego w rzeczywistości zmniejsza wydajność (może zrobiłem to źle?)

Zbadałem również pracowników sieci, aby sprawdzić, czy mogę podzielić ładunek (ponieważ kod działa dla każdego piksela osobno), ale przykład, który znalazłem na tym linkuhttp://blogs.msdn.com/b/eternalcoding/archive/2012/09/20/using-web-workers-to-improve-performance-of-image-manipulation.aspx faktycznie działa wolniej, gdy korzystasz z pracowników internetowych.

Co jeszcze mogę zrobić? Czy istnieje sposób na usunięcie rozgałęzienia z pętli? Inny sposób na rozwinięcie go? Czy jest to najlepsze, co mogę zrobić?

Edytować:

Oto niektóre z otaczającego kodu:

ParticleSpawner.prototype.drawParticles = function(ctx) {
    this._tempCtx.clearRect(0,0,900,675);

    var iterations = Math.floor(this._particles.getNumChildren() / 8);
    var leftover = this._particles.getNumChildren() % 8;
    var i = 0;

    if(leftover > 0) {
        do {
            this.process(i++);
        } while(--leftover > 0);
    }

    do {
        this.process(i++);
        this.process(i++);
        this.process(i++);
        this.process(i++);
        this.process(i++);
        this.process(i++);
        this.process(i++);
        this.process(i++);
    } while(--iterations > 0);

    this.metabilize(ctx);

}

i metoda procesu:

ParticleSpawner.prototype.process = function(i) {
    if(!this._particles.getChildAt(i)) return;
    var bx = this._particles.getChildAt(i).x;
    var by = this._particles.getChildAt(i).y;

    if(bx > 910 || bx < -10 || by > 685) {
        this._particles.getChildAt(i).destroy();
        return;
    }

    //this._tempCtx.drawImage(this._level._queue.getResult("particleGradient"),bx-20,by-20);

    var grad = this._tempCtx.createRadialGradient(bx,by,1,bx,by,20);
    this._tempCtx.beginPath();

    var color = this._particles.getChildAt(i).color;
    var c = "rgba("+color.r+","+color.g+","+color.b+",";

    grad.addColorStop(0, c+'1.0)');
    grad.addColorStop(0.6, c+'0.5)');
    grad.addColorStop(1, c+'0)');

    this._tempCtx.fillStyle = grad;
    this._tempCtx.arc(bx, by, 20, 0, Math.PI*2);
    this._tempCtx.fill();

};

Jak widać, próbowałem użyć obrazów zamiast kształtów gradientowych, ale wydajność była gorsza, próbowałem też użyć ctx.drawImage zamiast putImageData, ale traci alfa i nie jest szybszy. Nie mogę wymyślić alternatywy, aby osiągnąć pożądany efekt. Obecny kod działa doskonale w Google Chrome, ale Safari i Firefox są naprawdę wolne. Czy mogę coś jeszcze spróbować? Czy powinienem po prostu zrezygnować z tych przeglądarek?

questionAnswers(4)

yourAnswerToTheQuestion