【问题标题】:Picking triangles in OpenGL core profile when using glDrawElements使用 glDrawElements 时在 OpenGL 核心配置文件中拾取三角形
【发布时间】:2012-01-31 12:15:06
【问题描述】:

我正在使用 glDrawElements 绘制三角形网格,并且希望能够使用鼠标单击来选择/选择三角形。三角形的网格可以很大。

在固定功能的 OpenGL 中可以使用 GL_SELECT: http://content.gpwiki.org/index.php/OpenGL:Tutorials:Picking .. 但是我只对使用 OpenGL 核心配置文件感兴趣。

另一种可能性是使用“颜色编码”:

http://www.lighthouse3d.com/opengl/picking/index.php?color1

http://www.opengl.org/resources/faq/technical/selection.htm

.. 但据我所知,在使用 glDrawElements 时还不能指示每个三角形的信息?

最后,我可以通过鼠标位置发射拾取射线来进行基于 CPU 的拾取,但这会很慢,因为我想我必须在 CPU 上转换三角形,所以我更喜欢基于 GPU 的解决方案。

有没有人建议在 OpenGL 核心配置文件中使用 glDrawElements 时最好的选择方法是什么?

【问题讨论】:

  • 您的顶点是否多次用于不同的三角形?

标签: opengl glsl opengl-3


【解决方案1】:

关于“颜色编码”方法,您可以使用gl_PrimitiveID 使用适当的片段着色器填充颜色编码缓冲区,这基本上会给您绘制三角形的索引。

关于基于 CPU 的拾取,您可以使用处理加速结构和光线网格交点的现有库,例如 BulletOpcode

您的“最佳”选项取决于您的用例,很难说。

【讨论】:

  • gl_PrimitiveID 仅在单个绘图调用中有效。在许多绘图调用中,gl_PrimitiveID 发生了变化。
  • @NicolBolas 当然,要处理多个对象/绘图调用,应该添加另一个参数,以便能够将三角形 0 与两个不同的对象区分开来。每个对象的制服与gl_PrimitiveID 结合应该可以解决问题。我错过了什么吗?
  • rotoglup:非常感谢,我不知道 gl_PrimitiveID。我会尝试一下,让你知道它是如何工作的。现在我只有一个有很多三角形的对象,这是一个更简单的情况。
  • @rotoglup:最后一个问题。如何在 GPU 上将颜色编码为浮点数,然后再将其转换回 cpu 上的三角形 id?我认为我可以在浮点数上使用位操作来做到这一点,但它比我想象的要困难。
  • @WesDec 这可能是另一个问题的主题,但大致而言,如果您的目标平台允许,您可以简单地在integer texture 中输出整数值,或者找到适当的公式来编码您的 int在 RGBA8 中,类似于ozone3d.net/blogs/lab/20080604/glsl-float-to-rgba8-encoder - 抱歉,我手头没有准备好确切的答案。
【解决方案2】:

尝试从这个角度来看:OpenGL 仅用于绘制事物。采摘应该以另一种方式进行。如果您坚持使用 OpenGL(并非不合理),请使用带有整数 16 位单通道颜色缓冲区附件的 FBO,将对象 ID 渲染到其中。拾取减少读取 ID 的一个像素。

最后,我可以通过鼠标位置发射拾取射线来进行基于 CPU 的拾取,但这会很慢,因为我想我必须在 CPU 上转换三角形,所以我更喜欢基于 GPU 的解决方案。

我推荐这个。然而,不要变换所有的三角形,只需反向变换你的一个拾取射线。无论如何,您应该在一些空间细分结构中管理您的场景,因此对此进行测试应该是微不足道的。

【讨论】:

  • 谢谢!我没有空间结构(我现在不需要它),但我会尝试你建议的蛮力方式的逆变换方法。不知道为什么我没想到:)
【解决方案3】:

您确实可以在 DrawElements 调用中提供每个三角形的信息。然后您必须提供相应的数组(以前的 COLOR_ARRAY、TEXTURE_COORD_ARRAY 等,现在通常称为 VertexAttribArrays)。 如果您坚持使用 GPU,这可能是最简单的解决方案。

但是,通常的方法是从点击点向场景发射光线。因此,您要做的不是变换每个三角形,而是计算 射线和三角形之间的相交测试。如果射线相交,你会击中它, 如果不是你没有。如果你用蛮力来做,这确实会付出相当大的代价。

但是,通常您会将三角形包含在一些空间数据结构中(即您的场景图将/可以/应该有一些表示形式),例如八叉树 (http://en.wikipedia.org/wiki/Octree)例如。这将允许碰撞响应 在相当多的测试中。此外,您可以考虑三角形将在屏幕上占据的最终大小(因此在 大多数情况下)。

如果你真的想变得花哨,你也可以把整个过程放到 GPU 上(一个听起来很有趣的例子是例如http://blog.xeolabs.com/ray-picking-in-scenejs,但是当你使用 google 时会出现更多)。

我个人认为最容易实现的是解决方案 b) 软件光线拾取,然后是 a),最后是 GPU 拾取。从最简单的开始,如果您认为它不够快,请改进。不要被太多过早的优化所困扰(例如,光线投射拾取在我的 iPhone 上运行得非常好;)。玩得开心,祝您好运。

【讨论】:

  • COLOR_ARRAYTEXTURE_COORD_ARRAY等都是固定函数数组。它们在核心配置文件中不可用。
  • 是的,相同的 sh**,不同的名称 ;) 为清楚起见,添加了 VertexAttribArray。
  • cli_hit:这些是顶点属性(或“每个顶点信息”)。我的意思是没有相应的三角形属性(或“每个三角形信息”)。例如。不可能为每个三角形指定颜色或法线;您只能针对每个顶点执行此操作。
  • 好吧,当您使用普通三角形时,它非常清楚 - 顶点属性 == 三角形属性。如果你使用条带,你应该小心你指定哪一个,但你也可以在这里建立一个对应关系。应该没问题。
  • cli_hit:你是对的,但它并不完全相同。顶点属性通常在几个三角形之间共享,因此不是“每个三角形”。例如,如果我要为网格中的每个三角形提供独特的颜色,那么您将如何使用对 glDrawElements 的一次调用来为网格着色?如果有类似“TriangleAttribArray”的东西,那就很容易了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-13
  • 2011-06-09
相关资源
最近更新 更多