Android opengl transparency issues
I'm rendering 3 different polygons with the same smiley texture. The texture is a yellow circle put on a transparent background.
My issue is that if i put a smiley that is drawn earlier in front of another that is drawn later it will make the one drawn later transparent where the early ones background is transparent.
Well a picture is worth a thousand words! See Image of the problem and the smiley png here.
The issue doesn't occur if i put the lastly drawn smiley in front of the other, so the issue seems to be related to the drawing order. Anyone have any input?
public void onSurfaceCreated(GL10 gl, EGLConfig eglConfig) {
//Textures a loaded here See next section for the implementation o开发者_如何学JAVAf loadTextures method on the polygon class.
loadTextures(gl, context);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glClearColor(.5f, .5f, .5f, 1);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
}
public void onSurfaceChanged(GL10 gl, int w, int h) {
if(h == 0) {
h = 1;
}
gl.glViewport(0, 0, w, h);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
float ratio = (float) w / h;
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 30);
GLU.gluLookAt(gl, lookEyeX, lookEyeY, lookEyeZ, lookCenterX, lookCenterY, lookCenterZ, lookUpX, lookUpY, lookUpZ);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
draw(gl);
}
Implementation of the loadTexture method
public void loadTextures(GL10 gl, Context context) {
if(bitmap == 0) {
return;
}
//Get the texture from the Android resource directory
InputStream is = context.getResources().openRawResource(bitmap);
Bitmap bitmap = null;
try {
//BitmapFactory is an Android graphics utility for images
bitmap = BitmapFactory.decodeStream(is);
} finally {
//Always clear and close
try {
is.close();
is = null;
} catch (IOException e) {
}
}
//Generate one texture pointer...
gl.glGenTextures(1, textureIDs, 0);
//...and bind it to our array
gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[0]);
//Create Nearest Filtered Texture
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
//Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
//Use the Android GLUtils to specify a two-dimensional texture image from our bitmap
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
//Clean up
bitmap.recycle();
}
Even transparent fragments are written to the depth buffer. Your options are:
- Disable the depth buffer - either don't write to it or disable the depth test.
Enable the alpha test so that transparent fragments are rejected. e.g.:
GLES10.glEnable( GLES10.GL_ALPHA_TEST );
GLES10.glAlphaFunc( GLES10.GL_GREATER, 0 );
Sort your geometry and draw the quads in back-to-front order
Turn off depth-testing. The missing pixels of the rearmost smiley are missing because the foremost smiley has filled the depth buffer.
Obviously you will need to draw your smileys in the correct order, rearmost first.
I guess what you'd ideally want is for your depth buffer to accumulate alpha values rather than Z values... don't know how possible that is. :-(
精彩评论