【UnityShader】お絵かきシェーダー【1】 #53
前回の成果
Imageのアウトラインの数を指定した。
今回やること
表現の幅を増やすためにお絵かきシェーダーを学んでいきます。
事前準備
Scene上にQuadを配置します。
ソースコード
Shader "Unlit/Drawing_1" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { return float4(i.uv.x, i.uv.y, 0, 1); } ENDCG } } }
フラグメントシェーダーを変更して表現していきます。
UV値に合わせた色を出す
fixed4 frag (v2f i) : SV_Target { return float4(i.uv.x, i.uv.y, 0, 1); }
UVの座標に応じて色を変化させています。
UV値は左下が(0, 0)、右下が(1, 1)となっているので以下のような結果となります。
UV値のイメージ
結果
ディスタンスフィールド
ディスタンスフィールドとは、相手との距離を返す関数のことです。
これを使用し、異なる表現をしていきます。
distance
Unityのシェーダーでは、distance関数があるのでそれを使用します。
// xとyとの距離をfloatで返す関数
distance(x, y)
フラグメントシェーダーを以下のように書き換えます。
fixed4 frag (v2f i) : SV_Target { float4 col = distance(float2(0.5, 0.5), i.uv); return col; }
UVの単元でも説明しましたが、UV値は左下が(0, 0)、右下が(1, 1)となっています。
ですので(0.5, 0.5)は中央となり、中央との距離を求めています。
結果
step
次に、アルファ値を0と1でくっきり分けていきます。
そのためにstep関数を使用します。
// y >= x なら1.0を、x > y なら0.0を返す step(x, y) // 1.0が返ってくる step(0, 1) // 0.0が返ってくる step(0.5, 0.1)
このstep関数を使用し、フラグメントシェーダーを変更します。
fixed4 frag (v2f i) : SV_Target { float4 col = distance(float2(0.5, 0.5), i.uv); col = step(0.4, col); return col; }
距離が0.4までの部分を黒く、それ以上のところは白くすることができます。
結果
また、stepで指定したしきい値をサインカーブを使用することによりアニメーションさせることができます。
fixed4 frag (v2f i) : SV_Target { float4 col = distance(float2(0.5, 0.5), i.uv); col = step(abs(sin(_Time.y)) * 0.4, col); return col; }
結果
複数の円を出す
複数の円を出していきます。
考え方がわかりやすいようにグラフも添付します。
最初にディスタンスフィールドで描画したものが下記になります。
描画したもの
グラフ
ソースコード
fixed4 frag (v2f i) : SV_Target { float4 col = distance(float2(0.5, 0.5), i.uv); return col; }
次に適当に30倍に拡大してみます。
描画したもの
グラフ
ソースコード
fixed4 frag (v2f i) : SV_Target { float4 col = distance(float2(0.5, 0.5), i.uv) * 30; return col; }
次にサインカーブをして、その絶対値を取ります。
このようにすることにより、繰り返しとなり円が複数描画されます。
描画したもの
グラフ
ソースコード
fixed4 frag (v2f i) : SV_Target { float4 col = distance(float2(0.5, 0.5), i.uv) * 30; col = abs(sin(col)); return col; }
最後にstepを使用してくっきりとさせます。
描画したもの
グラフ
ソースコード
fixed4 frag (v2f i) : SV_Target { float4 col = distance(float2(0.5, 0.5), i.uv) * 30; col = abs(sin(col)); col = step(0.5, col); return col; }
何か表現したいことがあった場合、段階を踏んで描画結果を把握したりグラフを見たりすると早く実装出来ると思います。
グラフはこちらのサイト様のものを使用させていただきました。
今回は以上となります。
ここまでご視聴ありがとうございました。