游戏开发中经常混淆纹理和精灵的概念,下面来简单的区分一下
纹理:纹理只是简单的图像文件,一个拥有很多颜色数据的大列表,其作用是为了告知程序,图像的每个像素应该是什么颜色;
精灵:精灵是网格的2D等价物,通常只是一个四边形,(一对三角形合并成的网格),其作用是来渲染面向当前相机的平面;
精灵表:另一种被称之为精灵表的事物,它是在一个纹理文件内大量独立图像的几何,通常用于包含2D动画,
以上的这三种文件可以使用工具进行切分,比如,unity的sprite Atlas,用来形成角色动画帧所需要的独立纹理;
网格或者精灵都使用纹理,将图像渲染到他的表面,纹理图像文件通常由类似于ps、Gimp等工具形成,接着以类似于音频文件的方式导入项目中,在运行时将这些 文件加载到内存,推送到GPU的现存,并且在给定的DrawCall期间,由着色器渲染到目标精灵、网格上;
纹理压缩格式
与音频类似,Unity也由默认的设置列表导入纹理文件,以简化操作,可以通过这些导入设置来进行性能上的微调与纹理的品质提升,如下
Texture Type
该设置决定什么选项是可见的,特别是下面的Advanced下面的选项,并且需要知道的是,并不是所有的选项都能用于所有的纹理,因此哦明确所设置纹理的目的然后再去设置该选项,将其设置为Normal map(法线纹理)、Sprite(精灵)、Lightmap(光照纹理)等,
压缩格式
与音频的压缩格式类似,首先可以以多种常见的格式(jpg、png)导入纹理文件,但是应用程序中内置的实际压缩格式可以根据给定频台的GPU,从很多不同的纹理压缩格式中选择最适配的一种,不同的格式代表组织纹理颜色信息的不同方式,包括用于描述每个通道的不同位数(使用的位数越多,可以表示的颜色就越多)描述每个通道的不同位数(例如红色通道可能使用比绿色通道的位数),用于所有通道的总位数(更多的位数意味着更大的纹理、更多的磁盘和内存消耗),是否包含alpha通道
最重要的,还包括打包数据的不同方式,这允许GPU进行高效的访问,如果选择了错误的类型,访问小效率会特别的低
如何修改压缩方式?
使用Compression纹理导入选项进行如下选择
- None
- LowQuality
- NormalQuality
- HightQuality
选择none意味着不进行压缩,在这种情况下,最终纹理依然会对导入的文件类型进行格式转化,但是会选择一种不压缩的格式,因此品质没有任何损失或者损失很小,但是纹理比较大
其他的三种压缩格式都会选择压缩格式,同样,不同的平台会尝试不同的压缩格式,比如选择LowQuality意味着unity选择的压缩格式会显著的减少纹理大小,这样会造成失帧,选择hightquality,纹理文件就会比较大,占用内存比较多,但是失真会很小
这是由unity自动选择的 虽然是自动选择的但是可以人为的覆盖掉,如果点击Default旁边的某个某个选项卡,就会看到特定平台的设置,并且可以选择希望选择使用的压缩格式;
纹理性能增强
- 减少纹理文件的大小
- 谨慎的使用mipmap
- 从外部管理分辨率的降低
- 调正Anisotropic filtering级别
- 考虑使用图集
- 跳帧非正方形纹理的压缩率
- 异步纹理上传
减少纹理文件的大小
给定的纹理文件越大,推送纹理所消耗的GPU内存贷款就越多,如果每秒推送的总内存超过图形卡的总内存贷款,就会产生瓶颈,因为在下一个渲染过程开始之前,GPU必须等待所有纹理都上传完毕才能进行下一步操作,由此看来,小纹理自然要比大纹理更容易通过管线推送到GPU,因此我们需要找到高质量与性能之间的平衡点;为了确定是否存在内存带宽的瓶颈,一个简单的测试就是降低游戏中最丰富的、最大的纹理文件分辨率,重启场景,如果帧速率突然提高,那么应用程序中很可能收到纹理吞吐量的限制,如果帧速率没有明现改善,那么可能仍然有一些带宽,或者渲染管线的其他地方存在瓶颈;
谨慎的使用Mip Map
对于远处的物体,例如石头,树木等,如果玩家看不到细节,使用高精度细节的纹理就没有意义,当然玩家可能会看到轻微的效果提升,但是性价比是很低的,Mipmap的开发就解决了这个问题,它提前生成相同的低分辨率的替代品,保证他们占据相同的内存空间,在运行时,GPU根据透视图中的表面大小选择响应的mipMap级别;
使用GenerateMipMap开启,Unity自动处理这些低分辨率的副本生成,MipMap的几个选项可以影响它生成副本的级别,我们可以进行一些微调,因此来获取高质量的MipMap的集合但是需要衡量一下是否值得花时间去做;
在Scene视图中将DrawMode切换为MipMaps,如果纹理大于他们合适的大小,纹理以红色高亮呈现,反之以蓝色呈现
值得注意的是,纹理只有距离摄像机很远或者很近渲染的时候,才会使用MipMap方案,如果始终和摄像机保持固定的距离是不会使用的;
从外部管理分辨率的降低
Unity做了很多努力让很多工具可以尽可能的简单使用,并且允许将项目文件导入到工作空间中,比如.PSD、.TIFF文件,他们通常很大,且拆分为多图层的图像, Unity自动从文件的内容中生成引擎后续可以使用的纹理文件,但是,unity的自动纹理生成和压缩技术肯定不如专注于这项工作的软件做的好,当导入的时候可能会缩小图像比例,从而造成混叠失真,那么为了保证预期的质量水平,可以提供比需要的分辨率更高的文件,但是如果直接通过外部的应用程序缩小图像的比例,混叠可能就比较少,这样就可以用较低的分辨率达到可以接受的质量水平,从而小号更少的磁盘和内存空间;
调整Anisotropic Fitering级别
Anisotropic Fitering这种属性是一种对观察非常倾斜的纹理提升纹理质量的特性,,打开的时候,即使你观察的纹理很倾斜,在靠近摄像机的时候也会看的很清楚,如果不开启就会很模糊,需要注意的是,Anisotropic Fitering很昂贵,除非必要否则不要开启;
考虑使用图集
图集是一种技术,他是将一些较小的、独立的纹理合并到一个较大的纹理文件中,从而最小化DrawCall的数量,这也是进行动态批处理的有效方法,;
由于每种独特的材质都需要额外的DrawCall,但是每种材质只支持单一的主纹理,当然,他们也可以支持多个二级纹理,比如法线纹理、发射纹理等,然而,将多个祝文里合并到一个大的纹理文件中,渲染共享这个纹理的对象时,就可以最小化所使用的DrawCall数量;需要做的额外工作就是修改网格或者精灵对象的UV坐标,只采样大纹理的所需部分,需要注意的是即使将多个效地纹理合并到一个大的纹理文件中,内存消耗也是相同的,因为它推送到GPU的数据是一样的,只不过是推送的数量减少了;
图集不一定要用2D图形或者UI元素,如果创建了很多低分辨率的纹理,则可以将此技术应用到3D网格上,若3D游戏具有简单纹理的分辨率,或者扁平着色的低多边形风格,都可以使用图集;
由于动态批处理效果只影响非动画网格(MeshRenderer而不是SkinnedMeshRenderer),因此不要将动画角色的纹理文件合并到图集,原因是:由于动画角色的纹理是动画的,因此GPU需要将每个对象的骨骼乘以当前动画状态的改变,这意味着需要为每个角色都进行单独的运算,不管其是否共享了材质,这样的计算都会导致多余的DrawCall;
调整非正方形纹理的压缩率
纹理文件通常是以正方形,2的n次幂格式保存,但是也可能出现长方形的纹理,其高度和宽度仍然是2的n次幂,但是不推荐制作这样的纹理,一些GPu需要方形纹理格式,为此,Unity将自动拓展纹理到额外的空白处进行补偿,但是这些拓展出来的位置实际上是用不到的数据,但是这样就会占据GPU的带宽,因此尽可能的去使用方形的压缩率;
异步纹理上传
在纹理导入项中有一个导入设置是Read/Write Enable ,默认情况下,他是禁用的,禁用的好处是,纹理可以使用Asynchronous Texture Uploading 特性,这个特性由两个好处,一是纹理会从磁盘上异步上传到RAM中,且当GPU需要纹理数据的时候,传输发生在渲染线程,而不是主现程,这样的话不会阻塞主线程影响用户体验,同时纹理会同送到环形缓冲区中,一旦缓冲区中增加了新数据,数据就会持续不断的推送到GPU,如果缓冲区中没有新数据,就提前退出处理并等待,直到请求新的纹理数据;
这样的话,减少了每一帧准备渲染状态所花费的时间,允许更多的CPU资源花在游戏玩法,物理引擎等逻辑模块中;
但是,有利有弊,开启纹理的读写功能,本质上告诉unity ,我们想要随时的读取和编写该纹理,这暗示着GPU需要随时刷新对他的访问,因此而禁用该纹理的异步纹理上传功能,但是如果有那种模拟在画布上作画的效果,就不能禁用了,另外,他的这个上传的缓冲区大小也是可以修改的,可以在editor->project setting ->quality->other中设置;