【问题标题】:Is drawing front-to-back necessary for optimizing renders?优化渲染是否需要从前到后绘制?
【发布时间】:2013-03-28 02:24:53
【问题描述】:

我看到偶尔有文章建议在将顶点发送到 OpenGL(对于任何 OpenGL 变体)时,将顶点从距相机最近到最远的顺序排列。这样做的原因是,如果一个顶点位于另一个已经渲染的顶点之后,OpenGL 将不会完全处理/渲染它。

由于按深度对顶点进行排序是任何项目的成本高昂的组成部分,而且这种排序通常会频繁更改,因此这种设计有多普遍或必要?

我之前认为 OpenGL 会“查看”所有提交的顶点并在它们上处理自己的深度缓冲,而不管它们的顺序如何,渲染整个批次之前。但如果事实上一个顶点在另一个顶点之前被渲染到屏幕上,那么我可以看到排序如何提高性能。

优化渲染是否需要从前到后绘制?

【问题讨论】:

  • 您问的是 OpenGL 还是 OpenGL ES?因为答案不同,这取决于这两个平台执行的非常真实的硬件差异。
  • 很高兴知道这一点。我正在研究这两个系统的跨平台图形,因此在这方面,与两者或其中任何一个相关的答案都是有用的。

标签: opengl graphics opengl-es 3d opengl-es-2.0


【解决方案1】:

一旦基元被光栅化,它的 z 值可用于执行“early z kill”,从而跳过运行片段着色器。这是从前到后渲染的主要原因。提示:当您有透明(alpha 纹理)多边形时,您必须从后到前渲染。

OpenGL 规范定义了一个状态机,并没有指定渲染实际发生的顺序,只是结果应该是正确的(在一定的公差范围内)。

为清楚起见进行编辑:我在上面想说的是,硬件可以做任何它想做的事情,只要原语看起来已按顺序处理

但是,大多数 GPU 都是流处理器,它们的 OpenGL 驱动程序不会“批量处理”几何图形,除非可能出于性能原因(最小 DMA 大小等)。如果您先输入多边形 A,然后输入多边形 B,那么它们会一个接一个地输入管道,并且彼此独立(大部分)处理。如果 A 和 B 之间有足够多的多边形,那么 A 很有可能在 B 之前完成,如果 B 在 A 后面,它的片段将通过“early z kill”被丢弃。

为清楚起见进行编辑:我在上面想说的是,由于 hw 不会“批量”几何,它不能自动进行从前到后的排序。

【讨论】:

  • "没有指定渲染实际发生的顺序" 这种说法非常具有误导性。该规范非常清楚地说明了渲染命令的处理顺序。虽然允许实现在内部改变顺序,但它们不能做任何会改变顺序对用户来说很明显。简而言之,他们必须按顺序处理事物一样工作。
  • 我相信他的回答是指渲染顶点的顺序,而不是实际渲染命令的顺序。
  • @SebbyJohanns:我也是。OpenGL 规范非常清楚关于处理图元的顺序。一个实现可以在幕后做它喜欢做的任何事情,但它必须渲染所有的东西好像它是按照用户指定的顺序处理的。这也意味着单个渲染命令中的三角形序列。
  • 我已经编辑了我的帖子并澄清了一些事情(希望如此)。如果您还有其他 cmets,请告诉我。
  • 在 Android 中,您应该始终尝试从前到后绘制对象以利用早期的 z 剔除。在我们的例子中,它显着提高了性能(5-10 fps),特别是如果具有简单着色器的对象遮挡了具有复杂片段着色器的对象。一些 GPU(例如 PowerVR)确实具有先进的基于平铺的渲染管道,允许您不考虑顺序地绘制对象,但在另一个硬件(即 Tegra 和 Adreno GPU)上,早期 z 剔除的影响是显着的。
【解决方案2】:

您在这里混淆了一些概念。无需重新排序顶点 (*)。但是您应该从前到后绘制不透明的对象。这在 GPU 上启用了所谓的“早期 z 拒绝”。如果 GPU 知道 z 测试不会对像素进行着色,则它不必运行着色器、进行纹理提取等。但这适用于绘图调用中的对象,而不适用于单个对象。

一个简单的例子:你有一个玩家角色和一个天空背景。如果您先绘制玩家,GPU 将永远不必为玩家所在的像素进行纹理查找。如果你反过来做,你先画出所有的天空,然后把它遮住。

透明几何当然需要拉回前面。

( * )=顶点可以重新排序以获得更好的性能。但是做早期 z 更为重要,而且是针对每个对象完成的。

【讨论】:

    猜你喜欢
    • 2011-10-02
    • 2021-10-06
    • 1970-01-01
    • 1970-01-01
    • 2014-07-15
    • 1970-01-01
    • 1970-01-01
    • 2021-04-18
    • 1970-01-01
    相关资源
    最近更新 更多