我使用带有多个颜色附件(绘制缓冲区)的帧缓冲区,并使用多个着色器程序编写颜色。
每个着色器程序使用不同的渲染目标 例如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);
...
答案 0 :(得分:3)
使用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
指令码)。
您也可以使用此代码:
GLenum drawBuffers2[] = {GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
glDrawBuffers(2, drawBuffers2);
片段着色器输出的位置为0和1。这样做的一个缺点是,如果您想将代码移植到OpenGL ES,它将无法工作。在ES中, i 缓冲区只能是GL_NONE
或GL_COLOR_ATTACHMENT
i 。
答案 1 :(得分:1)
即使您的片段着色器未输出到特定输出位置,fragment在技术上仍然具有这些位置的输出。未写入的位置只有一个未定义的值。
因此,如果您的draw buffer setting说“将片段输出位置1并将其写入颜色附件1”,那么它就是这样做的。总是。直到你改变它。
您可以使用write masking关闭特定颜色缓冲区的写入。但实际上,适当地设置glDrawBuffers
可能更好。