在渲染的哪个阶段发生削波?

时间:2011-10-31 21:13:32

标签: optimization opengl

我有一些OpenGL绘图代码,我正在尝试优化。在决定是否将渲染数据发送到OpenGL之前,它目前正在测试客户端可见性的所有绘图对象。 (这比它听起来更容易。它正在绘制2D场景,因此裁剪很简单:只需测试视口矩形的当前坐标。)

我发现通过将整个场景传递给OpenGL并让GPU处理裁剪可以大大简化整个模型。但有时总数可能非常非常复杂,总共涉及多达100,000个精灵,其中大多数都没有被渲染,因为它们是离机的,我宁愿不以简单的名义杀死帧速率。

我正在使用OpenGL 2.0,我有一个非常简单的顶点着色器和一个更复杂的片段着色器。有没有保证说如果顶点着色器运行并确定多边形的所有顶点完全离开的坐标,那么剪切测试将应用于那里和片段着色器之间的某处,并防止片段着色器运行那个多边形?如果是这样,这是自动的还是我需要做些什么来启用它?我在网上查看了相关信息,但我没有找到任何结论......

3 个答案:

答案 0 :(得分:2)

在片段处理之前发生剪切和剔除。 http://www.opengl.org/wiki/Rendering_Pipeline_Overview

但是,如果你不自己剔除,你仍然会传递100000 * 4个顶点(假设你用四边形而不是点精灵渲染精灵)。根据卡的内存性能,这可能是一个问题。

答案 1 :(得分:2)

在NDC空间之前和之后的顶点变换阶段之后发生剪切; 剪裁平面应用于剪辑空间,视口剪辑在NDC空间中完成。这是光栅化之前的一步。剪切意味着通过在可见性边界处插入新顶点或者丢弃视口外部的片段来“切割”仅部分可见的面。你的意思通常叫做剔除。完全在视口之外的面部被剔除,在同一阶段就像剪裁一样。

从性能的角度来看,最好的代码是从不执行的代码,最好的数据是从未访问过的数据。因此,在您的情况下发送一个单独的绘图调用,使GPU处理大批量的顶点显然需要CPU负载,但它消耗GPU处理能力。在发送绘图命令之前剔除这些顶点会消耗CPU功率,但会占用GPU负载。目标是找到合适的平衡点。如果顶点的数量很少,那么简单的蛮力方法(只渲染整个事物)可能很容易胜过其他方案。

然而,使用简单而有效的数据管理方案可以极大地提高两端的性能。例如,像Kd树这样的空间细分结构很容易构建(您不必平衡它)。将顶点排序到Kd树中,如果靠近根的一个分支完全位于视口之外,则可以省略(剔除)树的大部分。准备绘制框架,迭代树的可见部分,构建要绘制的顶点列表,然后将此列表传递给渲染命令。可以在O(n log n)时间内平均遍历Kd树。

答案 2 :(得分:1)

了解剪辑剔除之间的区别非常重要。你似乎在谈论后者。

剪切意味着采用三角形并将其切成碎片以适合视口。 OpenGL规范将此过程定义为在顶点后着色器中发生,对于任何仅部分在视图中的三角形。

剔除意味着完全抛弃一些东西。如果三角形不完全在视野中,则可以将其剔除。 OpenGL并没有说剔除必须发生。请记住:OpenGL规范定义了行为,而不是性能。

话虽如此,硬件制造商并不愚蠢。可以轻松实现诸如不在视口外部栅格化三角形的明显努力,并提高性能。几乎所有存在的硬件都可以做到这一点。

类似地,通常使用光栅化技巧(而不是通过创建新三角形)实现剪切(如果可能)。视口之外的碎片不是由光栅化器生成的。根据OpenGL,这也是合法的,因为规范定义了明显的行为。如果你把三角形切成碎片,只要看起来难以区分,你就不在乎它。

你的问题基本上是“我不应该做多少工作来渲染屏幕外物体?”这实际上取决于你的场景是什么以及你如何渲染它。你说你正在渲染100,000个精灵。您是在进行100,000次绘制调用,还是这些精灵是您以更大粒度渲染的更大结构的一部分?您是否每帧都将顶点数据流式传输到GPU,或者顶点数据是静态的吗?