WebARを自前のJavaScriptコードで実装したい開発者にとって、Three.js + WebXR Device APIの組み合わせは最も柔軟な選択肢のひとつです。本記事では、Three.jsを使ったAR空間への3Dオブジェクト配置から、hit-test(平面検出)の実装、パフォーマンス最適化まで、実践的なコード例を交えて解説します。

Three.js + WebXRとは?

Three.jsはWebGL上で3Dグラフィックスを扱うための人気JavaScriptライブラリです(GitHubスター数:90,000以上)。WebXR Device APIはW3Cが標準化を進めるブラウザAPIで、ARおよびVRセッションをウェブから直接起動できます。

Three.jsはv128(2021年)からWebXRのサポートを強化しており、THREE.WebXRManagerを通じてARセッションの管理・レンダリングをシームレスに行えます。8th Wallのような月額有料サービスとは異なり、ライセンス費用ゼロで高度なWebARを実装できる点が最大の魅力です。

対応ブラウザ・デバイス

  • Android Chrome 81以降: WebXR AR完全対応(最も安定)
  • iOS Safari: WebXR ARは未対応(2024年現在)。iOSではAR.jsまたはModel Viewer経由でのAR Quick Lookを利用
  • Samsung Internet: 部分対応

環境構築

npmプロジェクトでの導入

npmを使う場合は以下のコマンドでThree.jsをインストールします。

npm install three

Viteを使ったプロジェクトでのセットアップ例:

npm create vite@latest my-webar -- --template vanilla
cd my-webar && npm install three && npm run dev

CDNで素早く試す

手早くプロトタイプを作るにはCDN経由が便利です。HTMLファイルに以下を追加するだけで利用できます。

<script type="importmap">{"imports":{"three":"https://cdn.jsdelivr.net/npm/three@0.164/build/three.module.js","three/addons/":"https://cdn.jsdelivr.net/npm/three@0.164/examples/jsm/"}}</script>

ARセッション開始の基本コード

WebXR ARセッションを開始する最小構成のコードです。

index.html(ARボタン):

<!DOCTYPE html>
<html><body>
<button id="ar-btn">ARを起動</button>
<script type="module" src="./main.js"></script>
</body></html>

main.js(ARセッション初期化):

import * as THREE from 'three';
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.xr.enabled = true;
document.body.appendChild(renderer.domElement);

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera();

document.getElementById('ar-btn').addEventListener('click', async () => {
const session = await navigator.xr.requestSession('immersive-ar', {
requiredFeatures: ['hit-test']
});
renderer.xr.setSession(session);
});

renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
});

hit-testで床面を検出して3Dオブジェクトを配置する

hit-test機能を使うと、カメラが向いている先の実世界の平面(床・テーブルなど)を検出し、その位置に3Dオブジェクトをスナップ配置できます。

// hit-testソースを取得
let hitTestSource = null;
session.requestReferenceSpace('viewer').then(refSpace => {
session.requestHitTestSource({ space: refSpace }).then(source => {
hitTestSource = source;
});
});

// アニメーションループ内でhit-testを実行
renderer.setAnimationLoop((timestamp, frame) => {
if (frame && hitTestSource) {
const hitTestResults = frame.getHitTestResults(hitTestSource);
if (hitTestResults.length > 0) {
const hit = hitTestResults[0];
const pose = hit.getPose(referenceSpace);
// poseの位置にオブジェクトを移動
myObject.position.setFromMatrixPosition(new THREE.Matrix4().fromArray(pose.transform.matrix));
}
}
renderer.render(scene, camera);
});

レンダリング最適化のポイント

モバイルでのWebARはCPU・GPU・バッテリーへの負荷が高いため、以下の最適化が重要です。

  • ポリゴン数を抑える: ARオブジェクトは10,000ポリゴン以下を目標にする
  • テクスチャ圧縮: KTX2/BasisUフォーマットを使用してテクスチャサイズを最大80%削減
  • LOD(Level of Detail): THREE.LODクラスを使い、距離に応じてポリゴン数を切り替え
  • シャドウ無効化: AR環境ではリアルタイムシャドウをオフにする(renderer.shadowMap.enabled = false
  • フレームレート制限: renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))でピクセル比を制限

AR.jsとの使い分け

項目Three.js + WebXRAR.js
対応ブラウザAndroid Chrome(iOS不可)iOS Safari含む広範囲
実装難易度中〜高低(A-Frameタグ記述)
マーカーレスAR◎ hit-test対応△ 限定的
マーカーAR△(追加実装必要)◎ NFTマーカー対応
カスタマイズ性◎ 高い△ 制約あり
おすすめ用途高品質ARアプリ開発iOS対応が必要なキャンペーン

Three.js WebARの実装でお困りですか?

WebXR・Three.jsを使ったカスタムWebAR開発の技術支援を行っています。要件定義からデプロイまでご相談ください。

技術相談はこちら →