什么是压缩纹理

在实际应用特别是游戏中纹理占用了相当大的包体积,而且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

OpenGL ES 压缩纹理的更多相关文章

  1. 2.x最终照着教程,成功使用OpenGL ES 绘制纹理贴图,添加了灰度图

    在之前成功绘制变色的几何图形之后,今天利用Openg ES的可编程管线绘制出第一张纹理. 学校时候不知道OpenGL的重要性,怕晦涩的语法.没有跟老师学习OpenGL的环境配置,现在仅仅能利用coco ...

  2. Android OpenGL ES(八)----纹理编程框架

    1.把纹理载入进OpenGL中 我们的第一个任务就是把一个图像文件的数据载入到一个OpenGL的纹理中. 作为開始.让我们又一次舍弃第二篇的框架.又一次创建一个程序,新建一个util工具包,在该包下创 ...

  3. Opengl ES之纹理贴图

    纹理可以理解为一个二维数组,它可以存储大量的数据,这些数据可以发送到着色器上.一般情况下我们所说的纹理是表示一副2D图,此时纹理存储的数据就是这个图的像素数据. 所谓的纹理贴图,就是使用Opengl将 ...

  4. 【AR实验室】OpenGL ES绘制相机(OpenGL ES 1.0版本)

    0x00 - 前言 之前做一些移动端的AR应用以及目前看到的一些AR应用,基本上都是这样一个套路:手机背景显示现实场景,然后在该背景上进行图形学绘制.至于图形学绘制时,相机外参的解算使用的是V-SLA ...

  5. OpenGL ES教程系列(经典合集)

    为了搞透播放器的开发,花了些时间收集这些资料,虽然我已经搞定opengles渲染视频的内容,但是想玩玩opengles,往深里玩,图像处理这块是个好的方向,所以opengles是值得好好学的.   O ...

  6. OpenGL ES: (5) OpenGL的基本概念、OpenGL ES 在屏幕产生图片的过程、OpenGL管线(pipeline)

    一. OpenGL的基本概念 OpenGL 的结构可以从逻辑上划分为下面 3 个部分: 图元(Primitives) 缓冲区(Buffers) 光栅化(Rasterize) 图元(Primitives ...

  7. Opengl ES之VBO和VAO

    前言 本文主要介绍了什么是VBO/VAO,为什么需要使用VBO/VAO以及如何使用VBO和VAO. VBO 什么是VBO VBO(vertex Buffer Object):顶点缓冲对象.是在显卡存储 ...

  8. Opengl ES之FBO

    FBO介绍 FBO帧缓冲对象,它的主要作用一般就是用作离屏渲染,例如做Camera相机图像采集进行后期处理时就可能会用到FBO.假如相机出图的是OES纹理,为了方便后期处理, 一般先将OES纹理通过F ...

  9. OpenGL ES学习笔记(三)——纹理

    首先申明下,本文为笔者学习<OpenGL ES应用开发实践指南(Android卷)>的笔记,涉及的代码均出自原书,如有需要,请到原书指定源码地址下载. <OpenGL ES学习笔记( ...

随机推荐

  1. Linux(深度)系统安装富士施乐(网络)打印机

    一般来讲,linux系统识别打印机没有问题,重点难点在于后面设置.此文特别感谢:河北石龙的陈一繁销售代表.P288dw施乐官网并未提供Linux的驱动并在安装过程中遇到很多问题,其不厌其烦的为我联系厂 ...

  2. CSS变量和浏览器前缀

    一.CSS变量 CSS变量是CSS的新特性,大多数浏览器都实现了这个功能,使用CSS变量有利代码复用,而且当我们修改变量值时,所有引用该变量的属性都会发生改变. 定义变量后可以有两种使用方法,第一种时 ...

  3. 【转载】linux-查询rpm包相关安装、卸载脚本

        测试过程中,有时要测试开发自己打的rpm包,为了确认打包正确,需要查询rpm包相关安装.卸载脚本,可以使用命令:   [root@6 /]#rpm -q --scripts mysql pos ...

  4. Linux 内存 占用较高问题排查

    Linux 内存 占用较高问题排查 niuhao307523005 2019-04-24 14:31:55 11087 收藏 11展开一 查看内存情况#按 k 查看 free #按兆M查看 free ...

  5. mysql集群无法启动成功

    场景:两台数据库运行一段时间后发现集群挂了,一台服务正常,一台不正常. 日志如下: [ERROR] InnoDB: Attempted to open a previously opened tabl ...

  6. Centos7 搭建prometheus+Grafana监控

    https://baijiahao.baidu.com/s?id=1676883786156871051&wfr=spider&for=pc node   scrape_configs ...

  7. centos 7编译32位软件的问题

    centos 7默认安装的gcc 为64位,所以在编译32位软件时需要用到32位的gcc库,于是可以增加glibc 32位库: sudo yum -y install glibc-bevel.i386

  8. java_[类加载器]

    Class 与 类加载 Class对象由JVM自动产生,每当一个类被加载时,JVM就自动为其生成一个Class对象,通过Class对象可以获得类的相关信息. 将类信息读到内存中过程,称为类加载 Jav ...

  9. 安装jdk env

    For centos yum list java-1.8.0-openjdk* yum -y install java-1.8.0-openjdk.x86_64 java-1.8.0-openjdk- ...

  10. 使用 Bridge to Kubernetes 简化云端开发

    当我们面对一个大型应用程序,它有大量的微服务,并希望完成一些功能开发? 我们面临许多挑战,其中之一将是处理正确的环境,如何进行开发.我们知道,在团队中解决这个问题的最佳方法是将其容器化并在云上托管.这 ...