由于我们使用了多UV,加上刚才各种材质特性,还需要实现不同光照模型,这样就会导致我们的shader变成一个庞大的uber shader家族,如何管理shader材质是一个重要的问题。
在工作流方面,一个自定义的材质面板是非常好用的工具,它可以在同一组shader中进行切换。同时可以开关feature,根据特性集来动态调整面板,还可以结合自己的工具进行性能分析、监控和预警。在发布和runtime方面,海量变种对编译速度非常敏感,我们去年把引擎版本从5.6升级到2018,因为2018修复了5.6的重复编译bug,同时大大提升了shader的编译速度。
接下来介绍一下光照系统,由三部分组成,预烘焙的环境光、主灯以及轮廓光。
我们希望有更丰富的光照变化,单LightProbe的效果太单调,没有场景,只能烘焙一个预设的Cubemap。我们的解决方法是沿竖直方向增加LightProbe采样点,让美术增加点光源和方向光作为额外光源,将其直接关照和Cubemap一起合并到环境SH,运行时根据世界坐标的高度在vs中进行插值计算环境光。
轮廓光方面,可以强调角色轮廓,增强体积感。
在使用轮廓光的时候,发现很多衣服存在漏光的问题,这是因为轮廓光没有ShadowMap计算。注意到漏光区域主要是局部形体,我们可以对Mesh静态结构进行预计算。在模型导入在T-pose下后计算网格每个顶点的遮挡信息。对于每个顶点,在其球面上发射若干条阴影光线,进行碰撞测试。
对于每条阴影光线,将其转化到对应顶点的切空间,并将阴影测试的结果累计入2阶SH中。最终结果是4个浮点数,可以把结果存到顶点色中。运行时把轮廓光转换到切空间采样SH进行遮挡判断。
这个是做到的结果,左侧是有轮廓光的,中间是轮廓光 遮挡,可以看到漏光现象大为缓解。因为SH近似存储所有遮挡信息,动态情况下也可以工作,即使增加轮廓光,也可以用这个方案进行统一解决,性能开销不会显著增加。
下面是阴影处理,由于Unity5的阴影不支持半透明物件投影和受影的,我们自定义了shadow pass。同时根据相机与人物的关系可以提升ShadowMap的利用率。我们把人物的包围体按竖直方向细分,根据相机和每个小段的相交结果,调整的投影矩阵。
此处下侧的图像是Shadow Map的情况,右侧是关闭自适应阴影,左侧是开启,可以看到阴影质量得到了相应的提升。