如何在Unity中实现非真实感渲染
《Twin Souls: Path of the Shadows》是一款游戏性很强,且具有优质卡通渲染效果的端游,本文将由Unity大中华区技术经理马瑞,为大家分享unity中如何实现非真实感渲染,也就是在Unity中用渲染管道来实现像《Twin Souls: Path of the Shadows》一样的卡通渲染的效果。
卡通渲染的原理
卡通渲染是一种非真实感渲染,也叫作Cel Shading或Toon Shading,旨在通过使用较少的阴影颜色,而非阴影梯度或色调及阴影,使3D计算机图形显得平坦。
上图中,从左至右分别是Diffuse着色器,Cel Shading和有三个阈的Cel Shading。 我们认为一个像素接收的光量是光方向和表面法线之间的点积(NdotL)。如果将此值取整为0或者1,或者定义不同的“等级”或“阈”,将导致不同的卡通渲染样式。在最简单的卡通渲染中,如果点积大于零,则将像素设置为点亮,如果点积小于零,则将像素设置为阴影。
实现方法
此效果可以根据您的渲染路径(Rendering Path)以不同的方式实现。渲染路径(Rendering Path)可以在相机的检视面板(Inspector)中设置。下面我们介绍一下正向渲染和延迟渲染,如果您对它们的具体实现代码感兴趣请点击【阅读原文】查看。
正向渲染
如果您的场景不使用多光源,正向渲染(Forward Rendering)是一个不错的选择。因为在这种模式下,渲染引擎会遍历所有光源的每个顶点和像素,可能会带来较大负担。 然而,如果您的场景只有几个或甚至一个光源,这个解决方案是非常轻量级的。具体实施的时候,您可以创建一个新的表面着色器(surface shader),您通过下面的代码,让边缘平滑。
NdotL = smoothstep(0, 0.025f, NdotL);
延迟渲染
延迟渲染(Deferred Rendering)的优点是它在多光源的场景中可以表现出很好的性能。当使用延迟渲染(Deferred Rendering)时,引擎会遍历场景中的每个光源,并将其与场景中的几何信息一起存储在缓冲区中。要改变延迟渲染(Deferred Rendering)管道,我们需要从Unity网站上下载内置着色器包。
接下来,对下载好的文件进行解压缩,在“DefaultResourcesExtra”文件夹中找到“Internal-DeferredShading.shader”,并将此文件复制到项目中的Resources文件夹。因为自从最初的解决方案发布以来,Unity进行了很多更新,所以我们还需要做以下步骤:
在解压缩的文件夹中找到UnityStandardBRDF.cginc和UnityDeprecated.cginc,并将它们移动到项目中的Resources文件夹。
将UnityDeprecated.cginc重命名为UnityDeprecatedEx.cginc,并使用以下代码替换整个代码,以便添加CustomLambertTerm 。
inline half CustomDotClamped ( half3 a, half3 b )
{
#if (SHADER_TARGET < 30)
return saturate(dot(a,b));
#else
return max(0.0h, dot(a,b));
#endif
}
inline half CustomLambertTerm ( half3 normal, half3 lightDir )
{
return smoothstep(0.0,0.05f, CustomDotClamped (normal, lightDir));
}
将UnityStandardBRDF.cginc重命名为UnityStandardBRDFCustom.cginc,删除其中的整个代码,并用BRDF_1_Unity_PBS方法的自定义实现替换它。它被重命名为BRDF_CUSTOM_Unity_PBS且使用我们的CustomLambertTerm。
在导入的Internal-DeferredShading.shader中,使用UnityStandardBRDFCustom.cginc中定义的自定义宏重写UNITY_BRDF_PBS函数宏:
#define UNITY_BRDF_PBS BRDF_CUSTOM_Unity_PBS
在着色器中包含UnityStandardBRDF.cginc和UnityStandardBRDFCustom.cginc:
#include "UnityStandardBRDF.cginc"
#include "UnityStandardBRDFCustom.cginc"
由于UNITY_BRDF_PBS函数完全被覆盖,因此可以从Internal-DeferredShading.shader中删除UnityPBSLighting.cginc。
在着色器中添加以下行:
if (light.ndotl <= 0.0)
light.ndotl = 0;
else
light.ndotl = 1;
最后,当所有这些步骤完成后,我们的Internal-DeferredShading.shader就大功告成了!然后,我们可以用新创建的着色器替换Deffered着色器:到Edit - > ProjectSettings - > Graphics。在Deferred中,选择我们要修改的文件。
之后,确保您的相机正在使用所需的渲染路径(延迟的Deferred), 现在您应该注意标准着色器(Standard Shader)已经应用了卡通渲染,如下图所示。
边缘
许多游戏使用卡通渲染对物体(Object)勾画轮廓,这样场景会有漫画一般的视觉效果。这种效果可以用许多不同的方式实现。 轮廓可以是纹理的一部分,着色器可以检查表面法线和视角之间的点积,或者可以在后处理中完成。最简单的解决方案是在您的相机中添加Edge Detection效果:
在层级结构(Hierarchy)中选择您的摄像机,然后在检视面板(Inspector)中点击 Add Component->Image Effects->Edge Detection->Edge Detection
突出边缘的效果如下图所示。
最终效果
在本文中,我们借助对《Twin Souls: The Path of Shadows》进行卡通渲染的解决方案,更改Unity的渲染管道以实现卡通风格 。最终,几乎没有使用其他添加,我们实现了类似的独特风格,如下图所示。
总结
非真实渲染技术非常有用,因为它不会替换整个照明模型,只是将现有的模型表面显示为点亮或阴影。它可以与图像效果完美融合,也可以在没有额外性能开销的情况下允许您使用完整的PBR容量。