提取特定像素的原始ID

时间:2017-09-06 11:41:04

标签: opengl

考虑使用正交投影渲染的场景中的对象集合。某些对象被其他对象遮挡,因此它们只是部分可见,或者根本没有在图像平面上注册,这是由深度缓冲区提供的。对象由三角形组成,三角形具有原始ID。 此时,图像将被渲染,每个像素都会分配一个颜色。

现在我需要做的是选择一个像素,然后告诉哪个对象位于此像素(深度占据)。互联网将此问题称为"对象选择/鼠标选择与光线投射"。但是,我无法帮助认为光线投射对于一项似乎微不足道的任务来说是一种过度杀伤。也就是说,OpenGL不应该跟踪绘制某个像素的最后一个原始ID吗?这意味着如果有一个特定的彩色片段投射到图像平面上,那么如果OpenGL遇到一个更接近相机的几何体,它将简单地覆盖像素颜色值(后一个几何体遮挡原始片段)和相关的产生这种颜色值的三角形。

因此它的primitiveID可以链接到一个像素并稍后访问,这似乎是一件合理的事情。可悲的是,我无法找到怎么做,也许它并不像我想象的那么微不足道。但我不明白为什么。

然后问题是:

  • 有没有办法提取与像素相关的原始ID(如果OpenGL完全这样做的话)?
  • 如果没有,那么不实施这种选择的原因是什么?

与往常一样,详细的答案和指向正确的方向同样受到赞赏。

2 个答案:

答案 0 :(得分:4)

Opengl不打扰跟踪每个像素的原始ID。相反,它使用深度缓冲区来存储每像素深度。

如果要获取原始ID,则需要添加颜色附件并将原始ID写入其中。然后,您可以读取该纹理以获取该像素的基元ID。

答案 1 :(得分:3)

  

也就是说,OpenGL不应该跟踪绘制某个像素的最后一个原始ID吗?

应该吗?这样的原始ID列表需要:

  1. 为每个基元分配唯一标识符。这要求系统在三角形光栅化时碰撞计数器。这意味着对于具有多个光栅化单元(实际存在,顺便说一句)的任何GPU的原子操作。

  2. 让用户对标识符进行一些控制。如果不控制标识符,用户将如何知道它呈现的哪个基元映射到哪个标识符?如果标识符全局递增,则用户需要一种方法将它们重置为已知值。

  3. 帧缓冲区大小的图像,对于每个样本,包含一个标识符。这意味着你有另一个帧缓冲大小的图像占用了宝贵的内存,并且每个FS都有一个隐含的写入这样的缓冲区。

  4. 在特定像素处从该图像读取的机制。

  5. 这样的系统会对曲面细分和几何着色器造成严重破坏,因为这些过程会生成新的基元。如果用户不确切知道将通过曲面细分生成多少个三角形,他们将如何找出哪个输出原语映射到哪个原始ID?

    OpenGL不再像这样做固定功能的东西了。相反,它为提供了构建你想要的任何机制的工具。

    Geometry shaders可以(理论上)在每次生成基元时使用atomic counters递增自身,将该值传递给FS。你可以在你想要的时候重置这个计数器。您可以创建FS将原始ID写入的整数纹理。您可以使用glReadPixels来读取该值。

    同样重要的是,如果你不需要这个(就像大多数人没有这样),那么资源就不会用于你永远不会使用的功能。