用于对象拾取的 Alpha 与整数纹理混合

Mic*_*rer 5 shader webgl rust webgl2

问题描述

你好!在我们的 WebGL 应用程序中,我们绘制了许多(甚至数十万)个形状,我们想发现当前鼠标下方的形状。我正在寻找一种有效的方法。

细节

这些形状是用Signed Distance Functions定义的。每个形状都是通过将预定义的 sdf 片段着色器应用于方形多边形(2 个三角形)来绘制的。每个形状都uint在 Rust 端分配了一个唯一的 ID ( )(我们在这里使用 WASM)。这个想法是将场景渲染两次(在 WebGL 1.0 中)或一次到多个渲染目标(在 WebGL 2.0 中),其中一个目标是编码为颜色的 ID。然后我们可以使用readPixels查询颜色并获取鼠标下形状的ID。不幸的是,我们尝试的每个解决方案都有一些缺点。

要求

  • 我们需要为每个形状编码 2 个整数(一个告诉我们它是什么形状,比如它是一个按钮,或者可能是一个滑块),第二个告诉我们它是哪个对象实例(例如第 5 个滑块)。
  • 我们将在舞台上有很多形状(和实例),因此对于每个 int,我们至少需要 24 位,最好是 32 位精度。

到目前为止他所尝试的

  • 将 ID 信息渲染为RGBA32UI纹理类型。在这个解决方案中,我们每个通道使用 32 位,因此我们可以使用 2 个通道来表示我们的 ID。不幸的是,混合仅适用于 RGBA 模式,并且仅当颜色缓冲区具有定点或浮点格式时才适用。我们需要某种形式的混合,因为在绘制形状(如圆形)时,某些部分需要透明。在 ID 颜色输出的情况下,我们的 alpha 始终为 0 或 1。
  • 渲染ID信息RGBA的质地和转换uintfloat通过使用GLSL intBitsToFloat然后回floatuint在生锈。不幸的是,这在 GLSL 330 中可用,而我们仅限于 WebGL 中的 GLSL 300。
  • 将 ID 信息渲染到RGB32UI纹理并discard用于某些像素。这会起作用,但它会导致性能问题,我们宁愿不喜欢使用它。
  • 将 Rust 端的 ID 信息转换为float,使用它代替uint,并将其渲染为RGBA纹理,然后将其转换回uintRust 端。这个解决方案的问题是它非常复杂,我们不能使用所有的 32 位(我们需要对可能的 NAN 编码格外小心),我们觉得应该有更好的方法来做到这一点。

LJᛃ*_*LJᛃ 3

混合被认为是需要浮点值的每片段函数的一部分,因此在渲染到非标准化整数纹理时它没有效果。

规范第 4.1列出了像素/片段发生的 9 种操作。

第 4.1.7 节“混合”是 9 个操作中的第 7 个操作,表示

仅当颜色缓冲区具有定点格式时才应用混合。如果颜色缓冲区具有整数格式,则继续下一步操作。

换句话说,如果您使用整数格式,则会跳过混合操作。

discard相反,如果 alpha 值低于给定阈值,您可以简单地提取片段。

if(alpha < 0.5) discard;
output_id = uvec4(input_symbol_id,input_instance_id,0,1);
Run Code Online (Sandbox Code Playgroud)