フレネル&セルによるアニメ調シェーダー


影はセル、ハイライトはフレネルで表現することを目的としたShaderです。

光の方向はDirectional Lightに依存しますが、ハイライトと影の濃さはマテリアルで操作します。

ShadowPower 影の強さ
ShadowCutOff セル影の範囲
ShadowOpacity 影の濃さ

FresnelColor フレネルの色
FresnelPower フレネルの強さ
FresnelOpacity フレネルの濃さ

CelLikeShader
Shader "Anime/CelLikeShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}

        _ShadowPower("Shodow Power",Range(0.0,1.0))=0.1
        _ShadowCutOff("Shadow CutOff",Range(0.0,1.0))=0.25
        _ShadowOpacity("Shadow Opacity",Range(0.0,1.0))=0.5

        [Space]
    _FresnelColor("FresnelColor", Color) = (1,1,1,1)
    _FresnelPower("FresnelPower", Range(1, 20)) = 2
    _FresnelOpacity("FresnelOpacity"     , Range(0, 1)) = 1

    }
    SubShader
    {

        LOD 100
        Pass
        {
        Tags { "LightMode"="ForwardBase"}

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "UnityLightingCommon.cginc" 
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;

                float3 viewDir : TEXCOORD1;
                float3 lightDir : TEXCOORD2;
                float3 normal : TEXCOORD3;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            half _ShadowPower;
            half _ShadowCutOff;
            half _ShadowOpacity;

            half4 _FresnelColor;
            half _FresnelPower;
            half _FresnelOpacity;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);

                o.viewDir = normalize(UnityWorldSpaceViewDir(v.vertex.xyz));
                o.lightDir = normalize(UnityWorldSpaceLightDir(v.vertex.xyz));
                o.normal = UnityObjectToWorldNormal(v.normal);

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);

                half vdotn = max(0,dot(i.normal, i.viewDir));
                half ldotn = max(0,dot(i.normal, i.lightDir));

                //影部分
                half shadow=pow(vdotn,_ShadowPower)*pow(ldotn,_ShadowPower);
                shadow=saturate(step(_ShadowCutOff,shadow)+(1-_ShadowOpacity));

                col=lerp(col,col*col*shadow,1-shadow);

                //フレネル部分
                half4 fresnel =_FresnelColor* pow((1.0 - vdotn) * 0.5 + 0.5, _FresnelPower);
                col.r=lerp(col.r,min(1,col.r+fresnel.r),_FresnelOpacity);
                col.g=lerp(col.g,min(1,col.g+fresnel.g),_FresnelOpacity);
                col.b=lerp(col.b,min(1,col.b+fresnel.b),_FresnelOpacity);

                return col;
            }
            ENDCG
        }
    }
}