Rでクリエイティブコーディング企画に挑戦している話

この記事について

この記事では、私が最近取り組んでいることとして、R言語を使ってクリエイティブコーディングをしているよという話をします。文章にするにあたって、考えたことの経緯とかはだいぶ脚色されているような気がしますが、事実として思っていたこととしてはだいたいこんな感じであってると思います。

skiagdの開発と#minacodingへの参加

さて、私は、あきる(paithiov909)という名前のアカウントでインターネットをしています。R言語を使ったプログラミングが好きで、趣味でRのパッケージを開発したりしています。

Rを使うようになったのは、もともとはテキストマイニングと呼ばれるような分析をやりたくて勉強してみたのがきっかけでした。一方で、今にいたるまで仕事や研究でRを使っているわけではないため、R言語はまあ好きなんだけれど、統計やデータ分析の話題にはそれほど関心がなく、Rの使いどころが自分でもよくわからないという状態がずっと続いていました。

そんななか、これも趣味で映像制作みたいなことに挑戦したくなり、何かのプログラムを書いてモーショングラフィックス的な映像を作ってみたいと思うようになりました。そこで、p5.jsや、あとはRemotionというライブラリなどを試しに使ってみたのですが、これはこれでいろいろ作れてすごいとは思ったものの、うっすら「なんか書きづらいなー」と感じていたんですよね。

また、同じころにいろいろ調べたところ、海外にはR言語でジェネラティブアートをつくっている人たちもいるらしいことを知りました。R言語製のジェネラティブアートには#rtistryというタグが付けられていることが多くて、たとえば、Nicola Rennieさんとか、Danielle Navarroさんとかの作品はよく見かける気がしますし、ggplot2関連のパッケージのメンテナとしてよく見かけるThomas Lin Pedersenさんも、実はジェネラティブアーティストとしても活動されているようで、Rでつくった作品を公開していたりします。

それで、こういうのを見て「Rでこれくらい描けるんだったら、がんばってJS/TSを書かなくても、Rで連番画像を書き出しちゃえば、あとはFFmpegとかを使って動画がつくれるのでは?」と考えるようになりました。自分が得意なRでつくれたら、それだけでも個人的にはちょっと嬉しいですしね。

あとは、これと前後して、Hiroaki Yutaniさんがsavvyという自前のフレームワークを用意してvellogdというR向けのグラフィックデバイスを作っていたのを見かけて、「この感じでRustのライブラリを利用したら、自分でも何かしらのRパッケージがつくれそう」と思ったというのもあります。

そこで実際につくってみたのが、skiagdというRパッケージです。これはskia-safeというSkiaのRustバインディングの機能をラップしているRパッケージで、GitHubでコミットログを見ると、どうやらこの2025年の3月くらいから1ヶ月くらいかけて集中的につくっていたようです。4月くらいにはZennで紹介記事を書いたりしていました。

当座のところ、SkiaのImage Filterはひと通り使えるようにしたいと思っている(あと、Color Filterはもしかしたらいらないかなと思いはじめた)ところで、ほしい機能的にはまだ全部実装できていません。未完成です。

しかし、いろいろと使ってみないことには開発しづらいと思っていたのもあって、最近、いわば試し切りみたいな感覚で、skiagdを使ったクリエイティブコーディングに挑戦してみています。

ちょうど6月には、#minacodingというクリエイティブコーディングの企画が催されています(別に6月以外に取り組んでもよいらしいけど、たぶん6月に取り組むのがメジャーな感じっぽい)。ほかの参加者の多くはたぶんp5.jsなどProcessing系のライブラリを使った作品を投稿しているようですが、そんななかで「おれはRで挑戦してるぞ!オラオラどうだー!くらえー!!」という強い気持ちで作品をつくって投稿しているところです。

たとえば、次のようなのをつくりました。どうでしょうか。ゆうてクリエイティブコーディング初心者のわりには、意外と悪くないと思うんですよね……

Day 6

Day 10

Day 13

Day 21

Rでクリエイティブコーディングしていて感じたこと

Rは行列が扱えるところがつよい

Rでクリエイティブコーディングをしてみている感想としては、この下の記事でもすこし触れていますが、Rっぽい書き方で書くのも意外と便利ということです。

少なくとも、私の場合、p5.jsやRemotionで「なんか書きづらいなー」と感じていたのは、図形を描くべき座標を計算するのにfor文を多用しなければいけないところでした。

R言語でRっぽい書き方をする場合だと、数値はベクトルや行列として扱えるので、for文を書かずにさまざまなデータを用意することができます。慣れの問題もあるでしょうが、たくさんの図形の座標をまとめて計算する必要があるようなときには、たぶんRで書くとコードの見た目をシンプルに保ちやすいです。

たとえば、次は、6000個の点からなる「三つ葉」の点群datを用意しているコードです。

## 三つ葉
trifolium <- \(n, offset = 0, sc = 1) {
  theta <- offset + seq(-pi, pi, length.out = n)
  r <- sc * cos(3 * theta)
  as.matrix(data.frame(
    x = r * cos(theta),
    y = r * sin(theta),
    z = 1
  ))
}

dat <-
  purrr::map(seq_len(60), \(i) {
    dplyr::tibble(
      id = i,
      col = grDevices::hsv(.0083, 1, seq(.333, .773, length.out = 100), alpha = .8),
      pos = trifolium(100, offset = i / 60, sc = i)
    )
  }) |>
  dplyr::bind_rows()

次の画像は、この点群を黒のみでプロットしたもの。

trifolium

11日目のテーマ「質感のあるコード」では、こうして用意した三つ葉を32回、すこしずつ回転・拡大しながらスクリーンで重ねて描画することで、次のようなお花を描きました。6000 * 32なので、全部で192,000個の点が描かれている計算になります。

minacoding-11

こういうのをわりとさらっと書ける(skiagdがこういうのをさらっと書けるように設計してあるというのもある)のは、当初からRでクリエイティブコーディングすることに求めていた部分だったので、このあたりのつよみを活かせると、一見複雑そうな作品もRでは比較的簡単に作れたりするような気がしています。

ひとつ前の状態が必要な処理は書きづらい

一方で、もちろん向き不向きというのはあって、今のところ感じているところとしては、レンダリングループを回しているときの「ひとつ前の状態」を見ないと次の状態がわからないような処理は、Rだとだいたい書きづらいです。

そもそも、R言語というのは、プログラミング言語としてはやや変わった言語です。立ち位置としては、たぶんSASとかMATLABとかに近いもので、とくに統計解析やデータ分析などのために、おもに研究・教育の場を中心に使われてきた歴史があります。

プログラミング言語としてのRは、(もちろんいろいろな紹介のされ方がある気がしますが)端的に言うと「遅延評価と弱い動的型付けを備えた関数型言語」です(今日的な意味あいでの「関数型言語」ではない気はするものの)。

R is a functional language, with lazy evaluation and weak dynamic typing (a variable can change type at will: a <- 1 ; a <- “a” is allowed). Semantically, everything is copy-on-modify although some optimization tricks are used in the implementation to avoid the worst inefficiencies.

この一節は、こちらのstackoverflowのスレッドからの孫引きですが、Rでは基本的に、オブジェクトはすべてimmutableであり、同じ名前の変数にオブジェクトを再代入しようとすると、いわゆる「シャドウイング」みたいなことが起こります。つまり、オブジェクトの値を更新したとき、基本的には常に、更新していない部分も含むデータ全体がコピーされて、新しいオブジェクトがつくられるというイメージです(引用で”copy-on-modify”と呼ばれている挙動)。

このあたりと関係しているのか(あるいは全然関係ないのか)よくわからないですが、Rでは、慣習的に、変数に値を再代入するような書き方があまり好まれません。だから、たとえば、p5.jsの作品を眺めていると、particleクラスのオブジェクトを用意して、draw()が呼ばれるたびにパーティクルの位置や速度を更新しつつ、寿命が尽きていたら消す、みたいな処理がしばしばありますが、そういうのはRの書き方には馴染まないですし、素直に同じように実装してしまうと、Rでは処理が遅いクソコードになりがちです。

したがって、このあたりはRで書くにはどうやら工夫が必要なところで、どういうパターンでどういった処理として実装すればよさそうか、まだ手探りで書いているところがあります。Rっぽく書くとしたらどういう書き方ができそうか考えるのはチャレンジングな課題ではありますが、そういうことを考えてばかりだと疲れるのと、作品をつくりこむうえではそんなに本質的な部分ではなさそうというのがあるので、あくまでできる範囲で、ほどほどに取り組んでいきたいです。

むすび

Rでのクリエイティブコーディングを便利にやるためのものとして、skiagdのほかに、次の2つのパッケージも並行してつくっています。

rasenganは点群をつくる関数をまとめるだけのつもりでつくりはじめたのですが、ノイズとかイージングとかも含めた諸々の詰め合わせになりつつあります。まあ、あれば便利という感じです。

aznyanはやっぱりポストエフェクト的なやつがほしいよなァ!と思って開発しているもので、メディアンブラーと拡散フィルタ(いわゆる発光エフェクト)あたりは雑にカッコいい見た目にできて便利だなと感じているものの、ぶっちゃけSkiaのRuntime Effectで十分だったのではと思いつつあります。いちおう、飽きるまでは機能を追加していくつもりです。

このあたりの開発とあわせて、今後もRでカッコいい作品をつくれるようにがんばっていきたいと思っています。