3D空間に動く雲を作る色々な手法

雲眺めるの良いですよね
ゲームやバーチャルの世界でも草の上でぼーっと雲を眺めるのはとても気持ちが良いものです

3Dの世界では建物や家はポリゴンで表現されますが、水や空気や空はどうしてもモデリングだけでは難しく、シェーダー（3D表示のプログラム）が関わってきます
しかし雲を表現する手法はいくつかあり、配布されたものを使うにしてもどれを使っていいのかわからなくなることは多いと思います
そういった人のために、色々な手法の名前と、つかいどころを紹介していきます

![total.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1376552/5462d335-1e87-f9c6-ab72-58e66e7fa89e.png)

## なぜシェーダーで雲を表現するのか

VRの世界で最も多い雲はSkyboxによるものです[^1]
[^1]: Skyboxもシェーダーだという話は説明をややこしくするので省略します
skyboxは画像をそのまま表示するため、動作速度が軽量で、写真さえ用意できれば最も幅広い表現力を持っています

しかし変形しながら動くような雲を表現するのは静止画のSkyboxでは難しく、実現するためにはシェーダーを使う必要があります

またこれは個人的な感覚なのですが、VR機器で見るとskyboxのピクセルや圧縮ノイズが見えやすく、そのせいで遠景が書き割りのように（実際にそうなのですが）見えてしまう問題があり、僕がシェーダーで雲を作ろうとした動機にもなっています

# 雲を表現する代表的な手法

2021年の12月にシェーダーの展示会である[ShaderFes2021](https://sites.google.com/view/shaderfes)が開かれました（現在も無料で見ることができます）

<iframe width="560" height="315" src="https://www.youtube.com/embed/sxyKsDOMYE4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

巨大展示用のアルファ展示室に僕含めて３つの雲が提出されていました
ちょうど違う手法の雲が３つ集まっていて面白かったので、違いとともに紹介していきたいと思います[^2]
[^2]: 他人のシェーダーの手法は予想な部分もあるのであしからず

## レイマーチング

[Procedural milky way by AYANO_TFT](https://vrchat.com/home/world/wrld_d84c9659-631c-4b70-8898-06ad547315c9)![VRChat_1920x1080_2022-02-21_22-54-46.582.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1376552/d577b95f-f530-6037-4f24-d95640b11b98.png)

3D空間上に数学的な図形を描画するレイマーチングという手法を使って、奥行きや濃さを計算することで、空間上に雲を描画します
また、レイマーチング雲の中を進む間に何度か計算を行ってそれを合計する手法をボリュームレンダリングと呼びます

![空白の図 (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1376552/6691afb8-93ac-dee0-d9c7-902f429b5493.png)


これらの手法の利点は、なんといってもカメラが雲の中に埋まったときに正確に描画が行われるという点です
つまり、雲海の上のギリギリから、雲に触れたり、あるいは雲に突っ込むようなことがあるワールドには最適です

こちらは同一作者の「[雲海の入り江 -Cove of clouds-](https://vrchat.com/home/launch?worldId=wrld_8117b65a-3e1f-4bb2-bd88-46ae615d5f3c)」で、雲の中に入った様子、雲と地形との組み合わせや雲の濃さが表現されています![VRChat_1920x1080_2022-02-22_00-36-16.493.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1376552/84aedf13-3b1d-9bcd-14a9-781bf28b95b4.png)
![VRChat_1920x1080_2022-02-22_00-36-38.409.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1376552/2bfc9210-2d0c-e5af-bdf2-e6a838da4141.png)


この種類の手法は、ゲームではゼノブレイドなどに採用されていることが知られています
[『ゼノブレイド2』の世界を覆う雲海は、光を行進させる“レイマーチング”で生み出された【CEDEC 2018】 \- ファミ通\.com](https://www.famitsu.com/news/201808/23162812.html)

残念ながら現在VRChatには使えませんが、超高品質雲アセットの[Massive Clouds Atmos](https://assetstore.unity.com/packages/tools/particles-effects/massive-clouds-atmos-volumetric-skybox-173160)でもこの手法が採用されています
<iframe width="560" height="315" src="https://www.youtube.com/embed/gJH_xAu_D-0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

弱点としては基本的に他の手法より重くなりがちな点
そのためジッタリングと呼ばれる手法で、わざとノイズを乗せることで、処理量を稼ぐなど多くの小技が使われています
VRで雲の色合いが大きく変わる部分をよく観察すると細かいノイズが入っていることがわかります
このノイズの量と動作の軽さは相関関係にあるので、ノイズの少ない雲は基本的に重いか、めり込んだときの処理が粗いか、なんかすごいアルゴリズムが使われているかのどれかです

![VRChat_1920x1080_2022-02-22_15-52-04.276_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1376552/47f3f7b9-d30e-767e-6915-0093079cd9df.png)
（Shaderfesのalpha展示室にあるAyRaymarch_FlatCloudの上部の拡大図、負荷軽減のため強いノイズが入っている）

また、他の雲にも言えることですが、視線が雲の高さギリギリ上になっている水平線近くの処理も苦手になりやすく、横方向の遠方をいかに誤魔化すかも重要です
水平線のスカイボックスやフォグの色は雲と同色にしておくと馴染みが良くなります

### つかいどころ

総じて描画コストは多めですが、自分自身が雲に入り込む可能性が高いワールドには極めて有用ということになります
また、3次元的な計算で出力されているため、光や雲の表現力も高クオリティになりやすくなります
雲そのものが主役のシーンには是非！という感じ
雲だけではなく、低い場所を這うような霧の表現にも使うことができます

## 頂点シェーダー

<iframe width="560" height="315" src="https://www.youtube.com/embed/w__unVZzT6I" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
（動画の下の雲海部分）

バーテックスシェーダーとも呼ばれる手法で、ポリゴンで作られた面の頂点を移動させて雲を表現する方法です
基本的に海などを作るのと同じ発想で、境界面をはっきりポリゴンで区切っておきつつ、色々な手法で柔らかさを表現します
テッセレーションなどの設定をすることで近づいてもポリゴンが見えづらくなります

雲の中に入ったオブジェクトに対しては、雲までの距離とオブジェクトの面の距離を計算して雲の色をつけることで、沈むごとに色が変わっていくようにし、奥行きがあるかのように錯覚させます
![空白の図 - 2ページ (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1376552/d81c040b-59a5-764d-b592-1e4801750ed2.png)

Shaderfesアルファ展示室、リノールさんのSea Of Cloudsでキューブが空に刺さっているのはこのデモだと思います
![VRChat_1920x1080_2022-02-23_04-51-59.117.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1376552/411391bb-83ad-474c-9ee1-9b3be72df1b3.png)

密度があるように見えて実際には奥にあるオブジェクトによって表面の濃さが変わっているだけですが、かなりきれいに物が雲に沈んでいるように見えます
注意点として、オブジェクトがめり込んだ場合は問題ありませんが、カメラそのものが雲にめり込むと破綻します
そのため、雲の中にカメラが入り込んだ場合を切り分けて考えて、中に入った場合はポストエフェクトをかけるなどの手法を組み合わせて雲の中を表現したり、そもそもめり込まない位置に置いてしまう必要があります

ゲームではアウターワイルズが爆発や雲として使っています(34秒付近がわかりやすい)

<iframe width="560" height="315" src="https://www.youtube.com/embed/s2tnCGkBxDQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

Sky 星を紡ぐ子どもたちではバーテックスシェーダで雲を表現しています[^5]
[^5]: 実際にはメインが頂点シェーダーであるものの、複数の技術の合成と思われるのですが、ちょっと超技術過ぎてわからない部分があります
このゲームはスマートフォンでも動くのに非常に美しくて感動的な風景が広がっています
自由な形状にしやすいのもこの手法の特徴ですね

<iframe width="560" height="315" src="https://www.youtube.com/embed/rWgFCd8KQrc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

仕組み的には水面シェーダーと同じなので、水用のシェーダーの色味などを調節することで雲を表現することができます
[no1am（ノラム） さんの「雲海のアーキペラゴ」](https://vrchat.com/home/world/wrld_d8b71aca-ddfb-4529-8c12-c2790ad106e6)というワールドでは、[落雷さんのRAKURAIOceanShader](https://booth.pm/ja/items/1738547)のパラメータを変えて、しなやかで静かな雲海を表現しています
![VRChat_1920x1080_2022-02-23_04-44-36.164.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1376552/52e9df49-423f-8014-1a19-a909a8a5c7ea.png)

### つかいどころ

ポリゴンを使っているので、色々な手法との組み合わせがしやすく、負荷やルックの調節が容易という特徴があります
またレイマーチングやボリュームレンダリングよりも比較的軽量になりやすいです
実写的な風景よりも比較的くっきりと分けたいスタイライズドな風景にマッチしやすく、海の役割の延長としての雲海にも向きます

## ノイズ平面加工

<iframe width="560" height="315" src="https://www.youtube.com/embed/pOdVAYGMp10" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

他の２つの手法が3D空間上に立体的な雲を想定して描画するのに対し、この手法は平面もしくはノイズの断面を使います
無茶苦茶雑に言ってしまえば、お絵かきのように雲を書き込んでいます
元のノイズデータが変形するため、動画で見ると雲が流れるだけではなく形が変わっているのがわかると思います
[TowelCloud](https://gitlab.com/towelfunnelvrc/towelcloud/-/wikis/TowelCloud)ではカメラの方向から、雲の想定半球との交点を求め、その方向に見えるべき雲の濃さを決定したあとに画像的な加工をして立体に見せかけます
![空白の図 - 3ページ (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1376552/172c1d3f-da86-71f8-ae35-1670e640572d.png)

そのため雲の色合いなどにかなり自由度がある反面、潜ることができませんし、他の物体と交差することもできません
背景にあるものを透過することはできます

実際には立体ではないものなので、厚みを感じさせるのは工夫が必要です
雲の元になるノイズと言われるグラデーションの画像からの色が濃さを雲の厚みと想定します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1376552/8a4e6735-326c-827e-f949-702aa7903945.png)
厚みの変化量（勾配）から表面の傾きを算出します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1376552/4f69ccba-a4b1-9058-158e-dfe099f883da.png)
傾きをノーマルマップのように使い、雲の陰影をつけます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1376552/2b128915-a485-9c80-41b3-d2ca237f1c17.png)
リムライトや拡散光、フォグなどを擬似的に追加して立体感を乗せていきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1376552/0b53ee19-2683-3bda-2c97-4e21e4a11301.png)

弱点はたくさんあります
本来だと雲というのは特に水平方向に重なることがあるのですが、この手法の雲は1枚の平面から立体感を出しているので、雲同士が遮蔽することはなく繋がったようになってしまいます
そのため、平面のまま遠方に伸ばすと、水平線近くが極めて不自然になってしまいます
これを軽減するために普通は平面ではなく、空を覆う半球や楕円球を想定して計算を行います
とはいえそれでも雲同士の遮蔽は無いため、夏の入道雲のようなモクモクとした雲は再現できません

陰影のないものだったら作るのは非常に簡単なので、shaderの入門として試してみるのも良いと思います

https://styly.cc/ja/tips/unity_flowingcloud/

陰影があるものの細かい技術解説についてはまた記事を分けて書いていこうかと思っています

ゲームでは遠方から流れてくる背景の雲はたいていこの手法を使っています

クオリティが高すぎて平たいようには見えませんが、ゼルダの伝説BOWもこの手法です
根拠はこちらのバグ技動画で、16秒あたりからフィールドを囲むように2重に半球状の平たい雲（おそらくポリゴンではなく計算座標上の半球）が確認できます
<iframe width="560" height="315" src="https://www.youtube.com/embed/BLB8Hb_bpQE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

雲に陰影がついていることから、勾配データも持っていると思います[^4]

[^4]: なお続編の公開動画を見る限りそちらでは別の手法を使っているみたいですね、次回作は雲の中に入る可能性があるためでしょう

### つかいどころ

前提条件として絶対に潜らない雲である必要があります
処理をあまり重くはしたくないけど、Skyboxの止まった雲ではなくアニメーションはしてほしい場合や、容量を稼ぎたい場合に使えます
また色が固定指定しやすいので、完全指示した色が欲しい場合も有用になります

## まとめ

3D空間で動く雲を再現する方法を3種類紹介しました
雲に潜るのか潜らないのか、そして負荷とクオリティ、テイストの違いがわかってもらえたら良いなと思います
TowelCloudに使っているテクニックについてはまた別の機会に解説します
動く雲は大好きなので、みんながチャレンジして3D空間に動く雲が増えてくれたら嬉しいなと思っています

タオルくんでした