TL

GPUテクスチャ圧縮

VRAM不足とテクスチャ帯域のボトルネックを、GPUがサンプリング時に直接展開できるブロック圧縮の原理から理解し、BC・ASTC・ETCを用途で正しく選べるようになります。

応用グラフィックステクスチャ圧縮ブロック圧縮ASTCGPU帯域最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.GPUテクスチャ圧縮は4×4テクセルを固定バイト長のブロックへ非可逆符号化し、サンプラがランダムアクセスで即時展開するため、JPEGと違いメモリと帯域を実行時に恒常的に削減する。
  • 2.BC1〜7はDirectX系デスクトップの標準で、色は端点2色+2〜3ビットの補間インデックスで表す。ASTCは可変ブロックとビットレートで品質を細かく調整でき、ETC2はモバイルGPUの基本形式。
  • 3.圧縮は品質と引き換えなので、法線マップは専用形式(BC5)、sRGB色はsRGB対応フォーマット、単色データは適切なチャンネル数を選び、ミップマップは各段を個別に圧縮する。

テクスチャ圧縮が解く問題

高解像度テクスチャは膨大なメモリを食います。4096×4096 の RGBA8 テクスチャは 1 枚で 64MB、ミップマップ込みで約 85MB です。数百枚を扱う現代のシーンでは、非圧縮のままでは VRAM に載りません。さらに深刻なのは 帯域 です。テクスチャユニットは毎フレーム膨大なテクセルをフェッチし、テクスチャマッピングとフィルタリング で見たバイリニアやトライリニアでは 1 ピクセルあたり複数テクセルを読みます。メモリ帯域は GPU の律速要因になりやすく、フェッチ量の削減はそのまま性能に効きます。

ここで JPEG や PNG は答えになりません。これらはファイルサイズを縮めますが、GPU で使う前にフル解像度へ 完全展開 する必要があり、VRAM 上では非圧縮に戻ってしまうからです。求められるのは「圧縮したまま GPU メモリに置き、サンプラがサンプリング時にその場で必要な部分だけ展開する」形式です。これが GPU テクスチャ圧縮であり、鍵は 固定圧縮率・ブロック単位・ランダムアクセス の 3 点にあります。

ブロック圧縮の基本原理

GPU テクスチャ圧縮のほぼすべては、テクスチャを 4×4 テクセルのブロック に分割し、各ブロックを独立に固定バイト長へ符号化します。BC1 なら 16 テクセル(非圧縮 RGBA8 で 64 バイト)を 8 バイト に、BC7 なら 16 バイト に押し込みます。

固定長であることが決定的に重要です。任意のテクセル (x, y) を読むとき、そのテクセルが属するブロックの先頭アドレスを割り算だけで直接計算できます。

テクセル (x,y) が属するブロックの位置とアドレス:

  bx = x >> 2          // 4で割る(ブロック座標)
  by = y >> 2
  block_index = by * blocks_per_row + bx
  addr = base + block_index * BYTES_PER_BLOCK   // BC1なら8, BC7なら16

  ブロック内オフセット:
  ox = x & 3           // 4の剰余(0..3)
  oy = y & 3

JPEG のような可変長エントロピー符号ではこの計算ができず、目的のテクセルまで前から順に復号せねばならないため、GPU のランダムアクセスと相容れません。固定長ブロックなら 1 ブロック読むだけでバイリニアに必要な 2×2 テクセルが揃う ことも多く、キャッシュ効率も良好です。展開回路は極小の専用ハードウェアで、サンプリング経路に組み込まれています。

端点補間という共通アイデア(BC1〜7)

BC 系(Block Compression、旧称 S3TC/DXT)に共通する発想は、ブロック内の 16 色を、2 つの「端点色」を結ぶ直線上の点として近似する ことです。自然画像では 4×4 の狭い領域内で色が急変することは稀で、多くは色空間内の短い線分に乗る、という統計的性質を利用します。

BC1(DXT1)を例にとります。ブロックの 8 バイトのうち、前半 4 バイトに端点となる 2 色を RGB565(各 16 ビット)で格納し、後半 4 バイトに 16 テクセルぶんの 2 ビットインデックス を置きます。復号側は 2 つの端点から中間 2 色を線形補間で生成し、{端点0, 端点1, 補間1, 補間2} の 4 色パレットを作ります。各テクセルはこの 4 色のどれかを 2 ビットで指すだけです。

BC1 ブロック(8バイト = 64ビット)の構成:

  color0 : RGB565  (16ビット)   // 端点色0
  color1 : RGB565  (16ビット)   // 端点色1
  indices: 2ビット × 16テクセル (32ビット)

  4色パレットの生成(color0 が color1 より大の場合):
    palette[0] = color0
    palette[1] = color1
    palette[2] = (2*color0 + color1) / 3    // 1:2の内分点
    palette[3] = (color0 + 2*color1) / 3    // 2:1の内分点

BC1 は 4 分の 1 のサイズ(RGBA8 比)で、1 ビットのアルファ(透明/不透明)まで表せます。この端点+インデックス方式が発展したのが後続の BC 群です。

形式ビット/テクセル主な用途と特徴
BC1 (DXT1)4不透明RGB/1ビットα。最小サイズ、粗い
BC3 (DXT5)8RGB+連続8ビットα。半透明テクスチャの定番
BC441チャンネル(グレースケール/ハイトマップ)
BC582チャンネル。法線マップ(XY)に最適
BC6H8HDR RGB(浮動小数点)。環境マップ向け
BC78高品質RGBA。複数モードで最良、圧縮は重い

BC7 は 1 ブロック内で複数の パーティション(テクセルを 2〜3 グループに分け各々別の端点対を持つ)や、可変ビット配分の モード を選べるため、端点直線 1 本では表せない複雑なブロックにも追従します。その代わり最適モード探索にエンコード時間がかかります。BC4/BC5 はアルファ格納で使われる 8 ビット補間ブロックを 1〜2 チャンネルへ転用したもので、法線マップは XY 2 成分を BC5 に入れ、Z はシェーダで z = sqrt(1 - x*x - y*y) と復元します。この経路は シェーディングと物理ベース描画(PBR) の法線マップ運用と直結します。

ASTC と ETC ── モバイルと可変ビットレート

BC 系は DirectX とデスクトップ GPU の事実上の標準ですが、モバイル/組込み GPU では別系統が広く使われます。

ETC(Ericsson Texture Compression)は OpenGL ES の標準形式です。ETC1 は RGB のみ 4 ビット/テクセルで、4×4 ブロックを 2×4 または 4×2 のサブブロックに割り、各サブブロックが基準色+輝度変調テーブルで明暗を表す方式です(色差より輝度に敏感な視覚特性を利用)。ETC2 は後方互換を保ちつつ画質を改善し、アルファ対応(EAC)を加えたもので、OpenGL ES 3.0 以降で必須サポートされます。

ASTC(Adaptive Scalable Texture Compression)は最も柔軟な新しい標準です。最大の特徴は ブロックサイズが可変 な点で、4×4 から 12×12 まで選べます。ブロックあたりのバイト数は常に 128 ビット固定なので、ブロックを大きくするほど 1 テクセルあたりのビット数が下がり、0.89〜8 ビット/テクセルを連続的に 選べます。同じ 128 ビットの中に端点の精度・パーティション数・インデックスの精度をどう配分するかを、ブロックごとに最適化して詰め込みます。

形式対応プラットフォームビットレートの柔軟性
BC1〜7DirectX/デスクトップ/コンソール形式ごとに固定(4 or 8)
ETC2 / EACOpenGL ES 3.0+/モバイル基本固定(RGB 4、RGBA 8)
ASTCVulkan/Metal/新しいモバイルGPU可変(0.89〜8、ブロック寸法で調整)
ASTC HDR対応GPUのみHDRも可変ビットレートで扱える

どの形式が使えるかは API と世代に依存するため、配布時は複数形式を用意して端末に応じて選ぶのが実務の定石です(グラフィックスAPIの系譜 の各世代の機能差も参照)。

固定圧縮率がもたらす予測可能性

JPEG は内容によりサイズが変わりますが、ブロック圧縮は「4×4 が常に N バイト」で内容に依存しません。これは欠点ではなく設計上の要請です。GPU がアドレスを算術で求めるにはサイズが一定でなければならず、VRAM 予算やストリーミング帯域も事前に正確に見積もれます。つまり圧縮率を品質側で吸収し、サイズは固定に保つ、という思想です。

非可逆圧縮のアーティファクト

これらはすべて 非可逆 です。端点直線への射影や大きいブロックへの詰め込みは情報を捨てるため、固有の破綻が出ます。

  • ブロック境界の不連続: 各 4×4 ブロックが独立符号化されるため、隣接ブロックの端点が食い違うとブロックの継ぎ目が段差として見えます。平坦なグラデーションで目立ちます。
  • 色にじみ・色ずれ: BC1 は色を RGB565 の端点+補間で表すので、彩度の高い微妙な色階調が近い色へ丸められます。とくに肌のグラデーションや空で顕著です。
  • 緑の縞(RGB565 由来): 端点が緑 6 ビット・赤青 5 ビットのため、グレー領域で緑寄りの色偏移やバンディングが出ることがあります。
  • 法線の破綻: 法線マップを BC1/BC3 のような色向け形式で圧縮すると、方向ベクトルが歪んでライティングが崩れます。これが BC5 や専用形式が要る理由です。
  • 鋭いエッジのリンギング/ブロック汚れ: 文字・UI・アイコンのような高周波エッジは端点直線に乗らず、ブロック内が濁ります。テキストアトラスは圧縮を避けるか BC7 を使います。
圧縮テクスチャを再圧縮・再エンコードしない

最悪の運用は「非可逆で圧縮された素材を展開し、加工して再び圧縮する」多重非可逆です。世代を重ねるごとにブロックアーティファクトが累積し、劣化が可視化されます。オーサリングは常に 非圧縮のマスター から行い、圧縮は書き出しの最終段で 1 回だけ掛けるのが鉄則です。ミップマップ生成も、圧縮前の高精度データに対して行ってから各段を圧縮します。

ミップマップとの関係

テクスチャ圧縮とミップマップは独立した最適化ですが、正しく組み合わせる必要があります。ミップマップは縮小時のエイリアシングを防ぐ 事前縮小画像の階層 で(詳細は テクスチャマッピングとフィルタリング)、圧縮とは直交します。

重要なのは、ミップの各段はそれぞれ独立に圧縮する という点です。展開してからミップ生成、ではなく、非圧縮の各段を作ってから段ごとに 4×4 ブロック圧縮を適用します。順序を守るべき理由は 2 つあります。

正しい順序:
  非圧縮マスター
    → 各ミップ段を高精度(非圧縮)で生成(2×2平均などのローパス)
    → 段ごとに BC/ASTC で圧縮
    → GPU へアップロード(段ごとに固定バイト長)

誤り:
  マスターを圧縮 → 圧縮結果を展開・縮小して下位ミップ生成
    → 非可逆の劣化が下位段に伝播し累積する

第一に、非可逆圧縮の劣化を含んだ画像を縮小すると、その劣化が下位ミップへ伝播します。第二に、ミップ生成(縮小=複数テクセルの平均)は本来 リニア空間 で行うべき線形操作で、圧縮とは別に色空間の扱いが要ります(色空間とガンマ補正 の縮小・平均の議論と同根です)。sRGB 色テクスチャは sRGB 対応の圧縮フォーマットを使い、サンプラのハードウェア sRGB 展開に任せるのが正解です。なお 4×4 に満たない最小段(幅 1〜2 テクセル)もブロック圧縮は 4×4 単位のため、端は複製やパディングで埋めた 1 ブロックとして符号化されます。

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

「JPEG と GPU テクスチャ圧縮の違いは何か」は頻出です。答えは (1) JPEG は使用前に全展開が必要で VRAM 上は非圧縮に戻るが、ブロック圧縮は圧縮したまま常駐し帯域も削減する、(2) JPEG は可変長でランダムアクセスできないが、ブロック圧縮は固定長で任意テクセルをアドレス計算で直接読める、の 2 点。また「法線マップをなぜ通常の色圧縮で潰してはいけないか」(端点直線への射影で方向が歪む→BC5 のような 2 チャンネル形式を使う)も定番です。

まとめ

  • GPU テクスチャ圧縮は 4×4 テクセルを 固定バイト長のブロック へ非可逆符号化し、サンプラが ランダムアクセスで即時展開 する。JPEG と違い VRAM と帯域を実行時に恒常的に削減する。
  • BC1〜7 は 端点 2 色+補間インデックス を基本アイデアとし、色は色空間内の短い線分に乗るという統計を利用する。BC5 は法線、BC6H は HDR、BC7 は高品質 RGBA に対応する。
  • ASTC は 128 ビット固定ブロックの寸法を変えて 0.89〜8 ビット/テクセル を連続選択でき、ETC2/EAC はモバイル(OpenGL ES)の基本形式。使える形式は API と世代に依存する。
  • 非可逆ゆえ ブロック境界の段差・色にじみ・法線の破綻 などが出る。多重圧縮を避け、非圧縮マスターから最終段で 1 回だけ圧縮する。
  • ミップマップとは直交する最適化で、各ミップ段を個別に圧縮 する。縮小はリニア空間で行い、sRGB 色は sRGB 対応フォーマットを使う。

グラフィックス Article

GPUテクスチャ圧縮を実務で読む

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

解決すること

グラフィックス

比較で見る軸

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

導入後に効く点

BC1〜7はDirectX系デスクトップの標準で、色は端点2色+2〜3ビットの補間インデックスで表す。ASTCは可変ブロックとビットレートで品質を細かく調整でき、ETC2はモバイルGPUの基本形式。

先に潰すリスク

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

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

判断チェックリスト

  • 自社の用途が「グラフィックス / テクスチャ圧縮」に近いか確認する。
  • 強みである「GPUテクスチャ圧縮は4×4テクセルを固定バイト長のブロックへ非可逆符号化し、サンプラがランダムアクセスで即時展開するため、JPEGと違いメモリと帯域を実行時に恒常的に削減する。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

グラフィックステクスチャ圧縮ブロック圧縮ASTCGPUグラフィックステクスチャ圧縮ブロック圧縮