读取ATI压缩纹理的问题

时间:2015-01-05 09:40:42

标签: android opengl-es opengl-es-2.0

我正在尝试在我的Android应用程序上使用压缩纹理。我在加载纹理时遇到问题,纹理似乎在对象的右侧“切断”。

对于压缩纹理我正在使用ATI的“TheCompressonator”。 为了测试我正在使用Nexus 5.

我怀疑问题在于我的“计算”纹理大小,但找不到此压缩格式的任何refenreces / specification。

有谁知道如何正确阅读此文件格式?

以下是来自nexus的截图:

Nexus 5, blowfish right side is cut off

这是它应该如何看(不介意黑色物体纹理,缺少图像) Samsung tab 2, this is how blowfish should look

这是我的代码段。

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),它将抛出无效指针异常。

1 个答案:

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