问题描述
你好!在我们的WebGL应用程序中,我们正在绘制许多(甚至数十万个)形状,并希望发现当前鼠标下面的形状。我正在寻找一种有效的方法来实现它。
详细信息
这些形状是使用有符号距离函数定义的。每个形状通过将预定义的sdf片段着色器应用于一个正方形多边形(2个三角形)来绘制。每个形状在Rust端分配了一个唯一的ID(uint
)(我们在这里使用WASM)。想法是在WebGL 1.0中渲染场景两次或者在WebGL 2.0中一次渲染到多个渲染目标(其中之一是以颜色编码的ID)。然后,我们可以使用readPixels
查询颜色并获取鼠标下形状的ID。不幸的是,我们尝试的每个解决方案都有一些缺点。
要求
- 我们需要为每个形状编码两个整数(一个告诉我们它是什么形状,例如按钮,或者可能是滑块的一部分;另一个告诉我们它是对象的第几个实例,例如第5个滑块)。
- 我们将在舞台上有很多形状(和实例),因此对于每个整数,我们至少需要24位,最好是32位的精度。
我们到目前为止尝试过的内容
- 将ID信息渲染到
RGBA32UI
纹理类型中。在此解决方案中,我们每个通道使用32位,因此可以使用2个通道来表示我们的ID。不幸的是,混合仅适用于RGBA模式,并且仅当颜色缓冲区具有定点或浮点格式时才会应用。我们需要某种形式的混合,因为在绘制形状(例如圆形)时,一些部分需要是透明的。在ID颜色输出的情况下,我们的alpha始终为0或1。 - 将ID信息渲染到
RGBA
纹理中,并通过GLSL使用intBitsToFloat将uint
转换为float
,然后在Rust中将其转换回uint
。不幸的是,这仅适用于GLSL 330,而我们在WebGL中受到GLSL 300的限制。 - 将ID信息渲染到
RGB32UI
纹理中,并使用discard
针对某些像素。这可能会有效,但会导致性能问题,我们宁愿不使用它。 - 在Rust端将ID信息转换为
float
,在渲染到RGBA
纹理中使用它,然后在Rust端将其转换回uint
。这种解决方案的问题是它非常复杂,我们无法使用所有32位(需要特别注意可能的NAN编码),并且我们感觉应该有更好的方法来解决。