我正在尝试对 HTML5 游戏使用以下效果:http: //somethinghitme.com/projects/metaballs/
但由于它是一款游戏(而不是图形演示),我对 FPS 的要求更严格,我需要时间来计算物理和其他一些东西,而我最大的瓶颈是元球的代码。
以下代码是我在剥离原始代码以获得性能后得到的,它不是很漂亮,但对于我的目的来说已经足够了:
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);
}
我的代码有另一个循环,我设法通过使用以下链接http://www.fatagnus.com/unrolling-your-loop-for-better-performance-in-javascript/中描述的技术来提高其性能,但是在此使用相同实际上会降低性能(也许我做错了?)
我还研究了网络工作者,看看我是否可以拆分负载(因为代码分别为每个像素运行)但我在这个链接上找到的例子http://blogs.msdn.com/b/eternalcoding/archive/2012/09 /20/using-web-workers-to-improve-performance-of-image-manipulation.aspx在使用网络工作者时实际上运行速度较慢。
我还可以做些什么?有没有办法从循环中删除分支?另一种展开方式?或者这是我能做的最好的吗?
编辑:
这是一些周围的代码:
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);
}
及处理方法:
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();
};
可以看出,我尝试使用图像代替渐变形状,但性能更差,我也尝试使用 ctx.drawImage 代替 putImageData,但它丢失了 alpha 并且速度并不快。我想不出替代方案来达到预期的效果。当前代码在 Google Chrome 上运行完美,但 Safari 和 Firefox 真的很慢。还有什么我可以尝试的吗?我应该放弃那些浏览器吗?