J.Doe
J.Doe

Reputation: 1552

OpenGL ES transparency not working, instead things just blend with the background

So I have a simple simulation set up on my phone. The goal is to have circles of red, white, and blue that appear on the screen with various transparencies. I have most of that working, except for one thing, while transparency sort of works, the only blending happens with the black background. As a result the circle in the center appears dark red instead of showing the white circles under it. What am I doing wrong?

Note I am working in an orthographic 2d projection matrix. All of the objects z positions are the same, and are rendered in a specific order.

UH OH

Here is how I set it so transparency works:

glEnable(GLenum(GL_DEPTH_TEST))
glEnable(GLenum(GL_POINT_SIZE));
glEnable(GLenum(GL_BLEND))
glBlendFunc(GLenum(GL_SRC_ALPHA), GLenum(GL_ONE_MINUS_SRC_ALPHA))
glEnable(GLenum(GL_POINT_SMOOTH))
//Note some of these things aren't compatible with OpenGL-es but they can hurt right?

Here is the fragment shader:

precision mediump float;
varying vec4 outColor;
varying vec3 center;
varying float o_width;
varying float o_height;
varying float o_pointSize;
void main()
{
    vec4 fc = gl_FragCoord;
    vec3 fp = vec3(fc);


    vec2 circCoord = 2.0 * gl_PointCoord - 1.0;


    if (dot(circCoord, circCoord) > 1.0) {
        discard;
    }

    gl_FragColor = outColor;//colorOut;
}

Here is how I pass each circle to the shader:

func drawParticle(part: Particle,color_loc: GLint, size_loc: GLint)
    {
        //print("Drawing: " , part)
        let p = part.position
        let c = part.color

        glUniform4f(color_loc, GLfloat(c.h), GLfloat(c.s), GLfloat(c.v), GLfloat(c.a))
        glUniform1f(size_loc, GLfloat(part.size))

        glVertexAttribPointer(0, GLint(3), GLenum(GL_FLOAT), GLboolean(GL_FALSE), 0, [p.x, p.y, p.z]);
        glEnableVertexAttribArray(0);
        glDrawArrays(GLenum(GL_POINTS), 0, GLint(1));
}

Upvotes: 0

Views: 752

Answers (1)

datenwolf
datenwolf

Reputation: 162164

Here is how I set it so transparency works:

glEnable(GLenum(GL_DEPTH_TEST))
glEnable(GLenum(GL_POINT_SIZE));
glEnable(GLenum(GL_BLEND))
glBlendFunc(GLenum(GL_SRC_ALPHA), GLenum(GL_ONE_MINUS_SRC_ALPHA))
glEnable(GLenum(GL_POINT_SMOOTH))

And that's not how transparency works. OpenGL is not a scene graph, it just draws geometry in the order you specify it to. If the first thing you draw are the red circles, they will blend with the background. Once things get drawn that are "behind" the red circles, the "occulded" parts will simply be discarded due to the depth test. There is no way for OpenGL (or any other depth test based algorithm) to automatically sort the different depth layers and blend them appropriately.

What you're trying to do there is order independent transparency, a problem still in research on how to solve it efficiently.

For what you want to achieve you'll have to:

  • sort your geometry far to near and draw in that order
  • disable the depth test while rendering

Upvotes: 5

Related Questions