3Dサイトに最適⁉ 「転送は軽いのにGPUでは重い」を解決するKTX2の話
かつ
2026/07/07
カツプロのトップページは、three.jsで作った「クジラと一緒に深海から宇宙まで旅する」スクロール3Dです。
こだわって作った自慢のページなのですが、長いあいだ深刻な問題を抱えていました。スマホだとローディングが終わらないのです。
この問題を解決するのに活用したのが KTX2(Basis Universal) という圧縮テクスチャ形式。
現時点ではあまり紹介の記事がほとんど無かったので、実際の数値と一緒に記録を残しておきます。
課題:12MBの3Dトップページ、スマホで開かない
トップページには3Dモデルが17体(クジラ・海の生き物・部屋・家など)あり、合計で約12MBありました。Wi-Fiでも読み込みが重く、スマホでは「ローディングが終わらない」報告が続いていました。
まずはモデルの圧縮(meshopt)や読み込みの遅延化で転送量を大きく削ったのですが、それでもスマホだけ動きが重く、発熱し、画質を上げるとカクつくという壁に当たりました。
原因:画像圧縮は「転送」しか軽くしていなかった
調べていて一番の学びだったのがここです。PNGやWebPといった普通の画像形式は、ファイルとしては小さくても、GPUに載る瞬間に無圧縮へ展開されます。
たとえば1024pxのテクスチャ1枚は、GPUメモリ上では約5.6MBになります。つまり200KBのWebPも、GPUの上では20MB級。うちのモデルは1体あたりテクスチャ4枚(色・法線・質感・発光)なので、17体で概算300MB級のGPUメモリを消費していた計算です。スマホのGPUには完全に許容量オーバーで、これが発熱とカクつきの正体でした。
さらに、画像をGPU用に展開する処理そのものがメインスレッドを塞ぐので、シーンの切り替わりで一瞬固まる原因にもなっていました。
解決策:KTX2 GPUが「圧縮のまま」読めるテクスチャ
KTX2(Basis Universal)は、この問題のために作られた形式です。魅力は3つ。
- GPU上でも圧縮されたまま:展開されないので、GPUメモリが約1/6〜1/10で済む
- 展開処理そのものが不要:読み込み時のカクつきが消える
- 1ファイルで全端末対応:iPhoneでもAndroidでもPCでも、それぞれのGPUネイティブ形式に自動変換(トランスコード)される
threejs.orgに載っているような「重そうなのにスマホでヌルヌル動く」サイトは、ほぼ例外なくこれを使っています。
変換方法(gltf-transform + KTX-Software)
glTF/GLBモデルなら、無料のCLIツールで変換できます。
# 1. テクスチャをKTX2(ETC1S)に圧縮
npx @gltf-transform/cli etc1s model.glb model-ktx.glb --quality 128
# 2. ジオメトリも圧縮するなら
npx @gltf-transform/cli meshopt model-ktx.glb model-final.glb
※ etc1sの実行には KTX-Software(無料)のインストールが必要です。
ひとつ、実際にハマった罠を共有します。元のGLBのテクスチャがWebPだと、KTXエンコーダが読めずに変換が「静かに」スキップされます。エラーも出ないので気づきにくい。AI生成モデル(Meshyなど)はWebPテクスチャのことが多いので、一度PNGに戻してから変換してください。
three.js側は3行
import { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js';
const ktx2 = new KTX2Loader()
.setTranscoderPath('https://cdn.jsdelivr.net/npm/three@0.169.0/examples/jsm/libs/basis/')
.detectSupport(renderer);
gltfLoader.setKTX2Loader(ktx2);
結果:転送1/10・GPUメモリ約1/8、画質はむしろ向上
KTX2化に加えて、章ごとの遅延読み込みやシェーダーの事前コンパイルも合わせた最終結果がこちらです。
| 指標 | 改善前 | 改善後 |
|---|---|---|
| ローディング画面が終わるまでの転送量 | 約11MB | 約1.1MB(1/10) |
| 最後まで見た場合の総転送量 | 約11.2MB | 約7.5MB |
| テクスチャのGPUメモリ | 概算300MB級 | 10数MB(約1/8以下) |
| テクスチャ解像度 | - | 2〜4倍に向上 |
一番うれしかったのは最後の行です。GPUメモリに余裕ができたので、軽くしながら同時に画質を上げるという普通は両立しない改善ができました。スマホでもローディングが数秒で終わり、発熱も減り、スクロールの引っかかりも消えました。
まとめ:3DをWebに載せるなら、KTX2は「いつか」ではなく最初から
- PNG/WebPの軽さは「転送だけ」。GPUの上では無圧縮ということを忘れない
- スマホの3Dで発熱・カクつき・クラッシュが出たら、まずテクスチャのGPUメモリを疑う
- KTX2は無料ツールだけで導入でき、three.js側の変更は数行
- WebPテクスチャのモデルは一度PNGに戻してから変換(静かに失敗する罠)
今回の改善は、カツプロの実際のプロジェクトとして行ったものです。3D表現やサイトの高速化に興味がある方は、ぜひカツプロのトップページを触ってみてください。このページ自体が実物のデモです。
この記事の著者・監修
カツ
カツプロ運営者のカツです! AI・Web関連から、日常のことなど、私目線の回答も交えながらお伝えします!
この記事をシェア