Shaderで波紋



uGUIのImageに、マウスの位置に波紋を表示してみる。
まず、波紋の式はこちら。

単位の波紋に対してスケール用の式を掛け合わせる。(半球をかぶせる感じ)


(なぜか角っこがジャギる…)

それぞれに式を掛け合わせ、時間経過で角度を動かすとこんな感じ。

このMacの標準で入っているグラフ生成ツール「Grapher」で作ったものを理想として、実装してみる。

ちなみに、googleでも検索ワードに式を入れると図形が表示される。(↓画像クリックで飛びます)

Grapherのように変数を宣言させて、それを動かしてアニメーションみたいなことはできないっぽい。

Shaderの方は前回同様uGUIのImageのShaderを導入。

_TouchX, _TouchY, _Speed, _Heightは外部から変えられるようにしてuGUI ImageのShaderのfragmentシェーダー部分を変更。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
fixed4 frag(v2f IN) : SV_Target
{
    float2 gap = IN.worldPosition - float2(_TouchX, _TouchY);
 
    float moveX = 0;
    float moveY = 0;
    float len = length(gap);
    float brightGap = 0;
 
    if (len <= _EffectRadius) {
        float p = sqrt(pow(_EffectRadius, 2) - pow(gap.x, 2) - pow(gap.y, 2));
        moveX = p * _Height * 0.0002 * (cos((len - _Time.w * _Speed) * 0.2));
        moveY = moveY;
    }
 
    float2 move = float2(-moveX, -moveY);
 
    half4 color = (tex2D(_MainTex, IN.texcoord + move + _TextureSampleAdd)) * IN.color;
 
    color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
 
    #ifdef UNITY_UI_ALPHACLIP
    clip (color.a - 0.001);
    #endif
 
    return color;
}

うまくいっているような、いないような… 陰影がなくわかりずらいので適当にmoveXとmoveYの合計値(外側への移動を明るく、内側への移動を暗く)して、角度を45度に回し、調整した数値を明るさとして足す。(これでいいのかな…?)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
fixed4 frag(v2f IN) : SV_Target
{
    float2 gap = IN.worldPosition - float2(_TouchX, _TouchY);
 
    float moveX = 0;
    float moveY = 0;
    float len = length(gap);
    float brightGap = 0;
 
    if (len <= _EffectRadius) {
        float p = (-1.0/_EffectRadius * pow(len, 2) + _EffectRadius);
        float p = sqrt(pow(_EffectRadius, 2) - pow(gap.x, 2) - pow(gap.y, 2));
        moveX = p * _Height * 0.0002 * (cos((len - _Time.w * _Speed) * 0.2));
        moveY = moveY;
 
        brightGap = _Height * 20 * (moveX + moveY) * cos(45); // 追加
    }
 
    float2 move = float2(-moveX, -moveY);
 
    half4 color = (tex2D(_MainTex, IN.texcoord + move + _TextureSampleAdd)) * IN.color;
 
    color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
    color.rgb += brightGap; // 追加
 
    #ifdef UNITY_UI_ALPHACLIP
    clip (color.a - 0.001);
    #endif
 
    return color;
}

そうすると

波紋っぽくなった!
Grapher便利!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です