Unity 2018.3.5.f1
越来越多的游戏中加入了类似海水的效果,效果挺不错的。这里自己也实现一个,就当做学习了。首先看实现的效果:
Unity 2018.3.5f1
项目中经常存在很多Material只是贴图不一样的情况,不同的Material是需要单独一个DrawCall来提交数据渲染这个对象的,比如下面场景中五个Cube对象,每个Cube对象使用了一个单独的Material,其中各自的Material只有贴图不一样。因为每个Cube使用了独立的Material,渲染花费了五个DrawCall:
如果我们把这些贴图合并到一张大的贴图中去(参考Unity贴图合并工具),然后让那些仅仅是贴图不一样的Material都使用这个合并后的大贴图。针对每个模型修改自己的UV,让Mesh的UV匹配到合并后的大贴图。这样这些模型就可以使用相同的Material了,Unity对使用相同的Material渲染的Mesh会进行动态合批(dynamic batching)。这样游戏运行时这五个Cube只需要一个DrawCall消耗了。进一步思考,dynamic batching可以在运行时刻开辟一块内存把这些分散的Mesh合并到一个新的Mesh中去,我们干脆直接在资源层面将这些Mesh合并,这样还节省运行时刻的内存。这办法可行,下面介绍下一个简单的Mesh合并工具的实现过程。
需要合并Mesh我们需要先了解其数据结构,一个Mesh文件基本组成部分:
两个独立的Mesh文件,我们只需要把它们这些信息合并就可以得到一个新的Mesh。这个新的Mesh包含了两者的信息。第一步获取这些信息:
在ShadowgunSample中学到了用shader实现一个广告牌(Billboard)效果,这里记录下。在ShadowgunSample的场景中,这个模型两边的光晕永远是对着移动中的摄像机,如下图:
在Unity的Manual中有段对GPU优化的提示:
Some GPUs, particularly ones found in mobile devices, incur a high performance overhead for alpha-testing (or use of the discard and clip operations in pixel shaders). You should replace alpha-test shaders with alpha-blended ones if possible. Where alpha-testing cannot be avoided, you should keep the overall number of visible alpha-tested pixels to a minimum.
意思是说某些类型的GPU设备,尤其是移动设备。在pixel shaders中使用了alpha-testing或者是使用discard和clip操作会导致很高的性能压力,应该使用alpha-blended来代替alpha-testing。
Unity 2018.3.5f1
这里实现了一个简单的合并贴图的工具,在Unity的Project窗口中,选中一个存放图片的文件夹。右键菜单中可以看到 [Pack Texture], [Pack Texture(All Relayout)] 选项, 即可合并该文件夹下的所有贴图。具体如图所示:
选中一个存放了图片的文件夹:
执行合图操作之后,将会合并贴图并将结果生成在事先在AtlasConfig.cs中配置好的路径中(这里测试配置的是Assets/Res目录)。结果包含两类文件Asset和Atlas,Asset文件保存了Atlas文件中每张贴图在图集中的偏移,缩放和对原始图片的引用。如果选中的目录下既有带Alpha的图片又有不带Alpha的图片,工具会根据是否带Alpha进行归类并且结果输出到不同的目录。如下图:
生成的Asset文件保存的信息如图:
由于这些合并后的贴图是用于Mesh的贴图,并且MeshRenderer会根据这些贴图再图集中的偏移而要改变自己的UV,所以为了避免每次合图之后MeshRenderer的都需要重写UV的操作,这里的合图有两个选项Pack Texture和Pack Texture(All Relayout)。Pack Texture选中执行过程中不会对之前合并好的贴图进行改变,保持其在图集中的位置偏移,而Pack Texture(All Relayout)相当于重新排列每张图片在图集中的位置。所以需要注意这两点: