Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】Three.js on mobile - the device gotchas that tank a configurator

2026年11月07日に「Dev.to」が公開したITニュース「Three.js on mobile - the device gotchas that tank a configurator」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

Three.jsでモバイル向け3Dアプリを作る際、デスクトップとの違いに注意が必要だ。画面の不要な高解像度レンダリングを抑え、GPUメモリを節約するためテクスチャを小さくする。また、アプリが一時停止すると画面が真っ暗になる問題や、タッチ操作とページの競合を防ぐ設定が重要となる。

ITニュース解説

システムエンジニアを目指す皆さんにとって、Web上で動作する3Dアプリケーション、特にThree.jsのようなライブラリを使った開発は非常に魅力的な分野だろう。しかし、PCのWebブラウザでスムーズに動作する3Dアプリケーションが、スマートフォンのブラウザで動かすと途端に動作がカクカクしたり、最悪の場合クラッシュしたりすることがある。これはプログラムのバグではなく、実はモバイルデバイス特有の環境に起因する問題が多い。本解説では、Three.jsを使った3Dコンフィギュレーター(商品の色や形などを自由にカスタマイズできるアプリケーション)を例に、モバイルデバイスで開発する際に陥りやすい落とし穴と、その具体的な対策を4つのポイントに絞って説明する。

まず、一つ目の問題は「ピクセル比率」だ。スマートフォンのディスプレイは非常に高精細である。これは「devicePixelRatio(デバイスピクセル比率)」という数値で表現され、一般的なPCが1であるのに対し、スマートフォンでは2や3、場合によっては4という値を示すことがある。このdevicePixelRatioは、Webブラウザが表示する論理的な1ピクセルを、物理的なディスプレイの何ピクセルで描画するかを示すものだ。もしThree.jsのレンダラーがこのdevicePixelRatioをそのまま受け取って描画しようとすると、例えばdevicePixelRatioが3のスマートフォンでは、PCの9倍ものピクセル数を計算して描画することになる。ユーザーから見れば画像が少し鮮明になる程度で、特に商品の見た目が劇的に変わるわけではないのに、レンダリングの負荷は劇的に増加し、結果として動作が遅くなる原因となる。この問題を解決するには、レンダラーに渡すピクセル比率を意図的に制限するのが有効な手段である。具体的にはrenderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))のように記述し、devicePixelRatioがたとえ3や4であっても、レンダラーには最大で2までしか使わせないようにする。この一行の変更だけで、スマートフォンでの3Dアプリケーションの動作が劇的に改善されることは珍しくない。

次に、二つ目の問題は「GPUメモリとテクスチャ」に関するものだ。スマートフォンとPCの大きな違いの一つに、GPU(Graphics Processing Unit、画像処理を担当する半導体)に搭載されているメモリの量がある。一般的なPCは数GBのGPUメモリを持っているのに対し、ミドルレンジのスマートフォンではその数分の一しか搭載されていないことが多い。3Dアプリケーションにおいて、このGPUメモリを最も大量に消費するのが「テクスチャ」である。テクスチャとは、3Dモデルの表面に貼り付ける画像データのことで、例えば商品の質感や模様などを表現するために使われる。PCでは問題なくロードできた高解像度のテクスチャも、スマートフォンではその生のデータサイズでGPUメモリに展開されるため、あっという間にメモリの上限を超えてしまうことがある。メモリ不足はアプリケーションのクラッシュやタブの強制終了を引き起こす。この問題を避けるためには、スマートフォン向けにはテクスチャのサイズを小さく抑えることが重要だ。例えば、PCでは4096x4096ピクセルのテクスチャを使っていたとしても、スマートフォン向けには1024x1024や2048x2048ピクセルに縮小することを検討すべきだ。さらに、KTX2のようなGPUフレンドリーな圧縮形式を使用することで、テクスチャがGPUメモリ上で展開される際も小さなサイズを保つことができ、メモリ使用量をさらに削減できる。

三つ目の問題は「コンテキストロスト」だ。Webブラウザ上で3Dグラフィックスを描画するために使われる「WebGLコンテキスト」は、特にモバイルデバイスでは突然失われることがある。これは単なる稀な現象ではなく、モバイル環境では頻繁に起こりうる「現実的な状態」と捉えるべきだ。例えば、ユーザーが3Dアプリケーションのタブをバックグラウンドに移動させたり、スマートフォン本体のメモリが不足したり、OSがバッテリー節約のためにGPUのリソースを一時的に回収したりすると、WebGLコンテキストが失われる可能性がある。もしアプリケーションがこの「コンテキストロスト」を適切に処理していなければ、ユーザーがアプリケーションに戻った際に、3Dモデルが表示されずに画面が真っ黒になってしまうといった事態が起こる。この問題に対応するためには、JavaScriptのイベントリスナーを使って、コンテキストロストの発生と回復を検知し、それに応じた処理を実装する必要がある。renderer.domElement.addEventListener('webglcontextlost', ...)でコンテキストが失われたことを検知したら、その場で3D描画のループを一時停止し、event.preventDefault()を呼び出してブラウザに回復処理を許可する。そして、renderer.domElement.addEventListener('webglcontextrestored', ...)でコンテキストが回復したことを検知したら、失われた3Dリソース(ジオメトリやマテリアル、テクスチャなど)を再構築し、描画ループを再開する、という一連のフローを組み込むことで、アプリケーションの安定性を高められる。

最後に、四つ目の問題は「タッチ入力」に関するものだ。PCでの3Dアプリケーションの操作はマウス入力が中心だが、スマートフォンでの操作はタッチ入力が基本となる。このタッチ入力は、単純に「小さなマウス」として扱うべきではない。スマートフォンにはピンチイン・ピンチアウトによるズームや、2本指での回転といった独自のジェスチャーが存在し、また、ユーザーがモデルを操作しようとしているのに、ブラウザのページ全体がスクロールしてしまうといった競合も発生しやすい。PC向けに設定したマウス操作用のコントロール(Three.jsのOrbitControlsなど)が、そのままスマートフォンで快適に使えるとは限らない。この問題に対処するためには、コントロールの設定をタッチ入力に特化させて調整する必要がある。例えば、OrbitControlsを使う場合、ダンピング(慣性)を設定することで滑らかな操作感を実現できるが、それだけでは不十分で、タッチイベントを明示的にコントロールに認識させ、ブラウザのデフォルトのスクロール動作などと競合しないように設定することが重要となる。これにより、ユーザーはモデルを自由に、かつ意図しないブラウザの動作に邪魔されることなく操作できるようになる。

以上の4つのポイントは、Three.jsを使った3Dアプリケーションをモバイルデバイスで動かす際に、多くの開発者が直面する共通の課題だ。これらの問題は、プロジェクトの終盤、特に顧客が自身のスマートフォンでテストする段階になって初めて発覚することが少なくない。しかし、そのような段階でこれらの問題に対処するのは、時間もコストもかかる非常に効率の悪いやり方である。そのため、開発の初期段階から、レンダラーのピクセル比率を制限したり、ブラウザのデベロッパーツールで動作をミドルレンジのデバイスに制限したりして、モバイル環境を想定したテストを積極的に行うことが極めて重要となる。ミドルレンジのAndroidスマートフォンなど、実際のモバイルデバイスで定期的にテストを実施することで、これらの「落とし穴」にプロジェクトの早い段階で気づき、スムーズな開発と高品質なアプリケーション提供につながるだろう。

関連コンテンツ

関連IT用語

関連ITニュース