2 Stimmen

Android OpenGL Transparenzprobleme

Ich rendere 3 verschiedene Polygone mit der gleichen Smile-Textur. Die Textur ist ein gelber Kreis auf einem transparenten Hintergrund.

Mein Problem ist, dass wenn ich ein Smiley, das früher gezeichnet wurde, vor einem anderen platziere, der später gezeichnet wurde, wird der spätere transparent, wo der Hintergrund des früheren transparent ist.

Nun, ein Bild sagt mehr als tausend Worte! Siehe das Bild des Problems und das Smile-PNG hier.

Das Problem tritt nicht auf, wenn ich den zuletzt gezeichneten Smiley vor den anderen setze. Das Problem scheint also mit der Reihenfolge des Zeichnens zusammenzuhängen. Hat jemand irgendwelche Hinweise?

public void onSurfaceCreated(GL10 gl, EGLConfig eglConfig) {
    // Texte werden hier geladen. Siehe nächsten Abschnitt für die Implementierung der Methode loadTextures in der Polygon-Klasse.
    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);
}

Implementierung der Methode loadTexture

public void loadTextures(GL10 gl, Context context) {
    if(bitmap == 0) {
        return;
    }
    // Hole die Textur aus dem Android-Ressourcenverzeichnis
    InputStream is = context.getResources().openRawResource(bitmap);
    Bitmap bitmap = null;
    try {
        // BitmapFactory ist ein Android-Grafikdienstprogramm für Bilder
        bitmap = BitmapFactory.decodeStream(is);

    } finally {
        // Immer aufräumen und schließen
        try {
            is.close();
            is = null;
        } catch (IOException e) {
        }
    }

    // Erzeuge einen Texturzeiger...
    gl.glGenTextures(1, textureIDs, 0);
    //... und binde sie an unser Array
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[0]);

    // Erstelle eine am nächsten liegende gefilterte Textur
    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);

    // Verschiedene mögliche Texturparameter, z. B. 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);

    // Verwende die Android GLUtils, um ein zweidimensionales Texturebild aus unserem Bitmap zu spezifizieren
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

    // Aufräumen
    bitmap.recycle();
}

2voto

ryanm Punkte 2879

Auch transparente Fragmente werden in den Tiefenpuffer geschrieben. Ihre Optionen sind:

  1. Deaktivieren Sie den Tiefenpuffer - entweder schreiben Sie nicht hinein oder deaktivieren den Tiefentest.

  2. Aktivieren Sie den Alpha-Test, damit transparente Fragmente abgelehnt werden. z. B.:

    GLES10.glEnable( GLES10.GL_ALPHA_TEST );

    GLES10.glAlphaFunc( GLES10.GL_GREATER, 0 );

  3. Sortieren Sie Ihre Geometrie und zeichnen Sie die Quadrate in der Reihenfolge von hinten nach vorne

1voto

Reuben Scratton Punkte 38292

Schalten Sie die Tiefentestung aus. Die fehlenden Pixel des hintersten Smiley fehlen, weil der vorderste Smiley den Tiefenpuffer gefüllt hat.

Natürlich müssen Sie Ihre Smileys in der richtigen Reihenfolge zeichnen, zuerst den hintersten.

Ich nehme an, dass Sie idealerweise möchten, dass Ihr Tiefenpuffer Alpha-Werte anstelle von Z-Werten akkumuliert... weiß nicht, wie möglich das ist. :-(

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X