JensF
JensF

Reputation: 33

Blitting FBO Color Attachments

I have 2 FBOs + MRT and they have identical attachments(4 color attachments each). using glBlitFrameBuffer works as expected for the depth buffer and for one color_attachment. However, when i blit multiple color attachments, things go bad. I have done a lot of research and tried a lot of different methods, none works. I am not using renderBufferStorage because my textures have different internal formats(RGBA and RGB16F). This sounds like a similar problem, except i am not using multisampling, only MRT.

OpenGL version 4.3

Why: I want to create a state of the terrain pre- lighting calculations so that i only need to render the terrain if there are changes(ie. camera movement) and then copy these color attachments to the next FBO. This is for deferred shading and the FBOs resembles the gBuffer a lot.

At first i expected that i should use glDrawBuffers which i am using in the initial setup, but there is no glReadBuffers and therefore i am assuming i have no way to link them. I might be wrong here, not an expert yet =)

Original code is written in Golang, should be easily transferable to C++ (will translate if requested).

UPDATE/SOLVED: For anyone stumbling onto this issue. When you are using glDrawBuffers() and using a call to glDrawBuffer() you are overwriting your glDrawBuffers() state. It needs to be reset to its orignal glDrawBuffers() state.

Update2: For those interested in a method like this i can confirm that it has incredible performance results, if you have a non-animated world and the camera doesn't move that often. For my purpose it is great (RTS), but for a FPS game like CS it would be a very bad approach.

Add the following after blitting (case specific):

var attachments = [4]uint32{gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2, gl.COLOR_ATTACHMENT3}
gl.DrawBuffers(4, &attachments[0])

FBO setup

gl.GenFramebuffers(1, &fbo.ID)
gl.BindFramebuffer(gl.FRAMEBUFFER, fbo.ID)

//setting up color attachments

gl.GenTextures(1, &fbo.Position)
gl.BindTexture(gl.TEXTURE_2D, fbo.Position)
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGB16F, windowWidth, windowHeight, 0, gl.RGB, gl.FLOAT, nil)
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbo.Position, 0)

//repeated 3 times for the additional color attachments

var attachments = [4]uint32{gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2, gl.COLOR_ATTACHMENT3}
gl.DrawBuffers(4, &attachments[0])

gl.GenRenderbuffers(1, &fbo.DepthBuffer)
gl.BindRenderbuffer(gl.RENDERBUFFER, fbo.DepthBuffer)
gl.RenderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT, windowWidth, windowHeight)
gl.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, fbo.DepthBuffer)

gl.BindFramebuffer(gl.FRAMEBUFFER, 0)

And now to the blitting part.

gl.BindFramebuffer(gl.READ_FRAMEBUFFER, fboIn.ID)
gl.BindFramebuffer(gl.DRAW_FRAMEBUFFER, fboOut.ID)

//works as expected
gl.BlitFramebuffer(0, 0, windowWidth, windowHeight, 0, 0, windowWidth, windowHeight, gl.DEPTH_BUFFER_BIT, gl.NEAREST)

//works as expected
gl.ReadBuffer(gl.COLOR_ATTACHMENT0)
gl.DrawBuffer(gl.COLOR_ATTACHMENT0)
gl.BlitFramebuffer(0, 0, windowWidth, windowHeight, 0, 0, windowWidth, windowHeight, gl.COLOR_BUFFER_BIT, gl.LINEAR)

//fails - no errors but produces some weird occurrences. 
gl.ReadBuffer(gl.COLOR_ATTACHMENT1)
gl.DrawBuffer(gl.COLOR_ATTACHMENT1)
gl.BlitFramebuffer(0, 0, windowWidth, windowHeight, 0, 0, windowWidth, windowHeight, gl.COLOR_BUFFER_BIT, gl.LINEAR)

gl.BindFramebuffer(gl.FRAMEBUFFER, 0)

Upvotes: 3

Views: 795

Answers (1)

derhass
derhass

Reputation: 45322

glDrawBuffer(x) is conceptually equivalent to calling GLenum bufs[1]={x}; glDrawBuffers(1, bufs). SInce the draw buffer state is part of the FBO state, your blitting code overwrites these states, and if these are not restored manually, the rendering afterwards will not work as intended. If you call this in a loop, this might lead to the wrong conclusion that the blitting is the issue, but in reality,the blitting is working correctly, just on wrong input data.

Upvotes: 1

Related Questions