【Unity】ShaderLab でスケッチはじめました

はじめに

ShaderToy とか見てるとすごい(小並感)な作品がたくさんありますよね!
Shadertoy BETA

ここまではいかなくても、ちょっと自分の作品の演出でカッコいいこと出来るようになりたいので、いろんなテクニックについてじゃぶじゃぶインプット(&ぼちぼちアウトプット)しています。

ShaderLab のスケッチ置き場
GitHub - setchi/Unity-ShaderSketches: Self learning shader in Unity3D

GPGPUの習作置き場
GitHub - setchi/Unity-GPGPU-Sandbox: Self learning GPGPU in Unity3D


setchi.hatenablog.com


この記事では最近取り組んでいる ShaderLab でのスケッチについて紹介します。

Transform

まずは基礎からということで、基本的な座標変換を ShaderLab 上で実装してみました。
物体を移動・変形・回転させるには、行列を使うと便利です。行列とベクトルを掛けると色々な座標変換が実現できます。

行列とベクトルを掛けて座標変換していくイメージは、こちらの動画(2分あたりからの座標変換の説明)が分かり易かったです。クォータ二オンも学べます!!

【Unity道場 博多スペシャル 2017】クォータニオン完全マスター - YouTubewww.youtube.com

平行移動

 \begin{equation}
\begin{bmatrix}
1 & 0 & t_{x} \\
0 & 1 & t_{y} \\
0 & 0 & 1 \\
\end{bmatrix}
\begin{bmatrix}
x  \\
y  \\
1
\end{bmatrix}
=
\begin{bmatrix}
x + t_{x}  \\
y + t_{y}  \\
1
\end{bmatrix}
\end{equation}

float3x3 translate(float x, float y)
{
    return float3x3(1, 0, x,
                    0, 1, y,
                    0, 0, 1);
}

float4 frag(v2f_img i) : SV_Target
{
    float2 st = i.uv;
    float t = _Time.y;
    
    st = mul(translate(sin(t) * 0.35,
                       cos(t) * 0.35),
                float3(st, 1));
    
    return box(st, 0.25);
}

Unity-ShaderSketches/Translate.shader at master · setchi/Unity-ShaderSketches · GitHub
translate 関数で変換行列を作り、座標系を移動させた後に箱を描画することで、動いているように見せています。
f:id:setchi_q:20171222143206g:plain

回転

 \begin{equation}
\begin{bmatrix}
\cos \theta & -\sin \theta & 0 \\
\sin \theta & \cos \theta & 0 \\
0 & 0 & 1 \\
\end{bmatrix}
\begin{bmatrix}
x  \\
y  \\
1
\end{bmatrix}
=
\begin{bmatrix}
x \cos \theta - y \sin \theta  \\
x \sin \theta + y \cos \theta  \\
1
\end{bmatrix}
\end{equation}

float3x3 rotate(float angle)
{
    return float3x3(cos(angle), -sin(angle), 0,
                    sin(angle), cos(angle), 0,
                    0, 0, 1);
}

float4 frag(v2f_img i) : SV_Target
{
    float2 st = i.uv;
    float t = _Time.y;
    
    st -= 0.5;
    st = mul(rotate(sin(t) * PI), float3(st, 1));
    st += 0.5;
    
    return box(st, 0.4);
}

Unity-ShaderSketches/Rotate.shader at master · setchi/Unity-ShaderSketches · GitHub
平行移動と同じく、rotate 関数で回転用の変換行列を作り、先に座標系を回転させてから箱を描画することで回転しているように見せています。
frag 関数内で st -= 0.5 と st += 0.5 しているのは、画面の真ん中を基準に回転させるためです。

f:id:setchi_q:20171222143113g:plain

拡大・縮小

 \begin{equation}
\begin{bmatrix}
S_{x} & 0 & 0 \\
0 & S_{y} & 0 \\
0 & 0 & S_{z} \\
\end{bmatrix}
\begin{bmatrix}
x  \\
y  \\
z
\end{bmatrix}
=
\begin{bmatrix}
S_{x} x \\
S_{y} y \\
S_{z} z \\
\end{bmatrix}
\end{equation}

float3x3 scale(float2 scale)
{
    return float3x3(scale.x, 0, 0,
                    0, scale.y, 0,
                    0, 0, 1);
}

float4 frag(v2f_img i) : SV_Target
{
    float2 st = i.uv;
    float t = _Time.y;
    
    st -= 0.5;
    st = mul(scale(sin(t) + 1), float3(st, 1));
    st += 0.5;
    
    return box(st, 0.2);
}

Unity-ShaderSketches/Scale.shader at master · setchi/Unity-ShaderSketches · GitHub
scale 関数で拡大・縮小用の変換行列を作り、座標系を拡大・縮小してから箱を描画することで動いているように見せています。
frag 関数内で st -= 0.5 と st += 0.5 しているのは、回転と同じく、画面の真ん中を基準に拡大・縮小させるためです。

f:id:setchi_q:20171222152259g:plain

Distance Field

次に学んだのは Distance Field を使った絵作りです。
Distance Field とは、ざっくり言うとある場所からの距離で空間を解釈し直す手法です。一部では文字の描画などにも使われています。

Distance Field に基づくノイズアルゴリズムに Cell Noise というものがあります。

Cell Noise

f:id:setchi_q:20171221230302g:plain
Cell Noise は、フィールド上の複数の点の中から最も近い点への距離を色で表したノイズです。
黒い部分の中心に点があると思ってください。その点に近いピクセルほど色が暗く、遠いピクセルほど色が明るくなっています。

Cell Noise を素直に ShaderLab で実装してアニメーションさせてみました。
Unity-ShaderSketches/CellNoise.shader at master · setchi/Unity-ShaderSketches · GitHub

Metaballs

f:id:setchi_q:20171222010437g:plain
Cell Noise をベースに違うエフェクトを作ってみました。
距離をどう解釈するかによって様々な模様を作れるのが Distance Field の面白いところのひとつだと思います。コードは Cell Noise とほぼ同じですが、step を使って点からの距離に対して段階的に色を出力しています。
Unity-ShaderSketches/Metaballs.shader at master · setchi/Unity-ShaderSketches · GitHub

Marble

f:id:setchi_q:20171222183219g:plain
こちらも Cell Noise のアレンジです。
動き的に Metaballs とほぼ同じですが、出力部分を smoothstep にして、その結果に対してさらに絞り込みをかけることで、点からの距離に対して輪切り状に色をつけています。
Unity-ShaderSketches/Marble.shader at master · setchi/Unity-ShaderSketches · GitHub

最後に

シェーダで絵を作るテクニックについての良さげな資料があったら教えてください!

作ったものはこちらに随時追加していきます。
github.com