【问题标题】:Drawing elements that aren't on canvas - expensive?不在画布上的绘图元素 - 昂贵?
【发布时间】:2016-04-28 02:24:22
【问题描述】:

我正在制作一个 JavaScript 游戏引擎 - demo - 我想知道这些选项中哪一个在画布上绘图成本最低:

  • 有条件检查对象的 x 和 y 坐标是否在高度和宽度范围内。
  • 不管怎样画对象,虽然很多不会出现。

第一个选项需要为每个对象和每个动画循环比较四个或更多的变量。我想知道这是否比绘制所有对象更便宜。

实际的游戏将有许多具有 x 和 y 坐标的对象,其画布以人类玩家为中心,位于更大的游戏地图上。

我使用 requestAnimationFrame 来进行绘制循环。我也没有使用任何框架。

【问题讨论】:

  • 为什么不使用分析器来检查呢?如果您可以使用更接近您的真实世界场景的东西,那就最好了。
  • 抱歉,在这里显示我的无知 - 什么是分析器?
  • 分析器可让您衡量性能。下面是 Chrome profiler 的介绍:developer.chrome.com/devtools/docs/cpu-profiling
  • 那太棒了。我会尝试两个,让你们知道会发生什么
  • 我的两分钱,如果您只需要根据某些条件进行绘制,最好经常检查,与单个画布绘图相比,额外的 if 或 4 个 if 是微不足道的费用......

标签: javascript html canvas


【解决方案1】:

GPU 会忽略屏幕外绘图,因此渲染时间更短(嗯——不是渲染!)。但是 CPU 仍会处理绘图命令,因此屏幕外绘图不是“免费的”。

但是您的性能受到了第二次打击。您正在按照自己的路径绘制每个圆圈:

ctx.beginPath();
ctx.arc(p.x,p.y,p.r,0,PI2);
ctx.fillStyle=p.color;
ctx.fill();       

在单个(多圆)路径中绘制所有常用颜色的弧线更有效:

ctx.fillStyle='red';
ctx.beginPath();
for(var i=0;i<len;i++){
    var p=players[i];
    if(p.color=='red'){
        ctx.moveTo(p.x,p.y);
        ctx.arc(p.x,p.y,p.r,0,PI2);
    }
}
ctx.fill();

这是一组高度未优化的性能测试:

  • 使用单独的 beginPath 路径在屏幕上绘制圆圈。
  • 使用单独的 beginPath 路径绘制屏幕外圆圈。
  • 在屏幕上绘制圆,每种颜色有 1 个多圆路径。
  • 使用每种颜色的 1 个多圆路径绘制屏幕外圆。

在我的普通开发计算机上,这些是性能结果:

  • 屏幕/单个路径:1050 毫秒
  • 离屏/单独路径:427ms

  • 屏幕上/每种颜色一条路径:528ms

  • 屏幕外/每种颜色一条路径:220 毫秒

高度未优化的性能测试:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var colors=['red','green','blue','gold'];
var playersOnscreen=[];
var playersOffscreen=[];
for(var c=0;c<colors.length;c++){
    var color=colors[c];
    for(var p=0;p<100;p++){
        playersOnscreen.push({x:50,y:50,r:10,color:color});
    }
}
for(var c=0;c<colors.length;c++){
    var color=colors[c];
    for(var p=0;p<100;p++){
        playersOffscreen.push({x:-50,y:50,r:10,color:color});
    }
}

var count=100;
var t1=performance.now();
for(var i=0;i<count;i++){ drawIndividualPaths(playersOnscreen); }
var t2=performance.now();
for(var i=0;i<count;i++){ drawIndividualPaths(playersOffscreen); }
var t3=performance.now();
for(var i=0;i<count;i++){ drawColorPaths(playersOnscreen); }
var t4=performance.now();
for(var i=0;i<count;i++){ drawColorPaths(playersOffscreen); }
var t5=performance.now();
alert('onscreen/individual='+parseInt(t2-t1)+', offscreen/individual='+parseInt(t3-t2)+', onscreen/by color='+parseInt(t4-t3)+', offscreen/by color='+parseInt(t5-t4));

function drawIndividualPaths(players){
    var len=players.length;
    var PI2=Math.PI*2;
    for(var i=0;i<len;i++){
        var p=players[i];
        ctx.beginPath();
        ctx.arc(p.x,p.y,p.r,0,PI2);
        ctx.fillStyle=p.color;
        ctx.fill();       
    }
}

function drawColorPaths(players){
    var len=players.length;
    var PI2=Math.PI*2;
    var clen=colors.length;
    for(var c=0;c<clen;c++){
        var color=colors[c];
        ctx.fillStyle=color;
        ctx.beginPath();
        for(var i=0;i<len;i++){
            var p=players[i];
            if(p.color==color){
                ctx.moveTo(p.x,p.y);
                ctx.arc(p.x,p.y,p.r,0,PI2);
            }
        }
        ctx.fill();
    }
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<h2>Please wait for perf tests to complete</h2>
<canvas id="canvas" width=300 height=300></canvas>

【讨论】:

    猜你喜欢
    • 2014-02-05
    • 1970-01-01
    • 2014-09-23
    • 2011-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    相关资源
    最近更新 更多