1) 到目前为止这是正确的吗?
嗯,或多或少。从概念上讲,帧缓冲区是一组具有特定语义的缓冲区,一个(甚至零个)或多个颜色缓冲区,可能是一个深度缓冲区,也可能是一个模板缓冲区。这些是片段的相应值写入的目标。
但要回答 2) 和 3),您必须了解 默认帧缓冲区 和 帧缓冲区对象 (FBO) 之间的区别。对于每个 OpenGL 上下文,都有一个默认帧缓冲区(其属性是在通过某些特定于平台的方式创建上下文时指定的),它包含一个颜色缓冲区(现在让我们忽略双重和立体缓冲),其中包含实际显示的内容,并且可能其对应的深度和模板缓冲区。因此,无论您想在显示器上看到什么,迟早都必须找到进入默认帧缓冲区的方式。但是此默认帧缓冲区的各个缓冲区是固定的,即您不能只将纹理或渲染缓冲区绑定到它,或者将其说深度缓冲区切换为另一个缓冲区(例如,您只能将内容复制到其中或从中复制出来,但不能将它们重定向到某个其他内存区域)。
除此之外,您还可以自己创建所谓的帧缓冲对象 (FBO)(与所有 gl...Framebuffer... 函数一起创建和使用的对象)。这些最终是轻量级 OpenGL 对象(即没有繁重的数据容器),它们为各个缓冲区通道(多种颜色附件、深度和模板附件)提供一组附件点,您可以将实际数据容器附加到这些附件点,像纹理或渲染缓冲区。所有这些附件一起定义了一个实际的帧缓冲区,类似于默认的帧缓冲区。但是 FBO 的优点是,您可以将任意容器附加到它,因此它允许直接渲染到纹理中。同样,它是否不绑定到某些操作系统资源或显示器,因此通常允许离屏渲染。
因此,对于在屏幕上显示(可能经过深度和模板测试)图元的日常工作,默认帧缓冲区就足够了,您根本不需要弄乱 FBO。如果您使用 FBO,例如想要在屏幕外绘制一些不会显示的东西,通常直接到纹理中以用于进一步处理,或者从 CPU 读取并在那里处理。很好的例子是阴影贴图创建(将场景渲染成深度纹理,然后在将要被阴影对象渲染到屏幕时使用)或后处理效果(将场景渲染成颜色纹理以通过一些额外的后处理着色器,然后最终放到屏幕上)。但最终用例数不胜数。
让我们再看看你的问题(但要小心重复;)):
2) 我想我在某处读到帧缓冲区是在
上下文已创建。
是的,但该帧缓冲区与帧缓冲区对象不同。
但是如果真的创建了帧缓冲区,我为什么要调用
glGenFramebuffersOES(1, &framebuffer) 和
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer)?
这反过来又用于创建您自己的不同于默认帧缓冲区的帧缓冲区对象。
但是假设我已经在上下文中有一个帧缓冲区,为什么我不能
检索它并将我的渲染缓冲区附加到那个?
因为默认帧缓冲区不具备完整帧缓冲区对象的功能,并且不允许将其数据重定向到其他数据容器(如渲染缓冲区)中。它仅具有连接到实际显示操作系统资源的预定义存储。
3) 什么是“默认帧缓冲区”?它是一个带有名称的帧缓冲区
0. 如果已经有默认的帧缓冲,为什么还要新建一个呢?
同上。 FBO ID 0 是默认帧缓冲区的占位符,因此意味着 “根本没有 FBO”。这意味着在执行glBindFramebuffer(GL_FRAMEBUFFER, 0)(这是您可以使用 ID 为 0 调用的唯一函数)时,您会告诉 GL,您从现在开始想要使用(读取和绘制)默认帧缓冲区而不是某些自定义 FBO .
所以底线是,在上下文创建时创建的默认帧缓冲区不具备帧缓冲区对象的全部功能,即将任意内存区域作为单独的缓冲区附加,这在某些(但不是全部)渲染场景中是必需的。如果您需要此功能,则必须使用您在问题中列出的功能创建和管理帧缓冲区对象 (FBO)。