最近の制作にまつわるフレームワークやアプリケーションは、制作における抽象的な思考をフレームワークとしてまとめて提供するものであるから、表現はおのずとツールが提供する抽象概念を土台として成立する。実際に制作をする段階では、低レイヤーの話をいちいち持ち出さずにゴールから逆算して早くたどり着ける道を選ぶだろうが、一方で、新しい表現の可能性を追求したいというクリエーターたちの深い欲求は、逆算的な思考ばかりでは深まらないかもしれない。
クリエイティブコーディングにまつわる制作環境は多様化を極めており、ツールは年々増えている印象がある。特にノードベースの環境は、ノンプログラマーへの導入のしやすさやパターンの再現のしやすさなど様々なメリットとともに受容されている。一方でコードベースにとどまる環境も依然としてあるし増えている。どちらが優れているかを判断するのは、さして重要ではないし個々人の考えに依存する。しかし、ツールを選ぶことで、少なからずそのひとのワークフローや表現の大まかなフレーム、作業対象とするレイヤーを規定することにはなるだろう。
本記事ではコードベースの環境を紹介する。コードベースの環境であれば、プログラミング言語の構文それ自体や、言語をとりまくエコシステムが発想の土台となる。プログラムはそれ自体がフレームワーク的・デザインパターン的である。ソフトウェアの振る舞いを決める設計道具であり、抽象的な思考の表現手段でもある。道具と表現の関係は、絵筆と絵柄の関係に例えられたりするが、プログラム言語と、発想の仕方・その出力の間には、より興味深いマチエール(メディウムとの摩擦から生じる質感)を生み出す可能性があるように思える。(それは視覚化する前の抽象レベルかもしれないが。)
前置きが長くなったが、比較的新しい言語を導入したオープンソースのクリエーティブコーディング環境について2つほど入門したので本記事で紹介したい。
Quil
ProcessingをClojureでラップした環境。Processingの関数をそのままClojureにバンディングしたもので、Processingランタイムそのものが動いている。Processing本家を使わずにQuilを選択する動機は完全にClojureの言語特性からくるものだと思われる。2014年にリリースされてから一定の支持を受け、国内記事でもQiitaで探すといくつかの記事を確認できる。
ClojureはJVM上で動作するLisp方言の関数型言語で、クラス宣言などができないかわりに言語仕様自体がコンパクトであり柔軟。ただforループや変数宣言といった基本的な構文ですでに発想が異なるのでJavaなどの他言語からうつるときにややハードルとなる。Clojure自体のメリットは様々なWeb媒体から見つかるが、こちらの記事は、言語の世界観の部分を説明しているので参考になる。Clojureの言語仕様以外の主な利点としては、
- ClojureScriptを利用したJavaScriptへのトランスパイルが可能である
- 実行ファイルを止めずに更新を反映できるREPL(Read-eval-print-loop)サーバの機能でLive Codingライクな開発ができる
などが挙げられる。
Quilの主なユーザに、Tyler Hobbs氏がいる。2Dの絵作りでとりわけ色彩のセンスに優れたアーティストでありエッセイも非常におもしろい。Clojureのカンファレンスの内容を起こしてエッセイにした記事”CODE GOES IN, ART COMES OUT“で、Clojureを使うメリットを説明している。曰く、
- GenerativeArtの制作プロセスは純粋なデータ処理のパイプラインであり、こうした構造と処理の記述に非常に適している
- REPLによるタイトなフィードバックループ、トライアンドエラーができ、ゴールを決めない無作為な作業に適している
- Javaのエコシステムを活用できる
- 柔軟な記法によって、クリエイティブワークに必要な柔軟なマインドセットを用意してくれる。書いていて楽しい
と語っている。
コード
一見するとタイプ量の少ないシンタックスシュガーのようにみえるが、不思議なカッコ(クロージャ!)が多く、演算子の順番、引数の関係、ループ構文に特殊さが見受けられる。以下は、exampleからの引用だ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
(ns quil-sketches.gen-art.09-sine-wave-with-noise (:require [quil.core :refer :all] [quil.helpers.drawing :refer [line-join-points]] [quil.helpers.seqs :refer [range-incl]] [quil.helpers.calc :refer [mul-add]])) (defn setup [] (background 255) (stroke-weight 5) (smooth) (stroke 0 30) (line 20 50 480 50) (stroke 20 50 70) (let [xs (range-incl 20 480 1) rads (map radians (range)) ys (map sin rads) ys (map #(pow % 3) ys) ys (map (fn [y rad] (* 30 y (noise (* 2 rad)))) ys rads) scaled-ys (mul-add ys 1 50) line-args (line-join-points xs scaled-ys)] (dorun (map #(apply line %) line-args)))) (defsketch gen-art-9 :title "Sine Wave with Noise" :setup setup :size [500 100]) (defn -main [& args]) |
これに相当するProcessingのコードは以下だ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
void setup() { size(500, 100); background(255); strokeWeight(5); smooth(); stroke(0, 30); line(20, 50, 480, 50); stroke(20, 50, 70); float xstep = 1; float lastx = -999; float lasty = -999; float angle = 0; float y = 50; for(int x=20; x<=480; x+=xstep){ float rad = radians(angle); y = 50 + (pow(sin(rad), 3) * noise(rad*2) * 30); if(lastx > -999) { line(x, y, lastx, lasty); } lastx = x; lasty = y; angle++; } } |
利用方法
詳しいインストール手順は、こちら。
Quil自体は、パッケージマネージャやビルドツールなどが同梱されたLeingenで環境構築が完了する。エディタにはVSCodeを使った。Windows環境のターミナルは(Linuxサブシステムを使わずに)Powershellで環境構築して開発ができた。Leingenのインストールの際にJava8が推奨とされている。LeingenはChocolateyでインストールすると楽だったがJavaのバージョンに齟齬があったりするとエラーがでる。Java8で、インストールおよびreplを含むleinのコマンド実行ができた。
Light Tableという、軽量なElectronベースのエディタでかつ、関数計算を逐次可視化できる機能(変数の監視やインライン評価)を持ったエディタに対応しており、これを使いながら実行ファイルを止めずに更新して開発していくスタイルはかなりいい感じに見える。しかしこのLight Tableは、自分の環境ではうまく動作しなかった(REPLサーバにアクセスしようとしたときにJavaランタイムエラーを吐く。この辺が解決策っぽいが雲行きが怪しかったので未着手)。
nannou
Rustを用いた、実行速度と柔軟性をあわせもつ環境。VulkanというOpenGLの上位互換となるモダンなグラフィクスAPIを、Processingに通じるような簡便なインターフェースで記述できるという点は可能性を感じる。オーディオ、OSC、DMX、レーザー出力(Ether-dream etc.)といったメディアアートに関わるIOのデモがすでに揃えられている。0.9.0のリリース記事が現状のスナップショットをよくあらわしている。ちなみにツール名はAphex Twinの楽曲名からきているとのこと。現在用意されているExampleは豊富とは言い難いが、ComputeShaderのデモや、VulkanのAPIを用いた描画、レーザーのIOなど、勉強できそうなものが多いと感じた。FrameBufferやビデオフォーマットが未対応であったりまだ実践的な機能でも未整備な点が多いが、Vulkano-rs(VulkanのRustラッパー)のデモなどを移植してみたりすると楽しいかもしれない。
ヌルヌル動く大量のエージェントや流体のデモがスゴイmactuitui氏が主に使っており、instagramの#nannouタグはほぼ独占状態。氏のデモを見ると夢が広がる。Processingからパフォーマンスの面での上位互換として、oFよりも先にくる候補なのかもしれない。
Rustは、C/C++と同等の実行速度のあるバイナリを生成できるクロスプラットフォームの言語でありながら、スクリプト言語のような柔軟かつ抽象的な記述ができる他、C/C++でネックだったメモリ管理にまつわる危険性が実質なくなっているなどメリットが多い。言語仕様に関する概要はこの記事などがわかりやすかった。
コード
Processingに影響を受けているが、若干のパラダイムの違いを感じる。状態を初期化して、その後即座に、描画の無限ループに入るという点はProcessingやopenFrameworksなどと同じ考えである。一方で命名はview、modelといったMVCパターンを想起させる言葉を用いている。p5やoFが信号やデータの逐次処理(Processing)というようなDSPっぽい印象を与える一方、イベントに応じてのみ状態変化していく状態機械、もしくはリアクティブプログラミングといったパラダイムをプログラマに印象づける。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// nannouのアイテムをロードする。 // Rustにはグルーバルに適用されるモジュールはなく、ファイル単位で必要モジュールをロードする必要がある。 use nannou::prelude::*; // appの状態をModelという構造体に定義していく。 // MVCパターンのModelに相当。 // Modelは、eventなどによって更新されていくことを想定されたパラメータ群となる。 struct Model {} // 実行ファイルのエントリポイントとなる。 // appに定義すべき関数などを任意で渡したのち実行する。 fn main() { nannou::app(model) .event(event) .simple_window(view) .run(); } // Model構造体のインスタンスを生成して返却する fn model(_app: &App) -> Model { Model {} } // イベントハンドラに相当。eventに応じて、modelを更新していく。 fn event(_app: &App, _model: &mut Model, _event: Event) { } // draw関数に相当。 fn view(_app: &App, _model: &Model, _frame: &Frame) { } |
利用方法
手順はここにまとまっている。VulkanやShadercのための必要ライブラリを揃えたのち、RustをインストールすればすぐnannouリポジトリのExampleをbuildできる。Windowsの場合、何も詰まることことがなくすぐに環境構築ができた(Linuxは少しめんどくさそう)。現状、エディタはVS Codeが推奨とされているが、Rustのシンタックスが対応していれば何でも問題ないように思える。プロジェクトに必要なパッケージを揃えたり、プロジェクトをビルドするのは、Rustに同梱されているCargoコマンドで完結できる。パッケージマネージャが開発ツールとつながっていることで、npmような効率的かつ柔軟なグルーコーディングができ、その点でも恩恵は大きい。$ cargo new projectnameでプロジェクトをファイルを用意し、$ cargo runで依存ファイルのロードとビルド、実行を同時に行う。かんたん。
最後に
上記2つのツールは、注目が集まっている(がとっつきにくい)イマドキの言語を楽しみながら学習する教材にもなり得る。また、本記事では特に注目できる2つのプラットフォームのみの紹介であるが、それ以外の情報としては、awesome-creative-codingなどを参考にすると良さそう。