如何最好地将ArrayBuffer的一部分绘制到画布上?

3

我有一个ArrayBuffer,我有一个名为 module.repaint的函数,它可以与 ArrayBuffer一起工作。在每次重绘调用中,我想把ArrayBuffer中的颜色放到画布上。

我是这样做的:

imgData.data.set(new Uint8ClampedArray(MEM, 0, siz));

但是,是否可能更快地将ArrayBuffer的一部分复制到另一个位置? 代码:

var MEM = new ArrayBuffer(2*1024*1024);
var canvas, ctx, imgData, siz;

var repaint = function() {
    // module.repaint works on the arraybuffer
    module.repaint();

    imgData.data.set(new Uint8ClampedArray(MEM, 0, siz));
    ctx.putImageData(imgData, 0, 0);

    requestAnimationFrame(repaint);
};

var init = function() {
    canvas = document.getElementById('canvas');
    ctx = canvas.getContext('2d');

    siz = canvas.width*canvas.height*4;

    imgData=ctx.createImageData(canvas.width,canvas.height);

    repaint();
};
2个回答

3
请注意,我没有检查增益是否重要,但我可以看到一些有用的优化。
首先,`Uint8ClampedArray`是缓冲区的视图,而不是缓冲区本身,因此您不需要每次都创建它。(您还可以在单个缓冲区上拥有多个视图)
您还应避免使用`imgData.data`的`set`方法,因为它将所有数据从一个数组复制到另一个数组(这是无用的)。相反,您可以在构造函数中设置您的`Uint8ClampedArray`。
有了这段代码,对`MEM`的每个更改都会自动影响`imgData`,因为`imgData.data`直接指向`MEM`。
var MEM = new ArrayBuffer(2*1024*1024);
var canvas, ctx, imgData, siz;

var repaint = function() {
    // module.repaint works on the arraybuffer
    module.repaint();

    ctx.putImageData(imgData, 0, 0);

    requestAnimationFrame(repaint);
};

var init = function() {
    canvas = document.getElementById('canvas');
    ctx = canvas.getContext('2d');

    siz = canvas.width*canvas.height*4;

    imgData = ctx.createImageData(new Uint8ClampedArray(MEM, 0, siz), canvas.width, canvas.height);

    repaint();
};

2
如果可能的话,请将您的module.repaint()重构为使用离屏画布而不是像素数组。
这样,您只需将离屏画布绘制到屏幕画布上即可,这是有效的,因为GPU可以执行blitting而不是给CPU带来负担。 putImageData较慢,因为它涉及CPU从像素数组中获取数据、将该数据设置到临时数组中并将临时数组传输到屏幕imageData中。这些都是给CPU带来负担并降低性能的活动。

该模块是一个asmjs模块。堆对象的byteLength必须是4096的倍数,并且堆对象的byteLength必须是2的幂。 - Iter Ator
markE:你说得对,drawImage相比putImageData的速度提升是巨大的,很可能远远超过使用asmjs所能提供的。@IterAtor:那么读一下markE的回答呢? - GameAlchemist
但是如果我想使用drawImage方法,那么我必须在每个循环中将实际的ImageData转换为图像。我不知道如何快速从ArrayBuffer中读取字节并将像素写入画布。 - Iter Ator

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接