-100p

-10p

+10p

+100p

Unity発光シェーダー

Unity uGUI用、発光シェーダー。UIをぼやっと光らせる処理。
(Bloom Shader for Unity uGUI)

関連ページ
UIに対する発光シェーダーを探してたものの、精度が低かったり結局PostProcessに頼ってるのしかなくて満足いかなかった。
で、BlurシェーダーとDoubleColorシェーダーを組み合わせれば自分でも作れるのではと試行錯誤してたら結構良いのが作れた。
実装方法もとてもシンプルになっている。

このシェーダーと シルエットシェーダー を組み合わせて、 発光シルエットシェーダー というマニアックな物も作ってる。そちらも併せてどうぞ。
光らせるという意味では、似たカテゴリで 虹色シェーダー もおすすめ。

発光シェーダー、コード全文

下が今回のシェーダーのサンプル動画。


下がコード全文。uGUI Imageへの反映方法は こちらの記事 参照。
Shader"UI/SimpleBloom"
{
    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
    }

    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;

        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;

                return col;
            }

            ENDCG
        }

        Pass
        {
            CGPROGRAM

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

                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;
                return col;
            }

            ENDCG
        }
    }
}

少し解説

最初のPassが画像を上下左右にぶれさせて重ねる、いわゆるBlurシェーダー。
これによってアウトラインが少し拡張される。
            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);
アウトラインは指定した画像の外までは伸びないので、あらかじめ周囲に透明部分のマージンを作った画像を用意。
また画像素材のMesh TypeはFull Rectに設定する。
MeshType変更のサンプル画像

2つめのPassがRGBの値をそれぞれ倍にして疑似的に光ってるように見せる、いわゆるDoubleColorシェーダー。
        Pass
        {
            CGPROGRAM

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

                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;
                return col;
            }

            ENDCG
        }

Inspectorのプロパティ値の意味は下の通り。
発光シェーダーのプロパティ
 Luminance 
: どの位光らせるかの値
 Blur Color 
: 拡張したアウトラインの色の設定
 Blur Distance 
: アウトラインをどこまで伸ばすかの値。初期値からいじらない方がいいかも
 Blur Power 
: 拡張したアウトラインのα値の強さ。初期値からいじらない方がいいかも
1
1

-100p

-10p

+10p

+100p