2025/09/22 20:12 Ray Marching a Blob in 3D

ロボ子、今日はメタボールについて話すのじゃ!なんだか美味しそうな名前じゃな。

メタボール、ですか。液体の塊のように融合する有機的な形状を3Dで表現したもの、とありますね。面白そうです。

そうそう!メタボールは、中心と半径で定義された単純な球を組み合わせることで作られるのじゃ。複数の球が互いに影響しあって、表面がシームレスに繋がるのがミソだぞ。

なるほど。ただ球を配置するだけでは硬い印象になりますが、メタボールは柔らかく滑らかな表現ができるんですね。

その通り!で、このメタボールを表現するために、符号付き距離フィールド(SDF)を使うのじゃ。点から表面までの距離を計算するのじゃ。

SDFですか。球の中心をc、半径をrとした場合、点pからの距離は ‖p - c‖ - r で計算できる、と。

そう!負の値は内側、ゼロは表面、正の値は外側を示すぞ。そして、複数の球を滑らかに融合するために、Inigo Quilezさんの2次多項式平滑最小関数を使うのじゃ!

h = clamp(0.5 + 0.5 * (b - a) / k, 0, 1)、smin(a, b, k) = mix(b, a, h) - k * h * (1 - h) ですね。kが大きいほどブレンドが柔らかくなる、と。

よくできました!法線の計算も重要じゃ。普通は4タップ四面体サンプリングを使うけど、コストを下げるために3タップ前方差分に切り替えたらしいぞ。

なるほど、パフォーマンス改善のためですね。他に工夫された点はありますか?

GGXマイクロファセット鏡面反射項とSchlick Fresnel、Smith geometryを使ったらしいぞ。鏡面反射項は f_s = (D * G * F) / (4 * (N * V) * (N * L)) で、拡散反射項は f_d = ((1 - F) * (1 - m)) / π * c * max(0, N * L) じゃ。

少し難しいですが、よりリアルな質感を表現するための工夫ですね。

そう!あと、リニアHDR値を表示するために、露出曲線 c_out = 1 - e^(-c * e_x) を使ったり、球体トレースに基づく安価な半影シャドウを追加したりしてるぞ。

色々な技術が組み合わさっているんですね。球の位置はCPU側で計算してGPUに渡している、というのも面白いです。

そうじゃ!1×Nテクスチャを使って、各テクセルに中心のxyzと半径のwをRGBA32Fで格納するのじゃ。フレームごとにアニメーションさせて、DataTextureに書き込んでアップロードするぞ。

フラグメントシェーダーでは、球ごとに1回のtexture2Dルックアップで済むんですね。効率的です。

じゃろ?開発中に一番効果があったのは、法線の計算を4タップから3タップに変更したり、安全率を用いた適応的ステッピングに切り替えたりしたことらしいぞ。品質を損なわずにパフォーマンスを上げることが大事じゃな。

なるほど。地道な改善が積み重なって、最終的なパフォーマンスに繋がるんですね。

そういうことじゃ!しかし、メタボールって聞くと、どうしてもミートボールスパゲティが食べたくなるのじゃ…。

博士、メタボールとミートボールは違いますよ!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。
