|
写文章的时间不多,也实在水不出什么文采,就简单报告一下动机,结果和一点点细节吧。
谁在用Runtime Virtual Texture这个技术
- UBI在2016年公布了在Far Cry 4中使用的Adaptive Virtual Texture其中就包含Runtime virtual texture.
- UE在4.25版本发布了Runtime Virtual Texture
- 鹅厂大佬公布天涯明月刀中使用了Runtime Virtual Texture,表示2层以上的混合就能表现出明显的性能优势
为什么需要Runtime Virtual Texture
- 你要做任何的大型的景观,就绕不开使用Unity Terrain/ UE4 Landscape这样的多层混合材质巨型动态Mesh。
- 从早年的world machine到现在流行的Houdini在地形制作这个部分都在疯狂地丰富一个东西---图层,8层,堪堪够用而已。
- 8层在十年前你可以认为是8张颜色贴图加两张控制图的混合,十张,好像是有点多,但是现在是PBR的时代,以Unity的Terrain材质为例8层意味着
(1 Albeto + 1 Normal + 1 Detail[AO R + Metal G + Roughness A])* 8 + 2 Control Map = 26次贴图采样
即每个像素,每帧都会有26次贴图采样。这就是为什么Unity官方推荐移动平台不要超过4层的原因。你以为4层就没事了吗?这个标准只能保证中端设备能跑30帧且烫不烫完全不care。
- Runtime Virtual Texture做的事情非常简单,把Terrain Mesh分块,把每块的26张贴图合并成2张render target,这样我们渲染的时候不管有多少图层到了渲染的时候都只有2个贴图采样,但是显存必然是有更大的开销的,空间换时间不多废话。
- 这里必须提出来一个问题,如果我们完全用静态资源,我们的资源到底有多大?以git工程的示例场景为例,一个传统的RPG视角,我们的LOD 0最小切割到8m * 8m,这样的一块在视角内要满足2k分辨率,需要至少1024分辨率的贴图,当然测试下来512也是可以忍的。对于一块512的Terrain,我们的贴图需求是 4096套1024贴图(albeto + normal + detail),这个资源量,再加上mipmap的开销,够刺激吧?
- 废话少说,上对比视频。测试设备为MI Mix2s, 高通枭龙845,Terrain为5层混合。第一个视频为Unity Terrain的真机表现,渲染水面时最高帧数不超过36帧,不渲染水面最高帧数不超过42帧,MipMap的瑕疵也很明显,发热有兴趣的小伙伴可以build一个包体验一下。第二个视频为Mighty Terrain使用1/4精度的Runtime Virtual Texture,渲染水面时最高帧数为45帧,不渲染水面最高帧数能回到60帧,且注意植被的材质细节更为突出。
Unity Default Terrain
https://www.zhihu.com/video/1461406036443324416
MightyTerrain QuaterResolution
https://www.zhihu.com/video/1461406354887479296
最后补上一个Half精度的真机表现,帧率优于Unity Terrain,表现也更好,但是离60帧还是有距离,高端设备可以考虑
MightyTerrain Half Resolution
https://www.zhihu.com/video/1461413162755481601
关于MightyTerrainMesh
- MightyTerrainMesh是我2019年在两次工作切换之间写的一个插件。大地图的表现一直是一个痛点,当年因为用Terrain2Mesh这个插件遇到各种限制所以决心自己造个轮子,扩展了一下Mesh的生成,能够对一块Terrain进行切分,并指定每个分块的贴图大小,而不是一整张basemap,这样对于一些中型场景,可以通过多用一点静态资源,换取合适的精度和效率。但是当年就很清楚,Terrain在移动平台上真正的痛点并不是Mesh的动态生成,而是材质的复杂度。
- 2019年做过一次更新,主要是以前也比较蠢,直接用readpixels/setpixels纯cpu的方式来混合贴图,因为慢,还用了jobs,其实,一个Graphics.Blit就搞定的事情,对使用过那个版本的亲们说声抱歉,我也只是一个还在成长的小白白。
- Unity Terrain的Mesh生成部分并不开源,即便开源,因为它是整块terrain为单位进行处理,也并不适合用来烘培Virtual Texture,个人的观念上,移动平台能够预处理的东西尽量预处理,所以在尝试Runtime Virtual Texture时,自然而然地决定了延续Mighty Terrain Mesh的开发,将离线烘培扩展到在线烘培的开发路径上来。
- MightyTerrainMesh包括一个静态LOD Mesh生成+四叉树动态加载的模块,这个部分具体细节可以参考之前文章
这次更新主要是在此基础上动态地烘培了多层烘培材质,实现了runtime virtual texture
关于MightyTerrainMesh的Runtime Virtual Texture的一些细节
- 首先我们的render target没有转换为压缩格式,所以显存的开销是需要时刻关注的问题。在VTDemo场景中,VTCreator是一个全局烘培贴图的对象,它可以设置每帧烘培virtual texture的数量,以及精度,默认是half精度,在far clip plane 1000m的情况下,显存的开销差不多是150mb。使用Quater精度的话,这个数值大概是50mb以下,显示效果会打一些折扣,但是个人觉得也足够满足需求。没有使用压缩格式的原因主要是暂时没有时间去研究这块,目前了解到的细节是需要使用compute shader,移动平台上这个有适配问题,暂时搁置。
- Render target没有使用Mipmap,而是实时烘培对应的Mipmap,即mesh切换到低级LOD时需要重新确定了这块mesh需要使用的贴图尺寸,并重新烘培。这在adaptive virtual texture中实际上是可以复用高级LOD的virtual texture的,前提是我们烘培时使用Mipmap并愿意承受更多的显存开销,所以这个也可以说是整个系统设计上的选择,是不是明智还是需要做一些测试,目前暂时搁置了。
- 附带地,MightyTerrainMesh在导出mesh时,导出了Terrain的Detail(grass)配置,在runtime使用job system重建了整个植被对象用draw instance的方式进行渲染,获得了更多对植被系统的控制权,但是一样也必须时刻关注cpu的开销,grass的实时构建着实是个不小的开销。
- 得益于URP的SRP Batch,所有的分块mesh使用相同的材质,贴图都为render target,整个terrain mesh的渲染仅有一个set pass call.
一些MightyTerrainMesh能做而Unity Terrain不能做的事
- Runtime Virtual Texture在中端移动设备上能带来久违的60帧。
- Detail(grass)的接管带来了Materail LOD的可能性,目前在VTDemo Scene中,离相机最近的一块Detail使用的是PBR + transcluent材质,而不是Unity Terrain默认的Diffuse+Lambert光照,只有远处的草使用的默认材质。
- 同样地,草不再限于只种在地表,水面的浮萍同样可以通过设置来实现。
- 草batch也不再是默认的直接poping out/off,而是使用了alpha cliping animation,植被的出现与消失是淡入淡出的动画过程。
- 通过修改shader实现了角色与植被之间的交互,视频中可以观察到。
一些MightyTerrainMesh可以做但是还没有做的事情
- Runtime烘培Decal
- occlusion clipping
关于测试项目的资源
这是本人用2天时间使用quixel资源+houdini+unity完成的资源。角色使用了asset store的免费资源,时间有限,仅作测试用途。
Git地址
欢迎fork并开发出更酷的feature。
最后,感谢壳木游戏对这个项目的支持,壳木游戏目前正在做一些突破移动游戏边界的有趣的事情,真诚地期待对图形编程,大世界程序化生成感兴趣的同好加入。简历请发送至
hr@camel4u.com
我们期待您的加入。 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|