threejs-volumetric-clouds について
Three.js のボリュメトリッククラウド描画を設計・検証するスキルです。グラフィックス開発者向けに、密度、照明、時間再構成と、誤差・コストの評価を扱います。
主な機能
- 01ワークロードと表現の選択
- 02光学・運動モデルの定義
- 03保守的な密度境界とレイマーチング
- 04雲の照明とシャドウ手法
- 05時間再構成と合成
活用シーン
- 01局所・広域描画方式の選定
- 02密度スキップと総当たり描画の比較
- 03雲の影と放射誤差の検証
- 04低解像度の雲を時間方向に再構成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ linegel/ threejs-complete-set-of-skill --skill threejs-volumetric-cloudsインストール後、Claude Code で/threejs-volumetric-cloudsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSEagents/openai.yamlreferences/density-and-marching.mdlighting-and-shadows.mdtemporal-reconstruction.md詳細
ボリュメトリック雲
気象スケールの要因から大まかな形状を作り、その形状を細部で侵食し、光学、影、時間に関する誤差を測定できる、境界付きボリュームを構築します。
プロセス
1. 主張とワークロードの分岐を選択する
まず主張を明示します。プロシージャルな天候、カバレッジ、形状、細部は通常、作成者が定義する見た目のモデルを構成します。Beer-Lambert減衰は、宣言された密度と係数に対して物理的です。デュアルローブ位相関数の近似、オクターブ多重散乱補償、パウダー、単純な地面反射は、輸送のリファレンスと照合して検証されるまでは近似のままです。
独立した各ワークロードの分岐を選択します。
| 判断 | 選択 | 証拠 |
|---|---|---|
| 局所的か広域か | 投影境界が小さい場合はフル解像度で範囲を限定したマーチング、広域をカバーする場合は低解像度のマーチング | 分岐全体のGPUコストと画像誤差 |
| 現在のグリッドをフル解像度にするか低解像度にするか | 再利用が少ない場合は現在のグリッドをフル解像度にし、広域で一貫性のある雲の場合はグリッドを低解像度にして再構成する | 現在のサンプル数、帯域幅、再構成誤差 |
| 密か疎か | 占有率が高い場合は境界付き適応マーチング、占有率が低い場合は保守的なマクロセルDDA | 階層構築・トラバーサルのコストを上回るサンプル数の削減 |
| レシーバーの影 | 雲の影に対する外部レシーバークエリがない場合はなし、地面/不透明レシーバーには列全体を対象とする2D光学的深度、雲内サンプルには短い太陽光マーチングまたは深度を考慮したライトプロダクト | 許可されたレシーバークエリと透過率誤差 |
| 降水 | 見た目のみの演出、または$threejs-rain-snow-and-wet-surfacesが受け取る、因果関係を考慮した液体/氷の放出 | 単位を明記した放出量、サポート範囲、輸送遅延、保存誤差 |
因果関係を考慮した降水では、液体と氷の質量フラックスをkg m^-2 s^-1で公開するか、時間間隔で積分した面積あたり質量をkg m^-2で公開します。その際、サンプル時刻、サンプル間隔、物理フレーム/原点、物理サポート範囲、面積/ヤコビアンの規約、落下遅延または輸送モデル、所有者、コントラクトのバージョン、世代、有効性、保存性のゲート、誤差を明示します。各時間間隔のデータは一度だけ$threejs-rain-snow-and-wet-surfacesに公開します。レシーバーはフラックスを時間間隔の質量に一度だけ変換し、宣言されたサポート範囲/ヤコビアンを維持したうえで、蓄積前に宣言された遅延または輸送を適用します。
密度/放出のレシピ、互換性のない物理フレーム/原点のマッピング、サポート範囲/ヤコビアンの規約、または遅延モデルが変更された場合は、新しい世代を開始します。レシーバーは古い世代または互換性のない世代を拒否し、以前の時間間隔の質量を再解釈しません。見た目のみの分岐は視覚用途に限定し、レシーバー入力を公開しません。
none分岐では、レシーバーの影のプロダクトを割り当てません。
完了条件: 5つすべての判断で、選択した表現とその観測可能な指標を明示していること。許可される各ワークロードに、反証可能なコストまたは誤差のゲートがあること。noneのレシーバー影分岐ではレシーバーコンシューマーを記録せず、割り当てをゼロにすること。見た目のみの降水ではレシーバー入力を公開しないこと。因果関係を考慮した降水では、単位を明記した世代が1つだけ存在し、互換性のあるコンシューマー1つがそれを受け入れること。
2. 1 つの光学モデルと運動モデルを定義する
無次元の形状密度を length^-1 の beta_s および beta_a とともに使うか、質量固有係数を使った物理的な質量密度を選びます。最初から最後まで同じ規約を保ちます。
以下の方程式では、beta は rho に対応する係数を表します。形状密度の場合は長さの逆数、物理的な質量密度の場合は質量あたりの面積です。
sigma_s = rho * beta_s
sigma_a = rho * beta_a
sigma_t = sigma_s + sigma_a
tau = integral sigma_t ds
T_step = exp(-sigma_t*ds)
DeltaL = T_acc * (j/sigma_t) * (1-T_step)
光学的厚さがゼロになる極限には DeltaL = T_acc*j*ds を使います。この極限は係数単独ではなく、sigma_t*ds に基づいて選択し、安定した expm1/級数評価を使います。ここで j は単位長さあたりの放射輝度です。直接光については、立体角積分が必要な有限円盤放射輝度と、明示的に定義された平行光照度の規約とを区別します。
位相関数は 2*pi*integral_-1^1 p(mu)dmu=1 となるよう正規化します。rayDirection はカメラからサンプルへの方向、toSun はサンプルから太陽への方向とします。このとき、mu=dot(toSun,rayDirection) により、mu=1 が前方散乱になります。二重ローブの重みは非負とし、合計を 1 に保ちます。
物理フレームとレンダリングフレーム間の変換、メートル単位のスケール、雲状態のクロック、およびマクロな空気速度をそれぞれ 1 つ定義します。経過シミュレーション時間にわたって速度を積分し、相対的な気象/形状/ディテールの動きは、そのマクロ移流からの有界なオフセットとして扱います。
完了条件: 均質なスラブがステップ分割に対して不変で、消散がゼロになる極限に到達すること。位相関数の求積が期待どおりの前方方向で正規化されること。更新頻度が異なる 2 つの処理が、許容誤差内で同じ運動軌跡を積分すること。
3. 有界かつ保守的な密度を構築する
高度/プロファイル、気象、形状、光学特性、および運動を通して、アクティブなレイヤーを分けて扱います。低周波の気象場とコンパクトな鉛直プロファイルで雲の質量を定義します。解像可能なスケールで形状を適用します。ディテールは高度に応じた浸食として使います。占有境界を粗くすることはできますが、保守的な境界計算で使う、気象/基本形状によって決まる空集合は維持する必要があります。
マクロオフセットを 1 つ積分し、有界な相対オフセットを加えます。
macroOffset += integral u_air(t) dt
weatherOffset = macroOffset + relativeWeatherOffset
shapeOffset = macroOffset + relativeShapeOffset
detailOffset = macroOffset + relativeDetailOffset
レイと、選択した球殻、スラブ、OBB、またはスパースボリューム領域との交差を求め、終点を最も近い不透明なシーン深度に制限します。占有された高度範囲を統合し、その補集合であるギャップだけをスキップします。水平方向の疎性には、気象、プロファイル、形状、ワープの到達範囲、および密度を増加させるすべての操作を含む最大密度マクロセルを構築します。平均ミップは外観用のフィルターであり、占有境界ではありません。
密度方程式、領域との交差、保守的なスキップ境界、およびステップ選択については、references/density-and-marching.md を参照してください。
完了条件: デバッグビューによって、スキップされたすべての区間/セルが空であるか、宣言された省略放射輝度の境界内にあることが証明されること。また、総当たりマーチと高速化マーチの透過率、HDR 放射輝度、および最初に寄与した深度が一致すること。
4. 選択した表現をマーチングしてライティングする
現在のシーンリニアな雲の放射輝度、透過率、および選択した時間方向の分岐に必要な深度データを書き込みます。光学的深度、解像済みフィールドの帯域幅、セル/レイヤーの境界、オペーク深度、雲区間の残りに基づいてステップを制限します。残りの光源誤差と背景減衰誤差に、すでに累積したスキップ誤差を加えた値が出力ゲートに収まった場合にのみ終了します。
Three.js r185 では、await renderer.init() を実行し、コンピュート/ストレージ処理を割り当てたり送信したりする前に renderer.backend.isWebGPUBackend === true を必須条件とします。その後、Fn().compute(count) を renderer.compute() から送信します。2D の現在/履歴/シャドウ用データには StorageTexture を使用し、書き込み可能なボリュームフィールドに限り Storage3DTexture を使用します。computeAsync() は処理をキューに登録するものであり、完了フェンスではないものとして扱います。PassNode.setResolutionScale() はパス全体をスケーリングするため、ホストシーンは必要な解像度に保ち、解像度を下げた雲は独自のパス/リソースに配置します。
雲の自己シャドウは、雲の光学的深度のみから計算します。地面のレシーバーには、太陽光線に沿った全区間を使用できます。雲内のサンプルには、その位置からの光学的深度が必要です。これは、短い太陽光線方向のマーチング、ディープオパシティスライス、または深度を考慮した別の表現で与えます。
タスクに散乱、大気由来の光、位相関数のフィッティング、雲のシャドウ、またはシャドウフィルタリングが含まれる場合は、 references/lighting-and-shadows.md を参照してください。
完了条件: ステップを半分にする制御と高照度サンプル数の制御が線形 HDR 誤差ゲートに収まり、雲を無効にする制御で透過率が 1、雲の放射輝度が 0 になり、許可された各シャドウ問い合わせで実際のレシーバー位置から光学的深度がデコードされること。
5. 広範囲の雲を再構築する
広範囲をカバーする解像度低減ブランチでは、オパシティで重み付けした代表深度と深度の広がりを格納します。
w_i = T_i * (1-T_step_i)
z_bar = sum(w_i*s_i)/sum(w_i)
variance_z = sum(w_i*(s_i-z_bar)^2)/sum(w_i)
寄与の分布が単峰性の場合にのみ、単一の代表面を使用します。広がりのあるレイヤーや複数のレイヤーには、前面深度とモーメント、または分割した履歴を使用します。移流する代表物理点を前のカメラに再投影します。不変の「現在のレンダリングから物理」への変換と「前の物理からレンダリング」への変換を記録し、原点の再基準化をまたぐ場合はこれらの変換を介してマッピングします。ホストの表面速度は別の信号です。
フレームレートに依存しない現在応答でブレンドします。
alpha_current = 1-exp(-dt/responseTime)
resolved = alpha_current*current + (1-alpha_current)*clippedHistory
ビューポート外、または深度/広がりの不一致、カメラカット、投影の変更、天候/トポロジーの不連続、エンコーディングの変更、解像度/ティアの変更、前の原点マッピングの欠如または互換性の欠如がある場合は、履歴を棄却します。ディスオクルージョン時や信頼度が低い場合は、現在応答を高めます。演算の前に無効なサンプルを棄却します。プレマルチプライされた線形 HDR の放射輝度と透過率は個別に分散クリップし、その後、区間に互換性のある輸送のみをアップサンプリングします。平均深度や前面深度では、隠れた背面の寄与を除去できません。
履歴、疎なフェーズ、深度エンコーディング、リセットポリシー、またはアップサンプリングが対象範囲に含まれる場合は、 references/temporal-reconstruction.md を参照してください。
完了条件: 密度を平行移動させる制御で期待される前のピクセルに再投影され、マッピングされた浮動原点の再基準化でもそのピクセルが維持され、カメラカット/トポロジー/互換性のない原点の制御で履歴の信頼度が 0 になり、測定したゴーストの減衰が応答モデルと一致し、深度エッジでのアップサンプリングがオペーク面をまたがないこと。
6. ライティングと画像の受け渡しを統合する
入射光の契約を1つ選択します。
- 所有者、リビジョン、サンプル時刻と経過時間、座標系、量、単位、基準、方向または角度範囲、フィルター、含まれる減衰、妥当性、誤差を宣言する、作成者が定義した光源。または
- 同じタプルを宣言する、大気ライティング。
大気の分岐では、大気によってすでに減衰した直接光、または大気透過率を伴う減衰前の光源のいずれかを選択します。適用対象となる雲のみの各透過率と不透明度による可視性係数は、それぞれ個別に乗算します。方向性の天空放射輝度と半球天空照度は区別してください。
ホストのトーンマッピングより前に雲を合成します。この転送が適用されるのは、モデル化された区間です。大気と雲の媒体が重なる場合は、区間全体に対する大気と雲の合成を直列に2回行うのではなく、連成したカメラ経路ソルバー、または検証済みの交互処理が必要です。
C_out = L_cloud + T_cloud * C_scene
WebGPURendererを1つ、ホストのRenderPipelineを1つ使用します。データリソースには、形式、フィルター、ミップマップのポリシーを明示し、NoColorSpaceを設定します。1回のディスプレイ変換は、ホストのrenderOutput()またはoutputColorTransformに任せます。診断用出力ノードを置き換えた後は、パイプラインをダーティとしてマークしてください。
完了条件: 入射光源の契約が完全に定義され、適用される大気、雲、ジオメトリの各係数が1回ずつ計上される減衰トレースがあり、雲バッファーが線形HDRのまま保たれ、雲をオフにするとホストの画像経路がまったく同じ状態に戻ります。
7. システムを検証する
以下を検証します。
- 均質スラブの転送、消光係数がゼロに近づく極限、位相関数の正規化
- 境界、奥行きによる不透明度クランプ、保守的なスキップ、早期終了誤差
- 固定シードでのウェザーマップの質量、侵食、オクターブフィルタリング、移流の連続性
- 適用対象となる各地表または雲内シャドウデコーダー、更新間隔、古い生成物の拒否
- 因果的な降水の場合、フラックスから区間への積分、更新間隔の再分割と物理的支持範囲/ヤコビアンによる面積の再分割時の質量保存、宣言された遅延から到達までの対応付け、古い世代の拒否。外観のみの制御では、受信側の入力を公開しないこと
- 適用対象となる各時間分岐について、密度の平行移動、奥行きエンコーディング、履歴の拒否、応答時間、奥行き対応アップサンプリング。座標原点の対応付けられた再配置と、互換性のない再配置も含めること
- 固定視点のHDR放射輝度、透過率、シルエット、ハローを、より高品質な参照と比較すること
- 作成、GPU処理の完了、破棄、および適用対象となる各リサイズ/品質層切り替え、履歴リセットのライフサイクル
完了条件: 選択したすべての分岐が、数値、時間、視覚、ライフサイクルの各ゲートに合格し、診断で保持されている各密度、シャドウ、履歴、因果的降水の世代が特定されます。
障害の兆候
| 症状 | 調査対象 |
|---|---|
| 多孔質な煙、または沸騰するようなちらつき | ウェザーマップの質量の原因、詳細の侵食、オクターブフィルター、共有される移流 |
| ステップ数による明るさの変化 | 光源の単位、または転送の積分 |
| カメラの遠平面に応じてコストが増加 | ボリューム境界、または奥行きによる不透明度クランプ |
| スキップ中に密度が消える | 古い、または非保守的なメジャー |
| カメラ移動による残像 | 代表奥行き、雲の速度、または拒否処理 |
| 平坦、または浮いて見える地表の影 | 受信側の表現、投影、または経過時間 |
| 雲の切り替え後に色が変わる | トーンマッピングの重複、または出力変換 |
担当範囲
このスキルの担当範囲は、ウェザーマップに基づく雲の密度、境界付きの雲輸送、雲のみの光学的深度シャドウ、雲固有の再構成です。分子/エアロゾル輸送と共有される太陽/天空光源には$threejs-sky-atmosphere-and-haze、シーン信号と最終出力には$threejs-image-pipeline、因果的な降水輸送と受信側での蓄積には$threejs-rain-snow-and-wet-surfaces、不透明なジオメトリのシャドウマップには$threejs-scalable-real-time-shadowsを使用してください。