openglgoframebufferdeferred-rendering

Rendering is different to single pass rendering


I've started updating my code to allow for multipass rendering. I'm fairly certain I'm doing framebuffers right but somehow I'm not getting the results I want. The code I'm using is based off the following tutorial: https://learnopengl.com/Advanced-OpenGL/Framebuffers

When I render to the default buffer I get exactly what I expect: enter image description here

However when I render that to a non-default framebuffer texture and place it on a quad, I get this very puzzling result: enter image description here

So my initial thinking is that there is something wrong with how I'm drawing the quad that my non-default framebuffer texture is placed on (the one spanning to all four corners of the window). But when rendering only that, with wireframes enabled, I getting exactly what I expect (and what the tutorial confirms I will get): enter image description here

So that leaves me thinking there are two possible issues with my code:

Wrong Framebuffer Configuration

When the non-default framebuffer draws everything to the texture, it is in some strange orientation and scale that results in everything rendering completely wrong (even though everything is perfect when rendered to the default framebuffer). Perhaps some previous buffer isn't cleared or there is something in the configuration that adjusts how the framebuffer renders onto the texture.

Quad Texture is Wrapping

The texture is too small and when wrapped on the quad that is much bigger, it repeats the output and apparently somehow rotates... Notice how the objects are pulled skew when it crosses the diagonal line to the top-right triangle of the quad. This must be related to some issue...

Code (in the order it executes):

framebuffer configuration

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

gl.GenTextures(1, &o.cbo)                                                                                             
gl.BindTexture(gl.TEXTURE_2D, o.cbo)                                                                                  
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGB, int32(o.screenWidth), int32(o.screenHeight), 0, gl.RGB, gl.UNSIGNED_BYTE, nil)
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)                                                     
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)                                                     
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, o.cbo, 0)                                

gl.GenRenderbuffers(1, &o.rbo)                                                                                        
gl.BindRenderbuffer(gl.RENDERBUFFER, o.rbo)                                                                           
gl.RenderbufferStorage(gl.RENDERBUFFER, gl.DEPTH24_STENCIL8, int32(o.screenWidth), int32(o.screenHeight))             
gl.FramebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, o.rbo)                       
if gl.CheckFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE {                                             
    log.Fatal("Framebuffer incomplete")                                                                               
}                                                                                                                     
gl.BindFramebuffer(gl.FRAMEBUFFER, 0)                                                                                 

...

first pass draw

gl.BindFramebuffer(gl.FRAMEBUFFER, o.fbo)                            
gl.Enable(gl.DEPTH_TEST)                                             

gl.ClearColor(clearColor.R, clearColor.G, clearColor.B, clearColor.A)
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)                  

gl.UseProgram(o.shaderProgram)                                       

...

draw each object

gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, gl.PtrOffset(0))
gl.UniformMatrix4fv(model_uni, 1, false, &model[0])                
gl.BindVertexArray(0)                                              

...

second pass draw

gl.BindFramebuffer(gl.FRAMEBUFFER, 0)                              
gl.Disable(gl.DEPTH_TEST)                                          

gl.ClearColor(1, 1, 1, 1)                                          
gl.Clear(gl.COLOR_BUFFER_BIT)                                      
gl.UseProgram(o.screenShaderProgram)                               
gl.BindVertexArray(o.quadVAO)                                      
gl.BindTexture(gl.TEXTURE_2D, o.cbo)                               
gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, gl.PtrOffset(0))

o.window.SwapBuffers()                                             
glfw32.PollEvents()                                                

quad vao

vertices := []float32{                                                                   
    1.0, 1.0, 1.0, 1.0, // 0 top right                                                   
    1.0, -1.0, 1.0, 0.0, // 1 bot right                                                  
    -1.0, -1.0, 0.0, 0.0, // 2 bot left                                                  
    -1.0, 1.0, 0.0, 1.0, // 3 top left                                                   
}                                                                                        
indicies := []uint8{                                                                     
    0, 1, 3,                                                                             
    1, 2, 3,                                                                             
}                                                                                        

var vertexArrayID uint32                                                                 
gl.GenVertexArrays(1, &vertexArrayID)                                                    
gl.BindVertexArray(vertexArrayID)                                                        

// Vertex buffer                                                                         
var vertexBuffer uint32                                                                  
gl.GenBuffers(1, &vertexBuffer)                                                          
gl.BindBuffer(gl.ARRAY_BUFFER, vertexBuffer)                                             
gl.BufferData(gl.ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW)        

// Element buffer                                                                        
var elementBuffer uint32                                                                 
gl.GenBuffers(1, &elementBuffer)                                                         
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer)                                    
gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, len(indicies)*4, gl.Ptr(indicies), gl.STATIC_DRAW)

// Linking vertex attributes                                                             
gl.VertexAttribPointer(0, 2, gl.FLOAT, false, 4*4, gl.PtrOffset(0))                      
gl.EnableVertexAttribArray(0)                                                            

// Linking texture attributes                                                            
gl.VertexAttribPointer(1, 2, gl.FLOAT, false, 3*4, gl.PtrOffset(2*4))                    
gl.EnableVertexAttribArray(1)                                                            

o.quadVAO = vertexArrayID                                                                

// Unbind Vertex array object                                                            
gl.BindVertexArray(0)                                                                    

Solution

  • The stride of the texture coordinate pointer is wrong. It should be 4*4 instead of 3*4 since the start of two consecutive vertices is 4 floats away from each other.