使用整数纹理进行Alpha混合以进行对象选择

5

问题描述

你好!在我们的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使用intBitsToFloatuint转换为float,然后在Rust中将其转换回uint。不幸的是,这仅适用于GLSL 330,而我们在WebGL中受到GLSL 300的限制。
  • 将ID信息渲染到RGB32UI纹理中,并使用discard针对某些像素。这可能会有效,但会导致性能问题,我们宁愿不使用它。
  • 在Rust端将ID信息转换为float,在渲染到RGBA纹理中使用它,然后在Rust端将其转换回uint。这种解决方案的问题是它非常复杂,我们无法使用所有32位(需要特别注意可能的NAN编码),并且我们感觉应该有更好的方法来解决。

在这种特定情况下,它只是选择其中之一(我们仅使用 alpha 为 0 或 1)。 - Michael Mauderer
为什么使用RGBUI32?您期望绘制2^96个对象吗?即使只使用RGBA8也会有40亿个标识符。 - gman
1
Alpha确实很重要,但它只是另一个渠道,没有特别之处。 - gman
还有一些其他的评论。你说每个形状需要2个整数,但是你可以使用1个整数来表示每个形状,并在代码中将这些整数映射回你的2个ID。你还说你需要24到32位的ID。这没有太多意义。你不可能以任何合理的性能绘制1600万到40亿个对象。而且屏幕上根本没有那么多像素。至于RGBA8,不需要从整数转换为浮点数。你输入Uint8 r,g,b,a作为Uint32。你读取为vec4,你写入该vec4,你得到与输入相同的Uint8作为Uint32。 - gman
@gman,你怎么将uint8(或32)输入RGBA8纹理中?难道不需要上传浮点数uniform到它的vec4中吗? - davidkomer
显示剩余8条评论
1个回答

3
混合被认为是需要浮点值的片段函数的一部分,因此在渲染到非标准化整数纹理时没有影响。
规范第4.1节列出了9个与像素/片段相关的操作。
第4.1.7节混合是其中第七个操作,它说:

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

换句话说,如果使用整数格式,则跳过混合操作。
相反,如果alpha值低于给定阈值,则可以简单地discard该片段。
if(alpha < 0.5) discard;
output_id = uvec4(input_symbol_id,input_instance_id,0,1);

LJᛃ,@gman,我正在与Michael(提出此问题的人)一起工作,并已编辑以提供更多上下文。我们担心“discard”的性能惩罚,因此如果有其他解决方案可用,我们宁愿不使用它。您是否可以再次查看问题并建议我们是否有其他可能的解决方案?实际上,我们还描述了一个我们认为会起作用的解决方案,但我们仍在寻找更好的东西(如果可能的话)。 - Wojciech Danilo
你只需要渲染一个像素来进行拾取,因此丢弃操作不会对性能造成影响。 - gman
请链接到正确的规范。OpenGL规范对于WebGL来说是不相关且经常错误的。链接到不相关的OpenGL规范会导致人们获得错误信息和沮丧,这是不好的。 - gman
@gman 确实,但无法链接PDF的部分非常令人讨厌。此外,我在定制规范和WebGL2规范中都没有找到相关声明。如果您找到了,请相应地编辑答案,谢谢! - LJᛃ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接