Any3DAny3D
·Any3D Team

プラットフォームが違えば運命も違う:圧縮方式の選定ガイド

3d-compressiontexture-compressionvertex-compressionoptimizationpipeline

前 4 編はそれぞれ頂点圧縮とテクスチャ圧縮のツールを扱いました。でもツールを使えることと、どれを、どのシーンで使うか は別の話です。この記事はそれに答えます──そして読み終えたら即決できるように努めます。

この記事を読めば答えられるはず:私のプロジェクトはどのプラットフォームで動くのか、初回描画のボトルネックはダウンロードか VRAM か、テクスチャと頂点はそれぞれどの方式にすべきか。

方針決め:シーン駆動、ツール駆動ではない

この記事のコア原則は一つだけで、シリーズ全体で繰り返し強調してきたことです:

「最も良い」圧縮方式はなく、「最もシーンに合う」方式だけがある。

選択を左右する三つの変数:

  1. プラットフォーム/デバイス:デスクトップ PC、モバイルブラウザ、VR ヘッドセット、ミニプログラム──能力の差は歴然
  2. 使い方:一回限りの表示(EC の商品ページ)か、長時間の没入(VR ゲーム)か
  3. 主なボトルネック:ダウンロードが遅いのか、VRAM が足りないのか、初回描画のデコードが重いのか

まずボトルネックを考え、それからツールを選びに戻りましょう。下のマトリクスはこの考え方を定着させたものです。

コア意思決定マトリクス:プラットフォーム × 推奨方式

この記事で最も重要な表です。プラットフォーム別に、テクスチャと頂点それぞれの推奨方式と理由を示します。

プラットフォーム / シーンテクスチャ方式頂点方式主なボトルネック主な理由
デスクトップ Web(PC ブラウザ)KTX2 または WebPMeshOpt / 量子化ダウンロード速度VRAM に余裕、重点は小さく速く
モバイル Web(スマホブラウザ)KTX2(必須)MeshOptVRAMスマホの VRAM はきつい、テクスチャはブロック圧縮必須
WebXR / VR ヘッドセットKTX2(必須)MeshOpt + LODVRAM +フレームレートVRAM 爆発でクラッシュ、フレームドロップで酔い
WeChat ミニプログラムKTX2 / WebPMeshOpt / 純量子化パッケージ+互換性パッケージサイズ制限、重いデコーダを避ける
EC の商品表示WebP(軽量)/ KTX2(精密)MeshOpt初回描画速度秒で開く要求、サイズで速度を買う
大規模シーン / デジタルツインKTX2(必須)MeshOpt + Draco + LODVRAM +ドローコールテクスチャ多く、モデル大、全方位に圧縮

覚えておくべき判断:

  • 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-transformoptimize コマンドは大半のシーンでの銀の弾丸──テクスチャタイプを自動判定し、推奨戦略でテクスチャを圧縮し、オプションで頂点も処理します。

# インストール
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 書き出し、テクスチャ圧縮、頂点圧縮、エンジン読み込みの全フローを歩き、完全な自動化スクリプトとシリーズ早見表を添えます。

応援する