【问题标题】:Do you have to call glViewport every time you bind a frame buffer with a different resolution?每次绑定不同分辨率的帧缓冲区时都必须调用 glViewport 吗?
【发布时间】:2016-02-16 12:56:57
【问题描述】:

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

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

这是必要的,还是程序中有其他问题?这是每帧都完成的,所以我担心如果我不必这样做会产生一些不必要的开销。

【问题讨论】:

    标签: opengl viewport resolution framebuffer


    【解决方案1】:

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

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

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

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

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

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

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

    【讨论】:

      【解决方案2】:

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

      是的,这是一个错误的假设(可能是由无数错位 glViewport 的糟糕教程提供的)。

      glViewport always 属于绘图代码。在将某些内容绘制到帧缓冲区之前,您总是使用正确的参数调用 glViewport。 glViewport设置的参数在转换管道中使用,所以你应该想到一个类似于glTransform(在固定函数管道中)或glUniform的命令的glViewport。

      【讨论】:

      • 谢谢! :) 所有教程我在帧缓冲区中使用与窗口相同的分辨率。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      • 2018-02-03
      相关资源
      最近更新 更多