Appearance
【Shader练习-米拉】
二次元角色渲染效果实现。
效果拆分演示:
MiLaShader.shader
shader
Shader "VP666/MiLaShader"
{
Properties
{
[NoScaleOffset]
_MainTex ("Texture", 2D) = "white" {}
[Header(Metal)]
_MetalMask ("Metal Mask", 2D) = "black" {}
_Gloss ("Gloss", Range(0, 1)) = 0.8
[Header(Rim)]
_RimColor ("Rim Color", Color) = (1,1,1,1)
_RimPower ("Rim Power", Range(0, 20)) = 10
_RimIntensity ("Rim Intensity", Range(0, 1)) = 0.5
[Header(Outline)]
_OutlineColor ("Outline Color", Color) = (0,0,0,1)
_OutlineWidth ("Outline Width", Range(0, 0.1)) = 0.001
}
SubShader
{
Tags { "RenderType"="Opaque" }
// Outline Pass
Pass
{
Name "OUTLINE"
Tags { "LightMode" = "Always" }
Cull Front
ZWrite On
ColorMask RGB
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
};
float _OutlineWidth;
fixed4 _OutlineColor;
v2f vert(appdata v)
{
v2f o;
float3 normal = normalize(v.normal);
float3 outlineOffset = normal * _OutlineWidth;
float3 pos = v.vertex + outlineOffset;
o.pos = UnityObjectToClipPos(float4(pos, 1.0));
return o;
}
fixed4 frag(v2f i) : SV_Target
{
return _OutlineColor;
}
ENDCG
}
// Main Pass
Pass
{
Name "FORWARD"
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
#pragma multi_compile_fwdbase_fullshadows
#pragma target 3.0
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
float3 normal : TEXCOORD1;
float3 worldPos : TEXCOORD2;
LIGHTING_COORDS(3,4)
};
sampler2D _MainTex;
sampler2D _MetalMask;
float _Gloss;
float4 _RimColor;
float _RimPower;
float _RimIntensity;
half toondiffuse(float3 normal, float3 lightDir)
{
float d = max(0.,dot(normal,lightDir));
// return step(0.5,d);//硬过度
return smoothstep(0.48,0.52,d);//软过度
}
v2f vert (appdata v)
{
v2f o = (v2f)0;
o.pos = UnityObjectToClipPos(v.vertex);
o.normal = UnityObjectToWorldNormal(v.normal);
o.uv = v.uv;
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// 主纹理
fixed4 baseDiffuseColor = tex2D(_MainTex, i.uv);
// 环境光和主纹理颜色
fixed4 ambientColor = UNITY_LIGHTMODEL_AMBIENT * baseDiffuseColor;
// 直接光与主纹理颜色
fixed4 lightColor = _LightColor0 * baseDiffuseColor;
// 兰伯特光照模型遮罩
float3 normalWS = normalize(i.normal);
half diffuseMask = toondiffuse(normalWS, _WorldSpaceLightPos0.xyz);
fixed4 diffuseColor = lerp(ambientColor,lightColor,diffuseMask);
// 阴影
fixed shadow = LIGHT_ATTENUATION(i);
diffuseColor = diffuseColor * shadow;
// 像素位置指向摄像机的方向
float3 viewDirWS = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
// 高光
float3 halfDirWS = normalize(_WorldSpaceLightPos0.xyz + viewDirWS);
float ndoth = max(0.0,dot(normalWS,halfDirWS));
float metal = tex2D(_MetalMask, i.uv).r;
float specularExponent = exp2(_Gloss * 11) + 2;
float specular = pow(max(0.0, ndoth), specularExponent) * _Gloss;
float highlight = specular * metal;// 高光遮罩
fixed4 specularColor = _LightColor0.rgba * highlight;
diffuseColor = diffuseColor + specularColor;
// 边缘光
half rim = 1.0 - saturate(dot(i.normal, viewDirWS));
half4 rimColor = (_RimColor * pow(rim, _RimPower)) * _RimIntensity;
return diffuseColor + rimColor;
}
ENDCG
}
}
FallBack "Diffuse"
}