I am trying to develop a particle system in C++ using OpenGL, and I am confused about how blending works. I am trying to use additive blending, and from my understanding, calling the glBlendFunc function with the following arguments:

glBlendFunc(GL_SRC_ALPHA, GL_ONE);

Will cause the following when you try to render something: It will take the R,G,B color calculated by the fragment shader (source color), multiply that by the alpha value calculated by the fragment shader (source alpha), and then add that to the R,G,B color that already exists in the frame buffer (dest color). But if this is true, then a black color, where (R,G,B,A) = (0,0,0,1), calculated by the fragment shader should leave the existing frame buffer color (dest color) unchanged since it is multiplying the source color value of 0 by the source alpha value of 1, which should obviously always yield 0, and then that 0 is added to the existing frame buffer color (dest color) which should leave it unchanged...right?

However, when I do this, instead of leaving the color unchanged, it actually makes it lighter, as shown here:

In this picture, the environment and sword are rendered with normal blending, and then the square particles are rendered around the sword with glBlendFunc(GL_SRC_ALPHA, GL_ONE); using a fragment shader that ALWAYS outputs (R,G,B,A) = (0,0,0,1). There are many particles rendered, and you can see that as more particles overlap, it gets brighter. When I switch the alpha output of the shader from 1 to 0 (source alpha), then the particles disappear, which makes sense. But why are they still visible when source color=1 and source alpha=0?

Here is the exact function I call to render the particles:

void ParticleController::Render()
{
    GraphicsController* gc = m_game->GetGraphicsController();
    ShaderController* sc = gc->GetShaderController();
    gc->BindAttributeBuffer(m_glBuffer);
    ShaderProgram* activeShaderProgram = sc->UseProgram(SHADER_PARTICLE);
    glDepthMask(false);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);

    gc->GetTextureController()->BindGLTexture(TEX_PARTICLES);

    activeShaderProgram->SetUniform(SU_PROJ_VIEW_MAT, gc->GetProjectionMatrix() * gc->GetViewMatrix() * gc->GetWorldScaleMatrix());

    activeShaderProgram->SetUniform(SU_LIGHT_AMBIENT, m_game->GetWorld()->GetAmbientLight());

    activeShaderProgram->SetUniform(SU_TIME, m_game->GetWorld()->GetWorldTime());

    CheckForOpenGLError();
    m_pa.GLDraw();
    CheckForOpenGLError();

    gc->BindAttributeBuffer_Default();
    CheckForOpenGLError();

    glDepthMask(true);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

And these are the last 4 lines of my fragment shader, ensuring that the particle color output (R,G,B,A) is always = (0,0,0,1):

fColor.r = 0.0;
fColor.g = 0.0;
fColor.b = 0.0;
fColor.a = 1.0;

Is there something I am missing?

0

There are 0 best solutions below