我是不是需要在我的 FBO 中使用 RenderBuffer 对象来渲染到保留 Alpha 通道的纹理?

Posted

技术标签:

【中文标题】我是不是需要在我的 FBO 中使用 RenderBuffer 对象来渲染到保留 Alpha 通道的纹理?【英文标题】:Do I need RenderBufferObject in my FBO to render-to-texture with alpha channel perserved?我是否需要在我的 FBO 中使用 RenderBuffer 对象来渲染到保留 Alpha 通道的纹理? 【发布时间】:2014-09-06 04:45:42 【问题描述】:

在 Windows 7(使用 nVidia GTS 450)上,我的帧缓冲区似乎被锁定为 0 alpha 位。这意味着当我调用 glCopyTexSubImage2D 来渲染到纹理时,纹理将始终是不透明的。

我正在编写我的 OpenGL 代码的替代版本,它将使用 FBO 渲染到纹理(而不是 glCopyTexSubImage2D),希望能够解决 alpha 被丢弃的问题。

如果我使用 FBO,是否还需要分配我自己的帧缓冲区(RenderBufferObject)?我对 FBO 的了解有点少,但我的理解是,如果我不提供渲染缓冲区存储,而只是附加纹理,它将使用现有的帧缓冲区(没有 alpha 位),因此我的纹理将仍然是完全不透明的。

编辑:我的项目设置有些混乱是我的 alpha 位被锁定为 0 的原因,我现在通过 glCopyTexSubImage2D 成功获得 8 位 alpha

【问题讨论】:

【参考方案1】:

纹理和渲染缓冲区的用途大多与 FBO 附件相同。您可以使用纹理或渲染缓冲区作为颜色附件,纹理或渲染缓冲区作为深度附件等。

主要区别在于,在完成对 FBO 的渲染后,如果您使用纹理作为附件,则可以像使用任何其他纹理一样使用它们进行采样。如果您使用了渲染缓冲区,则该选项不可用。渲染缓冲区只能用作 FBO 目标。之后你唯一能做的就是将它复制到另一个渲染目标,使用glBlitFramebuffer()

因此,渲染缓冲区对于完成 FBO 渲染后不再使用的缓冲区非常有用。通常,这对于深度缓冲区是正确的。对于最有趣的 3D 渲染,您将需要一个深度缓冲区来进行 FBO 渲染。但在很多情况下,一旦渲染完成,您将简单地丢弃深度缓冲区的内容。

您可能会问,如果您可以对纹理附件做同样的事情,为什么还要使用渲染缓冲区等等。可能有几个优点:

在某些 OpenGL 版本中,渲染缓冲区可以做的不仅仅是纹理附件。例如,ES 3.0 支持多重采样渲染缓冲区,但不支持多重采样纹理。 某些硬件架构具有多种内存布局,其中一种可能对渲染目标更有效,另一种对采样更有效。如果您分配渲染缓冲区,驱动程序知道它只会用作渲染目标,并且可能能够为此目的使用更有效的内存布局。 用于创建渲染缓冲区的 API 更简单。

这涵盖了一般背景。对于您的具体情况:

不,如果您渲染到纹理(即使用纹理作为 FBO 的颜色附件),您也不需要渲染缓冲区来实现相同目的。 您可能需要创建一个渲染缓冲区以用作 FBO 渲染的深度缓冲区。为此,您使用glRenderbufferStorage() 创建一个渲染缓冲区,并使用glFramebufferRenderbuffer() 将其附加为FBO 的GL_DEPTH_ATTACHMENT。请注意,默认帧缓冲区的深度缓冲区用于 FBO 渲染,因此如果您需要用于 FBO 渲染的深度缓冲区,则需要这样做。

顺便说一句,您的视频卡绝对应该支持帧缓冲区中的 alpha 位。在 Windows 下,您可以通过设置 PIXELFORMATDESCRIPTOR 结构中的 cAlphaBits 字段来请求 alpha 位。如果您想要帧缓冲区中的 alpha 位,则该字段使用的典型值为 8。

【讨论】:

cAlphaBits is ignored on Windows。即使将其设置为(8),glGetIntegerv 告诉我我的帧缓冲区仍然没有 alpha 位。事实上,纹理仍然是不透明的。 @Mr.Smith:这不是真的:“请注意,如上所述,当前通用实现不支持某些像素格式属性。通用实现是 Microsoft GDI 软件实现OpenGL 的。硬件制造商可能会增强 OpenGL 的部分功能,并且可能支持通用实现不支持的某些像素格式属性。自 aeons 以来,除了 Microsoft 的 GDI 渲染器之外的所有实现都支持 Windows 上的 Alpha 通道。 我相当肯定我使用的带有 alpha 位的帧缓冲区至少可以追溯到 Windows XP 和 NV34 GPU。而且我刚刚确认它们仍然在我当前运行 Windows 8.1 的笔记本电脑上受支持。在我测试的配置(Intel HD 4600 显卡)中,我得到了一个 cAlphaBits=8 的像素格式,甚至没有请求 alpha 位。 @derhass 我什至尝试禁用 Aero 并仅请求 24 位颜色和 8 位 alpha,但在我的 OpenGL 上下文中仍然得到 0 位 alpha。我认为您将纹理格式与帧缓冲区格式混淆了;我的纹理使用 8 位 alpha 通道成功创建,并且通过混合成功渲染,但我的帧缓冲区没有 alpha 位。 @Mr.Smith:不,我没有混淆纹理和帧缓冲区。您确定您甚至可以通过 nvidia 的 ICD 获得上下文吗?毕竟,您可能对 GDI 渲染器有一些回退。

以上是关于我是不是需要在我的 FBO 中使用 RenderBuffer 对象来渲染到保留 Alpha 通道的纹理?的主要内容,如果未能解决你的问题,请参考以下文章

通过 FBO 使用 Render to Target 时是不是需要重新生成 MipMap?

openGL FBO 复制到纹理导致黑色/深色图像

是否可以使用 LWJGL 以无头模式渲染到 FBO?

切换FBO时是不是保留glEnable?

使用 FBO 和着色器 OpenGL 渲染到纹理

OpenGL:如何设置 OpenGL 只渲染到 FBO,不输出到屏幕/窗口/控件?