プラットフォームが違えば運命も違う:圧縮方式の選定ガイド
前 4 編はそれぞれ頂点圧縮とテクスチャ圧縮のツールを扱いました。でもツールを使えることと、どれを、どのシーンで使うか は別の話です。この記事はそれに答えます──そして読み終えたら即決できるように努めます。
この記事を読めば答えられるはず:私のプロジェクトはどのプラットフォームで動くのか、初回描画のボトルネックはダウンロードか VRAM か、テクスチャと頂点はそれぞれどの方式にすべきか。
方針決め:シーン駆動、ツール駆動ではない
この記事のコア原則は一つだけで、シリーズ全体で繰り返し強調してきたことです:
「最も良い」圧縮方式はなく、「最もシーンに合う」方式だけがある。
選択を左右する三つの変数:
- プラットフォーム/デバイス:デスクトップ PC、モバイルブラウザ、VR ヘッドセット、ミニプログラム──能力の差は歴然
- 使い方:一回限りの表示(EC の商品ページ)か、長時間の没入(VR ゲーム)か
- 主なボトルネック:ダウンロードが遅いのか、VRAM が足りないのか、初回描画のデコードが重いのか
まずボトルネックを考え、それからツールを選びに戻りましょう。下のマトリクスはこの考え方を定着させたものです。
コア意思決定マトリクス:プラットフォーム × 推奨方式
この記事で最も重要な表です。プラットフォーム別に、テクスチャと頂点それぞれの推奨方式と理由を示します。
| プラットフォーム / シーン | テクスチャ方式 | 頂点方式 | 主なボトルネック | 主な理由 |
|---|---|---|---|---|
| デスクトップ Web(PC ブラウザ) | KTX2 または WebP | MeshOpt / 量子化 | ダウンロード速度 | VRAM に余裕、重点は小さく速く |
| モバイル Web(スマホブラウザ) | KTX2(必須) | MeshOpt | VRAM | スマホの VRAM はきつい、テクスチャはブロック圧縮必須 |
| WebXR / VR ヘッドセット | KTX2(必須) | MeshOpt + LOD | VRAM +フレームレート | VRAM 爆発でクラッシュ、フレームドロップで酔い |
| WeChat ミニプログラム | KTX2 / WebP | MeshOpt / 純量子化 | パッケージ+互換性 | パッケージサイズ制限、重いデコーダを避ける |
| EC の商品表示 | WebP(軽量)/ KTX2(精密) | MeshOpt | 初回描画速度 | 秒で開く要求、サイズで速度を買う |
| 大規模シーン / デジタルツイン | KTX2(必須) | MeshOpt + Draco + LOD | VRAM +ドローコール | テクスチャ多く、モデル大、全方位に圧縮 |
覚えておくべき判断:
- VRAM がボトルネックなら、KTX2 は必須(モバイル、VR、大シーンすべて該当)
- ダウンロードがボトルネックで VRAM に余裕があれば、WebP でも可(デスクトップ、EC)
- ミニプログラムなどパッケージに敏感な環境では、Draco より MeshOpt を優先──デコーダが小さく互換性も良い
- 超大モデルでのみ Draco を検討、圧倒的多数の中規模モデルでは MeshOpt のほうがバランスが良い
テクスチャ形式を全次元で比較
「KTX2 を使う」だけでは足りません。テクスチャ形式について、全次元を並べて見ましょう:
| 形式 | ファイルサイズ | VRAM 使用量 | アップロード速度 | 互換性 | 画質 | 適する用途 |
|---|---|---|---|---|---|---|
| PNG | 大 | 大(展開後) | 遅い | 極広 | ロスレス | 正確な数値/透過が必要、旧プラットフォームのフォールバック |
| JPG | 極小 | 大(展開後) | 遅い | 極広 | 損失あり | カラーマップ、ネットワーク優先 |
| WebP | 非常に小さい | 大(展開後) | 遅い | 比較的広 | 高 | デスクトップ Web、ダウンロード速度重視 |
| AVIF | さらに小さい | 大(展開後) | 遅い | 段階的普及 | 高 | 新プラットフォーム、極限圧縮 |
| KTX2 (ETC1S) | 小 | 極小 | 速い | トランスコード必要 | 中(カラーなら十分) | カラーマップ、モバイル/VR |
| KTX2 (UASTC) | 中 | 小 | 速い | トランスコード必要 | 高 | 法線/データマップ |
最初の 3 行(PNG/JPG/WebP/AVIF)の VRAM 使用量がいずれも「大」なのに注意──ディスクがいくら小さくても、VRAM に入れば元の生ピクセルに展開されます。これが従来形式の根本的な制限です。
ミックス戦略は一般的です:主要なカラーマップは KTX2 で VRAM を確保し、副次的なマップ(小さな emissive など)は WebP で手軽に。全部 KTX2 に一刀切りする必要はなく、ボトルネックで配分します。
意思決定フローチャート:ステップで選ぶ
マトリクスは結果、フローチャートはどう結果に至るかを示します。
あなたのプロジェクトはどこで動く?
│
├─ デスクトップ Web(VRAM に余裕)
│ └─ 初回描画が遅い?
│ ├─ 遅い → WebP(または AVIF)+ MeshOpt [ダウンロード速度重視]
│ └─ 遅くないがモデルが多い → KTX2 + MeshOpt [将来に余裕を残す]
│
├─ モバイル Web / VR / 大シーン(VRAM がきつい)
│ └─ テクスチャは必ず KTX2(カラー ETC1S、データ UASTC)
│ └─ モデルの頂点が超密集?
│ ├─ はい → + Draco [極限圧縮、遅い解凍可容]
│ └─ いいえ → + MeshOpt [バランス]
│
└─ ミニプログラム / 制限付きランタイム
└─ パッケージに敏感?
├─ 敏感 → 純量子化または MeshOpt + WebP [デコーダ ゼロ/小]
└─ 大丈夫 → MeshOpt + KTX2 [通常の組み合わせ]
頂点圧縮 vs テクスチャ圧縮:どちらに投資するか
よく聞かれます:予算が限られる場合、どちらを先に最適化する?モデルの構成を見ましょう:
| モデルの特徴 | 投資の重点 | 理由 |
|---|---|---|
| PBR キャラクター/製品(マップ多め) | テクスチャ圧縮 | テクスチャが 80%+、頂点の ROI が低い |
| CAD/スキャンモデル(頂点超密集、マップ少なめ) | 頂点圧縮 | 頂点が主な容量 |
| アニメーションキャラクター(骨骼+スキニング) | 両方に投資、ただし頂点は Draco 以外を優先 | アニメデータも容量を占め、Draco はアニメに弱い |
| 建築/シーン(大、中程度のマップ) | テクスチャ + LOD | テクスチャで VRAM 節約、LOD でドローコール節約 |
収益の大まかな順位:テクスチャ KTX2 > 頂点 MeshOpt/量子化 > ジオメトリ簡略化(LOD) > 頂点 Draco。収益の高いものから先に。
ミックス戦略:主要マップは KTX2、副次マップは WebP
すべてのマップを KTX2 に圧縮する価値があるわけではありません。典型的な PBR マテリアルは 5-6 枚のマップを持ち、全部 KTX2 にするのは工数が大きく、時には不要です。
実用的な分け方:
- 必須 KTX2:albedo(大、カラー)、normal(精度に敏感)、roughness/metallic(光照に影響)
- WebP/JPG で可:emissive(通常小)、AO(中低周波)、詳細法線(あれば)
判断基準:マップが大きいか、高周波ディテールか、頻繁にサンプリングされるか。三つとも該当 → KTX2;いずれも該当しない → 従来形式が楽。
自動選定:gltf-transform で一発
gltf-transform の optimize コマンドは大半のシーンでの銀の弾丸──テクスチャタイプを自動判定し、推奨戦略でテクスチャを圧縮し、オプションで頂点も処理します。
# インストール
npm install -g @gltf-transform/cli
# 標準最適化:テクスチャ KTX2 +頂点 MeshOpt +冗長削除
gltf-transform optimize model.glb model-optimized.glb \
--texture-compress basisu \
--meshopt
パラメータ説明:
| パラメータ | 効果 | デフォルト |
|---|---|---|
--texture-compress basisu | テクスチャを KTX2 に圧縮(ETC1S/UASTC を自動選択) | オフ |
--meshopt | 頂点で MeshOpt 圧縮を有効化 | オフ |
--simplify | ジオメトリ簡略化(頂点削減、損失あり) | オフ |
--weld | 重複頂点をマージ | オン |
--prune | 未使用のノード/マテリアルを削除 | オン |
モバイル向け「強力圧縮」の組み合わせ:
gltf-transform optimize model.glb model-mobile.glb \
--texture-compress basisu \
--meshopt \
--simplify --simplify-ratio 0.5 \
--prune --weld
デスクトップ向け「マイルド」な組み合わせ(ディテールを保ち、テクスチャと頂点だけ圧縮):
gltf-transform optimize model.glb model-desktop.glb \
--texture-compress webp \
--meshopt
再利用可能スクリプトにする
上記をプラットフォーム別バージョンを出すスクリプトにまとめます:
// compress.mjs —— target 別に異なる圧縮版を出力
import { optimize } from "@gltf-transform/functions";
import { NodeIO } from "@gltf-transform/core";
import { KHRONOS_EXTENSIONS } from "@gltf-transform/extensions";
const io = new NodeIO().registerExtensions(KHRONOS_EXTENSIONS);
const targets = {
// モバイル:KTX2 + MeshOpt +簡略化
mobile: { texture: "basisu", meshopt: true, simplify: 0.5 },
// VR:KTX2 + MeshOpt、簡略化なし(VR の至近距離視聴)
vr: { texture: "basisu", meshopt: true, simplify: null },
// デスクトップ:WebP + MeshOpt、マイルド
desktop: { texture: "webp", meshopt: true, simplify: null },
};
const input = process.argv[2];
const doc = await io.read(input);
for (const [name, cfg] of Object.entries(targets)) {
const out = doc.clone(); // 各ターゲット独立コピー
await optimize(out, {
textureCompression: cfg.texture,
meshCompression: cfg.meshopt ? "meshopt" : null,
simplify: cfg.simplify != null ? { ratio: cfg.simplify } : null,
});
await io.write(`model-${name}.glb`, out);
console.log(`✓ model-${name}.glb`);
}
node compress.mjs model.glb
# model-mobile.glb / model-vr.glb / model-desktop.glb を出力
実行時にデバイス別に対応版を読み込み(UA か WebGL 能力検出で判別)、初回描画体験を最適化します。次の記事のエンドツーエンド実践でこれを完全に繋げます。
一言メモ
- VRAM がボトルネック → KTX2、選択の余地なし
- ダウンロードがボトルネック、VRAM に余裕 → WebP/AVIF でも可
- デコーダサイズに敏感 → MeshOpt > 純量子化 > Draco
- 超大モデル → その時に Draco を検討
- 判断に迷う →
gltf-transform optimizeを一発走らせ、間違っていたら調整
次のステップ
選定フレームワークは整いました。最終記事で締めくくり:実在するモデルを出発点に、Blender 書き出し、テクスチャ圧縮、頂点圧縮、エンジン読み込みの全フローを歩き、完全な自動化スクリプトとシリーズ早見表を添えます。