loop-animation

レイマーチング立体Raymarched Forms

距離関数で定義した3D立体をレイマーチングで描き、球が溶け合ったり、箱がねじれたり、トーラスが回ったりする様子に陰影を付けるアニメーションです。

WebGL2 のシェーダーで、画素ごとに計算して描いています。初期設定で再生しています。

距離関数で表した3D立体に光と影を付けて描く。球が溶け合い、ねじれた箱やトーラスが回る(WebGL2)

このシーンで作る

パラメータ、色、エフェクトを変えて、GIF・APNG・WebP・MP4・WebM で書き出せます。

どう計算しているか

  1. 立体は距離関数(空間の点が立体の表面からどれだけ離れているかを返す関数)で表します。球なら |p| − 半径です。箱とトーラスも、それぞれ専用の式で距離を返します。
  2. 画面の画素ごとにカメラから視線を飛ばし、その地点の距離ぶんだけ前に進む操作を最大96回繰り返します(レイマーチング)。距離がほぼ0になった点を表面とします。
  3. 表面の向き(法線)は、距離関数を少しずらした位置で差を取って求めます。光の方向との内積で明るさを、視線に対する角度で縁の光と反射のハイライトを計算します。「トゥーン(段階)」では明るさを3段階に丸めて塗ります。
  4. 「溶け合う球」は5個の球を sin/cos で動かし、なめらかな最小値(境目を丸くつなぐ min)で合成します。つなぎの幅は「溶け具合」で変わります。「ねじれた箱」は高さに比例した角度で断面を回し、「球 ↔ 箱」は2つの距離関数を 0.5 − 0.5·cos(2πt) の割合で混ぜます。
  5. 立体全体を縦軸まわりに「1ループの回転数」ぶん回します。「ねじれ」は、箱のねじれ量とトーラスの表面のうねりの強さを変えます。
d(p) = smin(|p − cᵢ(t)| − rᵢ),  pos += dir·d(pos)·0.9

ループがつながる理由

時間 t は、2π·t に整数を掛けた sin/cos と回転角の中だけに出てきます。球の軌道は1倍か2倍の周波数、トーラスのうねりは2倍の周波数です。そのため t = 1 のときの形と向きは t = 0 と同じになります。

調整できるパラメータ

形

立体溶け合う球・ねじれた箱・トーラス・球 ↔ 箱
陰影なめらか・トゥーン(段階)
大きさ0.3 〜 1.6(初期値 1)
溶け具合0.01 〜 1(初期値 0.35)

動き

1ループの回転数0 〜 3(初期値 1)
ねじれ0 〜 3(初期値 1.2)

同じ分類のシーン(立体・擬似3D)