WebGL纹理详解——压缩纹理的使用

为什么要用压缩纹理

下面这张图是一辆陆虎越野车模型所用的纹理,原始分辨率为1024 x 1024。

WebGL纹理详解——压缩纹理的使用

浏览器从服务端加载这样一张图片时,其格式通常为JPEG,文件尺寸只有166KB,但是当WebGL处理一张纹理时就需要按照位图处理(这里所说的位图是指没有使用任何压缩算法的原始图片数据),如果图像中每个像素需要RGB三个通道,每个通道需要8位空间,那么整张图片就需要使用1024 x 1024 x 8 x 3 位的信息,也就是3M,这3M的信息都需要加载到GPU缓存当中,这和图片文件采用什么样的压缩格式没有任何关系。当调用gl.texImage2D方法时,浏览器内部就会将图片文件进行解压,转换成位图格式。如果图片包含透明信息,那么RGBA格式那么还要额外增加内存使用。

在简单了解WebGL处理纹理的过程后,会知道使用JPEG或者PNG文件作为纹理时会有这样的问题:

需要有图片解压过程,比较耗时。

因为纹理数据较大,所以传输纹理数据耗时较多。

纹理数据占用内存较多。通常是浏览器和GPU各自保存一份位图数据。

压缩纹理的出现就是来解决这些问题,经过某种算法压缩之后的纹理可直接被GPU使用,只有当shader进行纹理查询(texture lookup)才会进行解压操作,找到对应位置的像素颜色。GPU通常会对解压过程进行优化从而提升性能。

浏览器的图片缓存策略

为了更好的了解WebGL处理纹理时如何分配和使用内存,请看下面的实验。

首先,页面加载前文提到的陆虎车的纹理,打开Chrome的任务管理器(Task Manager),把 Image Cache 和 GPU Memory 这两项勾选,查看图片缓存和GPU内存用量。你可以打开这个demo自行观察。

这时 Image Cache 显示:4262K,GPU Memory 显示:17.7M。

现在,我们注释掉加载纹理的语句,这时候图片不会加载,纹理也不会被绘制出来。

此时 Image Cache 显示:0K,GPU Memory 显示:13.7M。

如果加载图片,但是不创建纹理会如何?

结果是 Image Cache显示:166K,GPU Memory显示:13.7M。

通过以上观察可以推出以下结论。

当仅下载图片时 Image Cache 以图片原始格式进行缓存,当创建纹理时,浏览器会解压成为位图格式,并将位图数据进行缓存。

GPU Memory 以位图格式保存纹理数据。

通过Chrome的Profile工具可以看到在JavaScript层面,其内存消耗只包含HTMLImageElement对象所占用的内存大小。

以上结论可以用下面这张图来概括:

WebGL纹理详解——压缩纹理的使用

当使用压缩纹理时,内存使用状况变为:

WebGL纹理详解——压缩纹理的使用

压缩纹理的种类

不同的GPU厂商会有不同的纹理压缩格式,具体如下:

S3TC/DXTn/BCn:桌面计算机常见的压缩格式。名字虽然有不同叫法,但都是指同一种压缩方式。通常以DDS文件格式保存。

PVRTC/PVRTC2:iOS设备上使用的压缩纹式。

ETC/ETC2:随着OpenGL ES 2.0 出现。

ASTC:2012年出现的一种新压缩格式。

ATC:Adreno GPU支持的一种压缩格式,Android手机上常用。

压缩纹理支持情况

WebGL1.0里,压缩纹理是通过扩展支持的,因此要看当前浏览器支持哪些扩展。具体判断方法如下:

var availableExtensions = gl.getSupportedExtensions(); for (var i = 0; i < availableExtensions.length; i++) { if (availableExtensions[i].indexOf(\'texture\') >= 0 && availableExtensions[i].indexOf(\'compressed\') >= 0) { // show in console console.log(availableExtensions[i]); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwpzxw.html