1
\$\begingroup\$

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.

enter image description here 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:

  1. Prepare the GBuffer
  2. Render Pass (render to FBO, output properties as textures)
  3. Stencil Pass (render light object for stencil operations)
  4. Light Pass (sample from previous textures for lighting calculations)
  5. 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.

\$\endgroup\$
2
  • \$\begingroup\$ It looks like blending is still active while you are creating the G-Buffer. glBlendFunc(GL_ONE, GL_ONE); only configures how the blending is performed. To turn the blending completely off you need to call glDisable(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\$
    – Wumpf
    Sep 8, 2015 at 19:48
  • \$\begingroup\$ I do disable it before writing into the GBuffer. I'll update my opening post with my render pass. Also, I can view the surfaces stored in the gbuffer. The same blending pattern appears to the standard diffuse scene after the lighting pass has occured, even though I'm just showing the GBuffer's content - not the post-processed scene. Bizarre \$\endgroup\$
    – Yattabyte
    Sep 8, 2015 at 19:51

1 Answer 1

1
\$\begingroup\$

I don't know why this is happening, but somehow despite the fact that I clearly disable blending at the end of my lighting function, and don't use it anywhere else in my rendering loop, this effect seems to happen.

However, if add the following line after disabling blending:

glBlendFunc(GL_ONE, GL_ZERO);

..then the problem disappears, for now. This is the default blending function.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .