opengl - 具有多个绘制缓冲区的帧缓冲区

标签 opengl

我使用带有多个颜色附件(绘制缓冲区)的帧缓冲区,并使用多个着色器程序写入颜色。

每个着色器程序使用不同的渲染目标。
例如SHADER1 仅使用第一个绘制缓冲区,但 SHADER2 使用第二个和第三个绘制缓冲区。

但是如果我只在片段着色器中指定渲染目标,如下所示:

// SHADER1.frag
layout(location = 0) out vec4 color;
void main() { color = vec4(1.0); }

这会导致在每个绘制缓冲区写入颜色,因此我必须清除第二个和第三个绘制缓冲区。

这是默认行为吗?
我应该像这样更新每个着色器程序的 glDrawbuffers 状态吗?

glUseProgram(SHADER1);
GLenum drawBuffers1[] = { GL_COLOR_ATTACHMENT0, GL_NONE, GL_NONE};
glDrawBuffers(3, drawBuffers1);

...

glUseProgram(SHADER2);
GLenum drawBuffers2[] = { GL_NONE, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
glDrawBuffers(3, drawBuffers2);

...

最佳答案

使用 glDrawBuffers() 设置的状态是帧缓冲区对象 (FBO) 状态的一部分。因此,只要您对所有渲染使用相同的 FBO,每次想要绘制到不同的缓冲区时都必须调用 glDrawBuffers()

根据您的描述,我认为您使用多个 FBO 会容易得多。使用与您在问题中使用的类似的伪符号,您可以在设置过程中进行一次这些调用:

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FBO1);
glFramebufferTexture2D(..., GL_COLOR_ATTACHMENT0, ..., BUFFER1, ...);
GLenum drawBuffers1[] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, drawBuffers1);

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FBO2);
glFramebufferTexture2D(..., GL_COLOR_ATTACHMENT0, ..., BUFFER2, ...);
glFramebufferTexture2D(..., GL_COLOR_ATTACHMENT1, ..., BUFFER3, ...);
GLenum drawBuffers2[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
glDrawBuffers(2, drawBuffers2);

然后每次渲染时:

glUseProgram(SHADER1);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FBO1);
...

glUseProgram(SHADER2);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FBO2);
...

为了实现此目的,您的 SHADER1 将有一个输出(位置为 0),SHADER2 有两个输出(位置为 0 和 1)。

如果出于某种原因你想坚持使用一个 FBO,并让你的方法发挥作用,你必须小心才能得到你想要的结果:

GLenum drawBuffers2[] = { GL_NONE, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
glDrawBuffers(3, drawBuffers2);

通过这些设置,并使用具有两个输出的着色器,您必须将输出的位置设置为 1 和 2(使用 glBindFragDataLocation()location code> 着色器代码中的指令)。

您也可以使用它:

GLenum drawBuffers2[] = {GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
glDrawBuffers(2, drawBuffers2);

位置 0 和 1 用于片段着色器输出。这样做的一个缺点是,如果您想将代码移植到 OpenGL ES,它将无法工作。在 ES 中,第 i 个缓冲区只能是 GL_NONEGL_COLOR_ATTACHMENTi

关于opengl - 具有多个绘制缓冲区的帧缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34082243/

相关文章:

opengl - 如何使用 cmake 在 OSX 上链接 libGL?

opengl - ATI 显卡上 GLSL 着色器的顶点统一组件的实际数量是多少?

c++ - OpenGL 漫反射照明计算错误

c++ - NormalTexture 在 Wavefront 资源 Material 格式中如何表示?

c++ - 在固定管道中使用 OpenGL 绘制时 mask 部分纹理

qt - 如何在 Qt4 OpenGL 应用程序中启用 HiDPI (Retina) 支持?

c++ - 将粒子位置(glm vec3s)顶点传递给顶点缓冲区对象

opengl - GLSL:检查是否支持扩展

c - 使用 MinGW : Undefined reference to '_imp__glewExperimental.' 的 GLEW 问题

c++ - 我需要有关从 C++ 中的文件进行解析的帮助