4

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

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

我最好的猜测是减速是令人难以置信的笨拙toDataURL()->load image->drawImage()->getImageData()

我的问题变成了:有没有更好的方法来访问 WebGL 画布上可用的扁平化 2D 像素数据?或者也许是在没有视差的情况下推断我的 3D 对象坐标的更好方法?老实说,任何比我目前做的更快地获得某种碰撞检测的方法都将非常有用。

编辑:WebGL context.readPixels()对我来说非常有用,与我以前的 kludge 相比,它的速度非常快。尽管应该注意,与常规图像像素数据阵列相比,数据阵列是从上到下镜像的。我只是简单地翻转了我的碰撞例程 Y 值检查并让它工作,尽管其他人可能会以更棘手的方式被绊倒。祝你好运!

4

2 回答 2

4

您可以使用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!:)

于 2012-02-28T07:37:58.413 回答
0
 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);

这很好用。

于 2013-08-11T15:20:46.517 回答