【TA】テクスチャの秘密

概要

マクロな視点で見ると、テクスチャとは2D画像であり、各ピクセルにはRGB値が存在する。

 

テクスチャの存在理由

Ⅰ. モデリング作業量の削減 = ジオメトリのディテールを犠牲にする

Ⅱ. ストレージ使用量の削減

Ⅲ. 読み込み速度の向上

 

もしモデルの全てのディテールを完全に表現しようとすれば、膨大な作業量が発生する。単純なモデルであれば対応しやすいが、人間のモデルとなると、その構造の複雑さに加え、服装のバリエーションや装飾の違いなども加わり、モデラーの負担が大幅に増大する。

 

しかし、モデルにテクスチャを適用することで、物体表面の表現技術をシンプルに保ちつつ、複雑な形状の変化を避けられる。ディテールを省略しながらも、元の見た目を大まかに再現することが可能になる。

 

テクスチャパイプライン

モデル空間座標 → 投影関数 → テクスチャマッピング → テクスチャ座標 → 変換関数 → 新しいテクスチャ座標 → テクスチャサンプリング [テクスチャ依存の読み込みを回避] → テクスチャ値

 

各ステップの説明

  • 投影関数:ここで言う「投影」は一般的な投影変換とは異なり、UV展開技術を指す。

  • テクスチャサンプリング(SAMPLER):ShaderLab でよく見られる SAMPLER という用語に関連する。

 

テクスチャ依存の読み込みとは?

「テクスチャ依存の読み込み」とは、フラグメントシェーダー内で新たに UV オフセットを計算し、それを元にテクスチャをサンプリングする処理のことを指す。この処理は、エッジシェーダーから直接受け取ったテクスチャではなく、計算された UV を使うため、以下の問題が発生する。

  1. GPUのパイプラインが中断される → 最適化の妨げになる

  2. 性能の大幅な低下 → フラグメントシェーダー内でUV計算を行うと、並列処理がしにくくなる

そのため、UV オフセットなどの計算は フラグメントシェーダーではなくエッジシェーダーで行うのが理想的 である。

 

例:モデル空間の点をテクスチャ座標に投影する

  1. モデル空間の点 (x, y, z) を UV 空間へ変換 → UV 座標 (u, v) を取得

  2. テクスチャサイズが 256 × 256 の場合

    • UV座標 (u, v) をテクスチャサイズと掛け算する

    • texCoord = (u * 256, v * 256) で実際のピクセル位置が求まる

  3. サンプリング設定に基づき、テクスチャから色情報を取得

これにより、効率的にテクスチャデータを適用できる。

 

テクスチャサンプリング設定:Wrap Mode(ラップモード)

Wrap Mode は、UV 座標が [0,1] の範囲外になった場合の挙動を決定する設定。

  • OpenGL:「包装模式 (Wrapping Model)」
  • DirectX:「テクスチャアドレッシングモード (Texture Addressing Mode)」

  • ゲームの地面 → Repeat(重复)

  • 水面の反射 → Mirror(镜像)

  • スプライトの端処理 → Clamp(边界约束)

  • 特殊な境界色を設定 → Border(边界填充)

 

テクスチャサンプリング設定:フィルターモデル

フィルタリング設定とは、テクスチャが変化によって引き伸ばされた際に、どのような手法でテクスチャを表現するかを決定するものである。

 

異なるサイズ、スケール比、角度、形状に対して、適切なサンプリング方式を選択することで、最適なテクスチャ表現を実現する。

 

最近隣(さいきんりん)

最も近いピクセルを使用してテクスチャをサンプリングする方法。この方式の問題点は、隣接するピクセルから情報を取得するため、ブロック状のピクセルが発生しやすく、テクスチャがピクセル化してしまい、処理の見た目が悪くなること。しかし、隣接するピクセルから取得するため、計算量が大幅に少なくなり、性能面では優れた結果を示す。

双线性插值(バイリニア補間)

ピクセルに対して、隣接する4つのピクセルを探し、2次元空間で線形補間を行い、最終的な混合値を取得する手法。最近隣と比較すると、サンプリングポイントが増えるため、画質の向上が見られ、少なくともブロック状のピクセルが発生することはない。しかし、補間に使用するのは最も近い4つのピクセルのみであるため、改善の効果には限界がある。

 

立方卷积(バイキュービック補間)

双線性補間と比較すると、この計算方法では周囲のピクセルを一周分取得するだけでなく、それらの変化率(勾配)の影響も考慮する。これにより、画質は前の2つの方法(最近隣・双線性補間)よりも向上し、より滑らかなテクスチャ表現が可能となる。ただし、計算コストが増えるため、性能を犠牲にして表現品質を向上させる手法である。

 

纹理缩小时的情况(テクスチャ縮小時の問題)

テクスチャを縮小した場合、最近隣やバイリニア補間には「色の欠落」や「チラつき(フリッカー)」の問題が発生する。

 

一般的なテクスチャでは、各ピクセルに対して適切なテクスチャ情報を持たせることで、フリッカーや情報の欠落を防ぐ必要がある。そのためには、①ピクセルのサンプリング頻度を上げるか、②テクスチャの周波数を下げる必要がある。テクスチャの周波数を下げる最も代表的な方法が MipMap である。

 

MipMap(ミップマップ)

MipMap は、テクスチャデータを階層的に管理するデータ構造であり、リアルタイムの計算で特定のピクセルに対して適切な解像度のテクスチャをすばやく選択できるようにする。

 

具体的には、元のテクスチャ(レベル0)を基に、2×2 のピクセル単位で平均を取り、新しい低解像度のテクスチャ(レベル1)を作成する。さらに、レベル1 のテクスチャを同様に処理してレベル2 を作成し、この手順を繰り返して最小の 1×1 のテクスチャ(最終レベル)まで生成する。

 

この階層構造により、適切な解像度のテクスチャを選択できるため、縮小時のチラつきや色の欠落を抑えることができる。ただし、すべてのレベルのテクスチャを保存するため、ストレージの使用量は元のテクスチャの約 1.33 倍 になる。

 

优化方法(最適化手法)

CPU 渲染优化的常见方式 —— Texture Atlas / Texture Array

CPU 側のレンダリング最適化では、DrawCall の削減 が重要な方向の一つである。この概念を理解するために、まず DrawCall とは何か を説明する。

 

1. DrawCall とは?

レンダリングテクスチャを画面に描画する際、CPU と GPU は協力してこのプロセスを完了させる必要がある。これらが並行して動作できるようにするため、システムは**コマンドバッファ(Command Buffer)を導入している。このバッファにはコマンドキュー(Command Queue)**が含まれており、CPU はこのキューにレンダリング命令を追加し、GPU はキューから命令を読み取り実行する。

 

CPU がオブジェクトをレンダリングする必要がある場合、対応するレンダリング命令をコマンドキューに追加する。GPU は前フレームのレンダリングタスクを完了した後、新しい命令をキューから取り出して実行する。命令の追加(CPU)と実行(GPU)はそれぞれ独立して行われるため、コマンドバッファの存在によって CPU と GPU は効率的に協力できる。

 

コマンドバッファ内の命令にはさまざまな種類があり、その中の一つが DrawCall である。DrawCall を呼び出すたびに、CPU は GPU に対してメッシュ情報、ステートパラメータ、シェーダー設定など、一連のデータを送信する必要がある。これらの操作は CPU の処理時間を消費する一方で、GPUレンダリング能力は通常、CPU が命令を送信する速度よりも遥かに高い。そのため、DrawCall の数が多すぎると、CPU がレンダリング命令の送信に多くの時間を費やし、最終的に全体的なレンダリング性能に影響を及ぼす可能性がある。

 

2. DrawCall を削減する方法

DrawCall を削減する一般的な方法の一つは、レンダリングプロセスにおけるテクスチャの切り替えコストを減らすことである。これを実現するために、以下の3つの技術がよく用いられる。

  • テクスチャアトラス(Texture Atlas)

  • テクスチャアレイ(Texture Array)

  • バインドレステクスチャ(Bindless Texture)

この中でも、テクスチャアトラスは実際のアプリケーションで最も一般的な方法である。

 

3. テクスチャアトラス(Texture Atlas)

テクスチャアトラスの核心的な考え方は、複数の小さなテクスチャを1つの大きなテクスチャに統合することである。これにより、GPU がテクスチャを切り替える回数を減らすことができる。

 

この方法を使用すると、複数のオブジェクトをレンダリングする際に、すべてのオブジェクトが同じテクスチャリソースを共有できるため、異なるテクスチャをバインドし直す必要がなくなる。各オブジェクトは UV 座標を調整する ことで異なる部分のサブテクスチャにアクセスできるため、頻繁なテクスチャのバインドを回避し、結果として DrawCall の削減 に繋がる。

 

4. テクスチャアレイ(Texture Array)

テクスチャアレイはテクスチャアトラスと似た概念だが、その実装方法は異なる。テクスチャアレイでは、同じサイズの複数のテクスチャを1つの配列に格納し、インデックスを使用してどのテクスチャを使用するかを選択する。

 

テクスチャアトラスと比較すると、UV 座標の調整が不要という利点がある。しかし、テクスチャアレイを利用するには、GPU が特定のシェーダー機能(例: gl_TextureIndex のような機能)をサポートしている必要がある。

 

5. バインドレステクスチャ(Bindless Texture)

バインドレステクスチャは、複数のテクスチャを一度にバインドし、シェーダー内で動的に使用するテクスチャを選択することで、レンダリング時のテクスチャ切り替えのオーバーヘッドを削減する手法である。

 

この方法は、最新のGPUの高度な機能に依存するため、すべての環境で使用できるわけではない。しかし、大規模なシーンのレンダリングや複雑なマテリアルシステムでは、バインドレステクスチャを活用することで大幅なパフォーマンス向上が期待できる。

 

6. まとめ

DrawCall の削減は、レンダリングの効率を向上させるために重要であり、テクスチャ切り替えの回数を減らすことがその主要な手段の一つである。

  • テクスチャアトラス(Texture Atlas) は最も一般的な最適化手法であり、ほとんどのプロジェクトで有効。

  • テクスチャアレイ(Texture Array) は、特定のGPU機能が必要だが、UV座標の調整不要というメリットがある。

  • バインドレステクスチャ(Bindless Texture) は、最新のハードウェア向けであり、大規模シーンや高度なマテリアル管理に適している。

プロジェクトの要件に応じて最適な手法を選択することで、レンダリングのパフォーマンスを効率的に向上させることができる。

 

GPUレンダリング最適化の一般的な方法 —— テクスチャ圧縮

テクスチャ圧縮を使用すると、レンダリングパフォーマンスを向上させ、以下のような効果が得られる。

  • CPUリソースの削減:CPU側でのデコード処理を回避し、CPU負荷を軽減する。
  • パッケージサイズの縮小:ストレージの使用量を削減し、アプリケーションのディスク占有を抑える。
  • データ転送量の削減:リソースのロード速度を向上させる。
  • 帯域幅の負担軽減:VRAMとシステムメモリ間のデータ転送を最適化し、レンダリング効率を向上させる。
  • メモリ利用率の向上:GPUメモリの使用を最適化し、リソースの効率的な管理を可能にする。

詳細な手法については、今後説明する。

 

立方体贴图(CubeMap)

立方体贴图(CubeMap) は、三次元テクスチャ座標を基にした環境マッピング技術であり、反射、屈折、スカイボックスなどのエフェクトを実現するために使用される。基本的な原理として、立方体をテクスチャマップとして使用し、各面に異なる方向のテクスチャを適用することで、全方位の環境情報を表現する。

 

凹凸贴图(Bump Mapping)

凹凸贴图(Bump Mapping) は、法線の擾乱(じょうらん)を利用した視覚効果であり、物体表面の細かな凹凸をシミュレートする技術である。これにより、追加のジオメトリ(ポリゴン)を増やすことなく、照明の影響を受けた際により豊かなディテールを表現できる。

位移贴图(Displacement Mapping)

位移贴图(Displacement Mapping) は、高さマップ(Height Map)を使用して頂点座標を直接変更し、モデルのジオメトリ形状を変形させる技術である。

この手法により、表面の凹凸が実際に変形し、よりリアルなディテールを表現できる。しかし、頂点位置の変更を伴うため、GPUの計算負荷が増大し、低性能なデバイスやリアルタイムレンダリングには適していない。