游戏渲染:SDF渲染还原死亡搁浅般的精细地面

最近,死亡搁浅2的预告片发布了:

让我回想起死亡搁浅1。死亡搁浅1确实是一部优秀的作品。从画面角度来说,如此大地形下,土壤和植被的细节能这么多,实在是令人惊艳。令我影响深刻的尤其是Sam在冥滩上瘫坐的时候,可以看见地面上的细节几乎是像素级的,真正把次世代这3个字诠释得淋漓尽致:

那么,这样精细的地面是如何能在玩家机器上跑得动的呢?(其次,在我个人的纯SDF渲染流程里,怎样应用上呢?)接下来我将以一个解释给纯小白的视角,介绍这背后的技术。
一 超级建模?
我们能想到最直观的方式,就是使用超精细的模型。
这个思路在UE5出现之前,是不可能被考虑的。原因很简单,所需要的三角面数太多,玩家机器根本跑不动。
而且一个超级模型处在传统渲染管线里,牵扯到方方面面的计算,一但玩家移动视角,三角面的剔除,LOD切换,大世界的载入.......会使得计算消耗呈倍增长,让几乎每一个环节都出问题。
二 法线贴图也不够
高精度三维模型的方案,不能被考虑的根本原因,还是数据量太大。如果我能减少数据量,岂不美哉?
有一点了解的朋友可能知道,游戏模型在制作的时候会使用高模制作,然后用算法生成一个没有细节的低模,最后将高模的细节烘培到一张法线图上,贴在低模上,就能看起来和高模类似。


这样模型顶点数可以降得非常少,并且还能看起来很细致。之所有有这么神奇的效果,是因为根据法线贴图计算出来的光照确实有着正确的光照强度。
对于不想关心数学的朋友,可以把它理解成一个神奇的化妆品,画在脸上可以勾勒轮廓,有明暗效果,并且其中含有的微型珍珠颗粒随着光照变化起到非常动人和精细的效果。

但法线贴图和此类化妆一样,虽然能模拟外表,但不能真正改变表面高度。导致我们从侧面看的时候,还是“平平无奇”。


假设我们的表面有一个小坑,坑里有一个小植物,那么从侧面看的时候,应该是看不到这个植物的——它应该被坑挡住了。而如果我们只有法线贴图,无论怎么变化视角,植物都能被看见。

所以我们缺少的,是高度带来的视觉遮挡问题
三 视差贴图还不够
既然缺少高度,那么我们就引入高度图。高度图比法线图更简单,只需要存储一个高度值就行了。

把高度图用上,却不改变模型顶点位置和数量的技术,叫“视差贴图”。
不得不说,这个名字起得不是很好。对于其效果来说,确实是起到欺骗人眼,但并没有改变实体的效果。
但是对其技术而言,跟视差没有什么关系,更和uv偏移没有什么关系。很多人一知半解,然后放网上以讹传讹,这也是为什么很多人没能真正理解和灵活运用视差贴图技术的真正原因——因为“视差贴图”技术真正地去(近似)计算了人眼射线和射线上高度曲线的相交点,从而根据相交点的位置取相应像素,从某种意义上是真正的RayTrace。之所以有人会跟uv扯上关系,是因为高度场本来就是由一张贴图决定的,算出了相交点;因为是一张图,肯定会跟uv有关系,但这个技术的本质跟什么uv偏移没有任何关系。
这个技术的本质,一言以敝之,就是视线射线与局部高度场求交点的问题,直观的方法是二分法,最后在两个正负点取中点。

之所以我说“近似”计算,是因为实际求交点考虑到性能问题,只会固定一个次数,或者接受一个error。
网上有很多乱七八糟的实现和解释,这里我就不赘述了。
现在,由于高度产生的遮挡问题是解决了:

但还是有很多缺点,比如二分法求交点,你得保证函数连续吧,但是高度图不一定连续啊,这就导致交点可能会不止1个,然后由于误差范围设置不当计算出错;迭代次数少了,出错;多了,太耗;error一致吧,性能不稳定;迭代一致吧,error不稳定.......
不过最重要的问题,还是我们花费了这么多性能,马上快赶上超级模型的消耗了,可侧面看还是平平无奇啊.......
四 置换贴图,最后的答案?
看了上文的内容,相信你也发现了:最后还是要真正地提高模型顶点位置,才行啊。
“置换贴图”技术就应运而生。这个名字取得更是狗食,因为还是用那张高度图,根本就没有别的图片。硬要解释的话,就是用它“置换”了原本平平无奇的模型。
从技术内容角度讲,它也没有任何技术难点,无非是根据高度图将模型顶点往上拉一下。不过由于模型是地模,根本没有顶点可拉,所以要配合硬件的曲面细分,先给Mesh加很多顶点,再往上拉(视频1min12s):


如果你是一个能独立思考的人,相信你也发现了:什么傻玩意儿,那我早搞个高模不就完事了,跟你这扯什么扯,还要高度图干啥。
事实证明确实如此:1.很多游戏开发者不适用GPU硬件的曲面细分和Geometry Shader,因为其性能问题和bug问题严重 2.UE5使用Nanite让游戏能支持超级模型,并在开发界面中彻底去除了曲面细分相关功能。
那死亡搁浅用的是啥呢?从网上看到的一些死亡搁浅culling(优化三角面剔除)操作,我个人倾向认为是纯堆三角面数(使用超级模型),然后手动处理Culling,LOD,加载流等所有头疼的东西。也就是说,不像UE5的Nanite开发了一劳永逸的自动化支持超级模型的流程,也没有用到各种花里胡哨,而是手动处理所有逻辑,保证玩家流程里能画质拉满。
所以分析下来,死亡搁浅的地形也没有那么精细,也没有用什么神奇技术,只是某几个单独场景比较精细罢了?
一方面,可以这么说,也许实际游玩的时候确实一般般,只不过被其他东西掩盖了:

另一方面,即使是“播片状态”,就这个画质来说,如果全用超级模型,我也很怀疑,玩家机器上是否能跑得动:

那么死亡搁浅到底用的是哪个技术,视差?置换?细分?它们自己的Nanite?......
对我来说,无所谓了。因为小岛的游戏不应该用来评价,而应该用来启发。
五 如果能超越这个时代
之前做SDF地形的时候,由于是纯数学建模,也没有对PBR支持全贴图流程,所以比较丑。

不过受到置换贴图的启发,我意识到,之前做的所谓SDF Terrain Detail,就可以看作是一种纯数学的置换贴图。现在我在SDF造型的基础上,加上高度图进行offset,也就是
SDFoffset = -k*HeightMap[uv].r
就能对SDF表面进行Displacement。并且不同的物体可以选择不同的k,displacement低可以选比如0.5的K,这样raymarch的步数会少一些,提升性能。而需要Displacement比较高的地方可以选0.1的K,用来应对计算错误,以支持更高的“拔高”。
选择了制作规范的PBR贴图后,发现配合SDF Displacement,效果确实比之前好得多。




由于处在我的SDF渲染流程里,使得每一块凸起的石头都可以产生实时SDF软阴影。在商业引擎中,目前只在UE5里看到类似的功能。(当然UE5对此也做了很多优化,导致了表现有bug,性能有提升等...总之那些方面是没有可比性)
六 总结:小岛,死亡搁浅,播片与技术
对死亡搁浅,我看过最多的负面评价,是不好玩,无聊。对小岛类游戏,是讨厌他的播片。这些都是合理的,但从另一方面讲,正是因为小岛痴迷于播片形式,才使得他可以在播片过程中追求极限。而这个追求极限的过程中,带来了技术的普及。我觉得之所以有那么多人崇拜小岛,可能就是因为他以自身经历证明了一件事:只要心怀善良,不与资本同流合污,是可行的;追求独特,是可行的;追求极限,是可行的;理想主义,是可行的。这难道不美好吗?
