Based on this tutorial,
I had allot of problems getting AMD based GPU’s to work.
I will post snippets of code bellow to detail the issue, but a simplistic explanation of the issue is that there is an issue with the depth test. I can see background objects tear infront of closer objects etc.
I contacted the original author regarding the issue, he does not seem to have access to AMD hardware so the question is open to be resolved, and I hope someone here have had similar issues.
The tutorial are covered in 3 stages, basic deferred shading to the final example using stencil buffer to draw a sphere (for point lights) to make GLSL only process the light volume.
Code can be downloaded from the tutorial, but to make it convenient I will post the important areas (and order of execution) here.
Edit:
There are a few additions in the code samples bellow, as compared to the original tutorial, but the same issues are confirmed on AMD gpu’s in its original state by multiple systems (6k/7k series).
Static types:
enum GBUFFER_TEXTURE_TYPE {
GBUFFER_TEXTURE_TYPE_POSITION,
GBUFFER_TEXTURE_TYPE_NORMAL,
GBUFFER_TEXTURE_TYPE_TANGENT,
GBUFFER_TEXTURE_TYPE_DIFFUSE_COLOR,
GBUFFER_TEXTURE_TYPE_NORMAL_COLOR,
GBUFFER_TEXTURE_TYPE_SPECULAR_COLOR,
GBUFFER_NUM_TEXTURES
m_shaderLight.setUniform("PositionTex", GBUFFER_TEXTURE_TYPE_POSITION);
m_shaderLight.setUniform("NormalTex", GBUFFER_TEXTURE_TYPE_NORMAL);
m_shaderLight.setUniform("TangentTex", GBUFFER_TEXTURE_TYPE_TANGENT);
m_shaderLight.setUniform("ColorDiffuseTex", GBUFFER_TEXTURE_TYPE_DIFFUSE_COLOR);
m_shaderLight.setUniform("ColorNormalTex", GBUFFER_TEXTURE_TYPE_NORMAL_COLOR);
m_shaderLight.setUniform("ColorSpecularTex", GBUFFER_TEXTURE_TYPE_SPECULAR_COLOR);
};
InitFBO
if (m_fbo != 0) {
glDeleteFramebuffers(1, &m_fbo);
}
if (m_depthTexture != 0) {
glDeleteTextures(1, &m_depthTexture);
}
if (m_finalTexture != 0) {
glDeleteTextures(1, &m_finalTexture);
}
for (size_t i = 0; i < ArraySize(m_textures); i++) {
if (m_textures[i] != 0) {
glDeleteTextures(1, &m_textures[i]);
}
}
// Create the FBO
glGenFramebuffers(1, &m_fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);
// Create the gbuffer textures
glGenTextures(ArraySize(m_textures), m_textures);
glGenTextures(1, &m_depthTexture);
glGenTextures(1, &m_finalTexture);
for (unsigned int i = 0 ; i < ArraySize(m_textures) ; i++) {
glBindTexture(GL_TEXTURE_2D, m_textures[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, m_windowWidth, m_windowHeight, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, m_textures[i], 0);
}
// depth
glBindTexture(GL_TEXTURE_2D, m_depthTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH32F_STENCIL8, m_windowWidth, m_windowHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_depthTexture, 0);
// final
glBindTexture(GL_TEXTURE_2D, m_finalTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_windowWidth, m_windowHeight, 0, GL_RGB, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT6, GL_TEXTURE_2D, m_finalTexture, 0);
GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (Status != GL_FRAMEBUFFER_COMPLETE) {
printf("FB error, status: 0x%x
", Status);
return false;
}
Pass Geometry:
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);
glDrawBuffer(GL_COLOR_ATTACHMENT6);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, m_windowWidth, m_windowHeight);
static GLenum DrawBuffers[] = { GL_COLOR_ATTACHMENT0,
GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2,
GL_COLOR_ATTACHMENT3,
GL_COLOR_ATTACHMENT4,
GL_COLOR_ATTACHMENT5};
glDrawBuffers(ArraySize(DrawBuffers), DrawBuffers);
// Only the geometry pass updates the depth buffer
glDepthMask(GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
draw geometry here...
glDepthMask(GL_FALSE);
Pass Light: (Will only demonstrate directional light, stencil done in point light)
glDrawBuffer(GL_COLOR_ATTACHMENT6);
for (unsigned int i = 0 ; i < ArraySize(m_textures); i++) {
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, m_textures[GBUFFER_TEXTURE_TYPE_POSITION + i]);
}
glUniformSubroutinesuiv( GL_FRAGMENT_SHADER, 1, &GLSLSubFSLightDirectional);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
m_shaderLight.setUniform(UniformLightMVP, mat4(1));
// Render the quad
glBindVertexArray(m_quad);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisable(GL_BLEND);
Then finally…
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_effectFBO);
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo);
glReadBuffer(GL_COLOR_ATTACHMENT6);
glBlitFramebuffer(0, 0, m_windowWidth, m_windowHeight,
0, 0, m_windowWidth, m_windowHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
Results:
Nvidia good
[ATTACH=CONFIG]522[/ATTACH]
AMD
Models disappears or blend into each other depending on camera angle
[ATTACH=CONFIG]521[/ATTACH]
Any feedback is greatly appreciated, if we find an answer I will credit whomever and let the author update the article so everyone can benefit from it.
Thanks.