这是我第一次尝试使用opengl进行多重采样(用于抗锯齿)。基本上,我在屏幕上绘制背景(不应该消除锯齿),然后我绘制应该消除锯齿的顶点。 到目前为止我做了什么:
{{1}}
问题是:当我调用glBlitFramebuffer(...)时,整个背景变黑,我只看到消除锯齿的顶点。
有什么建议吗?
答案 0 :(得分:9)
通常情况下,如果要在图像中考虑透明度的同时在现有渲染上渲染新图像/纹理,则混合是最明显的选项。将渲染到多重采样帧缓冲区视为具有透明度的图像,这正是您所拥有的情况。
在这种情况下,有一些挑战使混合的使用比平常更困难。首先,glBlitFramebuffer()
不应用混合。来自规范:
Blit操作绕过片段管道。影响blit的唯一片段操作是像素所有权测试和剪刀测试。
如果没有多重采样,这很容易克服。您可以通过绘制屏幕大小的纹理四边形来执行blit,而不是使用glBlitFramebuffer()
。由于现在所有片段操作都在使用,您可以使用混合。
Howerver,"绘制纹理四边形"由于您的内容是多重采样的,因此部分变得更加棘手。我想到了一些选择。
您可以将背景渲染到多重采样FBO而不是主帧缓冲区。然后,您可以像现在一样使用glBlitFramebuffer()
。
您可能会想:"但我不希望我的背景被消除锯齿!" 这不是一个真正的问题。您只需在绘制背景时禁用多重采样:
glDisable(GL_MULTISAMPLE);
我认为应该给你你想要的东西。如果确实如此,它是迄今为止最简单的选择。
OpenGL 3.2及更高版本支持多重采样纹理。为此,您将使用纹理而不是渲染缓冲区作为FBO的颜色缓冲区。纹理分配:
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8,
xsize, ysize, GL_FALSE);
还有其他方面我不能在这里介绍。如果您想探索此选项,可以阅读规范或其他来源中的所有详细信息。例如,着色器代码中纹理的采样工作方式不同,使用不同的采样器类型,以及只允许您一次读取一个采样的采样函数。
您可以使用glBlitFramebuffer()
的混合来解析多重采样内容,以及"手册"用于将内容混合到默认帧缓冲区中的blit:
glBlitFramebuffer()
从第一个FBO中的多重采样渲染缓冲区复制到第二个FBO中的纹理。虽然这看起来有点尴尬,并且需要额外的副本,这对性能不利,但它相当简单。
为此,您完全按照自己现在所做的操作,将多重采样的FBO内容复制到glBlitFramebuffer()
的默认帧缓冲区。但是你首先这样做,然后渲染背景 。
您可能认为这不会起作用,因为它会将背景放在其他内容的前面,这使得......背景不是很多。
但这里是混合再次发挥作用的地方。虽然在其他内容之上混合内容是使用混合的最常用方式,但您也可以使用它来渲染隐藏现有内容。要做到这一点,你需要做一些事情:
正确的混合功能。对于前后混合,通常使用:
glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);
这增加了以前没有渲染任何内容的新渲染(即目标中的alpha为0),并且在已经渲染的地方(即目标alpha为1)保持前一渲染不变。
如果渲染涉及部分透明度,混合设置会变得有点棘手。
这可能看起来有点复杂,但是一旦你了解混合功能的工作方式,它就非常直观。我认为它总体上是一个优雅而有效的解决方案,可以解决您的整体问题。