Android 使用压缩纹理( 二 )

2.ETC2ETC2 是 ETC1 的扩展,压缩比率一样,但压缩质量更高,而且支持透明通道,能完整存储 RGBA 信息 。ETC2 需要 OpenGL ES 3.0(对应 WebGL 2.0)环境,目前还有不少低端 Android 手机不兼容,iOS 方面从 iPhone5S 开始都支持 OpenGL ES 3.0 。ETC2 和 ETC1 一样,长宽可以不相等,但要求是 2 的幂次方 。
首先定义好 ETC2 的 Header:
// etc2_texture.hclass Etc2Header {public:    Etc2Header(const unsigned char *data);    unsigned short getWidth(void) const;    unsigned short getHeight(void) const;    unsigned short getPaddedWidth(void) const;    unsigned short getPaddedHeight(void) const;    GLsizei getSize(GLenum internalFormat) const;private:    unsigned char paddedWidthMSB;    unsigned char paddedWidthLSB;    unsigned char paddedHeightMSB;    unsigned char paddedHeightLSB;    unsigned char widthMSB;    unsigned char widthLSB;    unsigned char heightMSB;    unsigned char heightLSB;};// etc2_texture.cppEtc2Header::Etc2Header(const unsigned char *data) {    paddedWidthMSB  = data[8];    paddedWidthLSB  = data[9];    paddedHeightMSB = data[10];    paddedHeightLSB = data[11];    widthMSB        = data[12];    widthLSB        = data[13];    heightMSB       = data[14];    heightLSB       = data[15];}unsigned short Etc2Header::getWidth() const {    return (widthMSB << 8) | widthLSB;}unsigned short Etc2Header::getHeight() const {    return (heightMSB << 8) | heightLSB;}unsigned short Etc2Header::getPaddedWidth() const {    return (paddedWidthMSB << 8) | paddedWidthLSB;}unsigned short Etc2Header::getPaddedHeight() const {    return (paddedHeightMSB << 8) | paddedHeightLSB;}GLsizei Etc2Header::getSize(GLenum internalFormat) const {    if (internalFormat != GL_COMPRESSED_RG11_EAC        && internalFormat != GL_COMPRESSED_SIGNED_RG11_EAC        && internalFormat != GL_COMPRESSED_RGBA8_ETC2_EAC        && internalFormat != GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC) {        return (getPaddedWidth() * getPaddedHeight()) >> 1;    }    return (getPaddedWidth() * getPaddedHeight());}解析 ETC2 数据:
// ETC2 魔数static const char kMagic[] = { 'P', 'K', 'M', ' ', '2', '0' };static const bool IsEtc2Texture(unsigned char *data) {    return memcmp(data, kMagic, sizeof(kMagic)) == 0;}static const CompressedTextureInfo ParseETC2Texture(unsigned char *data, GLenum internal_format) {    CompressedTextureInfo textureInfo;    textureInfo.is_valid = false;    if (!IsEtc2Texture(data)) {        LogE("ParseETC2Texture: not a etc2 texture");        return textureInfo;    }    Etc2Header etc2Header(data);    textureInfo.is_valid = true;    textureInfo.width = etc2Header.getWidth();    textureInfo.height = etc2Header.getHeight();    textureInfo.size = etc2Header.getSize(internal_format);    textureInfo.internal_format = internal_format;    textureInfo.data = data + ETC2_PKM_HEADER_SIZE;    return textureInfo;}

推荐阅读