【问题标题】:Understanding buffers in OpenGLES iOS了解 OpenGLES iOS 中的缓冲区
【发布时间】:2013-05-06 13:53:09
【问题描述】:

我的理解:有所谓的帧缓冲区。它是一个指向缓冲区对象的指针数组。缓冲区对象可以是例如渲染缓冲区、纹理缓冲区或其他。如果我想绘制一些东西,我将渲染缓冲区附加到帧缓冲区,绘制到其中,最后调用一个方法将其发送到屏幕。

1) 到目前为止这是正确的吗?

我不明白的:

2)我想我在某处读到帧缓冲区是在创建上下文时创建的。唉,我再也找不到我看到这个的地方了。但是如果真的创建了帧缓冲区,为什么我必须调用glGenFramebuffersOES(1, &framebuffer)glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer)?据我了解,第一行创建了一个新的帧缓冲区,其中有一个空格用于附件,第二行将上下文的帧缓冲区指针设置为framebuffer。但是假设我已经在上下文中有一个帧缓冲区,为什么我不能检索它并将我的渲染缓冲区附加到它呢?

3) 什么是“默认帧缓冲区”?它是一个名称为0的帧缓冲区。如果已经有一个默认的帧缓冲区,为什么我要绘制还要创建一个新的?

【问题讨论】:

    标签: iphone ios opengl-es framebuffer


    【解决方案1】:

    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)。

    【讨论】:

    • 哇,太棒了。让我花点时间仔细阅读您的答案。
    • @MattN。 - 除了 Christian 上面所说的,framebuffer objects are the only rendering target on iOS,所以你不会在这个平台上使用默认的帧缓冲区。
    • @BradLarson 所以在 iOS 上确实有一个已经存在的默认 FBO 在玩吗?如果有办法访问这个(甚至可能重新附加它的附件),您可能需要提供一个额外的答案,以便更深入地了解 iOS 的复杂性(我自己做不到)。
    • @ChristianRau - 更重要的是,您必须为任何类型的渲染创建 FBO,无论是在屏幕上还是在屏幕外。屏幕渲染是通过创建 FBO 并将其附加到将显示它的 UI 层来完成的。如果我没记错的话,尝试渲染或使用默认帧缓冲区通常不会导致任何事情发生。
    • @MattN。 “Christian 的回答建议将渲染缓冲区对象直接发送到默认帧缓冲区的可能性。” - 无论如何答案都没有建议,它清楚地表明您可以 i> 将自定义渲染缓冲区附加到默认帧缓冲区,iOS 与否。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-29
    • 1970-01-01
    相关资源
    最近更新 更多