最终效果:
Inspector面板:
卡通着色:
基本思想:取法线方向与光线方向的点积,若点积大于零,证明是光线照射到的地方,则像素设置为高光;反之点积小于零则设置为阴影,这样高光和阴影之间边界明显,就是卡通着色的效果
关键代码:
half NdotL = dot(tangentNormal, i.lightDir);//点积,判定方向
//亮部与暗部判定
fixed4 color;
if (NdotL <= 0.0) {
NdotL = _Dark;
color.rgb = c.rgb * _DarkColor*_LightColor0.rgb * (NdotL * 2) * ambient;
}
else {
NdotL = _Specular;
color.rgb = c.rgb *_LightColor *_LightColor0.rgb * (NdotL * 2) * ambient;
}
color.a = c.a;
效果:
描边:
基本思想:剔除物体的正面,然后将物体背面的每一个面沿着法线方向外扩并渲染成指定的颜色,就可以达到描边的效果
关键代码:
v2f vert(appdata_full v) {
v2f o;
float3 dir = normalize(v.vertex.xyz);//任意一点的方向向量
float3 dir2 = v.normal;//法线方向
float D = dot(dir,dir2);//点积,判定方向
dir = dir * sign(D);//乘上点积的正负值,变成真正的方向值
dir = dir * _OutlineFactor + dir2 * (1 - _OutlineFactor);//把该点位置朝向与法线方向按外部变量_Factor的比重混合,来控制挤出多远
v.vertex.xyz += dir * _Outline;//将物体背面的点外扩
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}
效果:如开头所示
不足:描边线条不连续,在复杂模型中表现的十分明显,原因是描边是对模型背面进行外扩,在过程中面与面之间会断开连接,如图所示(暂无解决办法)
法线贴图:
原理:这个就很简单啦,只要保证法线贴图由模型空间转化到切线空间即可
关键代码:
v2f vert(appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);//切换到世界坐标
TANGENT_SPACE_ROTATION;//这个宏为我们定义好了模型空间到切线空间的转换矩阵rotation
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex));//模型空间->切线空间(为了卡通着色的点积)
o.viewDir = ObjSpaceViewDir(v.vertex);
return o;
}
float3 tangentNormal = UnpackNormal(tex2D(_NormalMap,i.uv));//解出切线空间法线
-------------------------------------------------------------------------------------------by NoJerry 2019/3/21 1:10