Unity Shader实战(2)-卡通着色+描边+法线贴图

最终效果:
Unity Shader实战(2)-卡通着色+描边+法线贴图_第1张图片
Inspector面板:
Unity Shader实战(2)-卡通着色+描边+法线贴图_第2张图片

卡通着色

基本思想:取法线方向与光线方向的点积,若点积大于零,证明是光线照射到的地方,则像素设置为高光;反之点积小于零则设置为阴影,这样高光和阴影之间边界明显,就是卡通着色的效果

关键代码:

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;

效果:
Unity Shader实战(2)-卡通着色+描边+法线贴图_第3张图片
描边:

基本思想:剔除物体的正面,然后将物体背面的每一个面沿着法线方向外扩并渲染成指定的颜色,就可以达到描边的效果

关键代码:

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;
}

效果:如开头所示

不足:描边线条不连续,在复杂模型中表现的十分明显,原因是描边是对模型背面进行外扩,在过程中面与面之间会断开连接,如图所示(暂无解决办法)
Unity Shader实战(2)-卡通着色+描边+法线贴图_第4张图片
法线贴图

原理:这个就很简单啦,只要保证法线贴图由模型空间转化到切线空间即可

关键代码:

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

你可能感兴趣的:(Unity,Shader)