Unity挑战大世界刷草(二)

草海信息的存储

我们要求记录草海中草的位置信息是为了能够创造出一个尽可能"确定"和"可控"的世界,试想如果没有这条限制,我们不在某种程度上确切记录草的位置,那么一片草海位置信息是可以用 0 bit 的容量来记录的,毕竟只要写个随机函数,让草自己随地扎根就行了,不用浪费空间存储每一株草在哪里。然而我相信大多数项目中,策划和场景美术同学应该不同意这么干,他们会希望能精确绘制出地表植被的分布,规定哪儿有草,哪儿没有,甚至在哪里必须放上几株并设置好朝向等等。

可是,另一方面,想要精确存储每一株草的位置信息似乎是一件不可能的事情,至少看起来很不划算。这点刚才已经算过,一个10公里的地形,每平方只种10根草,只记录位置一个信息,就要消耗掉数十GB的磁盘空间,更别提金贵的内存了。

余下能做的事情就是找出一种折中的办法来调和这对矛盾。这边我给出一种比较常用的解决思路:对于那些注定会成为草海的草(草海的主体),策划和美术同学放弃对每一株草的精确控制,转而控制一小块面积内草的各项属性。如果设置合理,我们能很轻易的降低整体信息量1到2个数量级,同时也能保持全局的草海分布趋势,达到效果和设备的平衡。按照这种思路,很自然的,我们想到使用密度来表示一个单位面积的地皮上有多少草,这样原本需要记录的数值,已经不再是单株草的坐标了,而是这整块地皮的中心点坐标,以及地皮上草的密度值。

这种将单位地皮作为整体打包记录密度的做法,使我们就把原来10 ~ 100株草的数据量一下子压缩到了1株的数据量,当然这个密度转化的过程中是有信息丢失的,我们丢失了单位面积内100株草的局部偏移信息。这是一个问题,但也是一个相对容易处理的问题,比如我们可以赋予每株草一个单位面积内随机的偏移来补全/伪造因合并而丢失的信息,亦或者由美术同学直接指定这一平米面积内草的分布,规定他们的位置和朝向。更妙的是,借由密度化地块这个过程,我们其实也离散化了整个世界,现在的世界地图(至少密度地图)对我们来说是一个一个平铺开来的,拥有固定尺寸的单元格,为方便计量,不妨预设单元格尺寸是1米,这样密度的单位也就变成了"N株草每平方米"。离散化的好处有很多,之后会细讲,其中主要的一点是我们从此可以丢掉浮点数,专注于整型的计算和存储了,而且一些数据结构的运用也会变得更加高效。

一般而言草海的分布是具有连续性的,打个比方,只要不是草海的边缘,一块地皮的密度与它四周8块领域地块各自的密度有很大概率是相等的,这说明在不丢失信息量的前提下,还有压缩密度图的空间,所以不论是把密度图存成纹理格式,在编码成某种形式的图片,还是将密度图在平面上切分,编入四叉树结构,都能再次大幅降低草海信息的体积。

最后对于那些确实有需要精确到位置和朝向的植被,我们不妨将之梳理出来,再开个小灶。只要这部分需求的总量不大,就不会造成实质上的问题。之于如何开小灶,我想方法也有很多,比如我们可以针对这些特殊植被再生成一张密度图来渲染,只不过这次密度单位不是1米,而是0.1米或更小,只要特殊植被数量不多,这些密度图经过压缩后也挤占不了多少空间。


技术选择

好了,到目前为止我们了解了渲染草海的基本特点,面对的挑战,以及一些重要概念和方案。是时候明确下基本技术选型了。


首先是草的几何表现形式,这里选择了模型草作为开发的基准。从技术实现角度出发,模型和面片草对程序来说区别其实不大,更多的是美术工作流的变化,以及视觉效果的转变。考虑到移动端对透明度测试的优化问题,以及植被与玩家交互作用的表现力等方面,暂时选择了模型草作为开发的基础,当然添加对面片草的支持相当容易,如果有需求的话,后续追加也不迟。

然后承接刚才密度的方案,我们需要将美术同学在世界空间中刷出来的草海,以密度块为基本单元,存入某种数据结构中压缩起来。这边选择支持简单的二维纹理编码(可以理解为压缩成图片),同时也支持四叉树编码密度,做四叉树这部分主要是基于个人兴趣,想尝试下构建一套快速范围搜索的算法,当然四叉树也是有别的好处的,之前也讲过,在内存中,四叉树理论上会比解压后的纹理密度图占用更少的体积。那么对于密度变化不复杂的地区,选用四叉树编码,就可能节约数兆字节的内存。

接下来是越来越为人所知的一个术语: GPU Instance。 还记得我们在开篇研究了草海的基本特点么?它具有“海量”和“同质”的特点。而GPU Instance 可以理解为一般图像引擎会提供的一套接口组件,专门用来处理符合“同质”特点的“海量” 实例。处理时,我们只使用一套几何构造作为所有实例的标准“模板”,然后CPU会告知GPU:“需要复制多少份这样的模板,这些模板最后放置在哪儿”等很少的信息,余下的活就交给GPU去处理了。如此一来,虽然GPU的活没少干,但是CPU解放了,自然能提升不少性能。

规范得说,我们可以通过调用了基于 GPU Instance 技术的 DrawMeshInstancedIndirect(...)接口来消减CPU管理Mesh个数,同时也降低了和GPU之间的IO负载,提高Batch数。如果有的同学不理解,也不用担心,后续我们也还会结合示例来详细阐述。而且这些内容在Unity官方文档上都有详细介绍,有兴趣的同学可以去读一读。

此外还值得一提的是,我们选择了面向移动端的 URP 渲染管线,因为其底层的一些优化,特别是 srpBatch 可能会对降低开放世界整体的 DrawCall 消耗有所帮助,这里就不做展开了。



好了,今天我们先到这里,做一个总结:草海位置信息很多很头疼,我们选择用密度块方式,通过四叉树编码后存放起来;然后针对表现层面的需求,我们使用Mesh面数较高的模型草作为草海的主要载体;最后提了一点 GPU Instance 的信息。接下来的文章会进入所谓“绘制草海”的主要环节,即算法逻辑的实现。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容