我正在使用 Three.js 在简单 DOM 元素上方的 webgl Canvas 渲染器上绘制 3D 模型,我需要在它们之间进行碰撞检测。我目前的工作方法是使用 renderer.domElement.toDataURL(),将其作为 imageData 对象加载,然后将其绘制到单独的 2D Canvas 上下文中,然后拉出 getImageData() 像素数组并使用 this awesome pixel collision function 进行迭代。 .
这是难以置信 慢,并将我的帧速率降低到几乎无法播放的 ~5-8 FPS。如果不运行此命中检测,我将获得大约 40-50 FPS。
我最好的猜测是速度变慢是非常笨拙的 toDataURL()->load image->drawImage()->getImageData()。
我的问题变成:有没有更好的方法来访问 WebGL Canvas 上可用的扁平化 2D 像素数据? 或者也许是在没有视差的情况下外推我的 3D 对象坐标的更好方法?老实说,任何比我目前做的更快地获得某种碰撞检测的方法都将非常有用。
编辑 :WebGL context.readPixels() 对我来说非常有用,并且与我之前的 kludge 相比速度非常快。但是应该注意的是,与常规图像像素数据阵列相比,数据阵列是从上到下镜像的。我只是简单地翻转了我的碰撞例程 Y 值检查并使其工作,尽管其他人可能会以更棘手的方式绊倒。祝你好运!
最佳答案
您可以使用 gl.readPixels
:
// 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 现在包含场景的像素数据作为无符号字节 (0-255),布局为
[R, G, B, A, R, G, B, A...]
应该是与 getImageData
相同的数据但成本要低得多。[ 编辑: ]
我忘了提到,如果您打算这样做,您需要使用
preserveDrawingBuffer
创建您的 WebGL 上下文。选项,像这样:var gl = canvas.getContext("experimental-webgl", {preserveDrawingBuffer: true});
这可以防止 WebGL 的内部工作在您到达缓冲区之前清除缓冲区(这将导致您读取大量空像素)。启用此选项可能会减慢渲染速度,但加载速度仍应高于 5-8 FPS! :)
关于collision-detection - imageData CanvasPixelArray 是否可以直接用于 Canvas WebGL 上下文?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9470043/