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