那是在一个阳光明媚的早上。我想应该是去年秋天的某个时候,我们终于等到了翘首期盼的消息:维京挑战者!终于来临!当然,它仍是一个早期的草稿:一個光头、没有任何皮肤纹理也尚未赋予任何材质——但我们依然为他来到我们的项目中而感到兴奋。 “快来人啊,把给这坏小子给我打上材质,然后丢进我们的场景吧!”我们就真的这么干了。而且它确实看起来非常炫酷。除了……有些地方看起来怪怪的。“呃,这家伙真的有接收动态阴影吗?”。事实上他真的有接收动态阴影,然而并非以我们所期望的方式。
 

1.jpg


他总体上看来并没有收到任何影子,因此我们也断定问题就出在阴影上,它看起来很奇怪,而且参差不齐。

问题所在

我们快速的对着色器(shader)进行了研究之后,丑陋的真相已原形毕露:不仅是一半的角色完全丢失了阴影,更别提这角色阴影看起來有种块狀的诡异感。
 

2.jpg


“为什么会这样呢?”,你可能因此而感到好奇。Unity5不是采用了全新的牛逼闪闪的软阴影过滤算法么?确实如此,而且的确很強大。说来也巧,但是,我们的一些场景最远有3000米的距离,而且我们已经决定,希望从那么远投射阴影,到视维的每一个像素上。现在,我们自然就竭尽所能地调整了级联分裂和阴影偏移,无论是近距离还是离镜头非常非常远,效果看起来都很不错。然而,到目前为止,我们却从未经历过这样一种情况,那就是在一个如此宏大的场景中添加一个离相机很近卻又具有诸多细节的角色。我们不仅缺乏用于在角色身上产生软阴影的分辨率,为确保场景美观所需要的深度偏移是如此之大,以至于它将角色一半的身体推出了阴影。原来,一块皮带在距离它1cm的盔甲上投射出软阴影,和一块中等尺寸的岩石在地面上投射出软阴影的情况并不完全相同。又有谁能料到呢,嗯?因此我们需要寻求一个解决方案来解決这困境。我们可以将Quality Setting里阴影级联(Shadow Cascades)的第一级移动到非常非常靠近相机的位置,但代价就是这场景浪費了一级可用。它仅仅会在我们的角色们真的非常非常靠近相机时才会运作,虽然这已经足够解决我们眼下遇到的这个问题了。

解决方案

然而,我们决定用一种比较老派的技术解決于这个问题。“如果我们仅仅针对角色另外渲染一个额外的阴影贴图呢?”说到做到。两百行代码之后,游戏引擎为我们展示了这样的画面:
 

3.jpg


此时,我们已经能够产生足够多的数据来呈现任何能够想到的华丽绝伦的阴影过滤了。虽然如此,我们并没有大量的时间去对最佳过滤进行微调,我们决定去做一个类似于Nvidia光导开关[1]的一个简单的距离感知采样方案。虽然没有出现在这些展示的截图中,我们还设有一个选项用于捕捉人物对焦领域之外的阴影投射数据的选项;比如说,我们仍然需要有静态的世界的阴影透射到这些动态的角色上。这类投影被会被投到阴影渲染镜头最近平面上,以确保他们在软阴影滤波方案中总是具有最大的拦截-接收距离 。如此一来,剩余的唯一的问题便是如何将上述工作集成到渲染管线了。在一些抓耳挠腮的琢磨之后,结果我们发现原来有一个非常简单的方法来对常见的Unity shader所用的阴影方法进行重写。经过几次反复,我们最终将其简化为只需添加两行额外的代码就可以对任意着色器添加这种独特的阴影支持:
 

4.jpg


请注意,为确保这种重写能够正常运作,这里的“include”部分必须写在其他的engine includes之前。显然,这里可能存在一些轻微的误导,因为我们在这里用了一个include文件来将真正的复杂部分给覆盖了。若有人想要做类似的事情,这里本质上可以归结为:
 

5.jpg


这里的条件判断决定了是否启用这种独特的阴影,以及我们目前是否正在呈现一个定向光。而第二个条件判断则决定了能否与其他类型的投影光源和平共处。

福利!

在经历了所有艰苦困苦的工作之后,我们究竟获得了怎样的令人满意的结果呢?下面就是同一个调试场景在打开和关闭这种“独特阴影”技术时,所呈现出来的场面。
 

0.gif


老派技术最终得分获胜!

总结

有一点需要注意的是——像绝大多数其他的渲染功能一样——增加更多的阴影贴图到你的项目是有代价的。阴影贴图会占用更多的显存,而且渲染他们会产生额外的绘图调用(draw call),同时这种运用也增加了着色器对于带宽使用和运算性能的需求。在The Blacksmith中,我们对系统进行了设置,使得我们能够更具角色距离相机的距离来决定这种独特的阴影技术是否被启用。因此,我们只在那些人物占据画面大部分的镜头中才会付出额外的渲染成本。对于一个普通的游戏而言,在玩家正常游戏的过程中可能永远不会出现角色如此靠近相机的情况,我想可能只有在近摄特定的过场动画时,才需要启用这种技术。为了更好地单独演示这一功能,我们已经把它抽离到了一个小的演示项目中,你可以从Asset Store获取它:https://www.assetstore.Unity3d.com/en/#!/content/39921该演示项目包含了一个最基本的场景,以模拟一些距离相机非常近的角色细节出现在宏大的户外场景中。即使第一級层阴影级联覆盖仅1%的阴影距离,在左侧运用了我们“特殊阴影技术”和右侧运用了常规级联阴影技术的维京挑战者之间,依然存在着相当显著的差异。
 

5.jpg