【Unity-Shader】#07 直線を描く

今回は、線をフラグメントシェーダで描画します。「スキャンライン」というらしい。

線を描く

f:id:snoopopo:20200904083731p:plain

fixed4 frag(v2f i) : SV_Target
{
    return step(0.3, i.uv.y) * step(i.uv.y, 0.4);
}

step

step(閾値, x)

xが閾値以上なら1, 閾値未満なら0 を返す。


上記の例は、UV座標のY座標が0.3~0.4 の位置にあるときに1を返すので、1=白が表示されている。

sin波を使って複数線を描く

fixed4 frag(v2f i) : SV_Target
{
    return sin(i.uv.y * 50);
}

複数線を書くために 0→1→0→1→0・・・ となる値が必要なので、今回はsin波を使います。

f:id:snoopopo:20200904092449p:plain

sin でウェーブさせた値をそのまま色として出力すると、上記のようになり、0(黒)→1(白)→0(黒)→1(白)→0(黒)・・・ を繰り返していることがわかる。

sinでだした値はゆるやかに0から1をいききした値になっている 0→0.1→0.2→…→0.9→0.8…→1
のでぼやけた線みたいな表示になっている。

ここでstepを使い、閾値を元に0か1だけの値にしてはっきりした直線にする。

f:id:snoopopo:20200904093414p:plain

fixed4 frag(v2f i) : SV_Target
{
    return step(0.3, sin(i.uv.y * 50));
}

線を動かす

fixed4 frag(v2f i) : SV_Target
{
    return step(0.3, sin((i.uv.y - _Time.y * 0.2) * 50));
}

_Timeを使ってUV座標のyを下に時間経過で移動させて線が動いているようにみせる。

f:id:snoopopo:20200904094136g:plain

画像と組み合わせたり…

f:id:snoopopo:20200904095920g:plain

白と黒の線が引けたところで、画像の表示と組み合わせてみるとちょっとゲームで使えそうになってきました。

fixed4 frag(v2f i) : SV_Target
{
    fixed4 color = tex2D(_MainTex, i.uv);
    if (color.a <= 0) {
        discard;
    }

    return (1 - step(0.8, sin((i.uv.y - _Time.y * 0.2) * 50))) * color;
}

画像の色と乗算しているため、 黒(0)は黒いまま、白(1)はx1となるので画像の色がそのまま表示されます。


f:id:snoopopo:20200904100915g:plain

fixed4 frag(v2f i) : SV_Target
{
    fixed4 color = tex2D(_MainTex, i.uv);
    color *= (1 - step(0.8, sin((i.uv.y - _Time.y * 0.2) * 50)));
    if (color.a <= 0) {
        discard;
    }

    return color;
}

黒い線の部分は破棄 discard しちゃうのもよさげだ…