关于冲突检测:imageData CanvasPixelArray是否可直接用于画布WebGL上下文?

Is an imageData CanvasPixelArray directly available to a canvas WebGL context?

我正在使用Three.js将3D模型绘制到简单DOM元素上方的webgl画布渲染器上,并且需要在它们之间进行碰撞检测。我当前的工作方法是使用renderer.domElement.toDataURL(),将其作为imageData对象加载,然后将其绘制到单独的2D画布上下文中,然后拉出getImageData()像素数组,并使用该超棒的像素碰撞函数进行迭代。

这非常慢,并且将我的帧速率降低到几乎无法播放的?5-8 FPS。如果不运行此命中检测,我将获得大约40-50 FPS。

我最好的猜测是,速度减慢是难以置信的toDataURL()->加载图像-> drawImage()-> getImageData()。

我的问题变成:是否有更好的方法来访问WebGL画布上可用的扁平2D像素数据?还是没有视差外推3D对象坐标的更好方法?老实说,任何比我目前正在执行的碰撞??检测更快的方法都是非常有用的。

编辑:WebGL context.readPixels()对我来说很棒,并且与我以前的混战相比超级快。尽管应注意,与常规图像像素数据阵列相比,该数据阵列从上到下镜像。我只是简单地翻转了碰撞常规的Y值检查并使其生效,尽管其他人可能会以更棘手的方式被绊倒。祝好运!


您可以使用gl.readPixels

1
2
3
4
5
6
7
// Render your scene first then...
var left = 0;
var top = 0;
var width = canvas.width;
var height = canvas.height;
var pixelData = new Uint8Array(width * height * 4);
gl.readPixels(left, top, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixelData);

pixelData现在包含以[R, G, B, A, R, G, B, A...]布局的无符号字节(0-255)的场景像素数据,应该与getImageData相同,但成本要低得多。

[编辑:]

我忘了提一下,如果您要执行此操作,则需要使用preserveDrawingBuffer选项创建WebGL上下文,如下所示:

1
var gl = canvas.getContext("experimental-webgl", {preserveDrawingBuffer: true});

这样可以防止WebGL的内部工作在到达缓冲区之前清除缓冲区(这将导致您读取大量空白像素)。 启用此选项可能会减慢渲染速度,但加载速度仍应比5-8 FPS快! :)


1
2
3
4
5
6
7
8
9
10
 renderer = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer:true });



 var gl = renderer.getContext()
 var buf = new Uint8Array(200 * 200 * 4);
 gl.readPixels(0, 0, 200, 200, gl.RGBA, gl.UNSIGNED_BYTE, buf);


console.log(buf);

这很好。