I'm trying to optimize my app by having compressed textures. Since a lot of my textures require alpha I can't use ETC1.
I've successfully compressed textures to other formats using hints from this post. Android OpenGL Texture Compression
Problem is I can't seem to adapt my code, to read this textures. The only thing I get with this code is black (colour, instead of texture).
Here is the method, that loads textures:
public static int loadCompressedTexture(Context context, int resourceId){
final int[] textureObjectIds = new int[1];
glGenTextures(1, textureObjectIds, 0);
if(textureObjectIds[0] == 0){
logTextureHelper(Log.WARN, "Could not generate a new OpenGL texture object");
return 0;
}
final InputStream bitmap = context.getResources().openRawResource(resourceId);
byte[] buffer;
ByteBuffer bf;
try {
buffer = new byte[bitmap.available()];
bitmap.read(buffer);
bf = ByteBuffer.wrap(buffer);
glBindTexture(GL_TEXTURE_2D, textureObjectIds[0]);//binds texture to texture object
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);//minimization filter
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);//send texture data to OpenGL to the CURRENTLY BOUND object
GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D, 0, GL10.GL_PALETTE4_RGBA8_OES, 512, 512, 0, bf.capacity(), bf);
//glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0); //unbind texture
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return textureObjectIds[0];
}
I currently trying to load resource that is 512x512px, compressed with PvrTexTool, using PVRTC 4bpp RGBA encoding.
Can anyone see what the problem is? Or better yet, point me to an example that works? From what I found I could only find examples for ETC1, who use some ETCUtil to load textures.
EDIT2: Ok I've solved it. There were 2 problems. First you need to use these texture filters.
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
Secondly I was not aware that pvrtc had a seperate header. The correct offset is thus 67 bytes. PVRTC format specification
This code now works correctly:
buffer = new byte[bitmap.available()];
bitmap.read(buffer);
int offset = 67; // 52 bit = header, 15 bit = metadata
bf = ByteBuffer.wrap(buffer, offset, buffer.length-offset);
bf.order(ByteOrder.LITTLE_ENDIAN);
long version = bf.getInt(0) & 0xFFFFFFFFL;
long flags = bf.getInt(4);
long pixelFormat = bf.getLong(8);
long colorF = bf.getInt(16);
long chanel = bf.getInt(20);
int height = bf.getInt(24);
int width = bf.getInt(28);
long depth = bf.getInt(32);
long nsurf = bf.getInt(36);
long nface = bf.getInt(40);
long mipC = bf.getInt(44);
long mSize = bf.getInt(48);
long fourCC = bf.getInt(52)& 0xFFFFFFFFL;
long key = bf.getInt(56)& 0xFFFFFFFFL;
long dataSize = bf.getInt(60)& 0xFFFFFFFFL;
// Log.d("TextureHelper","Buffer size: "+version+" "+flags+" "+pixelFormat+" "+colorF+" "+chanel+" "+height+" w: "+width+" h: "+height+" "+depth+" "+nsurf+" "+nface+" "+mipC+" "+mSize);
// Log.d("TextureHelper","Buffer size: "+fourCC+" "+key+" "+dataSize);
glBindTexture(GL_TEXTURE_2D, textureObjectIds[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glCompressedTexImage2D(GL_TEXTURE_2D, 0,GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, width, height, 0, bf.capacity()-offset, bf);
Log.d("TextureHelper","Buffer size: "+bf.capacity()+" : "+buffer.length+" error:"+GLES20.glGetError());
glBindTexture(GL_TEXTURE_2D, 0); //unbind texture
available()
method onInputStream
is not guaranteed to give the entire length of the resource. Can you check what it returns, and make sure that it matches the length of the file? – Reto Koradi