我使用带有多个颜色附件(绘制缓冲区)的帧缓冲区,并使用多个着色器程序写入颜色。
每个着色器程序使用不同的渲染目标。
例如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_NONE
或 GL_COLOR_ATTACHMENT
i。
关于opengl - 具有多个绘制缓冲区的帧缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34082243/