シェーダーからGIFアニメを生成するツール作った

f:id:amagitakayosi:20170509074747g:plain

github.com

シェーダーは、本来は3Dプログラムで物体に影をつけたり、視覚的なエフェクトを与えるための仕組みだ。
しかし、シェーダーだけで複雑なグラフィックを表現する事もでき、GLSL SandboxShadertoyには大量の作品が投稿されている。

今回は、フラグメントシェーダーのファイルからGIFアニメを生成するツールを作成した。
これを使うと、冒頭のGIF動画のようなものが作ることができる。
また、npmパッケージになっているので、フロントエンド開発のフローに沿ってシェーダーのサムネイルを作成できる。

実装はgistに転がってたスクリプトを参考にしている。

offscreen rendering with three.js and headless-gl, in coffee-script · GitHub

使い方

npm install -g glsl2img すると、 glsl2png コマンドと glsl2gif コマンドがインストールされる。

glsl2png

フラグメントシェーダのファイルを読みこんで、PNG画像を生成する。

$ glsl2png foo.frag             # out.pngを出力
$ glsl2png foo.frag -o foo.png  # foo.pngを出力
$ glsl2png foo.frag -s 640x360  # 画像サイズを指定

出力結果はこんな感じ。

https://cloud.githubusercontent.com/assets/1403842/25777407/30317b7c-3317-11e7-8dd1-b293f6a6091f.png

uniform変数は、デフォルトで time, resolution を受け取れる。
time-t オプションで指定できる。
それ以外のuniform変数を指定する場合は、 -u オプションでThree.jsのuniformの形式のJSONを受け取れる。

# どっちも同じ結果になる
$ glsl2png foo.frag -t 10
$ glsl2png foo.frag -u '{"time": { "type": "f", "value": 10.0 } }'

glsl2gif

フラグメントシェーダのファイルを読みこんで、GIFアニメを生成する。
デフォルトでは、15fps / 長さ1秒のアニメを作成する。
fpsと長さは -r -l オプションで指定できる。

$ glsl2gif foo.frag             # out.gifを出力
$ glsl2gif foo.frag -o foo.gif  # foo.gifを出力
$ glsl2gif foo.frag -s 640x360  # 画像サイズを指定
$ glsl2gif foo.frag -r 30       # 30fps
$ glsl2gif foo.frag -l 10       # 10秒

結果はこんな感じ

f:id:amagitakayosi:20170509075058g:plain

この記事の冒頭のGIFは、このシェーダーに -r 30 -l 2 を指定して作った。

shader sample · GitHub