FAL 制作メモ

作ったものを見せびらかしたり解説したりします。自作ゲームやクリエイティブコーディングの話が中心です。作ったものの置き場所はこちら→ https://www.fal-works.com/ Twitter→ https://twitter.com/falworks_ja

プログラミングで波のような膜のような何かを描く方法

これはProcessing Advent Calendar 2017 - Qiitaの5日目の記事です。初参加といいますかブログ記事を書くのすら初めてですが何卒。

プログラミングでお絵かきをする話をします。
一般に「クリエイティブコーディング」「ジェネレーティブアート」などと言われるものですが(※別々の概念です)、この記事でこう呼ぶのはちょっと大仰かもしれませんね。実際のところお絵かきとしか言いようがない。

f:id:fal-works:20171205142723p:plain
Noise Wave

この記事の趣旨

このたび先ほどの画像のようなスケッチを作ってみました。
こちらで動くやつが見られます。→ Noise Wave - OpenProcessing

どういう原理でこういう絵が描けるんだろう?
そう思ってくれた人を対象に、やり方を説明したいと思います。
見ただけでなんとなくコードを想像できる人には、あまり有益な情報は無いかもしれません。

一応、私が使用した言語は

  • TypeScript(JavaScriptが静的型付けになったやつ)
  • p5.js(アート・デザイン特化言語ProcessingがJavaScriptライブラリになったやつ)

ですが、考え方の話をしたかったので、以下ソースコードは一切出てきません。
そもそもJavaScriptを初めて触ったのが二ヶ月前なので技術的な話があまりできないのもある。

道具立て

次の2つを組み合わせます。

パーリンノイズ(Perlin noise)

これはそういう名前の関数です。
仮に f(x)とおくと、任意の数値 xを入力すると0.0~1.0の範囲で値を返すというものです。

グラフにすると下の図のように波打つ感じになります。
(JavaScriptで表示しているのだがお使いの環境で見えるでしょうか??)

入力の値を連続的に変化させると、出力値の方も連続的、かつ一見不規則に変化してくれるので、ジェネレーティブなものを作りたいときに重宝します。

なおこの例では1変数( xのみ)ですが、2変数・3変数にもできるので、CGの雲や炎のエフェクト、3Dゲームの地形の生成など、幅広く応用されているようです。

Processingだとnoise()として実装されているので、以下noise()と表記します。他の言語はよくわかりませんが何かしら手段があるでしょう。

半透明な線で濃淡を付ける

もう一つがこれです。
太めのフェルトペンとかで、ペン先が角ばっていて、紙と接触する箇所が線状になってるやつありますよね。
あれを紙の上でビーっと動かすと、紙には面的にインクがつきますね。
それと同じことをスクリーン上でやるわけですが、その時に色に透明度を持たせます。

すると、何度も色を塗られたピクセルはその分色が濃くなっていきます。
逆に高速で通過した部分は薄く色がつく。
結果、線をなめらかに動かせば、なめらかな濃淡ができます。

以上を利用するといろいろ変な絵が描けます。

描画方法

あとは上記の組み合わせです。
画面上に2つの点を解き放って、2点間を半透明の線で結びます。
そのうえで、それぞれの点の位置をnoise()でゆるやかに変化させれば、なんというか、その、結果的にああなるわけです。

具体的な動かし方

いろいろ考えられますが、今回の作例では、

  • Step 1: 経過時間をnoise()に入力して得た値を、点のx方向の速度とする
  • Step 2: 点のx座標をnoise()に入力して得た値を、点のy座標とする

というように2ヶ所でnoise()を使いました。
2つ目の点はy座標をひっくり返すことで上下に広がるようにしています。

あと今回は始点と終点で1点に収束してほしかったので、関数 y = \sqrt{\sin \theta}\;(0 \leqq \theta \leqq \pi ) を掛け算で重ね合わせました。
\theta = 0 の部分が始点、\theta = \pi の部分が終点に来るようにすると、それぞれ y=0 になります。
たんなる \sin \theta だと中央部分以外がつぶれすぎな気がしたのでルートをとることで調節しました。

パーリンノイズを無効化した場合

もし Step 1 でnoise()を使わず一定の速度にすると、2点のx座標が常にそろっているので、濃淡がなくなってしまいます。

f:id:fal-works:20171204203034p:plain
Step 1 無効化版

もし Step 2 でnoise()を使わず一定にすると、形としては \sqrt{\sin \theta} のグラフそのものになります。
あれっ……これはこれで面白いのでは??(作ってから思った)
メタリックな感じにも見える。

f:id:fal-works:20171204203041p:plain
Step 2 無効化版

パラメータの調整

原理は簡単でしたが、大まかな形ができた後の調整のほうがどちらかというと面倒です。
例えば……

  • noise()の変化を荒くするか細かくするかで、雰囲気がだいぶ変わるので、係数を与えて調整します。

f:id:fal-works:20171204203047p:plain
荒いnoise
f:id:fal-works:20171204203104p:plain
細かいnoise

  • あと、noise()の出力は全体としては0.5付近をうろうろすることになりますが、もうちょっと偏らせたいなぁとなる場面も多いので、数字をいじったり。
  • 2点の距離が離れすぎて微妙な結果になることがあったので、そういうときだけ遅れている方の点をスピードアップさせたり。

などなど。

結果

以上のようにして次の結果が得られた。(クリックで再生成)

作ってから思ったけどオーロラっぽいですね。最初からオーロラ描けばよかった。

余談: 似たようなジェネレーティブな作例

過去に、今回と同じテクニックを用いて、以下のようなものも描いています。

ロールシャッハテスト風の化け物

Rorschach - OpenProcessing

f:id:fal-works:20171204203110p:plain
Rorschach

なんだかよくわからない物体

Generative Something - OpenProcessing

f:id:fal-works:20171204203119p:plain
Generative Something

以上です。
いろいろできて面白いよというのが伝われば幸いです。