laxcat
laxcat

Reputation: 73

Why does alpha blending gradient textures yield unexpected results in OpenGL ES 2.0?

I have a radial gradient texture (RGBA) that goes from a black fully opaque color in the center to fully transparent one at the edges:

ball.png

I've set up an iOS project using the recent OpenGL template, which uses GLKit. I added texture capability and have the following code set in the setupGL method:

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

When I overlap two of these textures (each has a separate z) in an ortho projection on a white background, I expect something like this:

right.png

But instead I get this:

wrong.png

My question is simply: why? Can OpenGL ES 2.0's blending not achieve this effect? (I've gotten it to work before in OpenGL ES 1.1) Is there a common thing I'm missing? Is it maybe a premultiplied alpha problem with my texture? If so could it be something strange with my PNG or the way I'm loading it? I'm loading textures using GLKTextureLoader.

It's very possible I'm wrong, but I understand that it couldn't be a shader problem as alpha blending happens before it gets to the fragment shader. My shaders do little more than pass the information directly through. (Maybe that's a problem?)

Vertex Shader:

attribute vec4 position;
attribute vec2 texCoordIn;

varying vec2 texCoordOut;

uniform mat4 modelViewProjectionMatrix;

void main()
{
    gl_Position = modelViewProjectionMatrix * position;
    texCoordOut = texCoordIn;
}

Fragment Shader:

varying lowp vec2 texCoordOut;
uniform sampler2D texture;

void main()
{
    gl_FragColor = texture2D(texture, texCoordOut);
}

I've also tried setting the glBendFunc as follows, but I get the same results:

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

Any tips or common hangups are welcome. Thanks!

Upvotes: 4

Views: 2018

Answers (2)

laxcat
laxcat

Reputation: 73

Well, I'm an idiot. What's actually happening is a simple problem with my vertices. I was using a single glDrawArrays call to draw all the textures at once, but I forgot to add extra vertices between the rectangles to create the degenerate triangles. So basically a third ball was being drawn squashed in the center. But it LOOKED like an alpha blending problem!

Big dummy, right here.

Upvotes: 1

Tommy
Tommy

Reputation: 100652

If glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) and glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) produce identical results then it follows that your texture has a uniform alpha of 1.0. Hence you're getting what amounts to additive blending, giving the result you show. If anything it appears you're premultiplying by alpha and then throwing the alpha channel away.

So the obvious things to check are (i) the file on disk; and (ii) your texture loading code. If you're not asking for GLKTextureLoaderApplyPremultiplication (and that shouldn't affect your alpha channel anyway; presumably you're loading directly from disk?) then suspicions would fall on (i), though the image you've directly included above appears to act correctly.

Blending occurs after your fragment shader. In order to debug the problem further you might experiment with throwing away the rest of the information and, say, passing along the value from the alpha channel as the red channel with alpha = 1.0.

Upvotes: 2

Related Questions