In my project I'm trying to implement a deferred rendering system, problem is, I can't seem to get a second FBO to work.
UPDATE 1
Here is the FBO initialization code:
/// G-Buffer FBO
GLuint gBufferFBO;
glGenFramebuffers(1, &gBufferFBO);
glBindFramebuffer(GL_FRAMEBUFFER, gBufferFBO);
GLuint depthStencilTex;
glGenTextures(1, &depthStencilTex);
glBindTexture(GL_TEXTURE_2D, depthStencilTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 1024, 768, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthStencilTex, 0);
GLuint colorTex;
glGenTextures(1, &colorTex);
glBindTexture(GL_TEXTURE_2D, colorTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1024, 768, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
GLuint lightAccTex;
glGenTextures(1, &lightAccTex);
glBindTexture(GL_TEXTURE_2D, lightAccTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1024, 768, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, lightAccTex, 0);
GLuint viewNormTex;
glGenTextures(1, &viewNormTex);
glBindTexture(GL_TEXTURE_2D, viewNormTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1024, 768, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, viewNormTex, 0);
GLenum DrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, DrawBuffers);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
if((g_RenderManager->CheckFBO()))
return 1337; // Returns if there is an error
/// End G-Buffer FBO
/// Light Pass FBO
GLuint lightPassFBO;
glGenFramebuffers(1, &lightPassFBO);
glBindFramebuffer(GL_FRAMEBUFFER, lightPassFBO);
GLuint LPdepthStencilTex;
glGenTextures(1, &LPdepthStencilTex);
glBindTexture(GL_TEXTURE_2D, LPdepthStencilTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 1024, 768, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, LPdepthStencilTex, 0);
GLuint LPcolorTex;
glGenTextures(1, &LPcolorTex);
glBindTexture(GL_TEXTURE_2D, LPcolorTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1024, 768, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, LPcolorTex, 0);
GLenum LPDrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, LPDrawBuffers);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
if((g_RenderManager->CheckFBO()))
return 1337; // Returns if there is an error
/// End Color Pass FBO
Here is my code that draws to the FBOs:
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gBufferFBO);
glViewport(0, 0, 1024, 768);
glDrawBuffers(2, DrawBuffers); // GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
// Here I draw my geometry to the G-Buffer.
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, lightPassFBO);
glViewport(0, 0, 1024, 768);
glDrawBuffers(1, LPDrawBuffers); // GL_COLOR_ATTACHMENT0
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
// Here I draw light volumes.
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glViewport(0, 0, 1024, 768);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
glBindFramebuffer(GL_READ_FRAMEBUFFER, lightPassFBO);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBlitFramebuffer(0, 0, 1024, 768, 0, 0, 1024, 768, GL_COLOR_BUFFER_BIT, GL_NEAREST);
Rendering to the gBufferFBO
works fine, but when I try to render out different geometry with a different shader in lightPassFBO
, nothing is rendered. Using either glBlitFreambuffer
or just rendering to a quad, it still will not render.
And I clear each buffer before use, so that can't be the problem.
When looking in gDEbugger, it draws to my first buffer, but not my second.
Here is gDEbugger showing the first batch of geometry being successfully drawn into the first buffer:
And here is gDEbugger showing that a different batch of geometry is not being drawn into the second buffer!:
If it's worth anything, this is my shader code:
G-Buffer vertex shader
#version 330 core
smooth out vec2 vVaryingTexCoords;
smooth out vec3 vVaryingNormals;
uniform mat4 MV;
uniform mat4 MVP;
layout(location = 0) in vec3 vPos;
layout(location = 1) in vec2 vTexCoords;
layout(location = 2) in vec3 vNormals;
void main()
{
vVaryingTexCoords = vTexCoords;
vVaryingNormals = normalize(vec3(vec4(vNormals, 0.0) * MV));
gl_Position = vec4(vPos, 1.0) * MVP ;
}
And my fragment shader (passes out color, spec power and normals)
#version 330 core
in vec3 vVaryingNormals;
in vec2 vVaryingTexCoords;
uniform sampler2D vTexTest;
uniform float Shininess;
uniform vec3 vColoration;
void main()
{
vec3 normals = normalize(vVaryingNormals);
gl_FragData[0].rgb = vColoration;
gl_FragData[0].rgb *= texture(vTexTest, vVaryingTexCoords).xyz;
gl_FragData[0].a = Shininess;
gl_FragData[1].r = normals.x;
gl_FragData[1].g = normals.y;
gl_FragData[1].b = normals.z;
}
And my shader which should draw light volumes to my second buffer:
#version 330 core
uniform mat4 MVP;
layout(location = 0) in vec3 vPos;
layout(location = 1) in vec2 vTexCoords;
layout(location = 2) in vec3 vNormals;
void main()
{
vec2 vVaryingTexCoords = vTexCoords;
vec3 vVaryingNormals = vNormals;
gl_Position = vec4(vPos, 1.0) * MVP;
}
fragment shader:
#version 330 core
void main()
{
gl_FragData[0] = vec4(1.0,1.0,1.0,1.0);
}
UPDATE 2
My uniforms are created at load time. I have a class that looks for uniforms in a shader, and stores them to a map: the key is the uniform name, and the second value contains a GLuint
handle. I use glGetUniformLocation()
after creating a shader program, attaching shaders and linking it. I also do it after loading textures, so samplers will have a valid values.
Here is an example of loading my shader:
this->m_ShaderList[shaderName] = new CShaderProg(shaderName, true); // This just calls to glCreateProgram() and returns the handle
this->m_ShaderList[shaderName]->AttachShader(ShaderManager::CShader(*this->m_ptrMan->GetShaderSource(sVert), true));
this->m_ShaderList[shaderName]->AttachShader(ShaderManager::CShader(*this->m_ptrMan->GetShaderSource(sFrag), true));
this->m_ShaderList[shaderName]->LinkProgram();
...
// Then I check through each shader attached, adding uniform locations, if they don't exist
// If not found, add to list
if(it == this->m_UniformList.end()) {
GLint tmpint = 1; // this is just a dummy value. Initialising to -1 or 0 makes glGetUniformLocation() return -1
this->m_UniformList[VSdata[i+2]] = glGetUniformLocation(tmpint, VSdata[i+2].c_str());
}
I changed the code in the shaders to use layout(location = n)
as I don't do any attribute binding (I never have). I use VAO/VBO for my geometry and pass in the values to my shaders using glEnableVertexAttribArray()
and glDrawElements()
.
Something to note, using the G-Buffer shader on my second FBO results in geometry being rendered.
Sorry for such a lengthy post, but I've been having this problem for a few weeks now, and I just want to get to the bottom of why FBOs work for everyone else but me. The only other time I have found someone with this problem is here, but it was never answered.
Answer
Turns out my problem was with the uniform locations.
I wasn't querying the uniform location when using a different shader and I was only querying an abritray value (value of GLuint(1)
), not an actual program, which is why my first shader created (which I used on my first FBO) worked and my second shader created(which I use on my second FBO) didn't work.
Now I know that uniforms are only valid across one shader, not multiple ones.
Thanks @Andon M. Coleman!
No comments:
Post a Comment