我正在尝试在我的Android应用程序上使用压缩纹理。我在加载纹理时遇到问题,纹理似乎在对象的右侧“切断”。
对于压缩纹理我正在使用ATI的“TheCompressonator”。 为了测试我正在使用Nexus 5.
我怀疑问题在于我的“计算”纹理大小,但找不到此压缩格式的任何refenreces / specification。
有谁知道如何正确阅读此文件格式?
以下是来自nexus的截图:
这是它应该如何看(不介意黑色物体纹理,缺少图像)
这是我的代码段。
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);
int offset = 0; // 64 bit = header, 15 bit = metadata
bf = ByteBuffer.wrap(buffer, offset, buffer.length-offset);
bf.order(ByteOrder.LITTLE_ENDIAN);
int height = bf.getInt(16);
int width = bf.getInt(12);
int size = ((height + 3) / 4) * ((width + 3) / 4) * 16;
Log.d("TextureHelper","Buffer size: "+width+" "+height+" "+size);
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,ATC_RGBA_EXPLICIT_ALPHA_AMD, width, height, 0, size, bf);
Log.d("TextureHelper","Buffer size: "+bf.capacity()+" : "+buffer.length+" error:"+GLES20.glGetError());
glBindTexture(GL_TEXTURE_2D, 0); //unbind texture
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return textureObjectIds[0];
编辑:解决方案
buffer = new byte[bitmap.available()];
bitmap.read(buffer);
int offset = 128; // 64 bit = header, 15 bit = metadata
bf = ByteBuffer.wrap(buffer, offset, buffer.length-offset);
bf.order(ByteOrder.LITTLE_ENDIAN);
int height = bf.getInt(16);
int width = bf.getInt(12);
int size = ((height + 3) / 4) * ((width + 3) / 4) * 16;
Log.d("TextureHelper","Buffer size: "+width+" "+height+" "+size);
bf.compact();///////SOLUTION!
bf.position(0);
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,ATC_RGBA_EXPLICIT_ALPHA_AMD, width, height, 0, size, bf);
Log.d("TextureHelper","Buffer size: "+bf.capacity()+" : "+buffer.length+" error:"+GLES20.glGetError());
glBindTexture(GL_TEXTURE_2D, 0); //unbind texture
注意:您需要将数据放在0位置,如果只是偏移位置(128),它将抛出无效指针异常。
答案 0 :(得分:1)
您的尺寸计算看起来是正确的,但您需要将标题上传为图像数据。 在之后,从标题中提取宽度和高度,将字节缓冲区偏移适当的数量,以跳过标题并开始指向图像数据。
有几种方法可以做到这一点,但是这样的事情可以作为一个例子(这可以优化以删除第二个bytebuffer)。此外,我不确定您使用的纹理格式,但我们假设您的标题长度为124字节。
// assumption that buffer[] is the fully loaded contents of the file
byte[] buffer = ... // load entire file from input stream
// read the header
ByteBuffer bfHeader = ByteBuffer.wrap(buffer);
bfHeader.order(ByteOrder.LITTLE_ENDIAN);
int height = bfHeader.getInt(16);
int width = bfHeader.getInt(12);
// offset to image data
int headerSize = 124; // (replace with correct header size)
ByteBuffer bfData = ByteBuffer.wrap(buffer, headerSize, buffer.length-headerSize);
bfData.order(ByteOrder.LITTLE_ENDIAN);
// load image data
int size = ((height + 3) / 4) * ((width + 3) / 4) * 16;
glBindTexture(GL_TEXTURE_2D, textureObjectIds[0]);
GLES20.glCompressedTexImage2D(GL_TEXTURE_2D, 0,ATC_RGBA_EXPLICIT_ALPHA_AMD, width, height, 0, size, bfData);