不同平台不同命:壓縮方案選型指南
前 4 篇分別講了頂點壓縮和貼圖壓縮的工具。但工具會用是一回事,該用哪個、在什麼場景下用是另一回事。這篇就是來回答這個問題的——而且盡量讓你看完就能直接拍板。
讀完這一篇你應該能回答:我的專案跑在什麼平台,首屏瓶頸是下載還是顯存,貼圖和頂點各該上哪套方案。
先定調:場景驅動,不是工具驅動
整篇文章只有一條核心原則,也是這個系列反覆強調的:
沒有「最好的」壓縮方案,只有「最匹配場景」的方案。
影響選擇的三個變數:
- 平台/裝置:桌面 PC、行動瀏覽器、VR 頭盔、小程式——能力天差地別
- 使用方式:是一次性展示(電商產品頁),還是長時間沉浸(VR 遊戲)
- 首要瓶頸:是下載速度慢,還是顯存不夠,還是解碼卡首屏
先把瓶頸想清楚,再回來選工具。下面這張矩陣就是把這套思路固化下來。
核心決策矩陣:平台 × 推薦方案
這是全文最重要的一張表。按平台分,給出貼圖和頂點各自的推薦方案,以及理由。
| 平台 / 場景 | 貼圖方案 | 頂點方案 | 主要瓶頸 | 關鍵理由 |
|---|---|---|---|---|
| 桌面 Web(PC 瀏覽器) | KTX2 或 WebP | MeshOpt / 量化 | 下載速度 | 顯存寬裕,重點是檔案小、載入快 |
| 行動 Web(手機瀏覽器) | KTX2(必上) | MeshOpt | 顯存 | 手機顯存緊,貼圖必須塊壓縮 |
| WebXR / VR 頭盔 | KTX2(必上) | MeshOpt + LOD | 顯存 + 幀率 | 顯存爆炸會崩,掉幀會眩暈 |
| 微信小程式 | KTX2 / WebP | MeshOpt / 純量化 | 包體 + 相容性 | 包大小受限,避免重型解碼器 |
| 電商產品展示 | WebP(輕)/ KTX2(精) | MeshOpt | 首屏速度 | 要求秒開,體積換速度 |
| 大型場景 / 數位孿生 | KTX2(必上) | MeshOpt + Draco + LOD | 顯存 + draw call | 貼圖多、模型大,全方位壓 |
幾個值得記住的判斷:
- 只要顯存是瓶頸,KTX2 就必上(行動、VR、大場景都是)
- 下載速度是瓶頸、顯存寬裕時,WebP 也夠用(桌面、電商)
- 小程式這類對包體敏感的環境,優先 MeshOpt 而不是 Draco——解碼器小、相容好
- 超大模型才考慮 Draco,絕大多數中小模型 MeshOpt 更均衡
貼圖格式全維度對比
光知道「上 KTX2」還不夠。具體到貼圖格式,把所有維度攤開看:
| 格式 | 檔案大小 | 顯存佔用 | 上傳速度 | 相容性 | 畫質 | 適用場景 |
|---|---|---|---|---|---|---|
| PNG | 大 | 大(解壓縮後) | 慢 | 極廣 | 無損 | 需要精確數值/透明,或舊平台兜底 |
| JPG | 極小 | 大(解壓縮後) | 慢 | 極廣 | 有損 | 顏色貼圖、網路傳輸優先 |
| WebP | 很小 | 大(解壓縮後) | 慢 | 較廣 | 高 | 桌面 Web、追求下載速度 |
| AVIF | 更小 | 大(解壓縮後) | 慢 | 漸進 | 高 | 新平台、極致壓縮 |
| KTX2 (ETC1S) | 小 | 極小 | 快 | 需轉碼 | 中(顏色夠用) | 顏色貼圖、行動/VR |
| KTX2 (UASTC) | 中 | 小 | 快 | 需轉碼 | 高 | 法線/資料貼圖 |
注意前三行(PNG/JPG/WebP/AVIF)的顯存佔用都是「大」——無論磁碟多小,進了顯存都得解壓縮回原始像素。這是傳統格式的根本限制。
混合策略很常見:關鍵的顏色貼圖用 KTX2 保證顯存,次要貼圖(比如一個小 emissive)用 WebP 省事。不必一刀切全 KTX2,按瓶頸分配。
決策流程圖:一步步選
矩陣是結果,流程圖告訴你怎麼走到那個結果。
你的專案跑在哪?
│
├─ 桌面 Web(顯存寬裕)
│ └─ 首屏慢嗎?
│ ├─ 慢 → WebP(或 AVIF)+ MeshOpt [追求下載速度]
│ └─ 不慢,但模型多 → KTX2 + MeshOpt [為未來留餘地]
│
├─ 行動 Web / VR / 大場景(顯存緊)
│ └─ 貼圖必上 KTX2(顏色 ETC1S,資料 UASTC)
│ └─ 模型頂點超密?
│ ├─ 是 → + Draco [極限壓縮,能接受慢解碼]
│ └─ 否 → + MeshOpt [均衡]
│
└─ 小程式 / 受限執行時
└─ 包體敏感嗎?
├─ 敏感 → 純量化或 MeshOpt + WebP [零/小解碼器]
└─ 還行 → MeshOpt + KTX2 [常規組合]
頂點壓縮 vs 貼圖壓縮:該投哪個
經常有人問:預算有限,先最佳化哪頭?看模型構成:
| 模型特徵 | 投入重點 | 原因 |
|---|---|---|
| PBR 角色/產品(貼圖多) | 貼圖壓縮 | 貼圖佔 80%+,投頂點回報低 |
| CAD/掃描模型(頂點超密、貼圖少) | 頂點壓縮 | 頂點是主要體積 |
| 動畫角色(骨骼+蒙皮) | 兩頭都投,但頂點優先 Draco 之外 | 動畫資料也佔體積,Draco 對動畫支援弱 |
| 建築/場景(大、中等貼圖) | 貼圖 + LOD | 貼圖省顯存,LOD 省 draw call |
一個粗略的收益排序:貼圖 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 能力探測區分),首屏體驗最優。下一篇的端到端實戰會把這套完整串起來。
一句話備忘
- 顯存是瓶頸 → KTX2,沒得選
- 下載是瓶頸、顯存寬裕 → WebP/AVIF 也行
- 解碼器體積敏感 → MeshOpt > 純量化 > Draco
- 超大模型 → 才考慮 Draco
- 拿不準 →
gltf-transform optimize一鍵跑,錯了再調
下一步
選型框架有了,最後一篇收官:從一個真實模型出發,走完 Blender 匯出、貼圖壓縮、頂點壓縮、引擎載入的全流程,並附上完整自動化腳本和系列速查表。