我正在使用 VBO 渲染基于数百万个(最多十个)三角形的模型,我需要检测用户可以点击哪些三角形。
我尝试阅读并理解“名称堆栈”和“唯一颜色”是如何工作的。我发现名称堆栈最多只能包含 128 个名称,而唯一颜色最多可以有 2^(8+8+8) = 16777216 种可能的不同颜色,但有时可能会有一些近似值,所以它可以得到修改的..
哪种策略最适合我的情况?
我正在使用 VBO 渲染基于数百万个(最多十个)三角形的模型,我需要检测用户可以点击哪些三角形。
我尝试阅读并理解“名称堆栈”和“唯一颜色”是如何工作的。我发现名称堆栈最多只能包含 128 个名称,而唯一颜色最多可以有 2^(8+8+8) = 16777216 种可能的不同颜色,但有时可能会有一些近似值,所以它可以得到修改的..
哪种策略最适合我的情况?
基本上,您有两类选择:
“每个三角形的唯一颜色方式”,这意味着您将一个 id 附加到每个三角形,并将 id 渲染到单独的渲染目标。它可以是 32 位(RGB 为 8,a 为 8),但您可以添加第二个以获得更多想法。获取每个三角形的 id 会很麻烦,但实现起来相对容易。虽然(填充率)可能对性能非常不利。
适当的光线追踪。您几乎肯定想要一个加速结构(八叉树、kd、...),但您可能已经有一个用于截锥剔除的结构。一根射线真的不多,这个方法应该很快。
杂交种。可能是最容易实现的。渲染出顶点缓冲区 id(“每个缓冲区唯一的颜色:),当您知道选择了哪个顶点缓冲区时”,只需针对所有三角形跟踪一条射线。
在一般情况下,我会说 2) 是最好的选择。如果您想快速完成某些工作,请选择 3)。1) 可能没什么用。
如果您的 GPU 卡有 OpenGL 4.2,您可以使用imageStore()
GLSL 中的函数来标记图像中的三角形 ID。就我而言,我需要检测屏幕上预定义窗口后面的所有三角形。拾取(选择窗口上渲染的三角形)的工作方式类似。选择对我来说是实时运行的。
图像(或纹理)的最大尺寸应该 >= 8192x8192 = 64 M。因此它可以使用多达 64 M 个图元(如果我们使用 2、3 个图像,甚至更多)。
可以使用以下片段着色器将所有三角形 ID 保存在屏幕后面:
uniform uimage2D id_image;
void main()
{
color_f = vec4(0)
ivec2 p;
p.x = gl_PrimitiveID % 2048;
p.y = gl_PrimitiveID / 2048;
imageStore(id_image, p, uvec4(255));
}
为了保存在屏幕上渲染的所有三角形 ID:首先,我们预先计算一个深度缓冲区,然后使用稍微不同的片段着色器:
uniform uimage2D id_image;
**layout(early_fragment_tests) in;** //the shader does not run for fragment > depth
void main()
{
color_f = vec4(0)
ivec2 p;
p.x = gl_PrimitiveID % 2048;
p.y = gl_PrimitiveID / 2048;
imageStore(id_image, p, uvec4(255));
}