OpenGL Alpha Blending Issue, Blending ignored (maybe)?
Asked Answered
C

3

6

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.

Capitalism answered 20/6, 2013 at 22:24 Comment(0)
L
8

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.

Longhorn answered 21/6, 2013 at 13:9 Comment(0)
D
5

My guess is that the FBO's rgb channels are being rendered correctly, but because it also has an alpha channel, and it is being drawn with blending enabled, the end result has incorrect transparency where the particle overlaps the spaceship.

Either use glBlendFuncSeparate (described here) to use different blend factors for the alpha channel when you're drawing the particles:

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);

Or turn off blending altogether when you draw your FBO onto the screen.

Diablerie answered 21/6, 2013 at 8:32 Comment(1)
I accepted the other answer, which was posted after this one, because he/she better described the problem and what glBlendFuncSeparate what doing here. This is still the correct answer.Capitalism
B
0

In order to obtain texture transparency, other than:

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

you should assure also that:

  1. when creating the particle tex with glTexImage2D, use as format GL_RGBA (or GL_LUMINANCE_ALPHA if you are using gray shaded textures)

  2. when drawing the particle texture, after the glBindTexture command, call

    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);

Instead of GL_BLEND, you could use the correct texture functions as described in the glTexEnv reference: http://www.opengl.org/sdk/docs/man2/xhtml/glTexEnv.xml

Bouncy answered 21/6, 2013 at 12:8 Comment(2)
Incorrect. I specifically tagged opengl-3 to my question. This function is for versions less than 3.Capitalism
LOL I'm massively working with OpenGL SC, so I do know well this version. My fault did not notice the opengl-3 tag.Bouncy

© 2022 - 2024 — McMap. All rights reserved.