
2026/02/06 23:32
バーチャルテクスチャは、GPU のメモリや帯域幅を圧迫せずに極めて大きなテクスチャアトラスをシーンで使用できるレンダリング手法です。 画面上で実際に表示されているテクスチャ部分だけを **遅延ロード** して利用します。 ### 動作原理 1. **テクスチャの分割** - 高解像度の元画像を、例として 256 × 256 ピクセルといった同じサイズの小さなブロックに切り出します。 - 各ブロックは仮想アドレス空間内の独立したページとして扱われます。 2. **ページテーブル / マニフェスト** - CPU 側で、どのページがディスク上またはテクスチャキャッシュに保存されているかを管理するデータ構造があります。 - GPU には「仮想ページ座標 → 実際の物理位置(あるいは未ロード)」というコンパクトなページマップが渡されます。 3. **フラグメントシェーダーでの検索** - ピクセルをシェーディングするとき、フラグメントシェーダーは *仮想* UV 座標を計算します。 - ページテーブルを参照し、以下のようにページとサブUVを求めます。 ```glsl vec2 pageCoord = floor(vUV * texSize / pageSize); vec2 subUV = fract(vUV * texSize / pageSize) / (texSize / pageSize); ``` - その後、現在ロード済みのページだけを保持する **テクスチャアトラス** からサンプリングします。 4. **オンデマンドストリーミング** - 要求されたページが存在しない場合、GPU は一時的に停止して CPU に通知します。 - CPU がディスクからブロックを読み込むか、圧縮を解凍してアトラスへ配置し、ページテーブルを更新します。 - 以降のフラグメントは追加の停滞なしに新しくロードされたデータへアクセスできます。 5. **キャッシュ除外と LRU** - アトラスが満杯になると、最も最近使われていないページを除外して空き領域を確保します。 - 除外は CPU と連携し、必要になった際に再度ロードできるようにします。 ### 利点 - **メモリ効率** – 画面上で可視のテクスチャデータだけが VRAM を占有 - **拡張性** – テクスチャ全体を数テラバイト規模にしても対応可能 - **帯域幅削減** – 必要なブロックのみストリーミングで済む このように、バーチャルテクスチャは実際の GPU リソースを抑えつつ、オープンワールドゲームなどでリアルかつ高解像度の環境を実現します。
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
仮想テクスチャリングは、ゲームが膨大なテクスチャを1つの仮想アドレス空間として扱い、実際にレンダリングで必要となるページだけをストリームすることでGPUメモリ使用量を低く抑えつつ高解像度ディテールを提供します。
仕組み:
- アドレッシング – GPUシェーダーはUV座標を物理アトラス座標にマッピングし、ページテーブル(各ページのメタデータ:在住フラグ + スロットインデックスを格納した2‑Dテクスチャ)を使用します。
- フィードバック – 低解像度パスがアクセスされた仮想ページ/ミップレベルを記録し、各サンプルは(例:ミップレベル5ビット、各軸ページインデックス8ビット)でエンコードされ、CPUにより読み取られるバッファへ書き込まれます。
- 在住 – CPU側のページマネージャーはLRUスタイルのキャッシュを実装し、最低LODページのピニングオプションを持ち、欠落したページをストレージから非同期でロード、古いものを退避させ、ページテーブルを更新します。
歴史的背景: このアイデアは1996年のCrash Bandicootに初登場し、表示されているレベルセクションのみをストリームしてRAM/VRAM負荷を軽減しました。最初の商用エンジンで完全な仮想テクスチャリングを採用したのはid Tech 5のMegaTextureで、描画ごとのテクスチャバインドを排除しつつロードとレイテンシをCPU/I/Oへ移行しました。
現代的関連性: GPUは原生メモリより帯域幅に制限されており、ハードウェアの疎テクスチャは低レベルのアドレス変換を提供しますが、エンジンはクロスプラットフォームで一貫した動作を実現するためにカスタムポリシーを実装し続けています。仮想テクスチャリングは、仮想テクスチャサイズがGPUメモリを大幅に超える場合(例:巨大なオープンワールドや詳細な医療画像)に最も有効であり、それ以外では従来のテクスチャがより高速なイテレーションを提供します。
将来展望: エンジンはLRUキャッシュを洗練し、低LODページをピン留めするオプションやストレージからのさらに積極的な非同期ページロードを行うようになるでしょう。仮想テクスチャリングは、GPUメモリに対してテクスチャサイズが圧倒的に大きいプロジェクトで標準化されることが予測され、より豊かな環境を大型GPUなしで実現しつつCPUとI/Oサブシステムへの要求を高めます。
本文
Crash Bandicoot の開発を語るインタビュー
PlayStation 本体での Crash Bandicoot 開発について、Andy Gavin は「当時プラットフォーム上の他ゲームよりもはるかに豊かな環境、高解像度テクスチャ、滑らかなアニメーション」を実現した方法を語ります。
当時の PlayStation の開発パターン
ほとんどの PlayStation ゲームは同じ手順で進められていました。
レベルごとに CD からすべてのアセットをメモリへ読み込み、2 MB のシステム RAM と 1 MB の VRAMという限られたバジェット内で動かします。
レベルが開始した後は、音楽以外はほとんど CD を利用しませんでした。
このやり方では パフォーマンスの向上余地が残っていません。ゲーム中に見える領域はごく一部しかなく、それを構成するデータだけが必要なのに、CD から大量の不要なデータが読み込まれ続けます。
Crash Bandicoot が取ったアプローチ
Crash Bandicoot はレベルを 固定サイズページ に分割し、仮想メモリとして扱いました。
事前に計算された可視性マップで、各領域に必要なページだけを決定します。
作業セット(working set)がメモリ内に収まっている限り、ストリーミングは継続的かつプレイヤーには透明です。
実際には 総 RAM 容量 ではなく「1 ページに詰められるデータ量」が制約になりました。
レベルの有効サイズはディスク上で確保された領域になるので、メインメモリとは別次元の概念です。
現代エンジンでも同じ制約が存在
ハードウェアは進化しましたが、GPU は「どれだけのデータを効率的に扱えるか」で限界を迎えます。
以下のような映像が示す通りです。
Both scenes run on the original PlayStation.
Crash streams level data aggressively, enabling denser textures and more visual variety. Tomb Rider relies on traditional loading.
同じ制約は 科学的可視化 でも現れます。Biohub のプロジェクトでは、GPU メモリを何倍も超える大規模な多次元バイオイメージングデータのインタラクティブ表示を行っています。
仮想テクスチャリングはこの課題に自然に適合しますが、既存の説明は「レジディエンシー」や「フィードバック」の詳細を省略しがちです。実装を通じてそのギャップを明らかにしました。
1. 大きなテクスチャ
大規模オープンワールドやバイオイメージングでは、細部まで保持したまま 巨大テクスチャ が必要です。
VRAM に収まりませんし、GPU バスで大量データを転送するのも非現実的です。
制限はメモリや帯域幅ではなく画面解像度 です。画面に投影されるテクスチャ部分だけが最終画像に寄与します。
例:24 k テクスチャを 4 k ディスプレイで表示すると、常にフル解像度で見ることはできません。
ズームアウトではサンプリング数が減り、ズームインでは小さな領域だけが高解像度で見えます。
ほとんどのシステムはこの制約を活かし、テクスチャを ミップチェーン に分割し、各ミップを固定サイズページに切ります。
ランタイム時には必要なページのみ GPU へストリーミングします。
2D テクスチャのレンダリングは単純です:1 フレームで1つのミップレベルと数枚のページだけがアクティブになります。
Google Maps や Microsoft Deep Zoom のように、各ページをタイルとして描画し、LOD(Level of Detail)選択を行います。
しかし 3D では 複数のミップレベルを同時にサンプリング する必要があります。
近距離は高解像度ページ、遠距離は低解像度ページを使うため、LOD はピクセル単位で決定されます。
この点が仮想テクスチャリングの本当の課題です。
2. 仮想化されたテクスチャ
CPU が 仮想メモリ を解決したように、GPU でも「巨大テクスチャ」を仮想空間として扱い、必要なページだけを GPU メモリに保持します。
これにより、フルレゾのテクスチャ全体を確保せず、画面が実際にサンプリングする テクセル だけを転送できます。
主なメリット
| 項目 | 説明 |
|---|---|
| シーン全体のメッシュは単一仮想テクスチャからサンプリング | 複数テクスチャバインド不要 |
| LOD の選択が 3D で簡潔化 | フィードバックを用いてピクセルごとにミップレベル決定 |
| ページテーブルで残存情報管理 | レジディエンシーは明示的に追跡 |
GPU はハードウェアで スパーステクスチャ をサポートしていますが、ほとんどのエンジンは自前でページテーブルやレジディエンシーロジックを構築します。
3. システム全体
仮想テクスチャは 1 つのシェーダ ではなく、CPU と GPU の協調で動く一連のコンポーネントです。
各フレームで解決すべき 3 つの質問があります。
| 質問 | 内容 |
|---|---|
| アドレッシング | 各テクセルがどこから来るか(仮想空間) |
| フィードバック | 仮想ページが実際にアクセスされたか、何ミップで |
| レジディエンシー | GPU メモリ内に保持すべきページは? |
3.1 仮想→物理座標
アプリ側では UV がフル解像度テクスチャ全体を表しますが、実際には一部だけが GPU に存在します。
このギャップを埋めるために ページテーブル を用意し、仮想アドレス → 物理アドレスへの変換を行います。
- バーチャルテクスチャ:フル解像度空間を定義
- ページテーブル:各ミップレベルのページごとに「残存」かどうか、物理位置を格納(2D テクスチャとして実装)
- 物理アトラス:現在 GPU にロードされているページを保持
シェーダはまず仮想座標からミップレベルとページインデックスを計算し、ページテーブルで残存性と物理位置を取得します。
残存していない場合はフェールバック色(例:透明)を返します。
// GLSL のサンプル関数(省略) vec4 SampleVirtualTexture(vec2 uv) { … }
3.2 フィードバッパス
メインレンダーパスで毎フラグメントに書き込みを行うと、読み取り専用のテクスチャサンプリング が破壊されます。
そこで 低解像度オフスクリーンターゲット にレンダーし、必要な仮想ページとミップレベルをまとめて取得します。
uint EncodeFeedback(vec2 uv) { … }
フィードバックバッファは「ページインデックス + ミップレベル」をビットパックして保持します。
3.3 ページマネージャ
CPU 側で フィードバックを解読 → 「残存」かどうか確認 → 必要なら非同期ロード、物理アトラスに配置。
キャッシュは主に LRU(Least Recently Used)で管理し、必要に応じてページを置き換えます。
- ピン留め:最低LODレベルのページは常に残存させることで「ホール」を防止。
- ポリシー:キャッシュ容量、ロード優先度、I/O スケジューリングなどを調整。
フィードバック → ページマネージャ → レジディエンシー更新 のループで、システムは安定的に動作します。
レイテンシが高いと低解像度ページが先に表示されるだけですが、次フレーム以降に高解像度ページが補完されます。
4. 実装事例
id Tech 5(MegaTexture)
id Tech 5 は 完全仮想テクスチャパイプライン を採用し、すべての静的表面を単一仮想空間からサンプリング。
GPU メモリ使用量はワールドサイズに関係なく一定です。
主なコストは I/O レイテンシ であり、ページが遅延するとテクスチャポップインが発生します。
現代エンジン
- Nanite(Unreal Engine)や Virtual Geometry は同様の仮想化概念を拡張し、メッシュ も仮想化。
- Sparse Textures を利用することでハードウェアレベルでページテーブルがサポートされますが、ポリシーはエンジン側に委ねられています。
5. 科学的可視化への応用
バイオイメージングでは OME‑Zarr のような多次元チャンク形式を使用し、クライアントが「現在のビュー」に必要な分割と解像度だけをリクエストします。
仮想テクスチャリングはこの概念を GPU レベルで実現し、リアルタイムレンダリング と オフライン処理 をシームレスに統合できます。
- 1 つのレイマーチングパスで多チャンネルデータを描画
- 視認可能領域に応じて解像度が自動調整
まとめ:仮想テクスチャリングの本質
「パフォーマンスは総データサイズだけではなく、実際に可視化される画面空間・可視性・知覚解像度」によって決まる。」
- 大きな仮想空間を作り、小さな作業セット を維持
- システムが常に両者を調整し続けることで、実際に必要なデータだけを GPU に保持
これは テクスチャ のみならず、ジオメトリ や シェーダー資源 などの仮想化にも共通するパターンです。
Crash Bandicoot が 1996 年に示した原理は、今日の Nanite や仮想ジオメトリへと進化し続けています。
In large‑scale biomedical imaging, data is often stored in formats like OME‑Zarr that natively encode multi‑resolution chunked n‑dimensional data, enabling clients to request only the regions and resolutions needed for the current view.
For a deep dive into how GPUs select mip levels using screen‑space derivatives see “Mipmap Selection in Too Much Detail”. It walks through the process in detail and is a useful reference.
The idea predates Nanite. Carmack discussed virtualised geometry as a successor to MegaTexture during the id Tech 6 era, but left id Software to focus on Oculus Rift before such work could ship.