安卓OpenGL纹理压缩

55

我需要帮助查找有关如何在Android上使用纹理压缩的信息(或示例)。目前我有许多PNG文件需要减少它们占用的内存。我正在研究PVR压缩,但是我无法弄清楚如何在OpenGL中使用它。

请问是否有人能够指点迷津或提供一些示例?因为我现在找不到相关资料。

4个回答

85

Android主要支持四种纹理压缩类型:

  • ETC1(Ericsson纹理压缩)。该格式被所有Android手机支持,但它不支持alpha通道,因此只能用于不透明的纹理。
  • PVRTC(PowerVR纹理压缩)。支持使用PowerVR GPU的设备(如Nexus S、Kindle fire等)。
  • ATITC(ATI纹理压缩)。用于使用高通Adreno GPU的设备(如Nexus One等)。
  • S3TC(S3纹理压缩)。这种纹理压缩用于集成了NVIDIA芯片组的设备(如Motorola Xoom等)。

更详细的信息请参见这里这里

简而言之,如果您的纹理没有alpha通道,可以使用ETC1。如果它们具有alpha通道,并且您想要支持所有设备,则必须将纹理压缩为另外三种类型,并根据设备加载它们。

如何使用:

  1. 压缩PNG文件(您可以使用像ETC-PackPVRTexToolATI CompressonatorNvidia Texture Tools等工具),并将其添加到项目资产中。

  2. 确定设备中可用的扩展名,如果未使用ETC1:

public void onSurfaceCreated(GL10 gl, EGLConfig config) {

     String s = gl.glGetString(GL10.GL_EXTENSIONS);

     if (s.contains("GL_IMG_texture_compression_pvrtc")){
          //Use PVR compressed textures         
     }else if (s.contains("GL_AMD_compressed_ATC_texture") ||
              s.contains("GL_ATI_texture_compression_atitc")){
          //Load ATI Textures           
     }else if (s.contains("GL_OES_texture_compression_S3TC") ||
                s.contains("GL_EXT_texture_compression_s3tc")){
         //Use DTX Textures
     }else{
         //Handle no texture compression founded.               
     }

}           
  • 以原始数据形式加载压缩纹理。

  • 使用 glCompressedTexImage2D 代替 glTexImage2D:

  • public void onDrawFrame(GL10 gl) {
    
       ....
    
       gl.glCompressedTexImage2D(GL10.GL_TEXTURE_2D, level, internalformat, width, 
                                 height, border, imageSize, data);
    
    }
    

    2
    嗨@Xilliah,这个线程很旧了,你说的可能是对的,但是这个解决方案在我的几个项目中运行得非常好。如果你认为它不正确,你可以做两件事,要么告诉我你认为哪里有问题,我很乐意尝试修复它,要么请随意添加另一个答案,提供正确的解决方案...请提供建设性的评论!谢谢。 - gergonzalez
    你好Gergonzalez。我犯了一个错误并且是不正确的,但由于某些原因无法删除评论。只是我又傻了。你的答案很有帮助! - Tony
    不错!很高兴能帮忙 :) - gergonzalez
    只是想指出,这个解决方案不会减少您图像的总大小(很可能),但它会减小那些在GPU内存中使用的图像的大小。 - Mokosha
    您可以为特定设备针对不同的构建版本,并仅使用一种纹理压缩。Google Play将根据用户的设备提供适当的变体。 - Stan
    显示剩余3条评论

    5

    这是一个旧的线程,我想更新一下其中提到的信息,它可以在http://devtools.ericsson.com/etc上找到。 ETC2在Khronos标准的OpenGL ES 3.0和OpenGL 4.3中是强制性的。


    3

    2
    那太糟糕了,似乎只有一个保证:使用OpenGL ES 3.0 API时,ETC2 / EAC纹理压缩格式是可用的。 - leetNightshade

    3
    你不应该只使用PVR压缩在Android上,因为这样不能适用于所有型号。为了解决这个问题,你应该只使用ETC1(在所有GLES 2.0设备上都是强制性的)或者为不同GPU模式准备单独的纹理包。Android开发指南有一个辅助类来加载压缩格式。
    你可以使用etcpack进行压缩。
    请注意,ETC1不会得到alpha通道 - 你可以通过将alpha通道作为单独的纹理进行一些花哨的片段着色技巧来解决这个问题。

    我确实尝试过,但是Eclipse不知道ETC1Util是什么,也无法找到相应的导入...这个问题有什么原因吗? - Chris
    1
    你应该只使用ETC1(在所有GLES 2.0设备上强制执行),我认为它不是OpenGL ES的强制要求 - 在我看来,它是一个扩展:请参见http://www.khronos.org/registry/gles/。 - Simon F
    3
    它是GLES 1.0/1.1的扩展,但在GLES 2.0中被强制要求。 - Arne Bergene Fossaa

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接