1. 水を粒子の集まりとして計算する
水を、半径 3.5cm の粒子約10万個の集まりとして表します。粒子1個はおよそ 0.34 リットルぶんの水にあたり、10万個で、床に広がったときの水深がおよそ 35cm になる量です。このように、流体を粒子で表して計算する方法をまとめて粒子法と呼びます。代表的なものに SPH(Smoothed Particle Hydrodynamics)があります。
このデモでは、粒子法の一種である Position Based Fluids(PBF)を使っています。水はほとんど縮まないので、粒子のまわりの密度は常に一定でなければなりません。PBF は、この「密度一定」を拘束条件として扱い、拘束を満たすように粒子の位置を直接ずらしていきます。ばねのような力で押し返す方法に比べて、大きな時間刻みでも計算が破綻しにくいため、リアルタイムに向いています。
2. 近くの粒子だけを探す
密度は、各粒子から 14cm 以内にある粒子だけで決まります。10万個すべての組み合わせを調べると計算が追いつかないので、空間を 14cm 角の格子に区切り、粒子をそれぞれのマスに振り分けておきます。こうすると、自分のマスと隣のマスを調べるだけで済みます。この振り分けから密度の拘束の計算までを、すべて WebGPU の compute shader で、GPU 上で並列に行っています。
3. 水の表面を描く
粒子をそのまま描くと、水ではなくビーズの山に見えます(Points ボタンでこの状態を見られます)。そこで、スクリーンスペース流体レンダリングという方法を使っています。まず、画面から見た各粒子の奥行きを描き、次に、輪郭を保ったまま奥行きをなめらかにならします(バイラテラルフィルタ)。ならした奥行きから水面の向き(法線)を求めれば、粒子の集まりが1枚のつながった水面になります。この水面に、屈折、まわりの景色の映り込み、水の厚みに応じた色の吸収、濁りを加えて仕上げています。
4. 飛沫と泡
Splash をオンにすると、波の頂や流れが激しくぶつかる場所から、飛沫・泡・気泡の3種類の小さな粒子が生まれます。これらは水の計算には加わらず、まわりの水の流れに乗って動き、寿命が来ると消えます。白く泡立つ流れを、水本体の計算を重くせずに表すための工夫です。
5. 地下空間を作る
コンコースは幅 10.8m、天井高 3.1m です。階段は幅 3m、蹴上 17cm、踏面 30cm で、地上から地下へ約 2.9m 下っています。壁・床・階段・天井の形は数式(距離関数)で表しているので、水の粒子との衝突判定と描画に同じ形を使えます。床と壁のタイルには、汚れや擦れ、水に濡れたところの色の変化を描き込んでいます。奥まで流れた水は少しずつ排水されて、再び階段の上から流れ込みます。