【Unity-Shader】#10 ノイズ画像を使って絵をぶるぶるブレさせる

今回記事は、ノイズ画像を使って絵を歪ませてこんなかんじにぶるぶる横にブレるような動きを作ってみました。

f:id:snoopopo:20200911112829g:plain

▼今回の記事は前回の記事の続きっぽいかも。前回の記事はこちらです。

www.snoopopo.com

用意する画像

【歪ませたい画像】
f:id:snoopopo:20200911112928p:plain

【歪み情報として使うノイズ画像】
f:id:snoopopo:20200911112935p:plain

ノイズ画像自体もプログラムで作成することができますが、今回はその工程はすっ飛ばして既存の画像をつかいます。
このような画像のノイズのことを「パーリンノイズ(PerlinNoise)」または「GradientNoise」というらしい。

↓画像引用元、およびノイズ画像の作り方が書いてあるUnityのリファレンス。
Mathf-PerlinNoise - Unity スクリプトリファレンス

shader全文

Shader "Custom/NoiseDistortion"
{
    Properties
    {
        _MainTex("MainTexture", 2D) = "white" {}
        _NoiseTex("NoiseTexture", 2D) = "white" {}
    }

    SubShader
    {
        Cull Off

        Tags
        {
            "Queue" = "AlphaTest"
            "RenderType" = "AlphaTest"
        }

        Pass
        {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD;
            };

            sampler2D _MainTex;
            sampler2D _NoiseTex;

            float _Border;
            float4 _Color;

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

            fixed4 frag(v2f i) : SV_Target
            {
                fixed2 noiseUv = fixed2(i.uv.x + cos(_Time.y * 0.5), i.uv.y);
                fixed4 noiseColor = tex2D(_NoiseTex, noiseUv) * 0.05;

                i.uv.x += noiseColor.r;
                fixed4 color = tex2D(_MainTex, i.uv);

                if (color.a <= 0) {
                    discard;
                }

                return color;
            }

            ENDCG
        }
    }
}

今回も、フラグメントシェーダのみです。

前回の記事で、画像を歪ませるにはUV座標をずらせばよいことがわかりました。 今回は横ブレさせたいので、UV座標のX座標に手を加えることになりますが、これにノイズ画像を使います。

ノイズ画像は白黒の画像なので、色の範囲は(0,0,0)~(1,1,1)になっています。 この0~1の値をUV座標に加算することでUV座標をずらしこのような処理を実現しています。

解説

ノイズ画像をスクロールさせる

まずはじめにノイズ画像をUVスクロールさせます。
なんでかというと、さきほどノイズ画像の色0~1を使うと書いたが、この値は動かさないと変動しないからです。

fixed4 frag(v2f i) : SV_Target
{
    fixed2 noiseUv = fixed2(i.uv.x + cos(_Time.y * 0.5), i.uv.y);
    fixed4 noiseColor = tex2D(_NoiseTex, noiseUv);

    return noiseColor;
}

f:id:snoopopo:20200911115821g:plain

cosを使って移動速度を滑らかにしていますが、時間経過で変わるなら _Time だけでもOK。


ノイズ画像の色をUV座標に使う

ノイズ画像をUVスクロールさせているので、noiseColorの色はノイズ画像の0~1の間の変動値となっています。
それを歪ませたい画像のUV座標に使います。

今回は横ゆれだけさせたいので、
UV座標のX座標の値にノイズ画像から取得した値noiseColorの値を入れています。
noiseColor.r を加算しているけどgでもbでもいい。なぜなら白黒画像なのでrgbの値はすべて同じのはずだから)

fixed4 frag(v2f i) : SV_Target
{
    fixed2 noiseUv = fixed2(i.uv.x + cos(_Time.y * 0.5), i.uv.y);
    fixed4 noiseColor = tex2D(_NoiseTex, noiseUv) * 0.05;

    i.uv.x += noiseColor.r;
    fixed4 color = tex2D(_MainTex, i.uv);

    if (color.a <= 0) {
        discard;
    }

    return color;
}

先程のノイズ画像をスクロールしたコードと違ってnoiseColorに* 0.05かけているのは、
0~1の値を単純に加算するとブレ幅が大きいから微調整しただけです。

参考にさせて頂きました☆

qiita.com