zoukankan      html  css  js  c++  java
  • OpenGL ES 压缩纹理

    什么是压缩纹理

    在实际应用特别是游戏中纹理占用了相当大的包体积,而且GPU无法直接解码目前流行的图片格式,图片必须转换为RGB等类型的格式才能上传到GPU内存,这显然增加了GPU内存的占用。为了处理这些问题于是出现了GPU支持的压缩纹理格式,在GPU中进行解码。压缩纹理属于有损压缩,更在意解码速度,而编码在程序运行之前,因此速度较慢。

    压缩纹理的常见格式

    基于OpenGL ES的压缩纹理有常见的如下几种实现:
    1)ETC1(Ericsson texture compression)
    2)ETC2(Ericsson texture compression)
    3)PVRTC (PowerVR texture compression)
    4)ATITC (ATI texture compression)
    5)S3TC (S3 texture compression)

    ETC1

    ETC1格式是OpenGL ES图形标准的一部分,并且被所有的Android设备所支持。
    扩展名为: GL_OES_compressed_ETC1_RGB8_texture,不支持透明通道,所以仅能用于不透明纹理。
    且要求大小是2次幂。
    当加载压缩纹理时,参数支持如下格式: GL_ETC1_RGB8_OES(RGB,每个像素0.5个字节)

    ETC2

    ETC2 是 ETC1 的扩展,压缩比率一样,但压缩质量更高,而且支持透明通道,能完整存储 RGBA 信息。ETC2 需要 OpenGL ES 3.0(对应 WebGL 2.0)环境,目前还有不少低端 Android 手机不兼容,iOS 方面从 iPhone5S 开始都支持 OpenGL ES 3.0。ETC2 和 ETC1 一样,长宽可以不相等,但要求是 2 的幂次方。

    PVRTC

    支持的GPU为Imagination Technologies的PowerVR SGX系列。
    OpenGL ES的扩展名为: GL_IMG_texture_compression_pvrtc。
    当加载压缩纹理时,参数支持如下几种格式: GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG (RGB,每个像素0.5个字节) GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG (RGB,每个像素0.25个字节) GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG (RGBA,每个像素0.5个字节) GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG (RGBA,每个像素0.25个字节)

    ATITC

    支持的GPU为Qualcomm的Adreno系列。
    支持的OpenGL ES扩展名为: GL_ATI_texture_compression_atitc。
    当加载压缩纹理时,参数支持如下类型的纹理: GL_ATC_RGB_AMD (RGB,每个像素0.5个字节) GL_ATC_RGBA_EXPLICIT_ALPHA_AMD (RGBA,每个像素1个字节) GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD (RGBA,每个像素1个字节)

    S3TC

    也被称为DXTC,在PC上广泛被使用,但是在移动设备上还是属于新鲜事物。支持的GPU为NVIDIA Tegra系列。
    OpenGL ES扩展名为:
    GL_EXT_texture_compression_dxt1和GL_EXT_texture_compression_s3tc。
    当加载压缩纹理时,参数有如下几种格式: GL_COMPRESSED_RGB_S3TC_DXT1 (RGB,每个像素0.5个字节) GL_COMPRESSED_RGBA_S3TC_DXT1 (RGBA,每个像素0.5个字节) GL_COMPRESSED_RGBA_S3TC_DXT3 (RGBA,每个像素1个字节) GL_COMPRESSED_RGBA_S3TC_DXT5 (RGBA,每个像素1个字节)

    压缩纹理相关API的使用

    1) 获得GPU的型号

    glGetString(GL_RENDERER)
    

    2) 获得GPU的生产厂商

    glGetString(GL_VENDOR);
    

    3) 获取GPU支持哪些压缩纹理

    string extensions = (const char*)glGetString(GL_EXTENSIONS);
    

    4)判断是否支持ETC1格式的压缩纹理

    return (extensions.find("GL_OES_compressed_ETC1_RGB8_texture")!= string::npos);
    

    5) 判断是否支持DXT格式的压缩纹理

    return (extensions.find("GL_EXT_texture_compression_dxt1")!= string::npos ||
        extensions.find("GL_EXT_texture_compression_s3tc")!= string::npos);
    

    6)判断是否支持PVRTC格式的压缩纹理

    return (extensions.find("GL_IMG_texture_compression_pvrtc")!= string::npos);
    

    7)判断是否支持ATITC格式的压缩纹理

    return (extensions.find("GL_AMD_compressed_ATC_texture")!= string::npos ||
        extensions.find("GL_ATI_texture_compression_atitc")!= string::npos);
    

    8) 上传压缩纹理数据

    void glCompressedTexImage2D(
            GLenum target,
            GLint level,
            GLenum internalformat,
            GLsizei width,
            GLsizei height,
            GLint border,
            GLsizei imageSize,
            const GLvoid * data);
    

    internalformat即是压缩纹理格式的类型。
    9)查看设备支持的texture压缩格式,可以使用如下代码获取:

    int num_formats;
    glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_formats);
    std::cout<<"Texture extensions: "<<num_formats<<std::endl;
    
    int *formats = (int*)alloca(num_formats * sizeof(int));
    glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats);
    for(int i=0; i<num_formats; i++)
    {
        std::cout<<i<<" 0x"<<hex<<formats[i]<<dec<<std::endl;
    } 
    
    //注意使用PVRTC格式纹理时,纹理的filter mode不能设置为 GL_LINEAR_MIPMAP_LINEAR, 
    //否则的话加载出来的画线显示黑色, 这里有提到。
    

    10)glTexImage中指定压缩格式可以对上传的纹理进行压缩以改善内存使用,通过设置intenalFormat为表中一个值实现。通过这种方式进行图像压缩增加了纹理加载的开销,但却能够通过更有效地使用纹理存储空间来增加纹理性能,如果由于某些原因无法对纹理进行压缩,OpenGL就会使用下表中所列出的基本内部格式,并加载未经压缩的纹理。

    GL_COMPRESSED_RGB : GL_RGB
    GL_COMPRESSED_RGBA : GL_RGBA
    GL_COMPRESSED_SRGB : GL_SRGB
    GL_COMPRESSED_SRGB_ALPHA : GL_RGBA
    GL_COMPRESSED_RED : GL_RED
    GL_COMPRESSED_RG : GL_RG
    

    除了这些压缩格式外,OpenGL中还加入了一些特定的压缩格式,即GL_COMPRESSED_SIGNED_RED_RGTC1,GL_COMPRESSED_SIGNED_RED_RGTC2,和GL_COMPRESSED_SIGNED_RG_RGTC2,它们用于各种单颜色通道和双颜色通道压缩纹理,他们代替了兼容版本中GL_LUMINANCE和GL_LUMINANCE_ALPHA的功能
    11)判断纹理是否被成功压缩

    GLint comFlag; 
    glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_COMPRESSED,&comFlag);
    

    glGetTexLevelParameteriv第三参数支持的有:

    GL_TEXTURE_COMPRESSED:如果纹理被压缩返回1,否则返回0
    GL_TEXTURE_COMPRESSED_IMAGE_SIZE:获取压缩后的纹理大小(以字节为单位)
    GL_TEXTURE_INTERNAL_FORMAT:所使用的压缩格式
    GL_NUM_COMPRESSED_TEXTURE_FORMATS:支持的压缩纹理格式数量
    GL_COMPRESSED_TEXTURE_FORMATS:支持的压缩纹理格式数组
    GL_TEXTURE_COMPRESSION_HINT: 选择压缩格式的方式
    

    11)指定选择压缩格式的方式

    glHint(GL_TEXTURE_COMPRESSION_HINT,GL_FASTEST); //最快
    glHint(GL_TEXTURE_COMPRESSION_HINT,GL_NICEST);  //质量最好
    glHint(GL_TEXTURE_COMPRESSION_HINT,GL_DONT_CARE); //自行选择
    

    压缩纹理工具

    每种压缩纹理以及相应的厂商都提供了压缩纹理的工具,包括可视化工具和命令行工具,可自行下载
    1)Imagination Technologies PowerVR
    PVETextTool
    2)Qualcomm Adreno
    Adreno Texture Tool
    3)ARM Mali
    Mail Texture Compression Tool
    4)nVIDIA Tegra
    DirectX Texture Tool

  • 相关阅读:
    献给需要购买 阿里云产品的朋友
    当硬件没问题的时候,提升电脑运行速度
    IIS网页GZIP压缩
    前端优化-如何计算白屏和首屏时间
    Javascript 思维导图
    总结get和post区别---面试用
    点击切换样式、以及点击自身移除样式效果
    各行换色
    计算器
    无缝轮播图
  • 原文地址:https://www.cnblogs.com/wl-blog/p/15003104.html
Copyright © 2011-2022 走看看