I'm trying to draw transparent textures (text) in my app. Strangely, it works on the newest Nexus 7 and on my second generation Moto X but on the original Nexus 7 the textures are just black. I've got blending enabled and the texture is 512x512 so it's not a power-of-two issue. I'm also just using GL10 which should be supported on everything, right? Any reasons the textures wouldn't work on just this device?
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);
And here's the texture initialization, where I load the texture atlas:
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 shows what happens on the old Nexus 7. The bottom picture is a Moto X.
Edit: Here's a complete example. No transparency, doesn't draw anything on the old Nexus 7. If I get rid of the texture stuff it draws the square in white like it should.
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: Here's an example I found online. If I disable GL_TEXTURE_2D I get a white square. If I enable GL_TEXTURE_2D I get nothing.
MainActivity public class MainActivity extends Activity {
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);
}
}
Square
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);
}
}
What color format is it your texture is using? Does it match the color format your shader is expecting?
If your color format is RGBA8888 and the shader expects RGB256 you can get problems like this. (It will look for alpha channel information at the wrong place)
After much troubleshooting, I was able to solve the problem on both devices (and presumably all devices) by adding texture wrapping as 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);
I'm not sure why this was necessary for two devices but not the other two, though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With