Android OpenGL Texture not rendered
Here is my GL init code:
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glDisable(GL10.GL_DEPTH_TEST);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glViewport(0, 0, width, height);
float left = 0;
float right = width;
float top = height;
float bottom = 0;
gl.glOrthof(left, right, top, bottom, -1, 1);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
textures.put("ball", new Texture(gl, BitmapFactory.decodeResource(context.getResources(), R.drawable.ball)));
And here is my Texture class
public class Texture
{
int[] texture = new int[1];
static int real_width = 0;
static int real_height = 0;
Texture(GL10 gl, Bitmap bmp)
{
real_width = bmp.getWidth();
real_height = bmp.getHeight();
gl.glGenTextures(1, texture, 0);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);
bmp.recycle();
int error = gl.glGetError();
if (error != GL10.GL_NO_ERROR)
{
Log.e("ROLL", "GL Texture Load Error: " + GLU.gluErrorString(error));
}
}
public void draw(GL10 gl, float x, float y)
{
draw(gl, x, y, real_width, real_height);
}
public void draw(GL10 gl, float x, float y, float w, float h)
{
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
float[] vertices = { x + w, y + h, x, y + h, x, y, x + w, y };
float[] textureCoords = { 1, 1, 0, 1, 0, 0, 1, 0 };
ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
FloatBuffer vertexBuffer = byteBuf.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
byteBuf = ByteBuffer.allocateDirect(textureCoords.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
FloatBuffer textureBuffer = byteBuf.asFloatBuffer();
textureBuffer.put(textureCoords);
textureBuffer.position(0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]);
gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, 4);
gl.glDisableClientState(GL10.GL_VERTEX_AR开发者_开发知识库RAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
}
The problem I get is where nothing is drawn but a white box in the correct shape and position of where the texture should be.
The image is size 50x50 and I thought it would be due to the power of 2 thing, but this problem also occurs on the emulator.
Also, I do get an error in the log and it says: "GL Texture Load Error: invalid value", but I do not know what that means.
Finally, I draw the texture like this:
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
textures.get("ball").draw(gl, 10, 10);
From glTexImage2D:
- GL_INVALID_VALUE is generated if internalFormat is not 1, 2, 3, 4, or one of the accepted resolution and format symbolic constants.
- GL_INVALID_VALUE is generated if width or height is less than 0 or greater than 2 + GL_MAX_TEXTURE_SIZE.
- GL_INVALID_VALUE is generated if non-power-of-two textures are not supported and the width or height cannot be represented as 2k + 2 border for some integer value of k.
- GL_INVALID_VALUE is generated if border is not 0 or 1.
I assume that internal format would be wrong. What about trying to specify it for your own. More documentation about GLUtils you can find there.
But as first i see you haven't bind texture before loading it to GL.
gl.glGenTextures(1, texture, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);
bmp.recycle();
i solved doing:
- move all images to res/drawable-nodpi
- scale to a power of 2, in linux mogrify will do the job (find . -exec mogrify -scale '512x512!' {} \;)
if you load textures from exteral souces this code will do the conversion to closest power of 2 resized bitmap
public class ScalePowerof2 { // some devices require to scale texture bitmaps to power of 2 size 'ScalePower2.scalePowerof2(Bitmpap)' does the job
private static boolean isPowerof2(int v) { // is v a 2^n ?
for (int i=1; i!=0; i<<=1) if (v==i) return true;
return false;
}
private static int closestPowerof2(int v) { // n | 2^n <= v
for (int i=1; i!=0; i<<=1) if (i>=v) return i;
return 0;
}
public static Bitmap scalePowerof2(Bitmap bmp) {
Bitmap b=null;
if (bmp!=null) {
int w=bmp.getWidth(), h=bmp.getHeight();
if (isPowerof2(w) & isPowerof2(h)) return bmp; // ok, both 2^n nothing to do
w=closestPowerof2(w); h=closestPowerof2(h); // new 2^n values
b=Bitmap.createScaledBitmap(bmp, w, h, false);
}
return b;
}
}
精彩评论