实时卡通渲染勾边的处理方法一般有基于图像处理(深度图,法线图,颜色图)的PixelShader/FragmentShader边缘处理方法和基于顶点信息(顶点法线/顶点颜色)的VertexShader阶段处理的方法。
图像处理的优点是效果一致,可以对线条进行像素级别的颜色处理,勾边平滑。缺点是不容易对单一渲染对象逐个处理,不容易单独控制每个渲染对象的勾边细节阈值,渲染开销和分辨率成正比,勾边宽窄调整范围有限。
(崩坏三图)
基于顶点的勾边优点是系统开销相对较小,和分辨率无关,勾边宽窄可以调节。缺点是勾边平滑程度和模型面数高低有直接关系。
(崩坏三图)
卡通渲染比较流行的做法是基于顶点的勾边,基于顶点的勾边方法是2次渲染,第一次在fragementshader阶段每个顶点按法线方向位移一段长度,并且渲染背面,行程暗色的法线扩大图,第二遍渲染原本的对象。
常见的问题是由于顶点法线的不一致产生的边缘“断裂”
原因是由于位于同一位置的顶点的法线不一致,所以位移的方向不一致造成的。
例如图中的1,4顶点,他们在3DSMAX中是一个顶点,这个顶点被4个面共享(2个面这个图看不到),四个面属于4个光滑组,所以在导出的时候它分裂为了4个顶点,分别拥有不同的法线信息,正是如此,模型才有了AB面的硬边效果,但是也产生了顶点的分裂。一个不完美的解决办法是在3DSMAX中通过设置光滑组为一个让这几个顶点法线一致,这样一来导出的每个顶点将是唯一的,并且只有一个法线,但是模型将失去所有的硬边。不能为光照系统提供理想的信息。
另一种可行的方法是在MAXSCRIPT中处理,用顶点颜色信息(RGBA)中的RGB分量作为勾边用的法线方向,A作为扩张的“力度”数值,实现类似头发尖等尖角处理,最终的处理效果如下图中间的处理结果
最终在Unity中渲染结果如下中间所示。
上图从左到右依次是使用法线的勾边,使用MAXSCRIPT处理的顶点色控制勾边,使用平滑组一致的勾边。
关于编辑顶点法线的工具各个游戏引擎应该都有插件提供,但是使用3DSMAX的MAXSCRIPT编辑是比较根本的方法,这样避免了重新导入模型造成的顶点信息不一致的问题。
具体做法是使用MAXSCRIPT遍历当前选择的所有polygon的顶点,平均这个顶点在不同面的法线,得到的法线就是这个顶点唯一的法线,对结果进行值域为0到1的有效颜色区间处理(乘0.5+1),然后进行Alpha值的计算:计算这个点的所有面的角度和,除以360度,得到的值是这个角的“尖锐”程度,写入Alpha,最后写入顶点颜色。
/*
--------------------------------------------------------------------------------
Author: lijianpeng
--------------------------------------------------------------------------------
*/
function CalVertNormals =
(
if (getCommandPanelTaskMode() != #modify) do
setCommandPanelTaskMode #modify
if (Filters.Is_EditPoly()) do
(
local theNode = s