-100p

-10p

+10p

+100p

Unity発光シルエットシェーダー

Unityで発光シェーダーとシルエットシェーダーの合わせ技。
(Bloom and Silhouette Shader for Unity uGUI)

関連ページ
自作ゲームでどうしても発光シェーダーとシルエットシェーダー両方を良いとこ取りしたシェーダーが欲しくなった。
作業的には簡単だったので作ってみて、満足いったので共有。

発光シルエットシェーダー、コード全文

このシェーダーを使って作成した演出が次のもの。


下がコード全文。uGUI Imageへの反映方法は こちらの記事 参照。
Shader"UI/BloomSilhouette"
{
    Properties
    {
        _Luminance ("Luminance", Range(0.0, 10.0)) = 0.0
        _BlurColor("Blur Color", Color) = (1.0, 1.0, 1.0, 1.0)
        _BlurDistance("Blur Distance", Range(0.0, 20.0)) = 8
        _BlurPower("Blur Power", Range(0.0, 1.0)) = 0.1

        _SilhouetteBlendRate ("SilhouetteBlendRate", Range(0.0, 1.0)) = 0
        _SilhouetteColor("SilhouetteColor", Color) =  (1.0, 1.0, 1.0, 1.0)
    }

    SubShader
    {
        Tags { "RenderType"="Transparent" "Queue" = "Transparent" }
        Cull Off
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

        CGINCLUDE
        #pragma vertex vert
        #pragma fragment frag

        #include "UnityCG.cginc"

        struct appdata
        {
            fixed2 uv : TEXCOORD0;
            fixed4 color : COLOR;
            fixed4 vertex : POSITION;
        };

        struct v2f
        {
            fixed2 uv : TEXCOORD0;
            fixed4 color : COLOR;
            fixed4 vertex : SV_POSITION;
        };

        sampler2D _MainTex;

        fixed _Luminance;
        fixed3 _BlurColor;
        fixed _BlurDistance;
        fixed _BlurPower;

        fixed _SilhouetteBlendRate;
        fixed3 _SilhouetteColor;

        v2f vert(appdata v)
        {
            v2f o;
            o.uv = v.uv;
            o.color = v.color;
            o.vertex = UnityObjectToClipPos(v.vertex);
            return o;
        }

        ENDCG

        Pass
        {
            CGPROGRAM

            fixed4 blur(fixed2 uv, fixed w, fixed kx, fixed ky)
            {
                fixed2 shiftUv = fixed2(uv.x + kx * _BlurDistance, uv.y + ky * _BlurDistance);
                fixed4 tex = tex2D(_MainTex, shiftUv);

                tex.a = tex.a * w * _BlurPower * _Luminance;
                return tex;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 col = 0;

                 
//x軸 

                col += blur(i.uv, 0.01, 0, -0.0075);
                col += blur(i.uv, 0.02, 0, -0.006);
                col += blur(i.uv, 0.03, 0, -0.0045);
                col += blur(i.uv, 0.04, 0, -0.003);
                col += blur(i.uv, 0.05, 0, -0.002);
                col += blur(i.uv, 0.06, 0, -0.001);
                col += blur(i.uv, 0.06, 0, +0.001);
                col += blur(i.uv, 0.05, 0, +0.002);
                col += blur(i.uv, 0.04, 0, +0.003);
                col += blur(i.uv, 0.03, 0, +0.0045);
                col += blur(i.uv, 0.02, 0, +0.006);
                col += blur(i.uv, 0.01, 0, +0.0075);

                 
//y軸 

                col += blur(i.uv, 0.01, -0.0075, 0);
                col += blur(i.uv, 0.02, -0.006, 0);
                col += blur(i.uv, 0.03, -0.0045, 0);
                col += blur(i.uv, 0.04, -0.003, 0);
                col += blur(i.uv, 0.05, -0.002, 0);
                col += blur(i.uv, 0.06, -0.001, 0);
                col += blur(i.uv, 0.06, +0.001, 0);
                col += blur(i.uv, 0.05, +0.002, 0);
                col += blur(i.uv, 0.04, +0.003, 0);
                col += blur(i.uv, 0.03, +0.0045, 0);
                col += blur(i.uv, 0.02, +0.006, 0);
                col += blur(i.uv, 0.01, +0.0075, 0);

                 
//y軸を大きめに-にズラした上で、x軸を大きめに-から+に描画 

                col += blur(i.uv, 0.01, -0.006, -0.006);
                col += blur(i.uv, 0.02, -0.0045, -0.0045);
                col += blur(i.uv, 0.03, -0.003, -0.003);
                col += blur(i.uv, 0.04, -0.002, -0.002);
                col += blur(i.uv, 0.05, -0.001, -0.001);
                col += blur(i.uv, 0.05, +0.001, -0.001);
                col += blur(i.uv, 0.04, +0.002, -0.002);
                col += blur(i.uv, 0.03, +0.003, -0.003);
                col += blur(i.uv, 0.02, +0.0045, -0.0045);
                col += blur(i.uv, 0.01, +0.006, -0.006);

                 
//y軸を大きめに+にズラした上で、x軸を大きめに-から+に描画 

                col += blur(i.uv, 0.01, -0.006, 0.006);
                col += blur(i.uv, 0.02, -0.0045, 0.0045);
                col += blur(i.uv, 0.03, -0.003, 0.003);
                col += blur(i.uv, 0.04, -0.002, 0.002);
                col += blur(i.uv, 0.05, -0.001, 0.001);
                col += blur(i.uv, 0.05, +0.001, 0.001);
                col += blur(i.uv, 0.04, +0.002, 0.002);
                col += blur(i.uv, 0.03, +0.003, 0.003);
                col += blur(i.uv, 0.02, +0.0045, 0.0045);
                col += blur(i.uv, 0.01, +0.006, 0.006);

                 
//y軸を小さめに-にズラした上で、x軸を大きめに-から+に描画 

                col += blur(i.uv, 0.01, -0.006, -0.003);
                col += blur(i.uv, 0.02, -0.0045, -0.0022);
                col += blur(i.uv, 0.03, -0.003, -0.0015);
                col += blur(i.uv, 0.04, -0.002, -0.001);
                col += blur(i.uv, 0.05, -0.001, -0.0005);
                col += blur(i.uv, 0.05, +0.001, -0.0005);
                col += blur(i.uv, 0.04, +0.002, -0.001);
                col += blur(i.uv, 0.03, +0.003, -0.0015);
                col += blur(i.uv, 0.02, +0.0045, -0.0022);
                col += blur(i.uv, 0.01, +0.006, -0.003);

                 
//y軸を小さめに+にズラした上で、x軸を大きめに-から+に描画 

                col += blur(i.uv, 0.01, -0.006, 0.003);
                col += blur(i.uv, 0.02, -0.0045, 0.0022);
                col += blur(i.uv, 0.03, -0.003, 0.0015);
                col += blur(i.uv, 0.04, -0.002, 0.001);
                col += blur(i.uv, 0.05, -0.001, 0.0005);
                col += blur(i.uv, 0.05, +0.001, 0.0005);
                col += blur(i.uv, 0.04, +0.002, 0.001);
                col += blur(i.uv, 0.03, +0.003, 0.0015);
                col += blur(i.uv, 0.02, -0.0045, 0.0022);
                col += blur(i.uv, 0.01, -0.006, 0.003);

                 
//y軸を大きめに-にズラした上で、x軸を小さめに-から+に描画 

                col += blur(i.uv, 0.01, -0.003, -0.006);
                col += blur(i.uv, 0.02, -0.0022, -0.0045);
                col += blur(i.uv, 0.03, -0.0015, -0.003);
                col += blur(i.uv, 0.04, -0.001, -0.002);
                col += blur(i.uv, 0.05, -0.0005, -0.001);
                col += blur(i.uv, 0.05, +0.0005, -0.001);
                col += blur(i.uv, 0.04, +0.001, -0.002);
                col += blur(i.uv, 0.03, +0.0015, -0.003);
                col += blur(i.uv, 0.02, +0.0022, -0.0045);
                col += blur(i.uv, 0.01, +0.003, -0.006);

                 
//y軸を大きめに+にズラした上で、x軸を小さめに-から+に描画 

                col += blur(i.uv, 0.01, -0.003, 0.006);
                col += blur(i.uv, 0.02, -0.0022, 0.0045);
                col += blur(i.uv, 0.03, -0.0015, 0.003);
                col += blur(i.uv, 0.04, -0.001, 0.002);
                col += blur(i.uv, 0.05, -0.0005, 0.001);
                col += blur(i.uv, 0.05, +0.0005, 0.001);
                col += blur(i.uv, 0.04, +0.001, 0.002);
                col += blur(i.uv, 0.03, +0.0015, 0.003);
                col += blur(i.uv, 0.02, +0.0022, 0.0045);
                col += blur(i.uv, 0.01, +0.003, 0.006);

                col.r = _BlurColor.r;
                col.g = _BlurColor.g;
                col.b = _BlurColor.b;
                col.a = col.a * i.color.a;

                return col;
            }

            ENDCG
        }

        Pass
        {
            CGPROGRAM

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

                
//まずBloomを効かす

                col.r = col.r + ((i.color.r - 0.5) * col.r * _Luminance);
                col.g = col.g + ((i.color.g - 0.5) * col.g * _Luminance);
                col.b = col.b + ((i.color.b - 0.5) * col.b * _Luminance);
                col.a *= i.color.a;

                
//次にSilhouetteを効かす

                col.r = (col.r * (1 - _SilhouetteBlendRate)) + (_SilhouetteColor.r * _SilhouetteBlendRate);
                col.g = (col.g * (1 - _SilhouetteBlendRate)) + (_SilhouetteColor.g * _SilhouetteBlendRate);
                col.b = (col.b * (1 - _SilhouetteBlendRate)) + (_SilhouetteColor.b * _SilhouetteBlendRate);
                
                return col;
            }

            ENDCG
        }
    }
}

少し解説

処理的にはPassを2つ作って、発光シェーダーとシルエットシェーダーの処理を順に実行してるだけ。

プロパティとして外出ししてるパラメータは6つ。
    Properties
    {
        _Luminance ("Luminance", Range(0.0, 10.0)) = 0.0
        _BlurColor("Blur Color", Color) = (1.0, 1.0, 1.0, 1.0)
        _BlurDistance("Blur Distance", Range(0.0, 20.0)) = 8
        _BlurPower("Blur Power", Range(0.0, 1.0)) = 0.1

        _SilhouetteBlendRate ("SilhouetteBlendRate", Range(0.0, 1.0)) = 0
        _SilhouetteColor("SilhouetteColor", Color) =  (1.0, 1.0, 1.0, 1.0)
    }

大雑把に言うとLuminanceが発光度、BlurColorが発光のアウトラインの色。
SilhouetteBlendRateがシルエット率、SilhouetteColorがシルエットの色。
0
0

-100p

-10p

+10p

+100p