web3d-runtime について
three.jsでWeb 3Dシーンを開発する人向けのスキルです。WebGPUとWebGL2、シェーダー、性能測定、フォールバックを扱い、three.js r186で確認された互換性上の問題を重視します。
主な機能
- 01バージョン、レンダラー、フレームループの確認
- 02WebGPUとWebGL2のフォールバック案内
- 03TSLとコンピュートシェーダーの解説
- 04事前コンパイル、測定、リソース解放
- 05未実施の検証項目の明示
活用シーン
- 01WebGPUシーンの描画不具合の調査
- 02ShaderMaterialからTSLへの移行
- 03低性能デバイスでのフレーム時間の測定と調整
- 04デバイスロストやWebGPU非対応時の計画
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ssheleg/ web3d-dev --skill web3d-runtimeインストール後、Claude Code で/web3d-runtimeを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/performance-and-r3f.mdrenderer-and-loop.mdtsl-and-compute.md詳細
web3d-runtime — あらゆる GPU でシーンを実行し、その速さを証明できます
three.js の WebGPU 対応は急速に進化しています。r186 では、r180 で警告されていた箇所が例外を投げ、ポストプロセッシングのエントリポイントが改名され、Clock が非推奨になりました。それでも、同じ API の下には WebGL2 バックエンドが引き続き用意されています。ここでのバグの多くは目立ちません。シーンはレンダリングされますが、表示は正しくありません。そのため、このスキルではまず失敗例を取り上げ、それからパターンを説明します。
最初のアクション — 調査してから報告する
- バージョン。
package.jsonからthree、@react-three/fiber、@react-three/dreiを確認します。ここに記載されている情報は r186 に固定されています。別のリリースを使用している場合は、名前をそのまま信頼する前にreferences/renderer-and-loop.md→ Version notes を確認します。 - レンダラー。
three/webgpuのWebGPURendererですか、それとも従来のWebGLRendererですか?ShaderMaterial、RawShaderMaterial、onBeforeCompileをカスタムで使用している箇所はありますか? これらは WebGPU では動作しません(注意点)。 - ループ。 フレームを管理するのはどれですか?
setAnimationLoop、R3F のuseFrame、それとも複数のrequestAnimationFrameですか(バグです。シーンごとにクロックは 1 つです)。 - 速度の根拠。 Inspector、タイムスタンプ、最も性能の低い対象環境で負荷をかけた状態の FPS など、測定結果はありますか? それとも、感覚だけですか?
領域 · 現状 · 問題 · 修正 の表を報告し、次のアクションを 1 つだけ示します。
機能の段階
シーンごとに上から適切な段階を選びます。どの段階でも、ページが正常に動作する必要があります。
- WebGPU —
new WebGPURenderer()を実行し、その後await renderer.init()を呼び出します。 - 同じレンダラーの WebGL2 バックエンド — WebGPU が利用できない場合は自動的に使用されます(
running under WebGL2 backendとログに出力されます)。forceWebGL: trueで強制できます。この場合、計算負荷の高い機能には軽量な経路が必要です。init()の後にrenderer.backend.isWebGPUBackendで判定します。 - 穏やかな表示 — WebGL がまったく使えない場合、モーションの軽減が有効な場合、または復旧できないデバイスロストが発生した場合は、静止画像または CSS/SVG で、文字が完全に読める状態を保ちます。これは
sheleg-designの「穏やかな表示に切り替える」ルールを 3D シーンに適用したものです。
注意点 — r186、いずれも気づきにくいか、意外な挙動です
await renderer.init()の前にrender()を呼ぶと例外が発生します(そのため、clear()、hasFeature()、initTexture()を実行してください)。setAnimationLoopは自ら初期化を待機します。renderAsyncなどは r181 以降、非推奨です。positionNodeはスキニング、モーフィング、インスタンシングの後に位置を置き換えます。positionLocal.add(offset)ならそれらを維持できますが、positionGeometry.add(...)やbuffer.element(instanceIndex)だけでは、すべてのインスタンスが一点に潰れてしまいます。パーティクルでは 公式のパターンを使ってください。スプライトまたはポイントマテリアルでpositionNode = buffer.toAttribute()を指定します。- JS の再代入はシェーダーのストアではありません。
Fn内でa = a.add(1)としても、JS の名前が再束縛されるだけで 何も出力されません。.toVar()の後に.assign()/.addAssign()を使ってください。ノードに対する JS のifや 三項演算子も同じ問題があるため、If/selectを使ってください。 - アトミック演算の前に
storage(buf, 'uint', n).toAtomic()が必要です。 - **
computeAsync()は GPU の処理完了を待ちません。**結果を CPU に読み戻すのはrenderer.getArrayBufferAsync()だけです (r186 では再利用可能なTHREE.ReadbackBufferを使用できます)。 ShaderMaterial、RawShaderMaterial、onBeforeCompileに WebGPU 対応のマッピングはありません — オブジェクトは 「互換性なし」エラーとともに、通常のノードマテリアルとしてレンダリングされます。TSL に移植してください。drei の約 20 個のコンポーネントはこれらを基盤としており、同じように動作しません。- **アダプターは互換モードで要求されます。**互換モードしか提供しないデバイスでは、MSAA が通知なしに無効になります。
- WebGPURenderer では
alphaのデフォルト値がtrueです(WebGLRenderer では false)。不透明なキャンバスを前提とした 移植では、ページがキャンバス越しに見えてしまいます。 PostProcessingはRenderPipelineになりました。****Clockは非推奨です —Timer(core)を使ってください。 WebGPU ではPCFSoftShadowMapが削除されました(r183 以降、PCFShadowMapがソフトシャドウです)。renderer.dispose()は非同期です。- デバイスロスト:
renderer.onDeviceLostを使ってください(検証エラーやメモリ不足エラーにはrenderer.onErrorを使います)。 これは両方のバックエンドにあります。WebGPU デバイスに直接フックすると、WebGL2 へのフォールバック時に動作しなくなります。 - **R3F 9.8.1 のデフォルトは three.js と異なります。**ACES トーンマッピングが有効で、
shadows={true}は削除済みの ソフトシャドウマップを選択します(shadows="percentage"を使ってください)。また、useFrameのデルタ値はクランプされません。
手順
- レンダラーとループ — レンダラーは 1 つ、
await init()、setAnimationLoopは 1 つ、Timerも 1 つです (references/renderer-and-loop.md)。 - マテリアルとシェーダー は TSL で記述し、パーティクル単位またはインスタンス単位の処理にはコンピュートを使います
(
references/tsl-and-compute.md)。 - **事前ウォームアップ:**最初に表示されるフレームの前に
await renderer.compileAsync(scene, camera)を実行し (コンピュートにはcompileComputeAsyncも実行)、最初の操作で引っかからないようにします。 - 最も性能の低い対象で計測し、Inspector またはタイムスタンプクエリを使ってから、予算を割り当てます
(
references/performance-and-r3f.md)。 - **段階的に機能を落とす:**モーション低減、WebGPU 非対応、デバイスロスト、タブ非表示にはそれぞれ明記された 分岐があり、各分岐の動作を確認済みです。
- **後片付け:**ジオメトリ、マテリアル、テクスチャ、レンダーターゲットを破棄します。
await renderer.dispose()を実行します。
必要なものがない場合
- このホストにツールがまったくない場合 → コマンドとコードを記述し、実行結果は記述しません。計測していないサイズ、
パス、フレーム時間、「完了」は捏造された証拠です。そのようなチェックにはそれぞれ
NOT_RUNと記し、人が実行すべき内容を説明します。 - このホストにブラウザーや GPU がない場合 → ビルド、型チェック、レビューを行います。視覚的な確認とフレーム時間の判定には
NOT_RUNと記し、人が使うべきページとデバイスを示します。コードを読んだだけで「滑らか」と報告してはいけません。 - プロジェクトが古い three.js を使っている場合 → リリース間の差を明記します。r186 の名前をそのまま適用せず、 オペレーターの許可なしに依存関係をアップグレードしてはいけません。
- R3F プロジェクトで WebGPU を使う場合 →
references/performance-and-r3f.mdにある非同期glファクトリーパターンを使います。 切り替え前に、シーンで使われている WebGPU では動作しない drei コンポーネントを列挙します。
参考資料
| 読む項目 | 読むタイミング |
|---|---|
references/renderer-and-loop.md | レンダラー、フォールバック、ループとクロック、色とトーンマッピング、ポストプロセッシング、デバイスロスト、破棄処理を作成するとき |
references/tsl-and-compute.md | TSL マテリアルやシェーダー、コンピュートパス、パーティクル、アトミック操作、読み戻しを作成するとき、または GLSL を移植するとき |
references/performance-and-r3f.md | フレーム時間、ドローコール、メモリの計測や修正を行うとき、WebGPU で React Three Fiber を実行するとき、WebGPU で drei を使うとき |
アセットファイルと予算については web3d-assets、アニメーションの作成については web3d-animation を参照してください。公開されている
webgpu-threejs-tsl スキル(dgreenheck)は、このスキルの落とし穴を先に示す構成の参考になりました。
r186 に照らしてサンプルを再検証した際に見つかった誤りは、上記の落とし穴に含まれています。
トリガー
このスキルに誘導するその他のフレーズ:「WGSL」、「compute shader」/「コンピュートシェーダー」、「particles collapsed」/「パーティクルがつぶれた」、「device lost」/「デバイスロスト」、「React Three Fiber」、「post-processing」/「ポストプロセッシング」、「WebGL fallback」。
0.2.4 の説明からこちらに移動しました:「three.js WebGPU」、「3D シーンが遅い」。