unity 卡通风格渲染学习

使用的 unitychan 的模型进行练习

脸部/眼睛/头发渲染比较麻烦,每种材质都很特殊,实现起来细节很多,暂时使用原来的材质

基础的卡通风格渲染包括几个主要部分

漫反射 / 高光 / 轮廓光 / 描边

finalColor = diffuse + specular + rimLight
基础的贴图

漫反射
普通的漫反射为

环境光的颜色 * 法线和光的夹角
diffuse = diffuseColor * dot(N, L);
漫反射

卡通渲染的漫反射一般有着颜色分明的界限,形成不同颜色的条带
一般使用一张渐变或者是条状渐变的贴图进行采样,通常称为 RampTexture
颜色比较暗,看起来不是很明显

高光
blinn-phone模型的高光为

H = normalize(viewDir + lightDir);
specular = _SpecularColor * dot(N, H);

高光部分处理是削弱过度,增加对比

_SpecularEdge 为高光范围
float specular = step(_SpecularEdge, pow(NdotH, _Specular));
float3 specularColor = specular * _SpecularColor;
高光部分

轮廓光
轮廓光很容易营造气氛,表现人物线条,卡通渲染必不可少
一般使用菲涅尔反射计算,让模型边缘产生轮廓光

fresnelPower 为菲涅尔反射强度
float fresnel = step(_FresnelEdge, pow(1 - NdotV, _Fresnel));
float3 rimLight = _FresnelColor * fresnel;
轮廓光

描边
主要是为了将人物和背景区分出来
描边的方式很多,最简单方式可以使用一个pass绘制人物,在使用一个额外的pass绘制描边

描边的pass主要是在剪裁空间进行

  • 将物体的坐标和法线都变换到剪裁空间,其中法线先变换到相机空间,然后在变化到剪裁空间
  • 然后将物体的顶点沿着法线方向挤出一段
  • 最后填充上描边颜色
v2f vert(a2v v)
{
    v2f o;
    o.pos = UnityObjectToClipPos(v.vertex);
    float3 normal = normalize(mul((float3x3)UNITY_MATRIX_IT_MV, v.normal));
    float2 normalCS = mul((float3x3)UNITY_MATRIX_P, normal.xy);
    o.pos.xy += normalCS.xy * o.pos.z * _OutlineWidth;
    return o;
}

fixed4 frag(v2f i) : SV_Target 
{
    return _OutlineColor;
}
加上描边
最后的整体效果

对比了下 unitychan 的实现,法线有很多特殊的实现

  • 比如高光部分使用的是 NdotV 计算,并没有考虑光源的方向
  • 还有漫反射 / 高光 / 边缘光都是计算系数,然后根据贴图采样获得
  • 描边的部分并没有使用单一颜色,而是将整体颜色调暗

你可能感兴趣的:(unity 卡通风格渲染学习)