I’m fairly new to Framebuffer/renderbuffers but basically I have deferred rendering working-ish. But my implementation uses the framebuffers in conjunction with a renderbuffer which I’ve had a hard time with.
I currently have it where I draw the meshes into the GBuffer, then send the textures through to do all my lighting which outputs to the offscreen buffer and finally gets blitted to the screen. However this isn’t optimal as positions can be represented as just the depth information? but I haven’t a clue with my current setup (or whether it’s possible?).
Here’s my buffer(s) creation:
void CoolFunc (int width, int height)
{
#pragma region GBuffer
glBindTexture (GL_TEXTURE_2D, m_gtextures[GBufferID::POSITIONS]);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, nullptr);
glBindTexture (GL_TEXTURE_2D, 0);
glBindTexture (GL_TEXTURE_2D, m_gtextures[GBufferID::NORMALS]);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, nullptr);
glBindTexture (GL_TEXTURE_2D, 0);
glBindRenderbuffer (GL_RENDERBUFFER, m_gBufferRBO);
glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
glBindRenderbuffer (GL_RENDERBUFFER, 0);
glBindFramebuffer (GL_FRAMEBUFFER, m_gBufferFBO);
glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_gBufferRBO);
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_gtextures[GBufferID::POSITIONS], 0);
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_gtextures[GBufferID::NORMALS], 0);
assert (glCheckFramebufferStatus (GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
const std::vector<GLenum> gbufferAttachments { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers (gbufferAttachments.size(), &gbufferAttachments[0]);
glBindFramebuffer (GL_FRAMEBUFFER, 0);
#pragma endregion
#pragma region LBuffer
glBindTexture (GL_TEXTURE_2D, m_ltextures);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, nullptr);
glBindTexture (GL_TEXTURE_2D, 0);
glBindFramebuffer (GL_FRAMEBUFFER, m_lBufferFBO);
glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_gBufferRBO);
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_ltextures, 0);
assert (glCheckFramebufferStatus (GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
const std::vector<GLenum> lbufferAttachments { GL_COLOR_ATTACHMENT0 };
glDrawBuffers (lbufferAttachments.size(), &lbufferAttachments[0]);
glBindFramebuffer (GL_FRAMEBUFFER, 0);
#pragma endregion
}
Pseudo-ish render loop:
void RenderCoolFunc (void)
{
// All data is sent to shaders (Mostly using UniformBufferObjects)
#pragma region Phase 1 - Geometry to GBuffer
glUseProgram (Program::GEOMETRY);
glBindFramebuffer (GL_FRAMEBUFFER, m_gBufferFBO);
// Clear all buffers
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Do some pipeline switch enabling i.e. depth and stencil test... etc.
glBindVertexArray (...);
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, ...);
// One beautiful draw call
glMultiDrawElementsIndirect (...);
// Safety Unbind
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
glBindVertexArray (0);
glBindFramebuffer (GL_FRAMEBUFFER, 0);
glUseProgram (0);
#pragma endregion
#pragma region Phase 2 - GBuffer to LBuffer
glBindFramebuffer(GL_FRAMEBUFFER, m_lBufferFBO);
#pragma region Pass 1 - Global light
glUseProgram (Program::GLIGHT);
// Do More pipeline switch enabling...
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, m_gtextures[GBufferID::POSITION]);
glUniform1i (glGetUniformLocation (Program::GLIGHT, "u_position"), 0);
glActiveTexture (GL_TEXTURE1);
glBindTexture (GL_TEXTURE_2D, m_gtextures[GBufferID::NORMALS]);
glUniform1i (glGetUniformLocation (Program::GLIGHT, "u_normal"), 1);
glBindVertexArray (...);
glDrawArrays (GL_TRIANGLE_FAN, 0, 4); // Fullscreen Quad
//// Safety Unbind
glBindVertexArray (0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glUseProgram (0);
#pragma endregion
#pragma endregion
#pragma region Final Phase - LBuffer to Screen
glBindFramebuffer (GL_READ_FRAMEBUFFER, m_lBufferFBO);
glBindFramebuffer (GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer (0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer (GL_FRAMEBUFFER, 0);
#pragma endregion
}
Any help is greatly appreciate it!
Also would there be anyway to optimize the normals or anything else for that matter?