每次绑定具有不同分辨率的帧缓冲区时,是否必须调用glViewport?

时间:2015-11-15 09:36:10

标签: opengl viewport resolution framebuffer

我有一个程序,大约有3个不同大小的帧缓冲区。我在开始时初始化它们,给它们适当的渲染目标并更改每个渲染目标的视口大小。

我原本以为你只需要在初始化帧缓冲区时调用glViewport,但是这会在我的程序中产生问题所以我认为这是错的?因为它们的分辨率都不同,所以当我在每个帧中渲染时,我绑定第一个帧缓冲区,更改视口大小以适合该帧缓冲区,绑定第二个帧缓冲区,更改视口大小以适应第二个帧缓冲区的分辨率,绑定第三个帧缓冲区,更改视口大小以适合它,然后绑定窗口帧缓冲区并将视口大小更改为窗口的分辨率。

这是必要的,还是程序中的其他东西应该归咎于什么?这是每一帧完成的,所以我担心如果我不必这样做会有一点不必要的开销。

2 个答案:

答案 0 :(得分:9)

在开始绘制具有不同大小的帧缓冲区之前,您始终需要调用glViewport()。这是必要的,因为视口不是帧缓冲状态的一部分。

如果你看一下例如OpenGL 3.3规范,标题为“状态表”的第6.2节,从第278页开始,包含具有整个状态的表,显示每个状态的范围:

  • 第299页的表6.23列出了“每帧缓冲对象的状态”。列出的唯一状态是绘制缓冲区和读取缓冲区。如果视口是帧缓冲状态的一部分,则会在此处列出。
  • 视口在表6.8“转换状态”中列出。这是全局状态,与任何对象无关。

OpenGL 4.1引入了多个视口。但它们仍然是全球转型国家的一部分。

如果你想知道为什么会这样,那么唯一真正的答案是它是以这种方式定义的。看一下图形管道,它确实有意义。虽然glViewport()调用使得它看起来像是要在帧缓冲区中指定要渲染的矩形,但调用实际上定义了一个变换,该变换作为顶点着色器之间的固定功能块的一部分应用(或几何着色器,如果你有一个)和片段着色器。视口设置确定NDC(规范化设备坐标)如何映射到窗口坐标。

另一方面,帧缓冲状态决定了片段着色器输出如何写入帧缓冲区。因此它控制着管道的完全不同的部分。

从视口通常被应用程序使用的方式来看,我认为使视口成为帧缓冲状态的一部分会更有意义。但OpenGL实际上是一个用作图形硬件抽象的API,从这个角度来看,视口独立于帧缓冲状态。

答案 1 :(得分:7)

  

我原本以为你只需要在初始化帧缓冲区时调用glViewPort,但这会在我的程序中产生问题所以我认为这是错误的?

是的,这是一个错误的假设(可能是由于无数错误的教程错误放置了glViewport)。

glViewport 始终属于绘图代码。在您将某些内容绘制到帧缓冲区之前,您总是使用正确的参数调用glViewport。 glViewport设置的参数在转换管道中使用,因此您应该考虑类似于glTransform(在固定功能管道中)或glUniform的命令的glViewport。