简体   繁体   中英

How to properly draw a texture with opacity in Android OpenGL?

I'm trying to draw 5 different textures on the screen, but I can't seem to make the alpha work. Textures are rendered fine if there is no alpha, but when there is, there's a really weird "effect".

Ok, first off I call draw to all 5 of my textures with opacity (in the given order): 0.5 , 1.0 , 0.5 , 1.0 , 0.5 . But when I start the app I actually get 1.0 , 0.5 , 1.0 , 0.5 , 1.0 like there's an offset of 1. That's not all that's weird. About a half of second after my app launches the very first texture gets opacity of 0.5 , even weirder is that this is not happening on the second draw method, but somewhere between the first and second call to draw . How is this even possible?

This is the final result (it should be 0.5 , 1.0 , 0.5 , 1.0 , 0.5 , but as you can see it's not even close):

在此处输入图片说明

Now for some code (I've skipped some unrelevant parts).

Creating the surface:

public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
    // Textures are being loaded in here, which is just fine (code skipped)
    gl.glEnable(GL10.GL_TEXTURE_2D);
    gl.glShadeModel(GL10.GL_SMOOTH);
    gl.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
    gl.glClearDepthf(1.0f);
    gl.glEnable(GL10.GL_DEPTH_TEST);
    gl.glDepthFunc(GL10.GL_LEQUAL);
    gl.glEnable(GL10.GL_BLEND);
    gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
}

Updating the surface:

public void onSurfaceChanged(GL10 gl, int width, int height)
{
    // Here I pass width & height to my texture objects for future reference (code skipped)
    gl.glViewport(0, 0, width, height);
    gl.glOrthof(0, width, height, 0, 0, 1);
    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glLoadIdentity();
}

Drawing:

public void onDrawFrame(GL10 gl)
{
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    gl.glLoadIdentity();
    // Here I call draw of each texture object
}

Draw method of the texture object:

public void draw(GL10 gl)
{
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glFrontFace(GL10.GL_CW);
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE);
    gl.glColor4f(1.0f, 1.0f, 1.0f, this.alpha); // This is where the magic doesn't happen (: 
}

I've skipped the part where I create vertex/texture buffers and load the textures, that part follows this tutorial and seems to work just fine.

So.. what do you think am I missing? What could be the cause to this weird issue?

If I must guess, I'd say it's some weird hardcore OpenGL issue/bug or more like a flag I forgot to raise or something like that. It can't be the order of drawing or anything like that, I've double checked it all. I've also tried setting say 0.5f as opacity to each texture and it works perfectly, the problem only happens whenever the opacity of the textures differ from each other. I also don't think, that the weird between-draw flicker can be caused by user code, it's gotta be some OpenGL weirdness.

I must point out that I am using a 3rd party library to pack all of this GL magic into a live wallpaper, it's this awesome lib: GLWallpaperService

Why is the place where the magic happens not before the draw call? The default colour value is (1,1,1,1) so at first your start with alpha at 1.0, then you draw the texture and set the alpha to .5 and draw the 2nd texture with this value still set... Ergo the strange offset effect.

When the last texture is drawn you have an alpha of 1.0 (from the one before) and then set it to .5 which is used to draw the first texture in the next refresh: Since the alpha changes from 1.0 to .5 on the top most element it flickers. In the end you clearly get the result seen on the image you posted.

So this truly is where the magic happens:

gl.glColor4f(1.0f, 1.0f, 1.0f, this.alpha); // This is where the magic doesn't happen

So try removing that line and try it like this:

gl.glColor4f(1.0f, 1.0f, 1.0f, this.alpha); // This is where the magic does happen
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // Low mana, stop the magic

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM