https://www.freesion.com/article/20771238845/
核心的算法通过多个pass,从里到外一层一层的糊上一层透明diffuse,越靠外面的地方层次越少看起来越稀疏,越模糊
FurHelper.cginc
struct v2f { float4 pos : SV_POSITION; half2 uv : TEXCOORD0; half2 uv1 : TEXCOORD1; fixed4 diff : COLOR; }; float _FurLength; sampler2D _MainTex; float4 _MainTex_ST; sampler2D _FurTex; float4 _FurTex_ST; float _Blur; v2f vert(appdata_base v) { v2f o; v.vertex.xyz += v.normal * _FurLength * FURSTEP; o.pos = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); o.uv1 = TRANSFORM_TEX(v.texcoord, _FurTex); float3 worldNormal = normalize(mul(v.normal, (float3x3) unity_WorldToObject)); o.diff = LambertDiffuse(worldNormal); o.diff.a = 1 - (FURSTEP * FURSTEP); float4 worldPos = mul(unity_ObjectToWorld ,v.vertex); o.diff.a += dot(normalize(_WorldSpaceCameraPos.xyz- v.vertex), worldNormal) - _Blur; return o; } float _CutOff; float _Thickness; fixed4 frag(v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); fixed alpha = tex2D(_FurTex, i.uv1).r; col *= i.diff; col.a *= step(lerp(_CutOff, _CutOff + _Thickness, FURSTEP), alpha); return col; }
FurShader.shader
Shader "Custom/FurShader" { Properties { _MainTex("Texture", 2D) = "white" {} _FurTex("Fur pattern", 2D) = "white" {} _Diffuse("Diffuse value", Range(0, 3)) = 1 _FurLength("Fur length", Range(0.0, 1)) = 0.5 _CutOff("Alpha cutoff", Range(0, 1)) = 0.5 _Blur("Blur", Range(0, 1)) = 0.5 _Thickness("Thickness", Range(0, 0.5)) = 0 } CGINCLUDE fixed _Diffuse; inline fixed4 LambertDiffuse(float3 worldNormal) { float3 lightDir = normalize(_WorldSpaceLightPos0.xyz); float NdotL = max(0.2, dot(worldNormal, lightDir)); return NdotL* _Diffuse; } ENDCG SubShader { Tags{ "RenderType" = "Transparent" "Queue" = "Transparent" "LightMode" = "ForwardBase" } ZWrite Off Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.05 #include "FurHelper.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.10 #include "FurHelper.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.15 #include "FurHelper.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.20 #include "FurHelper.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.25 #include "FurHelper.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.30 #include "FurHelper.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.35 #include "FurHelper.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.40 #include "FurHelper.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.45 #include "FurHelper.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.50 #include "FurHelper.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.55 #include "FurHelper.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.60 #include "FurHelper.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.65 #include "FurHelper.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.70 #include "FurHelper.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.75 #include "FurHelper.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.80 #include "FurHelper.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.85 #include "FurHelper.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.90 #include "FurHelper.cginc" ENDCG } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #define FURSTEP 0.95 #include "FurHelper.cginc" ENDCG } } }