-->

【Unity Shader】UI溶解シェーダー

【Unity Shader】UI溶解シェーダー
 ※コードが古くなっていたのでURP用にコードを改修しました。(2026/08/21) 


前回 ドット欠けシェーダーを作った際に、ランダムノイズという関数について学習しました。
この関数をパーリンノイズという複雑な関数に入れ替えてみた所、画像が溶け出すような、世間で言うDissolve Shaderが簡単に作れました。

今回は こちらの記事と こちらの記事を参考しにしています。パーリンノイズの関数内で何が行われてるかは正直理解してないです。

たぶんパーリンノイズの中身が理解できれば、消えていく画像の周辺を赤くして燃焼シェーダーみたいなのが作れそうではあります。
いつか作ってみたい。

溶解シェーダーの概要

下は溶解シェーダーのサンプル動画です。
DissolvePowの値を上げていくと徐々にドット欠けの範囲が広がっていき、最終的に消滅します。

溶解シェーダーのコード全文

以下シェーダーのコード全文です。
.shader拡張子であればファイル名は何でもいいですが、とりあえず
 Dissolve.shader 
というファイルを作り、中身を全てコピペしてください。
Copy Code

Shader "UI/Dissolve"
{
    Properties
    {
        [HideInInspector]_MainTex("-",2D)="white"{}
        _DissolvePow ("DissolvePow", Range(0.0, 1.0)) = 0 //溶けていく力、1で完全に消滅する
        _Spot ("Spot", Range(1, 50)) = 10 //溶けていく際の穴の数
        _Roughness ("Roughness", Range(1, 20.0)) = 1 //欠けていくドットの粗さ
    }

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

        Pass
        {
            HLSLPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

                struct Attributes
                {
                    half2 uv : TEXCOORD0;
                    float4 positionOS : POSITION;
                    half4 color : COLOR;
                };

                struct Varyings
                {
                    half2 uv : TEXCOORD0;
                    float4 positionCS : SV_POSITION;
                    half4 color : COLOR;

                    //画像の縦横比、nointerpolationで線形補完を禁止
                    nointerpolation half2 ratio : TEXCOORD3;
                };

                //uGUI Image > Source Imageにアタッチされた画像を参照する
                TEXTURE2D(_MainTex);
                SAMPLER(sampler_MainTex);

                //SRP Batcherを適用
                CBUFFER_START(UnityPerMaterial)
                    //Propertiesに対応する変数
                    float _DissolvePow;
                    float _Spot;
                    float _Roughness;
                CBUFFER_END

                //ランダムノイズ(粗いノイズ、0~1の値がランダムに広がる)
                float random (half2 st)
                {
                    return frac(sin(dot(st.xy, float2(12.9898, 78.233))) * 43758.5453);
                }

                //パーリンノイズ(隣接する値が少しずつ異なる滑かなノイズ、ランダムノイズを参照する)
                float perlinNoise(half2 st)
                {
                    half2 p = floor(st);
                    half2 f = frac(st);
                    half2 u = f * f * (3.0 - 2.0 * f);

                    float v00 = random(p + half2(0, 0));
                    float v10 = random(p + half2(1, 0));
                    float v01 = random(p + half2(0, 1));
                    float v11 = random(p + half2(1, 1));

                    return lerp(lerp(dot(v00, f - half2(0, 0)), dot(v10, f - half2(1, 0)), u.x),
                        lerp(dot(v01, f - half2(0, 1)), dot(v11, f - half2(1, 1)), u.x),
                        u.y) + 0.5f;
                }

                //頂点シェーダー
                Varyings vert (Attributes input)
                {
                    Varyings output;

                    output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
                    output.uv = input.uv;
                    output.color = input.color;

                    //RectTransformのWidthのHeightの設定値を参照し、Imageの縦横比をratioに保存
                    float2 sizeDelta = abs(input.positionOS.xy) * 2.0;
                    output.ratio = sizeDelta.x / sizeDelta.y;

                    return output;
                }

                //ピクセルシェーダー
                half4 frag (Varyings input) : SV_Target
                {
                    half4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv);
                    col *= input.color;

                    //_Roughnessの入力値を実際に使う値まで細かくする
                    half fixRough = _Roughness * 0.001f;

                    //対象ピクセルのx座標とy座標を保存、ただしfixRoughの値に応じて座標の取得が大雑把になる
                    //またy座標にはratioを追加で掛けることで、座標を大雑把にした時の値に補正を乗せて欠けるドットを正方形に修正する
                    half roughX = floor(input.uv.x / fixRough) * fixRough;
                    half roughY = floor(input.uv.y / (fixRough * input.ratio)) * (fixRough * input.ratio);
                    half2 roughUv = half2(roughX, roughY);

                    //パーリンノイズにより、指定座標に対し(ほぼ)0~1のランダムな値が返ってくる
                    half rdm = perlinNoise(roughUv * _Spot);
                    //パーリンノイズから_DisolvePowを引き、その値が-0.1未満になった時対象ドットを消滅させる
                    half doVanish = step(0, rdm - _DissolvePow);
                    col.a = col.a * doVanish;

                    return col;
                }
            ENDHLSL
        }
    }
}
シェーダーファイルを作成したら、次にMaterialを新規作成し、Shaderの欄に
 UI/Dissolve 
を指定します。

この辺りの紐づけの仕様についてはこちらでも解説してあります。 p.63 : 【Unity Shader 基礎】Imageにシェーダーを反映させる方法

プロパティを解説

用意してあるプロパティは3つです。
溶解シェーダーのプロパティ
 DissolvePow 
: 溶けていく力。0から1まで設定可能で、0で全て表示、1で全てのピクセルが消える。
 Spot 
: 溶けていく際の穴の数、大きいほど穴の数が爆発的に増えていく。
 Roughness 
: DissolvePowを上げていく際の、欠けていくドットの粗さ。1から20まで設定可能。
Roughnessの値は大きくしすぎるとDissolveの良さが失われるので、最大値が少し抑え目にしてあります。
1
1