带有模板缓冲区 FBO 的延迟渲染器

Posted

技术标签:

【中文标题】带有模板缓冲区 FBO 的延迟渲染器【英文标题】:Deferred renderer with stencil buffer FBO 【发布时间】:2015-09-09 19:59:26 【问题描述】:

在我的延迟渲染器中,我为我的几何传递创建了一个 FBO,我还将深度 + 模板缓冲区存储到具有这些参数的纹理中:

附件:GL_DEPTH_STENCIL_ATTACHMENT 格式:GL_DEPTH_STENCIL 内部格式:GL_DEPTH32F_STENCIL8 数据类型:GL_UNSIGNED_INT_24_8

我可以成功地用深度和模板填充这个纹理。

我现在面临的问题是如何使用在我的几何传递中创建的模板缓冲区以便在其他地方使用它,比如当我进行定向光传递时,我只想处理被在我的几何通道上可见几何。

那么,我如何使用在几何过程中存储的模板缓冲区以供进一步使用?

【问题讨论】:

模板测试类似于深度测试,在渲染时,您正在从同一个缓冲区读取和写入。因此,如果您想在以后的渲染过程中使用模板缓冲区,则需要将其附加或 blit 到当前绑定的帧缓冲区。 好的,但我在着色器中使用深度缓冲区作为纹理采样器。我从未尝试将其用作实际缓冲区来进行深度测试,因此我什至不知道如何使用先前创建的模板进行模板测试。那么我该如何使用它们呢?我读过 blitting 并不总是有效。 需要注意的一点是,定向灯可能会影响您的整个场景,因此不需要模板测试即可剔除像素。那部分主要用于光体积和其他有界光源。 【参考方案1】:

您当然可以始终使用模板缓冲区进行模板测试。为了说明如何在基本级别上使用模板测试,以下是一个示例的关键调用,其中您在两遍中绘制,在第二遍中,我们将排除在第一遍中未覆盖的所有像素:

当您清除帧缓冲区时,请确保您包含用于清除模板缓冲区的位:

glClear(... | GL_STENCIL_BUFFER_BIT);

启用模板测试:

glEnable(GL_STENCIL_TEST);

设置模板功能/操作以将模板缓冲区中的值设置为所有渲染像素:

glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);

GL_ALWAYS 指定所有像素都通过了模板测试(即没有像素被拒绝)。 GL_REPLACE 指定模板缓冲区中的值被所有渲染像素的参考值替换,这是glStencilFunc() 的第二个参数。

为第一遍绘制几何图形。

将模板功能/操作更改为仅渲染模板缓冲区中值为 1 的像素:

glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

GL_EQUAL 指定只有模板缓冲区值等于参考值 1 的位置的像素通过模板测试,而所有其他像素都被拒绝。 GL_KEEP 指定模板缓冲区中的当前值在此通道中不会被修改。

为第二遍绘制几何图形。

但是按照我阅读您的问题的方式,您正在寻找不同的东西。您希望在稍后的渲染过程中从一个渲染过程中对模板缓冲区进行采样,类似于采样深度纹理的方式。

OpenGL 4.3 及更高版本支持此功能。 texId 是深度/模板纹理的名称,关键部分是这个纹理参数设置:

glBindTexture(GL_TEXTURE_2D, texId);
glTexParamteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);

这指定深度/模板纹理的模板部分应该用于采样。模板纹理仅支持最接近的采样,因此请确保您还具有以下值:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

毫不奇怪,基于值的性质,模板纹理被视为无符号整数纹理。这意味着着色器代码中的采样器类型需要为usampler2D

uniform usampler2D MyStencilTexture;

当你对纹理进行采样时,结果也将是无符号类型:

uvec4 stencilValue = texture(MyStencilTexture, textureCoordinates);

然后模板值将位于stencilValue.r

【讨论】:

好的,真的很有趣,我正在考虑将这种方法用于我要做的一些事情。但我正在寻找的是我认为不同的东西。目前我不需要像对深度缓冲区那样在我的着色器中对模板缓冲区进行采样,我只需要使用它来绘制我的视口的一部分,不包括其余部分以尝试优化一些绘图.例如,当我进行定向光通道时,我不需要绘制整个视口四边形,而只需要绘制一些几何图形的部分,因此我计划使用在我的第一个几何图形通道期间创建的模板缓冲区。跨度> @zeb 我添加了一些关于基本模板缓冲区使用的解释。 非常感谢。我现在就这样试试。 完美。我能够像我计划的那样使用模板测试。我的渲染管道现在看起来像这样:[first] geometry pass 填充 FBO,所以模板缓冲区也像你展示给我的那样 [second] 定向光传递 blits stencil buffer 从几何传递到光缓冲区并使用模板缓冲区,就像你告诉我的那样。 我使用相同的方法来实现天空盒。精彩的!非常感谢!

以上是关于带有模板缓冲区 FBO 的延迟渲染器的主要内容,如果未能解决你的问题,请参考以下文章

我可以避免将模板缓冲区从 FBO 传送到后台缓冲区吗?

GL_TEXTURE_3D 颜色和模板 FBO 附件

在 GLSL 中检索 FBO 数据

OpenGL ES 多目标渲染(MRT)

OpenGL:使用多个纹理渲染到 FBO

渲染到窗口帧缓冲区和 FBO 以保存全尺寸纹理图像