赞
踩
参考书籍:《Unity Shader 入门精要》
五种方法:
使用描边方法2,以及卡通风格的高光反射光照模型实现。
描边注意:在背面顶点扩展时,可能有正面的面,这时会出错。可想象一个半实心球,内部有个面向视角的面,顶点外扩时,内部的面会超出外表面,遮挡了外表面。解决办法是先让背面法线z值减0.5再归一化(背面压扁)。
高光实现:镜面反射使用Blinn模型,计算(n·h)时,做阈值比较,小于的就是高光部分。
Shader "Custom/Chapter 14/Toon Shading" { Properties { _Color ("Color Tint", Color) = (1, 1, 1, 1) _MainTex ("Main Tex", 2D) = "white" {} _Ramp ("Ramp Texture", 2D) = "white" {} // 漫反射渐变纹理 _Outline ("Outline", Range(0, 1)) = 0.1 // 轮廓线宽度 _OutlineColor ("Outline Color", Color) = (0, 0, 0, 1) // 轮廓线颜色 _Specular ("Specular", Color) = (1, 1, 1, 1) _SpecularScale ("Specular Scale", Range(0, 0.1)) = 0.01 // 高光反射的阈值 } SubShader { Tags { "RenderType"="Opaque" "Queue"="Geometry"} // 第一个Pass,延展背面顶点,实现描边。 Pass { NAME "OUTLINE" Cull Front // 剔除正面,只渲染正面 ... v2f vert (a2v v) { v2f o; // 顶点和法线变换到视角空间下,让描边可以在观察空间达到最好的效果 float4 pos = mul(UNITY_MATRIX_MV, v.vertex); float3 normal = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal); normal.z = -0.5; // 让法线向视角方向外扩,避免物体有背面遮挡正面 pos = pos + float4(normalize(normal), 0) * _Outline; //对外扩展,出现轮廓 o.pos = mul(UNITY_MATRIX_P, pos); return o; } ... } // 第二个Pass,基于Blinn光照模型,使用自定义高光光照模型,实现高光。 Pass { Tags { "LightMode"="ForwardBase" } Cull Back ... float4 frag(v2f i) : SV_Target { ... fixed spec = dot(worldNormal, worldHalfDir); // 高光区域抗锯齿操作,fwidth:邻域像素的近似导数。 fixed w = fwidth(spec) * 2.0; // _SpecularScale为0会完全消除高光反射,smoothstep:小于-w为0,大于w为1,否则在0到1之间插值。 fixed3 specular = _Specular.rgb * lerp(0, 1, smoothstep(-w, w, spec + _SpecularScale - 1)) * step(0.0001, _SpecularScale); return fixed4(ambient + diffuse + specular, 1.0); } ENDCG } } FallBack "Diffuse" }
通过判断不同光照下漫反射值,使用不同的渲染纹理。纹理组成一个色调艺术映射(Tonal Art Map, TAM)。
// 素描风格 Shader "Custom/Chapter 14/Hatching" { Properties { _Color ("Color Tint", Color) = (1, 1, 1, 1) _TileFactor ("Tile Factor", Float) = 1 // 平铺系数 _Outline ("Outline", Range(0, 1)) = 0.1 _Hatch0 ("Hatch 0", 2D) = "white" {} // 6张素描纹理,模拟不同阴影使用的纹理 _Hatch1 ("Hatch 1", 2D) = "white" {} _Hatch2 ("Hatch 2", 2D) = "white" {} _Hatch3 ("Hatch 3", 2D) = "white" {} _Hatch4 ("Hatch 4", 2D) = "white" {} _Hatch5 ("Hatch 5", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" "Queue"="Geometry"} UsePass "Custom/Chapter 14/Toon Shading/OUTLINE" // 使用前面的描边渲染Pass Pass { ... struct v2f { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; fixed3 hatchWeights0 : TEXCOORD1; // 6张纹理存在两个fixed3中 fixed3 hatchWeights1 : TEXCOORD2; float3 worldPos : TEXCOORD3; SHADOW_COORDS(4) }; v2f vert(a2v v) { ... o.hatchWeights0 = fixed3(0, 0, 0); o.hatchWeights1 = fixed3(0, 0, 0); float hatchFactor = diff * 7.0; // 放大7倍,便于分成7块,混合权重。 if (hatchFactor > 6.0) { // 纯白 } else if (hatchFactor > 5.0) { o.hatchWeights0.x = hatchFactor - 5.0; } else if (hatchFactor > 4.0) { o.hatchWeights0.x = hatchFactor - 4.0; o.hatchWeights0.y = 1.0 - o.hatchWeights0.x; } else if (hatchFactor > 3.0) { o.hatchWeights0.y = hatchFactor - 3.0; o.hatchWeights0.z = 1.0 - o.hatchWeights0.y; } else if (hatchFactor > 2.0) { o.hatchWeights0.z = hatchFactor - 2.0; o.hatchWeights1.x = 1.0 - o.hatchWeights0.z; } else if (hatchFactor > 1.0) { o.hatchWeights1.x = hatchFactor - 1.0; o.hatchWeights1.y = 1.0 - o.hatchWeights1.x; } else { o.hatchWeights1.y = hatchFactor; o.hatchWeights1.z = 1.0 - o.hatchWeights1.y; } o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; TRANSFER_SHADOW(o); return o; } fixed4 frag(v2f i) : SV_Target { fixed4 hatchTex0 = tex2D(_Hatch0, i.uv) * i.hatchWeights0.x; fixed4 hatchTex1 = tex2D(_Hatch1, i.uv) * i.hatchWeights0.y; fixed4 hatchTex2 = tex2D(_Hatch2, i.uv) * i.hatchWeights0.z; fixed4 hatchTex3 = tex2D(_Hatch3, i.uv) * i.hatchWeights1.x; fixed4 hatchTex4 = tex2D(_Hatch4, i.uv) * i.hatchWeights1.y; fixed4 hatchTex5 = tex2D(_Hatch5, i.uv) * i.hatchWeights1.z; // 全白和最浅的纹理混合。 fixed4 whiteColor = fixed4(1, 1, 1, 1) * (1 - i.hatchWeights0.x - i.hatchWeights0.y - i.hatchWeights0.z - i.hatchWeights1.x - i.hatchWeights1.y - i.hatchWeights1.z); fixed4 hatchColor = hatchTex0 + hatchTex1 + hatchTex2 + hatchTex3 + hatchTex4 + hatchTex5 + whiteColor; UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos); return fixed4(hatchColor.rgb * _Color.rgb * atten, 1.0); } ENDCG } } FallBack "Diffuse" }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。