out vec2 texcoords; // texcoords are in the normalized [0,1] range for the viewport-filling quad part of the triangle
void main() {
vec2 vertices[3]=vec2[3](vec2(-1,-1), vec2(3,-1), vec2(-1, 3));
gl_Position = vec4(vertices[gl_VertexID],0,1);
texcoords = 0.5 * gl_Position.xy + vec2(0.5);
}
如果你读过有关图形管线的教材(甚至GL规范),你可能会有这样的印象。但实际的GPU使用一些不同的方法,如 * 保护带削波 *。(这将是一个单独的主题,有关详细信息,请参阅Fabian "ryg" Giesen's fine blog article),但是一般的想法是光栅化器将仅为视口内的像素产生片段(或剪式矩形)无论如何,不管基元是否完全位于矩形内部,所以如果以下两个条件都成立,我们可以简单地向它扔更大的三角形:
6条答案
按热度按时间vnjpjtjt1#
我认为最有效的方法是绘制一个“全屏”三角形。要使三角形覆盖整个屏幕,它需要比实际的视口大。在NDC中(如果我们设置
w=1
,也包括剪切空间),视口将始终是[-1,1]
正方形。对于完全覆盖此区域的三角形,我们需要两条边的长度是视口矩形的两倍,这样第三条边将穿过视口的边缘,因此我们可以例如使用以下坐标(以逆时针顺序):一个月二个月一个月一个月三个月一个月一个月四个月一个月我们也不需要担心纹理坐标。要得到可见视口中通常的归一化
[0,1]
范围,我们只需要使顶点的相应纹理坐标变大,并且重心插值将对任何视口像素产生与使用四边形时完全相同的结果。这种方法当然可以与demanze's answer中建议的无属性渲染相结合:
为什么单个三角形更有效?
这 * 不是 * 关于一个保存的顶点着色器调用,以及在前端要处理的少一个三角形。使用单个三角形的最显著的效果将是更少的片段着色器调用
一旦图元的单个像素福尔斯2x2像素大小的块(“quads”)中,真实的的GPU总是会为该块调用片段着色器。这对于计算window-space derivative functions是必要的(纹理采样也隐含地需要这些,请参阅此问题)。
如果基元没有覆盖该块中的所有4个像素,则剩余的片段着色器调用将不会执行任何有用的工作(除了为导数计算提供数据之外),并且将是所谓的 * 辅助调用 *(什至可以通过
gl_HelperInvocation
GLSL function查询)。另请参见Fabian "ryg" Giesen's blog article了解更多详细信息。如果你用两个三角形渲染一个四边形,两个三角形都有一条边对角穿过视口,并且在两个三角形上,你会在对角边上产生很多无用的辅助调用。(长宽比1)。如果您绘制单一三角形,将没有这样的对角边(它位于视口之外,与光栅化器完全无关),因此将没有额外的辅助调用。
等一下,如果三角形延伸到视口边界,它不会被裁剪,实际上会在GPU上投入 * 更多 * 工作吗?
如果你读过有关图形管线的教材(甚至GL规范),你可能会有这样的印象。但实际的GPU使用一些不同的方法,如 * 保护带削波 *。(这将是一个单独的主题,有关详细信息,请参阅Fabian "ryg" Giesen's fine blog article),但是一般的想法是光栅化器将仅为视口内的像素产生片段(或剪式矩形)无论如何,不管基元是否完全位于矩形内部,所以如果以下两个条件都成立,我们可以简单地向它扔更大的三角形:
我们的三角形只比视口大3倍,所以我们可以非常确定根本不需要裁剪它。
"但这值得吗"
好吧,片段着色器调用的节省是真实的(特别是当你有一个复杂的片段着色器时),但整体效果在现实世界中可能几乎无法衡量。另一方面,这种方法并不比使用全屏四画面更复杂,而且使用 * 更少的数据 *,所以即使可能不会有很大的差异,也不会有什么坏处,所以为什么 * 不 * 使用它呢?
这种方法可以用于所有类型的轴对齐矩形,而不仅仅是全屏矩形吗?
理论上,可以将此方法与剪刀测试结合起来,绘制一些任意轴对齐的矩形(剪刀测试非常有效,因为它只是限制了首先产生的片段,而不是硬件中真实的的“测试”,即丢弃片段)。但是,这需要您为每个要绘制的矩形更改剪刀参数,这意味着大量的状态更改,并限制每个绘制调用只能绘制一个矩形,因此在大多数情况下这样做并不是一个好主意。
qeeaahzv2#
可以发送两个三角形创建一个四边形,并将其顶点属性分别设置为-1/1。
不需要将它们与顶点/片段着色器中的任何矩阵相乘。
下面是一些简单的代码示例:)
顶点着色器:
片段着色器:
wh6knrhe3#
完全不需要使用几何着色器、VBO或任何内存。
顶点着色器可以生成四边形。
绑定一个空的 VAO 。发送一个绘制6个顶点的调用。
ctzwtxfj4#
要输出全屏四边形几何着色器,可以使用:
顶点着色器为空:
要使用此着色器,可以使用带有空VBO的dummy draw命令:
h7appiyu5#
这与demanze的答案相似,但我认为它更容易理解。而且它只使用TRIANGLE_STRIP绘制了4个顶点。
goqiplq26#
以下代码来自类的draw函数,该类将fbo纹理绘制到屏幕对齐的四边形。
实际四边形本身和坐标从以下位置获得:
绑定和设置的vbo的我留给你。
顶点着色器:
因为位置是原始的,也就是说,没有乘以任何矩阵,四边形的-1,-1::1,1适合视口。