ささみ雑記帳

少し長くなりそうな色々を書き留めておくためのノート。

ノイズでグラデーション着色するシェーダーをつくる

ノイズを勉強した話の応用で、ノイズで着色して色々つくってみます。
前回の記事 sasanon.hatenablog.jp

ノイズの白黒に別の2色を割り当ててグラデーションする

このノイズを表示するだけシェーダーを元に、白黒に別の色を割り当てられるようにします。
変更点はあまりなくて、_BaseColor と _GradationColor パラメータを加えて、

    Properties
    {
        _NoiseTilingOffset ("NoiseTex Tiling(x,y)/Offset(z,w)", Vector) = (0.1,0.1,0,0)
        _NoiseSizeScroll   ("NoiseTex Size(x,y)/Scroll(z,w)"  , Vector) = (16,16,0,0)
        _BaseColor         ("Base Color"     , Color ) = (1,1,1,1)
        _GradationColor    ("Gradation Color", Color ) = (0,0,0,1)
    }

色をlerp(線形補間)します。

            fixed4 frag (v2f i) : SV_Target
            {
                fixed p = perlinNoise(i.uv, _NoiseSizeScroll.xy);
                //return fixed4 ( p, p, p, 1 );   // 白黒のノイズ画像を生成
                return lerp( _GradationColor, _BaseColor, p );   // 任意の2色のノイズ画像を生成
            }

白黒の入力値を別の色に置き換える考え方は、肉シェーダーのときもやっていましたね。
sasanon.hatenablog.jp

ノイズグラデーションで空を表現する

PhotoShop的にはパーリンノイズは雲模様フィルタなので、もちろん雲のある空が表現できます。
そしてノイズ周りでUVスクロールできるようにしたので、動きます。
f:id:sasanon:20181022034820g:plain

ノイズグラデーションのTilingを調節して板や髪のテクスチャを表現する

Tilingは1未満の範囲では、拡大縮小のような使い方ができます。
この拡大率をうまく変えると、色々と表現の幅が広がります。
例えば、(0.1, 0.02)くらい(UV比5:1)で色をうまく設定すると、板のようなテクスチャ感になりますが、
f:id:sasanon:20181022035633p:plain
(1.0, 0.05)くらい(UV比20:1)で色も変えると、キャラの髪に使えそうなテクスチャになります。
f:id:sasanon:20181022035657p:plain
(調整する手腕が問われる…ッ)

ノイズグラデーションで風を表現する

シェーダーをもう少し拡張すると、風のような筋も表現できます。
まず、透過色が使えるように設定を変更。

        Tags { "RenderType"="Transparent" }
        LOD 100
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

この時点で、透過色が使えるようになります。
f:id:sasanon:20181022050859g:plain
…これだと風というより吹雪っぽい(逆に吹雪表現には使えるかもしれません)。
なので、テクスチャを指定して表示範囲を絞れるようにしてみます。
Unlitシェーダーにある_MainTex周りを復活させて、vertexシェーダーから受け渡すUVを拡張します。
今回は(別名の変数に分けるのが面倒なので)xyにメインテクスチャ、zwにノイズテクスチャのUVを格納してみました。

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float4 uv : TEXCOORD0;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv.xy = TRANSFORM_TEX(v.uv, _MainTex);
                o.uv.zw = TRANSFORM_NOISE_TEX(v.uv, _NoiseTilingOffset, _NoiseSizeScroll);
                return o;
            }

fragmentシェーダーでは、メインテクスチャとノイズテクスチャの色を乗算でブレンドします。

            fixed4 frag (v2f i) : SV_Target
            {
                fixed p = perlinNoise(i.uv.zw, _NoiseSizeScroll.xy);
                return lerp( _GradationColor, _BaseColor, p ) * tex2D(_MainTex, i.uv.xy);
            }

これでテクスチャを指定できるようになりました。
ここに、Unityですぐに使えるDefault-Particleテクスチャを指定してみると、
f:id:sasanon:20181022051238g:plain 表示範囲が絞れて、風エフェクトっぽい表現ができるようになりました。

2色着色する程度だとPhotoShopで実現できる範囲と被るのですが、
UVアニメーションしたり、他テクスチャと合成したり、
単純なものでもシェーダー的な処理が入ると応用範囲が広がります。

ノイズグラデーションのソースコード

同じ階層に、前回記事のSasamiNoise.cgincと一緒に置くことで動くはずです。
gist.github.com