如何解析基于Unity3D的平坦四叉树地形与Virtual Texture的分析

如何解析基于Unity3D的平坦四叉树地形与Virtual Texture的分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

地形绘制有重复度高,高度控制自由,贴图复杂度高且有连贯要求等特点。因此必须要使用特化的绘制方法才得以完成绘制。先前Ubisoft Far Cry 5分享的地形绘制方法,使用了QuadTree + Virtual Texture的方法。这样的方法有很多优势,因为QuadTree提交的都是固定的面片,因此从剔除到提交都完全可以在GPU做,这和我们之前实现的GPU Driven Pipeline思路相仿,而Virtual Texture可以用来表示各种Geometry信息,如高度,漫反,法线,粗糙度等等…… 因此我们也决定使用这样的技术来实现大地形的绘制和编辑。

四叉树的实现对于算法能力扎实的朋友来说,并不算难事,所以这里直接就跳过四叉树的基本算法原理,拿出部分代码示例进行讲解。因为Virtual Texture加持的原因,在构建四叉树时不需要准备诸如Material ID之类的额外信息,只需要保存当前区块的位置坐标,LOD等级(用于切换LOD),以及缓存状态(方便递归)等,数据结构也会非常简单:

如何解析基于Unity3D的平坦四叉树地形与Virtual Texture的分析

有个小细节是,为提高内存分配性能,四个子节点是同时分配的,这一点许多习惯C++高级特性的开发者很容易习惯性的漏掉,但是性能都是从这种小细节抠出来的,因此一定要注意:

如何解析基于Unity3D的平坦四叉树地形与Virtual Texture的分析

因为使用了Unity提供的手动内存分配,因此完全可以使用Burst Compiler提高CPU端计算速度:

如何解析基于Unity3D的平坦四叉树地形与Virtual Texture的分析

准备完毕后直接提交到StructuredBuffer等Compute Shader用到时拿去做剔除绘制工作,渲染结果如下(Albedo贴图为局部UV显示):

Farcry 5提到的Procedural Virtual Texture分为两部分,第一部分Procedural和Adaptive,基本占了99%的工作量,主要工作量在于各种自动化生成,手动高性能编辑的工具,以及随玩家移动进行动态加载卸载的游戏逻辑;第二部分为Virtual Texture,基本占了不到1%工作量,本着柿子先挑软的捏的精神我们先把Virtual Texture部分简单实现以下。

所谓Adaptive Virtual Texture一句话总结就是:存贴图的对象池。首先,开一张Render Texture作为Index map,存储一个Scale Offset,也就是一个指向Atlas位置的索引。同时开一张Atlas,当地形加载到这一部分时,从硬盘加载贴图到Atlas的某个部分,并将新加载的部分的位置放到Index map中,也就是说使用Index map作为一张跳表。而渲染地形时,直接把当前地形的世界坐标当做UV读取Index map即可,相当于整个地形使用了一张硕大无比的贴图,只不过这个贴图中间大部分地方都是没加载的,读取贴图的伪代码大致如下:

Texture2D<float4> _IndexMap;Texture2DArray<float4> _Atlas; SamplerState sampler_Atlas;float4 _IndexMap_TexelSize;//Indexmap 的物理大小float4 TexVT(float2 uv){//将传入UV转换到Index map的绝对坐标。    uv *= _IndexMap_TexelSize.zw;//读取Index Map,XYZW四个通道意义分别为:大小比例,横向偏移,纵向偏移,数组索引    float4 scaleOffset = _IndexMap[(uint2)uv];//获取绝对UV的小数点后部分,得到局部UV偏移    float2 localUV = frac(uv);    localUV = localUV * scaleOffset.x + scaleOffset.yz;//使用换算出的UV读取Atlas    float4 value = _Atlas.SampleLevel(sampler_Atlas, float3(localUV, scaleOffset.w), 0);    return value;}

这一点在PPT中讲的也比较清楚了:

如何解析基于Unity3D的平坦四叉树地形与Virtual Texture的分析

这样灵活的空间分配和复用方式,可以使用视锥体只加载视野内的贴图,若内存和性能充裕且玩家常有高速转动镜头的需求,也可以使用摄像机坐标来加载相机四周的贴图。

同时PPT分享中也指出,由于所有世界空间中紧挨在一起的图片在IndexMap中也是紧挨的,因此在进行LOD降级时,只需要将四块区域的图片四合一放到另一块区域即可,顺水推舟,几乎没有额外消耗。

这里我们给出一套完整的API:

如何解析基于Unity3D的平坦四叉树地形与Virtual Texture的分析

软柿子轻而易举捏完。就只剩硬柿子了。当然,由于工作量巨大,可能需要本人开发数月或数年才能搭建一套有完整工具流程的Virtual Texture,所以这里只给出一个设想性质的原型用作学习探讨用途。

从上方的实现不难看出,Virtual Texture的实现过程全部是实时投射的Render Texture,实时加载,实时卸载,实时合并,因此在设计储存的数据格式时,我们也没必要储存一整张绘制好的贴图,因为这样会导致游戏的包体完全无法控制,我们只需要提供绘制所需的“种子”即可。

此类种子一般是示例贴图,Blend Mask贴图,贴花模型等,这些种子可以大量复用,并且可以使用程序化DCC工具生成,比如这里的RT就是由多张已经准备好的贴图按顺序混合,其中每张贴图都有不同的Tiling密度:

如何解析基于Unity3D的平坦四叉树地形与Virtual Texture的分析

虽然Tilling密集,但由于使用的Mask不同且混合均匀,并没有出现明显的重复感:

如何解析基于Unity3D的平坦四叉树地形与Virtual Texture的分析

只用Mask做混合显然是不够的,诸如石子,土路,苔藓等不规则物,在生产时往往是依赖贴花实现。贴花的实现思想也比较简单粗暴,直接在面片上方构建一个正交投影矩阵,并把模型的Geometry信息“拍扁”到贴图上:

如何解析基于Unity3D的平坦四叉树地形与Virtual Texture的分析

 
贴花本身就是模型,直接渲染贴花本身

最终有贴花的贴图丰富程度更高了:

如何解析基于Unity3D的平坦四叉树地形与Virtual Texture的分析

看完上述内容,你们掌握如何解析基于Unity3D的平坦四叉树地形与Virtual Texture的分析的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注编程之家行业资讯频道,感谢各位的阅读!

相关文章

这篇文章将为大家详细讲解有关Unity3D中如何通过Animator动画...
这篇文章主要介绍了Unity3D如何播放游戏视频,具有一定借鉴价...
这篇文章给大家分享的是有关Unity3D各平台路径是什么的内容。...
小编给大家分享一下Unity3D如何实现移动平台上的角色阴影,希...
如何解析基于Unity3D的平坦四叉树地形与Virtual Texture的分...
这篇文章主要介绍Unity3D如何实现动态分辨率降低渲染开销,文...