はじめに
水面に光が映り、立方体が静かに浮かぶ。そんな空間をWebブラウザで自由に歩けるようにする、NOCTE — A Quiet Space to Explore の制作を始めました。
AIに実装を手伝ってもらい、Blenderで形を作り、React Three FiberでWebへ持ち込む。完成までの過程を、全8回の制作ログとして残していく予定です。

目指す空間の参考画像です。今回の実装画面ではありません。
第0回で作るのは、この景色を支える土台です。Unityの初期シーンのように、白い地面と太陽光を置き、まずは歩ける状態にします。今回は、広さを決める、移動できるようにする、性能を測る。この三つを進めます。
- 広さの基準:1 unit=1mとし、200m四方を仮に設定する。
- 歩ける操作:マウスで見回し、歩く・走る・跳ぶ。
- 比較できる記録:今の描画性能と通信量を残す。
AIにまとめて作ってもらう方法もありますが、後から形や配置を調整するなら、何を足したのか分かる状態で進めた方が扱いやすいと思うのです。水面やモデルを加える前に、空間の寸法と動作の基準を用意しておきます。
この記事では、細かなコード解説よりも、AIに何を頼み、できたもののどこを確かめたかを中心に紹介します。キーボードとマウスのあるPCを使い、手順を追いながら試せる構成です。

STEP 1| 制作環境を用意する
最初に、AIへNext.jsとTypeScriptを使った制作環境の準備を頼みました。3Dの描画にはThree.js、そのシーンをReactで組み立てるためにReact Three Fiber(R3F)を使います。
役割を大まかに分けると、Reactが画面や設定の状態を管理し、Three.jsが3Dを描画し、R3Fが両者をつなぐ、という関係です。Blenderで形を作るのは次回からになります。
用語の図解は、タップすると原寸画像を開けます。
以下の指示例は、実際に渡した指示を、記事で使いやすい長さに整理したものです。一度にすべて作らせず、各段階で起動と表示を確かめてから先へ進めます。
Next.jsとTypeScriptで、ブラウザ上に3D空間を作るための最小構成を用意してください。Three.js、React Three Fiber、Dreiを導入し、互換性と使用バージョンを確認してください。まずはローカル起動と本番ビルドまで確かめ、移動や演出はまだ追加しないでください。
Next.jsのプロジェクトに3D用のライブラリを追加する場合、基本となるコマンドは次のとおりです。Node.jsとnpmが使える環境で、プロジェクトのフォルダを開いて実行します。
npm install three @react-three/fiber @react-three/drei
これはライブラリを追加するためのコマンドで、これだけで3D画面が完成するわけではありません。今回はAIが設定ファイルや画面を用意し、バージョンを固定して導入しました。ReactとR3Fの対応などは、R3F公式の導入ガイドでも確認できます。
起動は npm run dev。ブラウザに準備用の画面が表示されたら、次の段階へ進みます。
今回使ったライブラリとバージョン
記録時点の構成は、Next.js 16.4.0、React 19.3.0、TypeScript 7.0.2、Three.js 0.186.1、React Three Fiber 9.8.1、Drei 10.7.9です。
DreiはR3F向けの便利な部品を集めたライブラリ。導入はしていますが、第0回の実装では個別の部品をまだ使っていません。実際の準備は設定ファイルの作成から始め、固定した依存関係をインストールしました。
STEP 2| 広さを決め、 歩けるようにする
今回は、1 unit=1m を共通のルールにしました。後からBlenderで作るモデルも、この基準に合わせます。
空間の広さは、100m・150m・200m四方の候補を比較しました。ここで比べたのは実際に歩いた時間ではなく、移動速度を4m/sとしたときの計算上の目安です。
| 一辺の長さ | 端から端までの時間 |
|---|---|
| 100m | 約25秒 |
| 150m | 約37.5秒 |
| 200m | 約50秒 |
障害物のない直線移動なら「距離÷速度」で求められます。4m/sは、この体験のために選んだ設定で、現実の一般的な歩行速度を再現した値ではありません。
ひとまず200m四方を仮採用し、目線は1.65m、垂直方向の視野角(FOV)は60度にしました。寸法だけで広さの感じ方が決まるわけではないので、歩けるようにしてから調整します。
200m四方の白い地面と太陽光を用意してください。1 unit=1m、目線1.65m、垂直FOV60度、歩行4m/sを初期値にします。WASD移動、マウスでの見回し、Shiftで走行、Spaceでジャンプに対応させてください。Escで操作を解除し、Rで初期位置へ戻れるようにしてください。
できた空間には、距離の目安になるグリッドと境界線も加えました。走行速度は歩行の1.75倍、7m/sです。
| 操作 | キー・動作 |
|---|---|
| 操作を始める | 画面をクリック |
| 歩く・見回す | WASD・マウス |
| 走る・跳ぶ | Shift・Space |
| 操作を解除する | Esc |
| 初期位置に戻る | R |
移動とジャンプは、どう動いている?
クリックするとPointer Lock APIでマウスを捕捉し、移動量から視線を更新します。上下の角度を制限して、カメラが反転しないようにしました。
前進方向にはカメラの左右の向きだけを使うため、上を向いても地面に沿って進みます。斜め入力は方向ベクトルを正規化し、前進だけのときより速くならないようにしています。
移動距離は「速度×前フレームからの経過秒」で計算。ジャンプは初速5m/sと重力9.81m/s²で高さを更新する自前の処理で、着地時に地面へ戻します。空中での再ジャンプはできません。
今は平らな地面と外周の制限まで。後から置くモデルとの衝突判定や、坂道・段差への対応は、まだ実装していません。
STEP 3| 何も置いていない 今を測る
後からモデルや水面を加えたとき、見た目と一緒に動作も変わります。そこで、まだ何も置いていない状態を、比較の出発点として記録することにしました。
画面の隅にFPS、Frame Time、Draw Calls、Trianglesを小さく表示してください。30秒間の測定結果をJSONで保存できるようにし、画面サイズや描画DPRなどの条件も一緒に残してください。
画面上の小さな数値表示をHUDと呼びます。今回は、空間を見る邪魔にならないよう左上に置いています。

今回の実装画面。HUDの118.2 FPSなどは歩行中の1秒平均で、下の30秒測定とは別の値です。
計測には、開発中の画面ではなく本番ビルドを使いました。開発サーバーとは別のターミナルを開き、プロジェクトのフォルダで次を順に実行します。
npm run build
npm run start -- --port 3001
ブラウザで http://127.0.0.1:3001 を開き、Escで操作を解除。右下の「設定 / 計測」から「待機を測定」を選び、終了後に「JSONを保存」で記録を残せます。JSONは、数値と条件を後から読み返せるデータ形式です。
今回残した基準値は、この本番画面をBraveで開き、立ち止まったまま、連続描画を30秒間測った結果です。歩行中の性能をまとめた値ではありません。
| 項目 | 測定値 |
|---|---|
| 平均FPS | 約120 |
| 平均Frame Time | 8.33ms |
| Frame Timeの95パーセンタイル | 9.60ms |
| Draw Calls | 3 |
| Triangles | 2 |
95パーセンタイルは、測定したフレーム間隔の約95%がその値以下だった、という目安です。平均だけでなく、少し遅くなった側の様子も残しています。
測定条件と、数値の読み方
2026年10月12日、本番ビルド・Brave・描画DPR 1で測定しました。画面は約1288×1239 CSS px、Canvasの実寸は1287×1238px。ブラウザのズームは90%で、DevToolsを閉じ、1秒の準備時間のあとに30秒記録しています。
測定機はMacBook Pro(機種ID:MacBookPro18,2)、macOS 26.3.1、Brave 155.1.97.56。チップ名は記録していません。ブラウザ操作用の拡張機能は有効な状態です。
Draw CallsとTrianglesは、描画直後のThree.jsのrenderer.infoから取得。Frame Timeはperformance.now()で描画呼び出し終了時刻どうしの間隔を測り、その平均からFPSを求めています。GPU単体の処理時間を測った値ではありません。
Draw Calls 3は地面・グリッド・境界線。Triangles 2は地面を作る三角形で、グリッドや境界線は線として別に数えられます。200m四方という広さだけで、三角形の数が増えるわけではありません。参考:Three.jsの計測項目
60 FPSを目指すなら、1フレームの目安は約16.7msです。ただし、今回の約120 FPSが、どのPCでも出るわけではありません。今後はできるだけ同じPC、ブラウザ、画面サイズ、カメラ位置で測り、何を足したときにFrame Timeが伸びたかを見ていきます。
STEP 4| 読み込むデータ量も 確認する
画面が滑らかに動くかとは別に、最初にどれだけのデータを読み込むかも確認しておきます。次回以降、モデルやテクスチャを持ち込むときの比較に使うためです。
Chromeの開発者ツールなら、次の順で確認できます。
- アプリを開き、開発者ツールの Network タブへ進む。
- Disable cache をオンにし、通信記録を消してから再読み込みする。
- 読み込みが落ち着いたら、一覧のいちばん下の集計欄を見る。
transferredとresourcesを、それぞれ記録する。
transferred は転送量、resources は展開後のリソースサイズです。同じ数字ではないので、分けて残します。確認する場所は、Chrome DevTools公式の集計表示の説明でも紹介されています。
今回はBraveのDevToolsで測定しました。Chromeでの実測は、まだ行っていません。 キャッシュを無効にして再読み込みし、対象アプリの通信に絞ると、14件、転送量は約396kB、展開後は約1.40MBでした。
フィルターには domain:127.0.0.1 を指定し、拡張機能の通信と分けています。実際に確認する際は、自分のアプリのドメインに合わせます。
なお、これはDevToolsを開いて行った別の測定です。前の節のFPSはDevToolsを閉じて記録しており、条件を混ぜないようにしています。
STEP 5| 歩いて、 広さの感覚を確かめる
土台ができたら、画面をクリックして歩いてみます。最初は次の順に確認すると、調整する場所を見つけやすそうです。
- まっすぐ歩き、端までの距離がどう感じられるかを見る。
- 周囲を見回し、視野角やマウスの動きが合うか確かめる。
- 走行とジャンプを試し、移動の速さや高さを見る。
- 広さか速度のどちらか一方を変え、元の状態と比べる。
クリックでの開始、WASD移動、走行、ジャンプ、Escでの解除、RでのリセットはBraveで動作を確認しました。実マウスで見回したときの操作感や、歩行動画の収録は、引き続き確認していく部分です。
見た目を加えると、歩きやすさだけでなく、描画の負荷も変わります。まだ追加後の数値はありませんが、次のような点を記録していく予定です。
モデルや演出を加えたら、何が増える?
- 別々に描くメッシュや材質が増えると、Draw Callsが増えやすくなります。
- 細かいモデルでは三角形や頂点の数、大きなテクスチャでは通信量やGPUメモリの使用量に注意します。
- 影、反射、透明表現、後処理は、追加の描画や画素の処理によってFrame Timeが伸びる要因になります。
- 同じ画面サイズで描画DPRを1から2にすると、縦横がそれぞれ2倍になり、処理する画素数は4倍になります。
繰り返し置く物体にはインスタンシング、遠景には細部を減らすLODなどが候補です。ただ、三角形が少なくても反射や高解像度で重くなることがあります。一律の上限を決めるより、追加前後を同じ条件で比べていきます。参考:R3Fの性能改善ガイド
次回は、Blenderで 寸法と配置を考える
今回は、空間の広さ、歩ける操作、性能と通信量の基準値まで用意しました。まだ白い地面だけですが、ここからモデルを足し、変化を確かめていける状態になりました。
次回はBlenderで、簡単な形を使って寸法や配置を考える「グレーボックス」を作ります。中央のフレームはどれくらいの大きさにするか。立方体の間を通れるか。今回の200m四方を仮の基準に、測りながら組み立てていく予定です。
NOCTEの制作ログ:全8回の予定
- #00 歩ける3D空間の土台を作る — 今回。環境、移動、寸法、計測。
- #01 Blenderで寸法を決める — グレーボックスで大きさと配置を考える。
- #02 BlenderのモデルをWebへ — GLBを書き出し、R3Fに読み込む。
- #03 水面を作る — AIでの素材生成やノーマルマップを試す。
- #04 発光するフレームを作る — 発光マテリアルとBloom、負荷の比較。
- #05 空間の演出を追加する — 浮遊オブジェクト、月、空、照明。
- #06 描画を最適化する — インスタンシング、モデル統合、テクスチャの見直し。
- #07 完成と性能測定 — ワールドの公開と制作全体の振り返り。
内容や順番は、制作の結果に合わせて調整します。
少しずつ作り、測って、調整する。AIに実装を手伝ってもらいながら、自分でも扱える部分を増やしていくと、完成後の空間も、もっと自由に変えていけるのではないかと思うのです。
SHARE
この記事を共有
AUTHOR

SHIZUYA
Creative Developer / Designer / Musician
フロントエンド開発、3D表現、AI活用、音楽制作などを横断しながら、美しく機能する体験を追求しています。







