Unity Toon Shader II
ASE及CelShader概述
理论知识来源:西川善司の「試験に出るゲームグラフィックス」
一、ASE编辑器基础
ASE(Amplify Shader Editor):节点材质编辑器拥有可视化脚本节点,使得着色器编辑更加直观,但会产生大量冗余代码,并不是最优的shader解决方案(官方自带的Shader Graph插件与之类似,用哪一个看个人习惯)
1.输出节点
- 节点
- Albedo 漫反射贴图
- Normal 法线贴图
- Emission 自发光贴图
- Metallic 金属度,为0时可以认为是非金属,为1时可以认为是金属
- Smoothness 平滑度,与Metallic配合模拟金属材质
- Ambient Occlusion AO贴图,环境闭塞
- Transmission 透射
- Translucency 透明度,与Transmission配合模拟次表面反射
- Refraction 反射
- Opadty 不透明度 Opadty Mask 不透明度遮罩
- Custom Lighting 自定义光照
- Vertex Offset 顶点偏移,可用于外描边
- Vertex Normal 顶点法线
- Tessellation 曲面细分
- 参数面板
- Shader Name 着色器名称,与shader的文件名称不同
- Precision 精度
- Cull Mode 剔除模式
- Render Path 前向渲染/延时渲染
- Cast Shadows 投射阴影
- Receive Shadows 接受阴影
- Queue Index 渲染队列索引
- Fallback 回滚
- Render Type 渲染类型
- Render Queue 渲染队列
二、卡通材质概述
1.概述
主要由三种纹理组成:
- MainTex:也就是diffuse纹理,一般填充纯色
- SSSTex:用于控制暗面颜色的贴图
- LimTex光照贴图:控制明暗和高光效果,通过rgb三通道来控制光照效果
光照贴图R通道:LimTex.r,r通道控制光照强度,越白的地方高光越亮,高光越亮
$$
LimTex.r \times SpecMulti \times SpecColor
$$- SpeMulti(高光强度控制)
- SpecColor(高光颜色控制)
- 以上两者都是自定义的材质面板属性
光照贴图G通道:LimTex.g,g通道控制阴影,以0.5为分界,rgb灰度值为128,大于该阈值的越容易成为亮部,小于该阈值的越容易成为阴影
$$
LimTex.g \times VertexColor.r
$$- VertexColor.r(顶点颜色r通道)
光照贴图B通道:LimTex.b,b通道控制高光范围,越白的地方高光范围越大
判断条件为:$Blinn-PhoneSpecular + LimTex.b > 1.0$尽量利用贴图的空闲通道,例如MainTex的alpha通道或是LimTex的alpha通道,来做透贴、自发光、内描边
顶点色
- R通道:绘制阴影,颜色越黑越容易成为阴影
- G通道:对应到摄像机的距离,轮廓线粗细的变化系数,可以通过G通道实现随着摄像机的远近变化,模型不同部位的轮廓线产生不同的粗细变化
- B通道:摄像机的Z-Offset深度偏移,消除多余的描边,例如头发
- A通道:轮廓线的粗细
最终颜色由明暗反射颜色+高光颜色+自发光颜色+边缘光颜色,其中明暗反射颜色由亮部+第一层阴影+第二层固定阴影组成
2.明暗反射颜色
- 注册halfLambert本地变量
$$
C_{diffuse} = (C_{light} * M_{diffuse})(0.5 * (N * L) + 0.5)
$$
计算得到结果后额外乘以Light Attenuation(光线衰减)并注册本地变量halfLambert - 注册ShadowMask本地变量
即$LimTex.g \times VertexColor.r$ - 亮部、第一层阴影颜色、第二层阴影颜色
- 亮部即$MainTex \times MainColor$
- 第一层阴影即$MainTex \times SSSTex \times FirstShadowColor$
- 第二层阴影即在第一层阴影基础上乘以$SecondShadowColor$
- 非固定阴影选择:亮部或第一层阴影
- 亮部:$LimTex.g \times VertexColor.r > 0.5 \rightarrow LimTex.g \times VertexColor.r \times (1.2 - 0.1)$
- 第一层阴影:$LimTex.g \times VertexColor.r <=0.5 \rightarrow LimTex.g \times VertexColor.r \times (1.25 - 0.125)$
- Lerp函数A口接第一层阴影颜色,B口接亮部
- 注册RemapMask本地变量(用于ShadowMask重映射)
- 固定阴影选择:第一层阴影或第二层阴影
- Lerp函数A口接第二层阴影,B口接第一层阴影
- halfLambert与RemapMask相加后乘以0.5是因为原值范围均为0-1,乘以0.5可以将相加后的值重新限定在0-1
- 固定阴影与非固定阴影选择:
- $LimTex.g \times VertexColor.r > 0.1$为非固定阴影
- $LimTex.g \times VertexColor.r <= 0.1$则为固定阴影
- Lerp函数A口为固定阴影,B口为非固定阴影
3.高光(Specular)
- 这里依旧使用Blinn-Phone模型
$$
H = \frac{V + L}{|V+L|}
\\
C_{specular} = (C_{light} * M_{specular})max(0,N*H)^{M_{gloss}}
$$ - 光照贴图R通道控制光照强度:LimTex.r,r通道控制光照强度,越白的地方高光越亮,高光越亮
$$
LimTex.r \times SpecMulti \times SpecColor
$$ - 光照贴图B通道:LimTex.b,b通道控制高光范围,越白的地方高光范围越大
判断条件为:$Blinn-Phone-Specular + LimTex.b > 1.0$ - ASE节点如下:
- OneMinus函数=1-x
- A口接光照贴图R通道
- B口接光照贴图高光,通过光照贴图B通道控制高光范围
- C口接高光颜色
- D口接高光强度参数
4.边缘光(Rim)
- 类似菲涅尔反射,视线与物体越边缘的地方光的反射越强
- 简化公式:
$$
Rim = pow(1-max(0,dot(V,N)),RimScale)
$$ - ASE节点如下:
- 注意RimScale作为指数不能为0
- 使用Toggle Switch将Rim视为一个开关
- ln0口接高光+阴影
- ln1口接高光+阴影+Rim
5.外描边(OutLine)
- 描边的几种做法
- 边缘光伪描边,在一个PASS中完成渲染,快速简单,但效果差强人意
- 几何轮廓线渲染,沿顶点法线方向向外扩展,需要两个PASS,第一个渲染模型背面,第二个渲染模型正面,适用于大多数光滑物体,对于立方体这类不连续的表面会出现断边现象(优化:修改模型顶点法线,平均计算法线并把法线转换到切线空间,存入顶点色中,过程较为复杂)
- 图像后处理,边缘检测
- ASE节点如下:
- 最后连接到输出节点的Local Vertex Offset口
6.自发光
- 后处理:
- 进入U3D包管理器,安装Post Processing
- 创建Post-processing Profile
- 为摄像机创建一个post process层,并添加一个Post-process Layer组件,组件的Layer选择为刚创建的post procsee
- 将模型的层选择为post process,并添加Post-process Volume组件,选择之前创建的Post-processing Profile,勾选Is Global,权重设置为1
- 点击Add effect添加Bloom效果
- 调整Intensity,Threshold到想要的效果
- 自发光信息存于MainTex的alpha通道中,最后计算得到的自发光与阴影高光叠加在一起即可。ASE节点如下:
三、贴图绘制
画贴图就不必多说了,阴影和高光这些根据需求来画,重点是利用贴图的各个通道,提升贴图利用率,第二部分讲到的贴图及各个通道的具体内容仅适用于本实例,实际制作过程完全可以按照自己的需求来完成贴图的绘制(需要本实例用到的贴图、模型、着色器的同学可以联系我获取)
下面展示最终效果
完结散花~
Unity Toon Shader II
https://baifabaiquan.cn/2021/05/30/unity卡通渲染基础2/