在Android OpenglES 2.0中加载压缩纹理

时间:2014-12-24 20:33:21

标签: android opengl-es-2.0

我正在尝试通过压缩纹理来优化我的应用。由于我的很多纹理需要alpha,我不能使用ETC1。

我已经使用这篇文章中的提示成功地将纹理压缩为其他格式。 Android OpenGL Texture Compression

问题是我似乎无法调整我的代码,阅读这个纹理。我用这段代码唯一得到的是黑色(颜色,而不是纹理)。

这是加载纹理的方法:

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];
}

我目前正在尝试使用PVRTC 4bpp RGBA编码加载使用PvrTexTool压缩的512x512px资源。

有人能看出问题所在吗?或者更好的是,请指出一个有效的例子?从我发现的我只能找到ETC1的例子,他们使用一些ETCUtil来加载纹理。

EDIT2:好的,我已经解决了。 有2个问题。首先,您需要使用这些纹理过滤器。

  

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

其次我不知道pvrtc有一个单独的标题。因此,正确的偏移量为67个字节。 PVRTC format specification

此代码现在可以正常运行:

            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

1 个答案:

答案 0 :(得分:2)

您想通过glCompressedTexImage2D加载PVRTC 4bpp RGBA纹理吗?您应该使用COMPRESSED_RGBA_PVRTC_4BPPV1_IMG而不是GL10.GL_PALETTE4_RGBA8_OES。

IMG_texture_compression_pvrtc https://www.khronos.org/registry/gles/extensions/IMG/IMG_texture_compression_pvrtc.txt

我不确定,但似乎Android GLES20没有这些常量,所以你需要定义它。

// PowerVR Texture compression constants
public static final int GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00;
public static final int GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01;
public static final int GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02;
public static final int GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03;

你应该在glCompressedTexImage2D调用后检查glGetError。 glGetError的值应为GL_NO_ERROR。