Load PVRTC2/4 Compress Texture on Android

The Advantage of Compress texture
Note, the texture compress method here means some formats that also be supported by our display card.
So compress texture will take less storage, less bandwidth and hardware optimized.

Of course, such texture compression will make a bit loss, but it will not be so obviously in the game.

 

Check hardware supported texture compress format
Before we do texture compress, we need to make sure whether our hardware support PVRTC texture compression support. For android device, we could use glGetString function to get support features. The following code used check which texture compress format supported on our device:

    string ext = (const char*)glGetString(GL_EXTENSIONS);
    if ( -1 != ext.find("GL_IMG_texture_compression_pvrtc") )
    {
        //"GL_IMG_texture_compression_pvrtc" supported;
    }
    else if ( -1 != ext.find("GL_AMD_compressed_ATC_texture") )
    {
        // "GL_AMD_compressed_ATC_texture" supported
    }
    else if ( -1 != ext.find("GL_OES_texture_compression_S3TC") )
    {
        // GL_OES_texture_compression_S3TC" supported
    }
    else
    {
        "unsupported texture compression";
    }

 

Compress texture with PVRTC format

You could use external tool named “PVRTexTool”to do the texture compression, and you could download this tool from Imagination without pay. You could compress texture as following command:

// 2 bits per texture pixel
PVRTexToolCL.exe -f OGLPVRTC2 -i arrow.png -o arrow.pvr
// 4 bits per texture pixel
PVRTexToolCL.exe -f OGLPVRTC4 -i arrow.bmp -o arrow.pvr

And the compression process will take care of the alpha channel at the same time if you provide this channel at the same time. But if you want to more higher precision, I would suggestion you use OGLPVRTC4 instead of OGLPVRTC2.  

 

Load the PVRTC compression texture

You could find some useful document about the PVRTC file format under the PVRTexTool directory. The follow is the code that used to load one PVRTC compressed texture without mip-maps. The workflow is very cleanly here:
1) check the PVRTC file header first;
2) find the meta data block size, skip the meta data block to the texture content address [If you check my code carefully, you will find that I calculated an offset value to get the real texture data instead of strictly following the document guide. The document guide says that the real texture data located after the meta data without any offset, but the situation is some offset must need. And another thing you may notice is the way calculating the texture size based on the texture size and compression format];
3) now you know the texture size ,PVRTC compression format and texture content, so you could create a OpenGL texture object and upload the texture data with function glCompressedTexImage2D.

    NFile file;

    if ( !file.Load(fname) )
        return ;

    int len = file.GetLength();
    if ( len <= sizeof(PVRTextureHeaderV3) + 1 )
    {
        file.Close();
        return ;
    }

    U8* fileConent = new U8[len];
    int count = file.Read(fileConent, len);
    assert(count == len);
    file.Close();
    
    // check the file header first
    PVRTextureHeaderV3* texHeader = (PVRTextureHeaderV3*)fileConent;
    if ( texHeader->u32Version != PVRTEX_CURR_IDENT )
    {
        delete[] fileConent;
        return ;
    }
    
    // skip to the texture part
    int texStart = sizeof(PVRTextureHeaderV3) + texHeader->u32MetaDataSize;
    int texLen = len - texStart;
    if ( texLen > 0 )
    {
        int width = texHeader->u32Width;
        int height = texHeader->u32Height ;

        GLenum format;
        int size;
        if ( texHeader->u64PixelFormat == ePVRTCI_2bpp_RGB )
        {
            format = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;    
            size = (width * height) >> 2;
        }
        else if ( texHeader->u64PixelFormat == ePVRTCI_2bpp_RGBA )
        {
            format = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
            size = (width * height) >> 2;
        }
        else if ( texHeader->u64PixelFormat == ePVRTCI_4bpp_RGB )
        {
            format = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
            size = (width * height) >> 1;
        }
        else if ( texHeader->u64PixelFormat == ePVRTCI_4bpp_RGBA )
        {
            format = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
            size = (width * height) >> 1;
        }
        else
        {
            assert(false && "Unsupported PVRTC texture compression!");
            format = 0;
            size = 0;
        }
        
        glEnable(GL_TEXTURE_2D);
        glGenTextures( 1, &m_tex ); 
        glBindTexture( GL_TEXTURE_2D, m_tex );

        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
        glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
        
        // assume that the texture data located at the end of the file
        int offset = len - size;
        U8* texData = fileConent + offset;

        glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, size, texData);

        delete[] fileConent;
    }

 

Reference

http://stackoverflow.com/questions/9148795/android-opengl-texture-compression
http://www.brokenteapotstudios.com/android-game-development-blog/2011/06/android-pvrtc-texture-encoding-and-performance.html

转载于:https://www.cnblogs.com/open-coder/archive/2012/12/15/2819262.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值