TL

メッシュとジオメトリ表現

3D モデルがなぜ頂点バッファとインデックスバッファに分かれるのか、法線・UV・接線が何のためにあるのかを、GPU の都合と幾何の両面から整理し、LOD やハーフエッジまで見通せます。

応用グラフィックスメッシュ頂点バッファLODテッセレーション最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.メッシュは頂点属性の配列(頂点バッファ)と三角形の頂点参照の配列(インデックスバッファ)に分かれ、共有頂点を再利用してメモリと変換コストを削る。
  • 2.法線は陰影、UV はテクスチャ、接線はノーマルマップの座標系に必要で、これらの不連続がある頂点は位置が同じでも複製せざるを得ない。
  • 3.LOD は距離に応じて三角形数を落とす仕組み、テッセレーションは GPU 上で三角形を細分する仕組みで、位相編集にはハーフエッジのような隣接情報を持つ表現が使われる。

メッシュは「点の属性」と「点のつなぎ方」を分けて持つ

3D モデルの標準的な内部表現はポリゴンメッシュ、実務上はほぼ三角形メッシュです。曲面も含めあらゆる形状は最終的に三角形の集まりへ分解され、GPU(/hardware-components/ 参照)はこの三角形を単位に処理します。ここで押さえるべき本質は、メッシュが 「頂点そのものが持つ属性」「どの頂点をどうつないで三角形にするか」 という2種類の情報を、別々の配列として保持する点です。

前者を格納するのが 頂点バッファ、後者が インデックスバッファ です。頂点バッファには各頂点の位置・法線・UV・色などが並び、インデックスバッファには「三角形 k は頂点 a, b, c で構成される」という参照が三つ組で並びます。両者を分けるのは、隣接する三角形が頂点を共有するからです。立方体の各頂点は3面に共有され、細かいメッシュでは1頂点が平均6枚前後の三角形に共有されます。位置や法線を三角形ごとに丸ごと持てば同じデータが何度も重複しますが、インデックス参照なら実体は1つで済みます。

インデックス描画のデータ構造:

  頂点バッファ(Vertex Buffer)… 頂点の実体を1つずつ
    v0 = { pos, normal, uv, ... }
    v1 = { pos, normal, uv, ... }
    v2 = { pos, normal, uv, ... }
    v3 = { pos, normal, uv, ... }

  インデックスバッファ(Index Buffer)… 三角形 = 頂点番号の三つ組
    tri0 = (0, 1, 2)
    tri1 = (0, 2, 3)
      共有頂点 v0, v2 は実体1つを2つの三角形が参照

この分離はメモリ削減だけでなく、頂点シェーダの実行回数を減らす 効果が大きい。GPU は変換済み頂点を小さなキャッシュ(ポストトランスフォームキャッシュ)に保持し、同じインデックスが再登場すれば頂点シェーダを再実行せずキャッシュ結果を使います。頂点の参照順をキャッシュに乗りやすく並べ替える最適化を 頂点キャッシュ最適化 と呼び、描画性能に直結します。

ストリップとファンより、インデックス描画が主流

かつては頂点共有のためにトライアングルストリップ(直前2頂点を使い回して1頂点で1三角形を追加)やファンが多用されました。今は任意の接続を表せて頂点キャッシュも効くインデックス描画が主流です。ストリップは形状に制約がある一方、インデックスバッファは接続の自由度が高く、ツールチェーンやハードウェアの最適化も充実しています。

頂点属性 ── 法線・UV・接線はそれぞれ別の目的を持つ

頂点が持つ属性は位置だけではありません。代表的なのが 法線・UV・接線 の三つで、混同されがちですが目的がまったく異なります。

属性何を表すか何に使うか
位置モデル空間の座標 (x,y,z)座標変換・ラスタライズの基礎
法線 (normal)その頂点での面の向き(単位ベクトル)陰影計算(拡散・鏡面)で光の当たり方を決める
UV (texcoord)テクスチャ画像上の2D座標頂点をテクスチャのどこに対応づけるか
接線 (tangent)UV の U 方向に沿った面内ベクトルノーマルマップを面上の座標系へ展開する

法線 は陰影の要です。ランバート反射なら明るさは法線と光源方向の内積で決まり、鏡面反射も視線と反射ベクトルの関係で計算するため、面の向きを表す法線が必須です。頂点法線は通常、その頂点を共有する面法線を面積などで重み付き平均して求めます。滑らかに繋げたい面ではこの平均で丸め、折り目として見せたいエッジ(ハードエッジ)ではあえて平均せず、辺の両側で別々の法線を持たせます。

UV はテクスチャ空間への写像です。3Dサーフェスを2D画像へ「展開(UV アンラップ)」した結果を、各頂点の (u, v) として持ちます。ラスタライズ時にこの UV を画素位置へ補間し、テクスチャをサンプリングします。透視投影後は単純な線形補間だと歪むため遠近補正補間が必要ですが、それはラスタライザ側の仕事です。

接線 はノーマルマップのために存在します。ノーマルマップはテクスチャの各テクセルに「面に対する相対的な法線」を格納したもので、これを実際の空間へ持ち込むには、面上に基準となる座標系(接線空間, TBN)が要ります。接線 T(U 方向)、従接線 B(V 方向)、法線 N の3本で TBN 行列を作り、テクスチャ内の法線をワールド空間の法線へ変換します。接線は UV の張り方に依存するため、UV が決まって初めて計算できる従属的な属性です。

属性が不連続な頂点は位置が同じでも複製が必要

GPU の頂点は「位置・法線・UV をひとまとめにした1レコード」であり、どれか一つでも値が違えば別頂点として複製せざるを得ません。UV の継ぎ目(シーム)、ハードエッジ(法線の折り目)、色の境界がある箇所では、幾何的には同一の点でも属性が2通り以上必要になり、その分だけ頂点が増えます。だから最終的な頂点数はモデルの「角の数」ではなく「属性の不連続の数」で決まります。UV シームやハードエッジを増やすほど頂点数が膨らむのはこのためです。

頂点フォーマットとメモリレイアウト

頂点バッファは単なる数値の並びで、GPU に対しては「各頂点が何バイトで、どのオフセットに何の属性があるか」を 頂点レイアウト(入力レイアウト) として別途宣言します。属性の並べ方には二方式があります。

レイアウト並べ方向いている場面
インターリーブ1頂点分の全属性を連続配置し、それを繰り返す全属性を毎回読む描画(キャッシュ効率が高い)
非インターリーブ属性ごとに別配列(位置だけの配列、法線だけの配列…)一部属性だけ使うパス(例: 深度のみ描画)

インターリーブは1頂点を読むと必要な属性が同じキャッシュラインに揃うため、通常描画で有利です。一方、シャドウマップ生成のように 位置だけあればよいパス では、位置だけを別配列にしておくと不要な法線・UV を読まずに済み帯域を節約できます。属性の精度も設計対象で、位置は32ビット浮動小数点、法線は正規化された符号付き整数へ量子化、UV は16ビット浮動小数点、といった圧縮でメモリと帯域を削るのが常道です。

LOD ── 遠いものは粗く

画面上で数画素にしかならない遠方のモデルに、数万三角形をフルで処理するのは無駄です。距離やスクリーン上の占有面積に応じて 三角形数の異なる版を切り替える のが LOD(Level of Detail)です。

古典的な方式は 離散 LOD で、あらかじめ高・中・低ポリの複数メッシュを用意し、距離のしきい値で入れ替えます。単純で高速ですが、切り替わる瞬間に形が飛ぶ ポッピング が起きるため、2つの LOD を一時的に重ねて溶かす(ディザや透過でクロスフェードする)などの緩和が要ります。三角形数を減らすメッシュ簡略化には、辺を1本潰して2頂点を1つに統合する エッジコラプス が広く使われ、統合時の形状誤差を二次誤差計量(QEM)で評価して誤差の小さい辺から潰します。

近年は連続的に詳細度を変える方向へ進み、メッシュを小さな三角形クラスタ(メッシュレット)に分割し、クラスタ単位で詳細度を選ぶ手法が実用化しています。クラスタごとに階層的な簡略化版を持ち、カメラから見て必要な粒度のクラスタだけを選んで描くため、モデル全体ではなく画面に効く部分だけ細かくできます。これは後述するメッシュシェーダの実行モデルと噛み合います。

LOD は三角形削減だけでなく「頂点処理と描画コール」の削減でもある

LOD の効果は塗る画素の削減にとどまりません。三角形が減れば頂点シェーダの実行回数、頂点フェッチの帯域、そして小さすぎる三角形(1〜2画素)が量産する非効率なラスタライズも減ります。特に遠景の密なメッシュは、画素は少なくてもサブピクセル三角形でシェーダ効率が激しく落ちるため、LOD は見た目以上に効きます。「遠い=軽い」ではなく、粗い版へ切り替えて初めて軽くなります。

テッセレーション ── GPU 上で三角形を増やす

LOD が主に三角形を減らす話なのに対し、テッセレーション は逆に GPU 上でパッチ(制御点の集合)を細分し、実行時に三角形を 増やす 仕組みです。粗い制御メッシュだけを転送し、細かい面は GPU が生成するため、頂点データの転送量を抑えつつ近距離では滑らかな曲面を作れます。

ハードウェアテッセレーションは、細分の密度(テッセレーションファクタ)を距離などに応じて動的に指定でき、これ自体が連続 LOD として働きます。生成した頂点を制御点から補間・変位させることで、ディスプレイスメントマップ(高さテクスチャ)による本物の凹凸も付けられます。ノーマルマップが陰影だけを偽装するのに対し、変位は実際にジオメトリを動かすため輪郭やセルフシャドウにも効く点が違いです。

テッセレーション段の流れ(概念):

  制御点パッチ(粗い面)
    │  ① 分割数を決める(距離が近いほど細かく)
    ▼
  固定機能テッセレータ … パッチを規則的に細分し新頂点を生成
    │  ② 生成された各頂点の重心/パラメトリック座標
    ▼
  頂点評価(制御点から実座標を計算・変位)
    │  ③ ディスプレイスメントマップで高さを加算
    ▼
  細分された三角形(下流のラスタライズへ)
細分しすぎは逆効果

テッセレーションで三角形を過剰に増やすと、1三角形が1画素未満のサブピクセル三角形だらけになり、ラスタライザとシェーダの効率が急落します。GPU は 2x2 画素(クアッド)単位でフラグメントを処理するため、極小三角形はクアッドの大半が無駄になる「クアッドオーバーシェーディング」を招きます。テッセレーションファクタは画面上の三角形サイズが数画素を下回らないよう、距離に応じて抑えるのが定石です。

メッシュシェーダ ── 固定パイプラインを置き換える新しい前段

近年の GPU では、頂点フェッチ・頂点シェーダ・テッセレーション・ジオメトリシェーダという固定的な前段を、メッシュシェーダタスクシェーダ の2段で置き換えられます。メッシュシェーダはコンピュートシェーダに近く、開発者が自前でメッシュレット(数十〜百程度の三角形の塊)を組み立てて直接ラスタライザへ出力します。

利点は、固定機能の入力アセンブラを介さずに どの三角形を出すかをプログラムで決められる ことです。カメラから見えないメッシュレットを事前に丸ごと捨てる(クラスタカリング)、LOD をクラスタ単位で選ぶ、といった制御が自然に書けます。前述のメッシュレット単位の連続 LOD は、この実行モデルがあって初めて効率よく回ります。

ハーフエッジ ── 隣接を引ける位相表現

頂点バッファとインデックスバッファは 描画には最適 ですが、編集には向きません。「この辺を共有する2つの面は?」「この頂点の周りの面を一周したい」といった 隣接クエリ が、インデックス配列だけでは全探索になってしまうからです。メッシュ簡略化・細分化・スムージングなどの位相操作には、隣接を定数時間で辿れる表現が要ります。その代表が ハーフエッジ(半辺)構造です。

ハーフエッジは、1本の無向辺を 向きの異なる2つの有向半辺 に分けて表します。各半辺は「次の半辺」「対(逆向きの半辺)」「起点の頂点」「属する面」への参照を持ちます。この4つの参照だけで、面の外周を一周する、隣の面へ渡る、頂点まわりの辺を扱う、といった操作がすべてポインタ辿りで書けます。

ハーフエッジが持つ参照:

  halfedge {
    next   : 同じ面の次の半辺(面を反時計回りに一周)
    twin   : 逆向きの半辺(=隣の面側。境界なら無し)
    origin : この半辺の始点となる頂点
    face   : この半辺が属する面
  }

  隣接クエリの例:
    ある面の全頂点        → next を面が閉じるまで辿る
    辺を共有する隣の面    → twin.face
    頂点まわりの面を一周  → twin.next を繰り返す
ハーフエッジは多様体メッシュを前提とする

ハーフエッジや同系のウィングドエッジ・クワッドエッジは、各辺が高々2面に共有される 2次元多様体 のメッシュを前提とします。1本の辺を3面以上が共有する非多様体形状(T字接合や、面から飛び出すヒレ)は twin が一意に決まらず、そのままでは表せません。CAD やスキャンデータでこうした形が混じると、多様体へ修復するか、非多様体を扱える表現へ切り替える必要があります。描画用のインデックスメッシュは非多様体でも平気ですが、位相編集では前提を満たすかの確認が要ります。

編集用のハーフエッジと描画用のインデックスバッファは、目的が違うので実務では 相互変換して使い分け ます。オーサリングツールやジオメトリ処理はハーフエッジ(や類似の隣接表現)で位相を編集し、GPU へ渡す直前にフラットな頂点バッファ+インデックスバッファへ焼き込みます。「隣接を辿れること」と「連続配列で高速に流せること」は両立しにくく、段階で最適な表現に持ち替えるのが定石です。

試験・面接で問われる勘所

「頂点数はモデルの頂点(角)の数と一致するか」と問われたら、否、と答えるのが要点です。GPU の頂点は位置・法線・UV を束ねた1レコードなので、UV シームやハードエッジ(法線の不連続)があると幾何的に同一の点でも複製され、頂点数は属性の不連続の数で増えます。あわせて「描画にはインデックスバッファ、位相編集にはハーフエッジ」と表現の使い分けを述べられると理解が伝わります。

まとめ

  • メッシュは 頂点バッファ(頂点の実体)インデックスバッファ(三角形の頂点参照) に分離され、共有頂点を再利用してメモリと頂点シェーダ実行回数を削る。頂点キャッシュ最適化が描画性能に効く。
  • 法線は陰影、UV はテクスチャ写像、接線はノーマルマップの TBN 座標系 に使う別目的の属性。いずれかが不連続な頂点は位置が同じでも複製が必要で、最終頂点数は属性の不連続の数で決まる。
  • LOD は距離に応じて三角形を減らす 仕組みで、離散 LOD のポッピングやサブピクセル三角形の非効率を避ける。メッシュレット単位の連続 LOD が近年の主流。
  • テッセレーションは GPU 上でパッチを細分して三角形を増やす 仕組みで変位も付けられるが、細分しすぎるとサブピクセル三角形とクアッドオーバーシェーディングで逆効果になる。
  • 隣接クエリを要する 位相編集にはハーフエッジ のような表現を使い、描画直前にインデックスメッシュへ焼き込む。多様体前提など各表現の制約を踏まえて使い分ける。

グラフィックス Article

メッシュとジオメトリ表現を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

グラフィックス

比較で見る軸

難易度: advanced / カテゴリ: グラフィックス / タグ数: 5

導入後に効く点

法線は陰影、UV はテクスチャ、接線はノーマルマップの座標系に必要で、これらの不連続がある頂点は位置が同じでも複製せざるを得ない。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
グラフィックス
タグ数
5

判断チェックリスト

  • 自社の用途が「グラフィックス / メッシュ」に近いか確認する。
  • 強みである「メッシュは頂点属性の配列(頂点バッファ)と三角形の頂点参照の配列(インデックスバッファ)に分かれ、共有頂点を再利用してメモリと変換コストを削る。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

グラフィックスメッシュ頂点バッファLODテッセレーショングラフィックスメッシュ頂点バッファ