OpenGL Alpha Blending Issue, Blending ignored (maybe)?

flagoworld picture flagoworld · Jun 21, 2013 · Viewed 9.1k times · Source

EDIT + BETTER SOLUTION:

In case anyone happens to run into the problem I was running into, there are two solutions. One is the solution accepted, but that only applies if you are doing things how I was. Let me explain what I was doing:

1.) Render star background to screen

2.) Render ships, then particles to the FBO

3.) Render FBO to screen

This problem, and therefor the solution to this problem, occurred in the first place because I was blending the FBO with the star background.

The real solution, which is supposedly also slightly faster, is to simply render the star background to the FBO, then render the FBO to screen with blending disabled. Using this method, I do not need to mess with glBlendFuncSeparate...

1.) Render stars, then ships, then particles to FBO

2.) Render FBO to screen with blending disabled

----------ORIGINAL QUESTION:----------

From what I understand of the issue, blending is being ignored somehow. The particle texture with alpha transparency completely overwrites below pixels.

I am creating a top-down game. The camera is slightly angled so that there is some feeling of depth. I am rendering my ships, then rending the particles above them...

After beginning the OpenGL context

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glCullFace(GL_BACK);

In the render loop, I do this:

glBindFramebuffer(GL_FRAMEBUFFER,ook->fbo);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);

entitymgr_render(ook); //Render entities. Always 1.0 alpha textures.

glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);

//glBlendFunc(GL_SRC_ALPHA,GL_ONE); //This would enable additive blending for non-premult
particlemgr_render(ook); //Render particles. Likely always <1.0 alpha textures
//glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

glBindFramebuffer(GL_FRAMEBUFFER,0);

If I run with the above code, I get results like this...

Particle tex:

Particle tex

Screenshot from OGL Profiler (Mac tool):

Screenshot from OGL Profiler

Screenshot of the FBO without any particle rendered:

Screenshot of the FBO without any particle rendered

Screenshot of the FBO with some particles rendered on top:

Screenshot of the FBO with some particles rendered on top

As you can see, the particle, despite having alpha transparency, doesn't blend with the ship rendered below. Instead, it just completely overwrites the pixels.

Final notes, setting pixel transparency in the shader blends correctly - the ship appears below. And here is my shader:

#version 150
uniform sampler2D s_tex1;
uniform float v4_color;
in vec4 vertex;
in vec3 normal;
in vec2 texcoord;

out vec4 frag_color;

void main()
{
    frag_color=texture(s_tex1,texcoord)*v4_color;
    if(frag_color.a==0.0) discard;
}

Let me know if there is anything I can provide.

Answer

user1961169 picture user1961169 · Jun 21, 2013

Looks to me like it is rendering the alpha channel as well into the frame buffer, so when you write the particles, the src alpha channel is getting mixed with the destination alpha channel, which is not what you want here.

This is exactly why the glblendfuncseparate() function was created. Try this...

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);

So, the alpha channel of your particles will be used to determine the colours of the final pixels, but the alpha channels of the source and destination will be added together.