今天要做一个毛球的效果
核心的算法通过多个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
}
}
}