2015-12-04 219 views
0

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

每个着色器程序使用不同的渲染目标。
例如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

绘图缓冲区的默认设置仅为“GL_COLOR_ATTACHMENT0”。所以除非你更早的改变了这个值,否则它只能渲染到第一个缓冲区。 –

回答

2

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

根据你的描述,我认为这将是您更容易使用多个宗教组织。用类似的伪符号,你在你的问题用一个,你可以在安装过程中进行这些调用一次:

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中,缓冲区只能是GL_NONEGL_COLOR_ATTACHMENT

+0

感谢您的回答,并且对于迟到的回复感到抱歉。 [WIKI](https://www.opengl.org/wiki/Fragment_Shader#Output_buffers)说,“每次改变glDrawBuffers状态并重新验证FBO可能不是一个好主意。”它可能在不同的范围,但是没有性能问题经常改变glDrawBuffers? –

+1

@HyunanKwon切换帧缓冲器可能相当昂贵。它非常依赖平台,但与其他状态变化相比,我会将其视为重量级。这意味着你不应该多次来回切换。我不确定在单个FBO中切换绘制缓冲区是否会比绑定不同的FBO更好。我想不出它应该是什么原因。 –

1

即使你的片段着色器不会输出到特定的输出位置,即fragment技术上还为那些位置输出。未写入的位置仅具有未定义的值。

因此,如果您draw buffer setting说“拿片段输出位置1,并将其写入附色1”,然后就是它会做什么。总是。直到你改变它。

你可以使用write masking打开特定的颜色缓冲写入关闭。但实际上,适当设置glDrawBuffers可能会更好。

+0

您如何看待性能问题(经常更换glDrawBuffers)? –