threejs-geometry について
Three.js のメッシュ形状と頂点データを扱うスキルで、ジオメトリの選択と構築を支援します。ジオメトリ表現、有効な属性、測定に基づく最適化、所有権、形状検証を扱います。
主な機能
- 01プリミティブまたはカスタムジオメトリの選択
- 02位置・法線・色・UV・インデックスバッファの作成
- 03動的属性と境界の更新
- 04測定された描画コールのボトルネックにインスタンシングを適用
- 05ジオメトリの所有権と破棄の管理
活用シーン
- 01頂点データからカスタムメッシュを作成
- 02法線、UV シーム、巻き順、カリングの問題を修正
- 03実行中に変化するジオメトリを更新
- 04反復メッシュの描画コールを削減
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ akillness/ jeo-skills --skill threejs-geometryインストール後、Claude Code で/threejs-geometryを入力して読み込まれたか確認します。
同梱ファイルSKILL.toonevals/evals.json
詳細
Three.js ジオメトリ
メッシュの形状や頂点データを扱う場合は、このスキルを使用してください。表面の見た目については
threejs-materials、画像や UV アセットの処理については threejs-textures、シーン全体のセットアップについては
threejs-fundamentals に振り分けてください。
このスキルを使用する場面
- 組み込みプリミティブ、
BufferGeometry、ShapeGeometry、テキストジオメトリを選択する - カスタムメッシュ用の位置、法線、色、UV、インデックスを生成する
- 動的属性を安全に更新する、または壊れた法線、頂点の巻き順、カリングを修正する
- 描画コールのコストを測定したうえで、同一のメッシュの繰り返しを
InstancedMeshに置き換える
手順
ステップ 1:最もシンプルなジオメトリ表現を選択する
- トポロジーが機能に合致する場合は、組み込みジオメトリから始めます。
- 生成またはインポートした頂点データには
BufferGeometryを使用します。旧式のGeometryは、現在の Three.js では使用しません。 - 頂点が実際に共有されている場合は、インデックス付きジオメトリを選択します。法線、UV、頂点カラーを変える必要がある継ぎ目には、インデックスを設定しないでください。
- 機能が明示的に所有する場合を除き、1 つのメッシュのジオメトリは変更しない共有データとして扱います。インスタンスごとに変更する前にクローンしてください。
ステップ 2:有効な属性バッファーを構築する
const geometry = new THREE.BufferGeometry();
geometry.setAttribute(
"position",
new THREE.Float32BufferAttribute([
-1, -1, 0,
1, -1, 0,
0, 1, 0,
], 3),
);
geometry.setIndex([0, 1, 2]);
geometry.computeVertexNormals();
geometry.computeBoundingSphere();
const mesh = new THREE.Mesh(geometry, material);
属性の項目サイズは、意味に合わせる必要があります。位置と法線は 3、UV は 2、色は通常 3 です。GPU にアップロード済みの属性を変更した後は、attribute.needsUpdate = true を設定してください。動的な位置が以前の境界を超えて移動する可能性がある場合は、境界を再計算してください。
ステップ 3:測定でボトルネックを確認してからパフォーマンス機能を適用する
| 状況 | 推奨される方法 |
|---|---|
| 1 つのジオメトリ/マテリアルのコピーが多数ある | InstancedMesh |
| インスタンスごとの色や変換 | インスタンス属性/行列 |
| 大規模な静的地形またはモデル | インデックス付き BufferGeometry、適切なカリング |
| 非常に小さなパーティクルが数千個ある | 1 つのジオメトリ/マテリアルを使う Points |
| デバッグ用エッジまたは技術的なワイヤーフレーム | EdgesGeometry / WireframeGeometry |
| トポロジーまたはマテリアルが異なる | 別のメッシュを使用します。インスタンス化を無理に適用しないでください |
const instances = new THREE.InstancedMesh(geometry, material, count);
const matrix = new THREE.Matrix4();
for (let i = 0; i < count; i += 1) {
matrix.makeTranslation(i * 2, 0, 0);
instances.setMatrixAt(i, matrix);
}
instances.instanceMatrix.needsUpdate = true;
ステップ 4:所有権と破棄を管理する
機能が所有するジオメトリを使用するものがなくなったら、geometry.dispose() を呼び出してください。置き換えた後は、置き換え前のジオメトリを破棄します。アセットローダーのキャッシュ済み/共有ジオメトリは、最後の利用者がいなくなるまで破棄しないでください。
ステップ 5:形状と予算を確認する
- ヘルパーやデバッグビューを使って、法線、UV の継ぎ目、面の巻き順、境界ボリュームを確認します。
- 穴、NaN、または裏面の欠落がないか、代表的な低密度および高密度の入力で確認します。
- インスタンス化の前後で、描画コール数と GPU/CPU のフレーム時間を測定します。
- 機能の通常のライフサイクルと破棄処理を通じて、動的なジオメトリの更新をテストします。
例
破棄可能なプロシージャルグリッドを構築する
安定した入力値から属性を生成し、アップロード前に配列の長さを検証してから、ジオメトリの所有者をクリーンアップ関数とともに保持します。大規模なジオメトリを毎フレーム再作成するのは、ほとんどの場合バグです。測定で妥当性が確認された場合に限り、動的属性を変更してください。
読み込んだメッシュまたは生成したメッシュを中央に配置する
geometry.computeBoundingBox() を使用し、その中心からオフセットを算出してから、境界を更新します。単一の頂点から中心を推測したり、アセットのローカル原点に意味がある場合にメッシュ変換を適用したりしないでください。
ベストプラクティス
- シーン内で座標系と単位の規則を統一します。
- 型付き配列を使用します。毎フレーム、オブジェクト配列から頻繁に使う頂点バッファーを構築しないでください。
- トポロジーや位置に応じて必要な場合にのみ法線を再計算し、レンダリングのたびに再計算しないでください。
- 動的な位置を変更した後は境界を更新し、視錐台カリングが正しく機能するようにします。
- インスタンス化は描画コールを最適化するものであり、コストの高いシェーダーや過剰に詳細なジオメトリを解決するものではないと考えてください。