I've just finished implementing deferred shading into my engine, and noticed that when a large object overlaps another smaller object, it blends through it.
For example, in this scene I have a large plane floor, and on top of it rests 3 rectangle walls. When looking at these walls anywhere from above the floor, one can see that the floor blends through the walls.
Alternatively, here's a small video clip showing what I mean
I've been following a tutorial series on OGLDev, and have followed the guide very closely, with the sole exemption being that I use a component based system.
The general format of my rendering loop is as follows:
- Prepare the GBuffer
- Render Pass (render to FBO, output properties as textures)
- Stencil Pass (render light object for stencil operations)
- Light Pass (sample from previous textures for lighting calculations)
- Final Pass (draw back to default FBO)
Specifically, during my rendering pass the lights are rendered using geometrical objects, such as a bounding sphere for point lights (the only light currently implemented).
I believe that the issue is with the function
glBlendFunc(GL_ONE, GL_ONE);
I may have multiple lights in a scene, so I need to be able to blend them all together, however when I do that I seem to also get surfaces blending together. If I disable the blend function, the problem disappears but then only the last light processed will render.
The blend function occurs in the following function:
Lighting Pass:
void DLightPointComponent::LightPass(DCamera *cam, GBuffer *gbuffer)
{
// Obtain required objects for lighting pass
PointLight point = getPointLight();
BaseLight base = point.getBaseLight();
Attenuation atten = point.getAtten();
DModelComponent *BSphere = getSphere();
DSuperShader *shader = getSuperShaderProgram();
QMatrix4x4 mat = getModelMatrix(), mat2 = BSphere->getModelMatrix();
DMeshComponent *mesh = BSphere->getMeshComponent();
// Scale up bounding sphere
float BSphereScale = CalcPointLightBSphere(point)*5000000000;
mat2.scale(BSphereScale);
// Prepare textures for sampling
gbuffer->BindForLightPass();
// Upload uniforms to shader
shader->bind();
shader->bindCamera(*cam);
shader->pushMatrix(mat);
shader->pushMatrix(mat2);
mesh->setShaderProgram(shader);
mesh->bindToShader();
... (upload the many light uniforms to shader) ...
// Specific OpenGL operations
glStencilFunc(GL_NOTEQUAL, 0, 0xFF);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
// Render the bounding sphere
mesh->pollWholeMesh();
//Clean up shader
glCullFace(GL_BACK);
glDisable(GL_BLEND);
shader->popMatrix();
shader->release();
}
My rendering pass in question:
void oglWidget::RenderPass(QList<DComponent*> *components, DCamera *cam, GBuffer *gbuf)
{
// Obtain the gbuffer shader, and bind all prerequisites to the shader
DSuperShader *shader = gbuffer->getSuperShaderProgram();
gbuf->BindForGeomPass();
shader->bind();
shader->bindCamera(*cam);
// Specific OpenGL functions
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
// Render geometry into GBuffer
for (int x = 0, total = components->size(); x < total; ++x)
components->at(x)->pollLocal(shader);
// Shader Cleanup
shader->release();
shader->popMatrix();
shader->purgeCamera();
glDepthMask(GL_FALSE);
}
If any further information is wanted, I'll post it.
glBlendFunc(GL_ONE, GL_ONE);
only configures how the blending is performed. To turn the blending completely off you need to callglDisable(GL_BLEND);
which you actually do at the end of your lighting pass. Can you be sure that the blending is disabled while you create the G-Buffer? It is also often very useful to display the different G-Buffer surfaces. This way you can make sure if it is there where things go awry. \$\endgroup\$