2015-06-16 31 views
12

Ich versuche, transparente Texturen (Text) in meiner App zu zeichnen. Seltsamerweise funktioniert es auf dem neuesten Nexus 7 und auf meiner zweiten Generation Moto X, aber auf dem ursprünglichen Nexus 7 sind die Texturen nur schwarz. Ich habe Blending aktiviert und die Textur ist 512x512, also ist es kein Zweierpotenzproblem. Ich benutze auch nur GL10, die auf allem unterstützt werden sollte, oder? Irgendwelche Gründe würden die Texturen nicht nur auf diesem Gerät funktionieren?Android OpenGL Transparente Textur zeichnet Schwarz

gl.glEnable(GL10.GL_BLEND); 
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); 
gl.glEnable(GL10.GL_TEXTURE_2D); 
// text drawn here 
gl.glDisable(GL10.GL_TEXTURE_2D); 
gl.glDisable(GL10.GL_BLEND); 

Und hier ist die Textur der Initialisierung, wo ich die Texturatlas laden:

public void loadGlyphs(GL10 gl, Context context) { 
    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.text_bitmap); 
    gl.glGenTextures(1, textures, 0); 
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); 

    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); 

    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); 

    bitmap.recycle(); 
} 

Top zeigt, was auf dem alten Nexus geschieht 7. Das untere Bild ist ein Moto X.

Bad

Good

Edit: Hier ist ein komplettes Beispiel. Keine Transparenz, zeichnet nichts auf dem alten Nexus 7. Wenn ich das Textur-Zeug los werde, zeichnet es das Quadrat in Weiß, so wie es sein sollte.

MainActivity.java

import android.app.Activity; 
import android.opengl.GLSurfaceView; 
import android.os.Bundle; 


public class MainActivity extends Activity { 

    private GLSurfaceView glView; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     glView = new TestView(this); 
     setContentView(glView); 
    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 
     glView.onPause(); 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     glView.onResume(); 
    } 
} 

TestView.java

import android.content.Context; 
import android.opengl.GLSurfaceView; 

public class TestView extends GLSurfaceView { 
    private TestRenderer renderer; 

    public TestView(Context context) { 
     super(context); 

     renderer = new TestRenderer(context); 
     setRenderer(renderer); 
    } 
} 

TestRenderer.java

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.opengl.GLSurfaceView; 
import android.opengl.GLU; 
import android.opengl.GLUtils; 

import java.nio.ByteBuffer; 
import java.nio.ByteOrder; 
import java.nio.FloatBuffer; 

import javax.microedition.khronos.egl.EGLConfig; 
import javax.microedition.khronos.opengles.GL10; 

public class TestRenderer implements GLSurfaceView.Renderer { 

    private FloatBuffer floatBuffer; 
    private FloatBuffer textureBuffer; 
    private Context context; 
    private int[] textures; 

    public TestRenderer(Context context) { 
     this.context = context; 
     textures = new int[1]; 
    } 

    public void onSurfaceCreated(GL10 gl, EGLConfig config) { 
     floatBuffer = ByteBuffer.allocateDirect(4 * 2 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer(); 
     floatBuffer.put(-0.5f); 
     floatBuffer.put(-0.5f); 
     floatBuffer.put(-0.5f); 
     floatBuffer.put(0.5f); 
     floatBuffer.put(0.5f); 
     floatBuffer.put(-0.5f); 
     floatBuffer.put(0.5f); 
     floatBuffer.put(0.5f); 
     floatBuffer.rewind(); 

     textureBuffer = ByteBuffer.allocateDirect(4*2*4).order(ByteOrder.nativeOrder()).asFloatBuffer(); 
     textureBuffer.put(0); 
     textureBuffer.put(1); 
     textureBuffer.put(0); 
     textureBuffer.put(0); 
     textureBuffer.put(1); 
     textureBuffer.put(1); 
     textureBuffer.put(1); 
     textureBuffer.put(0); 
     textureBuffer.rewind(); 

     Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.test); 
     gl.glGenTextures(1, textures, 0); 
     gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); 
     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); 
     GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); 
     bitmap.recycle(); 
    } 

    public void onSurfaceChanged(GL10 gl, int w, int h) { 
     gl.glMatrixMode(GL10.GL_PROJECTION); 
     gl.glLoadIdentity(); 
     GLU.gluPerspective(gl, 45.0f, (float) w/(float) h, 0.1f, 100.0f); 
     gl.glMatrixMode(GL10.GL_MODELVIEW); 
     gl.glLoadIdentity(); 
    } 

    public void onDrawFrame(GL10 gl) { 
     gl.glLoadIdentity(); 
     gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
     gl.glClear(GL10.GL_COLOR_BUFFER_BIT); 
     gl.glTranslatef(0.0f, 0.0f, -5.0f); 

     gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); 

     gl.glEnable(GL10.GL_TEXTURE_2D); 
     gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 
     gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 
     gl.glFrontFace(GL10.GL_CW); 
     gl.glVertexPointer(2, GL10.GL_FLOAT, 0, floatBuffer); 
     gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer); 
     gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); 
     gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 
     gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 
     gl.glDisable(GL10.GL_TEXTURE_2D); 
    } 
} 

Edit: Hier ist ein Beispiel, das ich online gefunden. Wenn ich GL_TEXTURE_2D deaktiviere, bekomme ich ein weißes Quadrat. Wenn ich GL_TEXTURE_2D aktiviere, bekomme ich nichts.

MainActivity public class MainActivity erstreckt Aktivität {

private GLSurfaceView glSurfaceView; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
       WindowManager.LayoutParams.FLAG_FULLSCREEN); 

     glSurfaceView = new GLSurfaceView(this); 

     glSurfaceView.setRenderer(new GlRenderer(this)); 
     setContentView(glSurfaceView); 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     glSurfaceView.onResume(); 
    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 
     glSurfaceView.onPause(); 
    } 

} 

GlRenderer

public class GlRenderer implements Renderer { 

    private Square square; 
    private Context context; 

    public GlRenderer(Context context) { 
     this.context = context; 
     this.square = new Square(); 
    } 

    @Override 
    public void onDrawFrame(GL10 gl) { 
     gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 
     gl.glLoadIdentity(); 
     gl.glTranslatef(0.0f, 0.0f, -5.0f); 
     square.draw(gl); 
    } 

    @Override 
    public void onSurfaceChanged(GL10 gl, int width, int height) { 
     if(height == 0) { 
      height = 1; 
     } 
     gl.glViewport(0, 0, width, height); 
     gl.glMatrixMode(GL10.GL_PROJECTION); 
     gl.glLoadIdentity(); 

     GLU.gluPerspective(gl, 45.0f, (float)width/(float)height, 0.1f, 100.0f); 

     gl.glMatrixMode(GL10.GL_MODELVIEW); 
     gl.glLoadIdentity(); 
    } 

    @Override 
    public void onSurfaceCreated(GL10 gl, EGLConfig config) { 
     square.loadGLTexture(gl, this.context); 

     gl.glEnable(GL10.GL_TEXTURE_2D); 
     gl.glShadeModel(GL10.GL_SMOOTH); 
     gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); 
     gl.glClearDepthf(1.0f); 
     gl.glEnable(GL10.GL_DEPTH_TEST); 
     gl.glDepthFunc(GL10.GL_LEQUAL); 
     gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); 
    } 
} 

Platz

public class Square { 

    private FloatBuffer vertexBuffer; 
    private float vertices[] = { 
      -1.0f, -1.0f, 0.0f, 
      -1.0f, 1.0f, 0.0f, 
      1.0f, -1.0f, 0.0f, 
      1.0f, 1.0f, 0.0f 
    }; 

    private FloatBuffer textureBuffer; 
    private float texture[] = { 
      0.0f, 1.0f, 
      0.0f, 0.0f, 
      1.0f, 1.0f, 
      1.0f, 0.0f 
    }; 

    private int[] textures = new int[1]; 

    public Square() { 
     ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4); 
     byteBuffer.order(ByteOrder.nativeOrder()); 
     vertexBuffer = byteBuffer.asFloatBuffer(); 
     vertexBuffer.put(vertices); 
     vertexBuffer.position(0); 
     byteBuffer = ByteBuffer.allocateDirect(texture.length * 4); 
     byteBuffer.order(ByteOrder.nativeOrder()); 
     textureBuffer = byteBuffer.asFloatBuffer(); 
     textureBuffer.put(texture); 
     textureBuffer.position(0); 
    } 

    public void loadGLTexture(GL10 gl, Context context) { 
     Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), 
       R.drawable.test); 

     gl.glGenTextures(1, textures, 0); 
     gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); 

     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); 

     GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); 

     bitmap.recycle(); 
    } 

    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); 
    } 
} 
+0

Vielleicht ist es die Art der Textur, die Sie verwenden. Zeigen Sie Ihren Textur-Erstellungs-/Initialisierungscode an. – MuertoExcobito

+0

@MuertoExcobito hinzugefügt, dass Code –

+0

Ich fuhr herauszufinden, welche Textur-Formate Sie verwenden, aber GLUtils.texImage2d tut das intern, so dass es nicht so informativ ist. Aber vielleicht hängt Ihr Zeichnungscode davon ab, in einem bestimmten Kanal zu sein (z. B.Alpha), und es stattdessen in rot setzen? Dies war ein Problem in OpenGL beim Wechsel zu 3.2 Core, da 'GL_ALPHA' veraltet war. – MuertoExcobito

Antwort

1

Nach viel Fehlerbehebung, ich war in der Lage, das Problem auf beiden Geräten (und vermutlich alle Geräte) zu lösen, indem sie Textur Verpackung Hinzufügen wie so:

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); 

Ich bin nicht sicher, warum dies für zwei Geräte notwendig war, aber nicht für die anderen zwei.

2

Welche Farbe Format ist es Ihre Textur verwendet? Passt es zum Farbformat, das dein Shader erwartet?

Wenn Ihr Farbformat RGBA8888 ist und der Shader RGB256 erwartet, können Sie Probleme wie diese bekommen. (Es wird an der falschen Stelle für Alphakanal Informationen suchen)

+0

Ich log 'nur GLUtils.getInternalFormat (Bitmap) 'und bekam 6408 zurück, was entspricht GL_RGBA –

+0

Hmmm, können Sie versuchen, öffnen Sie Ihre Textur in GIMP zum Beispiel und exportieren Sie es im RGB-Modus? Versuchen Sie dann, in Graustufen zu exportieren und den Unterschied zu sehen? Einige andere Dinge, die ich versuchen würde: Versuche die Präzision deines Shaders auf HIGHP float zu ändern. Versuchen Sie, den Alpha-Kanal von der ersten Bitebene zur letzten Bitebene (oder umgekehrt) zu wechseln. Verwenden Sie Texturkomprimierung? Einige Komprimierungsalgorithmen unterstützen keinen Alphakanal ... – DKIT

+0

Das Umschalten zwischen RGB und Graustufen hat das überhaupt nicht beeinflusst. Ich änderte png Kompressionsniveau in GIMP von 9 zu 0 ohne Unterschied. Ich habe auch ein anderes Beispiel hinzugefügt. Interessanterweise gibt es in diesem Beispiel keine Transparenz und das Bild wird immer noch nicht angezeigt. Kann es GLUtils nicht einfach so erzeugen? Texturen funktionieren in anderen Apps, daher bin ich mir nicht wirklich sicher, was der Deal ist –