ひとことで
木や草を、骨組みのアニメーションを使わずに頂点シェーダーで頂点の位置を少しずらすだけで風に揺らす方法です。幹は大きくゆっくりしなり、枝は枝ごとに違う周期で揺れ、葉は細かく速くはためく、というように層ごとに違う揺れを重ねることで、軽いのに生き生きとした植物になります。
ゲームでの使いどころ
- 草原や森:何万本もの草や何千本もの木を、1 本ずつアニメーションさせることはできません。GPU インスタンシングで描き、揺れはシェーダーで作るのが定番です。
- 風の見える化:草原を明暗の波が渡っていくと、見えない風の向きと強さが伝わります。天候や嵐の演出、プレイヤーを目的地へ導く風の表現(『ゴースト・オブ・ツシマ』のガイドの風など)にも使われます。
- インタラクション:キャラクターが通った所の草を押し倒す、爆風で木がしなる、といった効果も、同じシェーダーに「押す力」を足すだけで作れます。
- 旗、布、髪の毛先:同じ考え方で、固定端からの距離に応じて揺らせば、軽い布や飾りの揺れにも使えます。
しくみ
Crytek の『Crysis』で使われた手法(GPU Gems 3「Vegetation Procedural Animation」)がよく知られています。揺れを 3 つの層に分けます。
- 幹のしなり(メインベンディング):木全体が風下へ倒れます。根元は動かず、高い所ほど大きく動くよう、高さの 2 乗に比例させます。
は風の強さ、 は突風による強弱、 は木の高さです。横にずらすだけだと幹が伸びて見えるので、ずらした量に応じて少し下げると、長さがほぼ保たれます。
-
枝の揺れ(ディテールベンディング):枝ごとに違う周期と位相で上下に振れます。枝の付け根からの距離に応じて大きくします。頂点ごとに「どの枝のどこにいるか」(付け根の位置、枝の長さ、位相)を頂点属性や頂点カラーに焼き込んでおきます。
-
葉のはためき:葉の先ほど、速く細かく、葉ごとにばらばらの位相で震えさせます。
さらに、突風を場所ごとの時間の遅れとして加えます。風向きに沿った位置で位相がずれるサイン波やスクロールするノイズを使うと、草原の上を強い風の帯が波のように通り過ぎていきます。
実装のポイント
- 影も同じように揺らす:影を描くための深度用マテリアルにも同じ頂点処理を入れないと、木は揺れているのに影は止まったまま、というずれが出ます。
- 情報は制作時に焼き込む:枝の付け根や葉の位置は、モデルを作る段階で頂点カラーや UV の空きチャンネルに書き込んでおきます(SpeedTree などのツールはこれを自動で行います)。
- 草は簡単に:草は細いので、根元からの高さ(UV の縦方向)に応じたしなりと、ランダムな位相の小さな震えだけで十分です。1 本ごとの位相は、インスタンスの位置から作ります。
- 遠くは止める:遠景の木は揺れの層を減らすか止めて、コストを抑えます(LOD)。
つまずきやすい点
- 全部が同じ動きをする:位相をそろえたままだと、森全体が一斉に同じ動きをして不自然です。木ごと、枝ごと、葉ごとに位相をずらします。
- 根元が浮く・めり込む:根元の重みが 0 になっていないと、幹ごと地面の上を滑ります。高さの 2 乗のように、根元でちょうど 0 になる関数を使います。
- 法線がそのまま:頂点をずらしても法線は元のままなので、大きく曲げると陰影がずれます。曲がりが小さいうちは気にならないので、たいていはそのままにします。
- 強風で形が崩れる:ずらす量をそのまま大きくすると、枝が伸び縮みして見えます。強い風では揺れの幅より「倒れ込む角度」を大きくし、幹の長さを保ちます。
デモで試すこと
- 「色」を「層で色分け」にすると、幹(橙)、枝(青)、葉(緑)の 3 つの層に分けて頂点を動かしていることが分かります。
- 「幹のしなり」「枝の揺れ」「葉のはためき」を 1 つずつオフにして、それぞれの揺れが見た目にどう効いているかを比べてください。葉のはためきだけでも、止まった木に比べてずっと生き生きして見えます。
- 「突風の波」をオフにすると、すべての草が同じ強さで揺れ、風の帯が消えます。オンにすると、明暗の帯が風向きに沿って草原を渡っていきます。
- 「風の強さ」を上げると幹が大きく倒れ込み、「風向き」を変えると倒れる向きと突風の波の進む向きが変わります。