シェーダーで絵を描く


# 要約

  • シェーダーでアイコンを描きました。
  • 書き方はいろいろありますが、個人的に一番楽な方法を紹介します。

# はじめに

以前のアイコンに飽きたので、アイコンを描きました。

これはGLSLを書けるTwigl (opens new window)というサイトで作りました。

ソースコードも一応貼っておきます。

ソースコード(Twigl) (opens new window)

シェーダーで絵を描く方法はいろいろありますが、今回私はスマホで書いていたのでコードの速度や長さは気にしない最も楽な方法をとりました。

この記事ではそれを紹介します。
(あくまで私が楽だと思う方法ですので、ご了承ください。)

# 描き方

  1. uvを[-1, 1] x [-1, 1]の範囲にする
  2. 描画の最終的な有無をfloat cで定義する
  3. c += float(ブール演算)で図を追加する

以上です。

# 1. uvを[-1, 1] x [-1, 1]の範囲にする

描きたい図にも寄りますが、基本的には[-1,1]であると嬉しいです。

  • 対称にするときにabsだけで可能
  • 関数グラフとしてとらえやすい
  • [x,y] -> [r,θ]の変換が楽で、変換後の値も扱いやすい

などの嬉しさが考えられます。

# 2. 描画の最終的な有無をfloat cで定義する

後述のブール演算と加算の処理によって、cは0か1以上の値をとります。
この値を用いて「cが0の時」と「cが1以上の時」で処理を分けることが出来ます。

例えば色にするときには

vec3 col=vec3(c);

などとすると、cが0の時は黒、cが1以上の時は白になります。

# 3. c += float(ブール演算)で図を追加する

GLSLではfloat(true)1.0float(false)0.0になります。

この方法の嬉しいところは、やはりブール演算が使えるところです。
例えば

c += float(any(lessThan(vec2(0.9),abs(uv))));

とすると、こんな感じになります。

直感的で嬉しいですね。

# 実際に描いてみる

陰陽太極図を描いてみましょう。

これです。

#define PI acos(-1.)
#define INV (1.-2.*c)
float c=0.;
c+=float(uv.x>0.0);
c+=float(length(uv-vec2(0,0.5))<0.5);
c-=float(length(uv+vec2(0,0.5))<0.5);
c+=INV*float(length(uv-vec2(0,0.5))<0.1);
c+=INV*float(length(uv+vec2(0,0.5))<0.1);
c*=float(length(uv)<1.0);
col=vec3(c);

*とかINVなどを使っていますが、これもブール演算として考えてください。

  • *1.0だけくりぬく
  • INV1.0の時だけ色を反転する

という感じです。

やはり直感的なので、使いやすいです。

# まとめ

図を描くときにはブール演算の使用を検討してみてはいかがでしょうか。

ただ、コードゴルフにはあまり向いていません(float()と書かなければいけないので)