法线外扩描边介绍

使用法线外扩的方法进行描边制作是当下游戏制作描边效果最常用的方法,市面上的多款火爆二次元游戏都使用的是法线外扩描边。在网上对其原理的介绍和教程众多,这里就不再赘述,简要来说其涉及到的操作如下:

  • 在正式渲染物体前加一个渲染Pass进行描边渲染;
  • 渲染描边时,使用法线对物体进行外扩使物体变大;
  • 在正式渲染物体时使用深度测试使其盖在描边上;

其中包含了诸如多Pass渲染、对物体进行法线处理以防止断面等工作,网上大多是使用更自由的Unity进行制作,使用UE制作的教程较少,且均涉及了对引擎、渲染管线的修改和C++的使用,十分麻烦。

但经过我的研究,在UE5时代制作法线外扩描边十分方便,不需要使用一点点C++,完全使用UE提供的功能和蓝图就可以。

使用UE5自带的多Pass效果

使用Overlay材质实现多Pass效果

在静态网格体组件属性面板中,渲染的高级菜单中有一个覆层材质属性。其可以实现多Pass渲染效果,这个材质会在这个模型正式渲染后覆盖在其上方再次渲染。

静态网格体组件的覆层材质属性

制作适用于Overlay功能的法线外扩描边材质

有了这个功能那就好说了,可以直接制作一个用于法线外扩的材质,其要开启双面,并使用不透明度进行正面剔除(目前UE不支持正面剔除):

法线外扩描边材质

上到Overlay材质后效果如下(黑色描边),可以发现北效果不错,但也出现了常见的由于模型硬边导致的描边断边效果:

效果及断边问题

对于该问题的解决方法一般为将平滑后的法线信息储存到顶点色或2UV中,并使用该信息进行法线外扩。在网上传统的案例中,或是在DCC软件中做,或是在外部写一个针对FBX文件的处理脚本,都非常不方便。

既然都使用UE了,那当然是在UE中直接进行处理最方便。

使用UE自带功能制作法线平滑工具

Geometry Script插件介绍

Geometry Script是一个UE5时代出现的官方插件,可用于使用蓝图程序化生成网格体等操作。

Geometry Script官方文档 | 使用Geometry Script制作工具

在使用前要先开启并重启。

Geometry Script插件

法线平滑工具制作思路

根据官方文档的介绍,使用Geometry Script制作法线平滑工具的思路如下:

  1. 创建动态网格体池并申请动态网格体;
  2. 处理法线并保存;
  3. 将处理后的法线存入原网格体;
  4. 保存网格体,并进行相关设置;

法线平滑工具制作

这里需要使用编辑器工具蓝图的功能,使用方法可参考这篇博客或官方文档。

  1. 新建一个BakeNormalToVC的函数;

  2. 创建动态网格体池,并注意在最后进行内存回收(找不到节点的话是插件没开或开了没重启);

    Geometry Script插件

  3. 获取当前选择的资产并转换为静态网格体,保存为本地变量;

  4. 申请2个动态网格体,一个用于处理法线一个用于保存,以防止处理的过程对原模型产生其它影响;

    申请动态网格体

  5. 处理并获取法线,将其映射后存入Temp动态网格体中。这里先统一设置了一下顶点色颜色,防止由于没有顶点色导致的获取失败;

    处理并保存法线信息

  6. 将处理好的动态网格体存入原来的静态网格体资产中,同时要释放内存以便下一个模型的处理;

    导出并释放内存

可以发现这里我只处理了Lod0,其它Lod的处理也一样,写一个循环即可。但别忘了关闭每个Lod的Recompute Normal设置;

对于骨骼网格体的处理也一样,只需将所有 Static Mesh 的节点换成 Skeletal Mesh 即可;

工具使用方法

找到要处理的静态网格体资产,右键 -> 脚本化资产行为 -> [你的函数] 即可。

效果展示

处理完静态网格体后,将描边材质更改为使用顶点色的外扩;

使用顶点色进行外扩

可以看到效果非常不错。

更改后的描边效果

其它问题

复杂模型内描边消除

对于复杂模型直接用这种法线外扩方法进行描边会出现内描边瑕疵(使用的人物模型为虚幻商城官方免费资产):

复杂模型出现的内描边问题

可以使用深度的方式进行内描边去除,在材质中做如下改动:

使用深度去除内描边

修改后的效果如下:

修改后的效果

精确控制描边粗细

  1. 距离变化:在材质中加入使用Actor Position或World Position运算的距离因子即可;

  2. 根据模型变化:可以将描边粗细存入顶点色A通道;

插件自身Bug问题

在我的测试和使用过程中,共发现了以下几种Bug:

  1. 对于骨骼网格体,经常出现顶点色无法写入的问题。经测试,其实是成功写入了,但不知道为啥UE没有识别到。解决方法是把该网格体导出重新导入一遍,很奇怪;
  2. 对于骨骼网格体,有时会出现写入顶点色后软硬边也变了的情况。暂未找到解决方法,可以重新导入一下模型,但不导入顶点色(忽略顶点色);