coding, photo, plant and demo

*TDF2015で史上最高の4KB誕生か? Optical Circuit

tech demo 20150301 112425
今年のTokyoDemoFestは行けなかったのですが、そこで凄まじい作品が発表されてました。それがcombined demoで優勝した4KB introのOptical Circuit。

まずはこれを見ていただきたい。(是非1080pで見てください。ちなみに最初に貼ったurlは音と映像の同期が取れていなかったようです)

http://www.youtube.com/watch?v=ZT_rlKRT4K8

これが4KB弱のwindowsの実行ファイルから生成された映像と音なのであります。全く意味が分かりませんね。

2009年にRGBAが発表した4KB IntroのElevatedが当時与えた衝撃は凄く、間違いなく歴史上最も重要な4KB Introです。しかし、それすらもこのOptical Circuitの刺激的かつ多彩なシーンの数々を見た後では物足りなく感じます。一体どうやってこんな凄い映像と音が4KBに収まるのだろう?不思議になってとても簡単ではありますが解析してみました。

http://www.youtube.com/watch?v=_YWMGuh15nE


デモを解析するのは超高速レイトレーシングで度肝を抜かれたheaven sevenを逆アセして調べて結局分からなくてexceedの人に聞いた10代の時以来かも。ちなみにElevatedに関してはkiokuさんが以前解説しておられます。
http://kioku.sys-k.net/archives/2009/05/4kb_intro_eleva.html

調査の下準備

まず普通に実行してVisual Studioでアタッチしてメモリをぶっこ抜きます。
最近の4KB introの殆どはfragment shaderで作られているので、shaderさえ抜けば大体の仕組みは分かります。ということでgl_FragColorとかでダンプしたメモリを検索してshaderゲット!minimizeされているとはいえ即効でソースコードが手に入るのだから、逆アセが必須だった頃と比べれば格段に解析が楽ですね。ソフトレンダの頃なんて山のようにfpu命令が出てきて読むの不可能だったもんなー。今回はx86コードは読まず、shaderだけ読みました。

技術的な見どころ(音楽)

さてshaderを検索したら2種類見つかりました(正確にはもっと沢山メモリ上に存在するが、マクロを利用した変形)。普通に考えたらvertex shaderとfragment shaderですが、vertex shaderの様子がおかしい。ray marchingをしたいならvertex shaderはやることがないはずなのですが、色々計算しまくっているし、out vec2とか書いてあってgl_Positionとか使ってない。

これってもしかして…
そう、実はこのIntroのサウンド、vertex shaderで生成されています。
昨年のTokyoDemoFestでtomohiroさんが4KB Intro「雇用の欺瞞」で編み出したvertex shaderで曲を生成するという変態すぎる技です。GL_TRANSFORM_FEEDBACK_BUFFERを使ってGPUで計算させた結果を受け取るそうです。それを皆の前で言った時、全員から「それshaderでやる必要あんの?」とデモの名前とともに総ツッコミを受けましたが、Cで普通に書いてコンパイルするより小さくなるようです。よっしんさんによるとOptical Circuitの場合違いは200bytesとのことでかなり大きいらしい!tomohiroさんの考えが天才的過ぎて凡人の我々には当時理解できなかったということか!残念です。

気になる方は是非「雇用の欺瞞」のソースコードを見てみてください。
https://github.com/demotomohiro/Falsity-of-employment/blob/master/sound.hpp
https://github.com/demotomohiro/Falsity-of-employment/blob/master/sound.vs

で、Optical Circuitも同じ方法を使っているようです。そのおかしなvertex shaderを取り出して実行したらそのままサウンドトラックが得られました。一応ソースコードを置いておきます。
https://github.com/mitsuman/IntroSound/blob/master/optical_circult.cpp

最初聞いた時、サビの速弾き(?)っぽいところとか、なんとなく数式から生成した音っぽいな、とか、よっしんさんが数式で音楽を作るのにハマっていたのを知っていたので、もしやとは思ったんですが、まさかの全編数式とは想定外でした。それでこんなにまともな曲が作れるなんて!こんな芸当が出来る人、世界に他に何人いるんだ??

TDF2013 のときにもよっしんさんは4KB Introを出して優勝しているのですが、そのときは4klangを使ってかなり豪華な楽曲を投入したため、4KBの内の半分がサウンドになったそうです。お陰で音楽は4KBとは思えないレベルでしたが、残りの2KBで映像を作ることになってかなり厳しかったそうです。その反省(?)から、サウンドでもアグレッシブにサイズを削りに行ったのではないかと勝手に推測しています。

技術的な見どころ(映像)

さてこれもshaderなのですが、2つ見つかったうちの1つは音楽なので、残りは1つしかありません。あれ、vertex shaderは?と思ったらひとつのファイルがifdefでvertex shaderになったり、fragment shaderになるようです。fragmentとvertexで共通の関数や共通の宣言が使えるので、圧縮に一役買いそうです。他にもifdefに入れる値を変えることで、1つのファイルが幾つものshaderに化けるようです。普通ならuniformで動作を切り替えるわけですが、あえてifdefでshaderを別々にコンパイルするのは何故かは分かりません。圧縮の問題とはあまり思えないし速度的な問題でしょうか。

vertex shader

いわゆるカメラワークの計算です。カメラの位置やレイの方向を決めてvaryingでfragmentに渡します。よくあるパターンだとfragment shaderでカメラワークも計算して、vertex shaderは何もしない事が多い気がします。その方が特殊効果も掛けやすいですし。ですがoptical circuitでは速度を稼ぐためか、vertex shaderで計算しておいてvaryingで補間してfragment shaderへ渡すようです。メッシュが何分割されているのかはshaderだけ見ても僕には推測できず不明です。

fragment shader

基本はray marchingのようです。distance fieldを定義してレイを進め、交点を求めぶつかったら法線を計算して反射。なるほど、けど不思議なのは交点を見つけても色を一切計算しないことです。普通のray marchingなら、交点で色を計算して加算していくはずです。Optical Circuitではその代わり反射したときの交点を4点記録しています。

何かがおかしい。これがOptical Circuit(光回路)の由来でもある、綺羅びやかなフラクタルのような線状光源のトリックの前段なんですね。
実はこの後にも同じようなループがあります。今度はdistance fieldを使わず一定間隔で、視点から記録したレイの通った道をトレースしていきます。そしてトレースしながらその座標からフラクタルで得た結果を明るさとして合算していきます。このフラクタルはdistance fieldに対してlight fieldとでも呼べばいいんでしょうか(ここでは便宜上そう呼ぶことにします)。

この様にフラクタルで回路状のものを光源として作っているのがこのintroの最大の特徴で、故にOptical Circuitという名前になったのではないかと思いました。
なおフラクタルで回路っぽい画を作るには下記のようにすればよいようです。
https://www.shadertoy.com/view/XlX3Rj#

このレンダリング手法自体はvolume renderingと呼ばれるもので、demoの世界だと例えばvolume lightの計算とかでも似たような処理をします。例えばこのgodrayと呼ばれる雲から光が差し込んでいる様子とか(ray marchingでrayを進めながらその時点のrayから光源までの雲の厚さを等間隔でサンプリングして光の筋を計算)。ただ反射も含めてvolume renderingする点や、光源自体にフラクタルを多用している点が今までにない映像表現に繋がっているのだと思います。

ところで、Pouetではcdakと比較されcdak2等と書かれています。確かにdistance fieldを駆使して複雑巨大なジオメトリを作るところは同じです。

http://www.youtube.com/watch?v=cjSJc2eCetE

しかしcdakと比べても圧倒的なのは、より複雑かつ多彩な変化を魅せるジオメトリ、そして先にも述べたvolume renderingと反射が織りなすド派手なライティングでしょう。これを理解していれば単純にcdak2等とは評価できないはずです。しかしこのジオメトリがたったこれだけのコードから生み出されているとは…distance関数はまだ読んでないですが、あまりに黒魔術的すぎます。コードを見ると分かるのですが、このraymarch+volume renderingの仕組みでかなりを占めてますからね。distance関数等は大した量じゃないんですよ。

ちなみにcdakの模様は乱数でfill rectしてsobelを掛けたものをテクスチャとして張り付けてます。
Cdak by Quite - How?

Optical Circuitではなんとsamplerは一切使わずワンパスで画が生成されています。つまりglsl sandboxでも動くはず…ほんとかな?

演出的な見どころ

上で述べた技術はいわゆるレンダリングや数学であり、計算機を制御するための技術です。対して演出というものは、人の感情を制御するための技術と言えるでしょう。ベンチマークではなく人に見せて評価してもらうとなると、必然的にその演出が重要となってきます。これはデモに限らずゲームでも、映画でも音楽でも何でも同じだと思います。

それでOptical Circuitなのですが、作者はかつて超連射68kという傑作シューティングを作ったファミべのよっしんさんです(0x4015はファミコンのレジスタでしたっけ??)。技術は勿論のこと、人にどうやったら緊張と緩和、恐怖と安堵、興奮と快感といった感情を効果的に与えることができるか、少なくともシューティングゲームの文脈では職人の様に体得しておられるはずです。それがこのデモの全体の構成や細々とした演出に反映され、ある種の中毒性を生んでいる気がします。

あと、宇宙船のシーンはそのままゲームを連想させますが、時折現れる紫や緑を使った色使いや鉄鋼のような重厚なジオメトリとか、明滅する光源、ソナーの様に拡散していく光とか、超連射を始めとする演出を連想させる部分があったりするのも、僕のただの妄想かもしれませんがニヤリとしてしまうポイントです。

まとめ

  • 音は数式で魔術的に作りこまれている。レンダリングにはvertex shaderを使用
  • 映像はray marching+distance fieldで反射を含んだパスを確定、パスをなぞった等間隔サンプリング+light fieldで色確定
  • distance fieldとlight fieldは黒魔術的に作りこまれており解読困難
  • TDFに行けなくて非常に悔しい

これで4KBに興味を持った方は 最近の4k introが凄い とかを見るといいかも。