3

我从头开始实施 webgl 拾取,并决定沿着 GLSL 路线走,与光线相交测试相反。

所以我将整个场景渲染到一个单独的帧缓冲区中,为每个对象分配一个唯一的颜色,该颜色作为统一变量传递给片段着色器。当渲染场景时,我 gl.readPixels() 缓冲区,并在单击坐标处获取颜色值(我反转坐标系统以说明 GL 与浏览器坐标系统不同)。

我遇到的问题是着色器表示传递给 gl_FragColor 着色器输出的颜色,因为 vec4 浮动,每个颜色通道的范围为 0.0-1.0,而 gl.readPixels() 将颜色通道返回为 0-255 范围内的整数......做这个翻译失去一些精度,并且可能会产生拾取错误(如果场景中有很多对象(超过 255 个),或者如果整数到浮点舍入大于区分不同对象 ID 所需的粒度)。

有谁知道如何解决这个问题,或者指出我正确的方向?readPixels() 可以返回 0.0-1.0 范围内颜色通道的浮点值吗?我可以打包分布在多个通道上的单个对象 ID(这样我就不仅限于单个通道并且只能选择 255 个对象吗?)

谢谢您的帮助

4

5 回答 5

2

There exists some tricks to read floats from GPU to CPU in WebGL:

http://lab.concord.org/experiments/webgl-gpgpu/webgl.html

More specific:

于 2013-06-04T07:25:43.537 回答
2

这是一个老问题,但只是提供...

我可以打包分布在多个通道上的单个对象 ID(这样我不限于单个通道并且只能选择 255 个对象)吗?

您可以可靠地对 8 位 gl.readPixels 检索的每个颜色分量进行 8 位编码。在您的片段着色器中,您可以使用 float redComponent = float(intObjectId) / 255.0。如果你把它放在 gl_FragColor 中,它会可靠地返回它开始的数字,如果它在 0 到 255 之间。不需要四舍五入。

您可以通过 mod 和除法来编码更大的整数,例如

    int objectId = 12345; // up to 65535...
    float f = float(objectId);
    // put low 8 bits into .r, and next 8 bits into .g
    gl_FragColor = vec4(mod(f,256.) / 255., mod(floor(f / 256.0), 256.0) / 255.0, 0,1);

要知道的是范围从浮动 [0.0, 1.0] 映射到 int [0,255]。它们映射到范围的中间,所以 0.0 到 0.5/255 映射到 0,0.5/255 到 1.5/255 映射到 1,依此类推。非常稳定!

于 2013-10-31T03:21:11.020 回答
1

OpenGL 规范准确地说明了从 int 到 float 以及从 float 到 int 的转换应该如何进行。

请参阅第 2.3.5 节,“定点数据转换”:

  • 从整数类型到浮点数的转换应该通过除以 2^b-1 来完成,即在字节的情况下为 255.0,如david van brink的回答。
  • GPU从浮点类型到整数类型的转换总是通过四舍五入到最接近的整数来完成。只要内部帧缓冲区格式具有足够的精度,这应该没问题:8 位无符号整数、16 位浮点数(具有 10 位尾数)和 32 位浮点数都适用于此目的。
于 2019-08-07T17:21:33.600 回答
0

我知道在 OpenGL 中,您可以从指针创建纹理(我的意思是,获取指针指向的内存片段作为纹理的内容)。我相信相反的过程也可能,但不太确定如何以及是否可以完成。就像是:

*p = myTexture;     // texture -> pointer
my_data = p[i][j];  // read byte data

如果可以做到这一点,那么您可以将内容读取为字节数据,然后将其转换为浮点数(或任何适合您的方式)。但是,如果这甚至可能以及如何在 JavaScript 中完成,那么这个问题仍然存在……不过,这就是我要走的路。

希望这可以帮助。

于 2013-06-03T22:01:39.253 回答
0

不幸的是,虽然您可以使用 OES_texture_float 扩展来渲染浮点帧缓冲区纹理,但看起来您仍然无法使用 readPixels 将它们读取为浮点数(请参阅https://bugzilla.mozilla.org/show_bug.cgi?id =681903https://groups.google.com/forum/#!topic/webgl-dev-list/s83_IvYbPM4

看起来这是一个未来的功能,但看起来它还没有在任何地方实现。

如果您因为成本太高而避免进行光线相交测试,那么最好为您的对象使用优化的结构,例如包围体或八叉树/kd 树。

于 2013-06-03T21:01:18.387 回答