【问题标题】:Determining if a polygon is inside the viewing frustum确定多边形是否在视锥体内
【发布时间】:2011-06-16 15:13:38
【问题描述】:

这是我的问题。我听说opengl会忽略视锥之外的顶点,并且在渲染管道中不考虑它们。最近我遇到了同一篇文章,说你应该自己检查一下,如果一个点不在里面,你有责任找出不是opengl的!现在,

  1. opengl 是这样吗?它是否理解一个点是否不在内部,而不是渲染它?
  2. 我正在开发一个草地场景,矩形上有大约 4000 棵草。我的 FPS 很糟糕,我想出的唯一解决方案是决定哪些草在视口内,然后只渲染它们!我的问题是,哪种解决方案最适合我找出哪个矩形不在内部或哪个矩形在内部?

请考虑我的问题主要不是关于点,而是关于矩形。此外,我需要根据草的距离对草进行排序,因此最好在客户端内存中使用本地内存。

如果有任何有效且实时的方法可以确定任何给定的网格是在截锥体内部还是外部,请告诉我。谢谢。

【问题讨论】:

  • 您是否有理由不能使用 Z-buffer 来避免基于距离的排序?
  • 如果 Z-buffer 真的能帮到我,我没弄明白。但我确实使用 ALPHA_TEST。

标签: c opengl graphics rendering glsl


【解决方案1】:

即使为真,OpenGL 也不会在截锥体之外显示多边形(与任何其他 3d 引擎一样),它必须考虑它们以检查是否存在内部,然后 fps 减慢。通常需要一些智能优化算法来避免不可见物体淹没场景。检查例如 BSP 树+PVS 或门户作为起点。 要检查应用程序是否存在瓶颈,您可以尝试使用gDebugger。如果没有什么是合理的错误,那么优化以仅绘制 PVS(可能的可见集)就是要走的路。

【讨论】:

  • 为什么这样的操作会减慢我的工作速度?我只有 4000 棵草,即 16000 个顶点!
  • 尽可能快地运行在管道中。如果您的 fps 不令人满意,则必须进行优化。另一个想法是:纹理总是一样的吗?如果不是,您是否绘制排序以尽可能减少纹理变化的矩形...?
  • 所有相同的纹理,相同的坐标,固定的功能,关灯,静态草,使用的 VBO,STATIC_DRAW!每件事看起来都合乎逻辑,但我没有 FPS!!!!
  • 我在回复中添加了一个建议的工具。
  • 感谢您添加最后一部分。我正在调查。
【解决方案2】:

OpenGL 不会在屏幕外渲染像素(“片段”),因此它必须以某种方式进行剪辑...

更准确地说:

  • 您提交您的几何图形
  • 您进行了绘图调用(glDrawArrays 或 glDrawElements)
  • 每个顶点都经过顶点着色器,它计算顶点在相机空间中的最终位置。如果您没有编写顶点着色器 (=old opengl),驱动程序将为您创建一个。
  • 透视分割将这些坐标转换为标准化设备坐标。粗略地说,这意味着您的相机的平截头体变形以适合 [-1,1]x[-1,1]x[-1,1] 框
  • 此框外的所有内容均被剪裁。这可能意味着完全丢弃一个三角形,或者如果它跨越一个剪切平面则细分它
  • 每个剩余的三角形都被光栅化为片段
  • 每个片段都经过片段着色器

所以基本上,OpenGL 知道如何剪辑,但每个顶点仍然必须经过顶点着色器。因此,提交你的整个世界当然可以,但如果你能找到一种提交所有内容的方法,你的 GPU 会更快乐。

当然,这是一种权衡。如果你花 10 毫秒检查 CPU 上的每一片草地,以使 GPU 只绘制最少量的数据,这也不是一个好的解决方案。

如果你想优化草,我建议剔除大片(5m x 5m 左右)。这是标准的 AABB 截头锥体测试。

如果您想优化更通用的模型,您可以研究四叉树以用于“平面”模型,八叉树和 bsp-trees 用于更复杂的对象。

【讨论】:

  • 谢谢。又一个问题在我脑海中浮现。我曾经在一个场景中绘制 20000 个顶点,我的 FPS 大约是 60!这次是20左右!正在多次使用纹理!如果您需要查看,我可以发布我的代码!
  • 拜托,但在另一个问题。并包括更多细节(之前/之后)
  • 代码其实很大很多文件,不知道怎么发!请告诉我,我可以通过邮件将其发送给您。
  • 我添加了代码,请看一下。 [仅重要部分]。
  • 抱歉,这不是 StackOverflow 的工作方式。我相信您可以提取代码中最重要的部分,并解释您如何使用文字进行渲染。更重要的是,在执行此操作时,您通常会更准确地了解您的问题。在解释问题时找到问题的答案并不少见。
【解决方案3】:

是的,OpenGL 不会光栅化超过视锥体的三角形。但是,这并不意味着这对应用程序来说是最佳的:OpenGL 实现将转换顶点坐标(通过使用固定管道或顶点着色器),然后,通过归一化坐标,它最终知道三角形是否位于视锥体内。

这意味着在这种情况下没有像素被光栅化,但顶点数据的处理都是一样的;根本不会产生源自不可见三角形的片段!

OpenGL 扩展ARB_occlusion_query 可能会对您有所帮助,但请在讨论部分明确说明:

遮挡查询是否会使其他可见性算法过时?

    No.

    Occlusion queries are helpful, but they are not a cure-all.  They
    should be only one of many items in your bag of tricks to decide
    whether objects are visible or invisible.  They are not an excuse
    to skip frustum culling, or precomputing visibility using portals
    for static environments, or other standard visibility techniques.

关于网格深度排序的问题,你应该使用深度缓冲区:本质上,网格片段只有在它与视口的距离小于相同位置的前一个片段时才会有效地渲染。这使您知道对网格进行排序。这个缓冲区基本上是免费的,它可以让您提高性能,因为它丢弃了更多的片段。

【讨论】:

    【解决方案4】:
    1. 是的。就像其他人指出的那样,OpenGL 必须执行大量每个顶点的操作来确定它是否在截锥体中。它必须为您发送的每个顶点执行此操作。除了必须发生的处理开销之外,请记住,将这些顶点从 CPU 传输到 GPU 还会产生额外的开销。您希望避免向 GPU 发送它不会使用的信息。尽管 CPU 和 GPU 之间的带宽在现代硬件上相当不错,但仍然存在限制。

    2. 你想要的是Scene Graph。场景图经常使用某种空间划分方案实现,例如QuadtreesOctreesBSPTrees 等。空间划分允许您智能地确定哪些几何图形是可见的。它可以一次消除巨大的几何空间子集,而不是在每个顶点的基础上执行此操作(就像 OpenGL 强制执行的那样)。渲染复杂场景时,可以节省大量性能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-22
      相关资源
      最近更新 更多