Three.js で僕の部屋を表現する
GPT-6 Astra がリリースされた。思い返せば 9 月 5 日の朝、真夜中に起きてトイレに行き、何気なくスマホの時間と通知を見たら GPT-6 がリリースされていた。公式発表では特に Blender を操作する能力がアピールされていた。そこで僕はトイレを済ませるとすぐにパソコンの前に向かい、デモ作りに取り掛かった。ずっとやってみたかったプロジェクト――自分の部屋を使ってインタラクティブな自己紹介を作る――を実現するためだ。
Blender を使ったレンダリングとベイク処理(Bake)により、部屋のシーン画像とインタラクションはおよそ2時間で初版が完成した。正直なところ、これにはかなり驚かされた。従来のモデルもマルチモーダルには対応していたものの、人に見せられるレベルで完全に再現するにはまだ大きな開きがあった。しかし今回は One Shot でかなり見事なクオリティに仕上がったのだ。あとは微調整とテキストの修正だけだった。
GPT-6 の再現度は非常に高く、3Dシーンへの理解も優れている。コーヒーの湯気や Matrix 風のアニメーション、原稿用紙のしわを表現するシェーダーなども、僕が出したい効果を言葉で伝えただけで実装してくれた。
もうひとつの試みとして、TSL を採用した。TSL は Three.js が WebGPU と WebGL の互換性を保つために用意した構文であり、通常の Shader や素の WebGPU よりも格段に書きやすい。TSL はブラウザが WebGPU をサポートしているかを自動で判別し、非対応の場合は WebGL へフォールバックしてくれる。構文に共通する部分も多いため、言語モデルにとってもコードの移行が容易だ。
この記事では僕の制作手法について書き残しておこうと思う。全体のアーキテクチャは大まかに以下の通りだ:
- Blender で部屋をモデリングし、光源や影をあらかじめテクスチャマテリアルに焼き付ける(ベイクする)
- Three.js を使って視点切り替え、モデルのレンダリング、インタラクションを制御する
- 工夫を凝らし、シーン内のオブジェクトをクリック可能に設計する
1. 写真撮影
最初のステップは撮影だ。自分の部屋の写真を撮り、Codex から直接 Blender MCP を呼び出して、部屋のモデリングを行わせた。最初のバージョンはこんな感じだ:
部屋全体の骨組みがしっかり出来上がっており、Scene 内の Layer もきちんと名前が付けられている!これなら人間が手動で手を入れるのも簡単だ。
次はシェーディング(色塗り)だ。これも同様に Blender MCP を介して行った。GPT-6 Astra は写真の中の色をしっかりと理解できる。そこに僕自身のアイデアを加えていくつか要素を追加した。例えば、本棚の上にソーシャルメディアのリンクを割り当てるための3つの立方体を配置した。
2. UV展開とライトのベイク
シーンが完成した後、Web上でレンダリングするためにはさらにいくつかの手順が必要になる:
UV展開(UV Unwrapping)
コンピューター上で 3D オブジェクトをレンダリングすることは、2D のテクスチャ(Texture)を指定されたルールに従って 3D オブジェクトの表面に貼り付ける作業だとイメージすると分かりやすい。このプロセスを UV ラッピング(UV Wrapping)と呼ぶ。
例えば、立体的な立方体の紙箱を辺に沿って切り開き、十字型の平面に広げる。この切り開いて展開する作業が Unwrapping(展開) であり、包装紙を再び紙箱へと包み直す対応関係が Mapping / Wrapping(マッピング / ラッピング) だ。
例を挙げると、これが僕のギターの UV 展開図だ。僕の理解では、UV 展開はモデリング作業の中でも特に退屈な工程のひとつだが、AI を組み合わせることでこの作業を劇的に簡略化できる。
ただ、ここで僕には分からない部分も出てきた。この UV 展開の出来が良いのか悪いのか、僕には判断がつかないのだ。分かっているのは、最終的な見た目がかなり良い仕上がりになったということだけだ。
ライトのベイク(Baking)
Three.js には光と影を動的に計算するライティング API が豊富に用意されている。しかし、リアルタイムの光影計算はパフォーマンスへの負荷が大きい。そのため、僕は最初の段階から AI に対し、Three.js の動的光源は使わず、直接ベイク処理を行うよう指示していた。ベイクとは、負荷のかかる光と影の計算を事前に行っておき、モデルのテクスチャ(Texture)に直接描き込んでしまう技術のことだ。
事前に計算されているからこそ、レンダリングソフト特有のリアルなライティングや反射、陰影をそのまま保持できる。その代償として、光と影があらかじめ焼き付けられているため、オブジェクトと一緒に動かすことはできない。
3. インタラクション
次はオブジェクトとのインタラクションだ。オブジェクトを実際の I/O と連動させるには、Raycast を使ってマウスポインタの座標を変換し、オブジェクトと接触しているかを判定する。そのため、部屋の中の各オブジェクトには個別に Mesh を作成した。判定自体のロジックも AI に書かせたもので、僕が指示したのは Three.js の API を使って判定を行うことだけだ。
続いて、僕自身がこだわって追加した細かな演出について紹介する:
- ホバー時にオブジェクトが少し浮き上がり、クリック時に効果音が鳴る
- PC モニターの Matrix アニメーション演出(中身は日本語だ!)
- コーヒーカップから立ち上る湯気のエフェクト
- 原稿用紙のしわのエフェクト
- オブジェクトクリック時の視点移動
- すべての操作をキーボードやインデックスのガイドから行える設計
- 中国語、英語、日本語の3言語に対応
- 視点移動のアニメーション中に ESC キーを押した際、いきなり切り替わるのではなく現在の進行位置からスムーズに遷移して戻る演出
- reduced motion への配慮:有効時は湯気や画面のアニメーション効果が自動で停止する
- PC やスマートフォンにおいて、視覚的な刺激を減らすためにこの設定をオンにしているユーザーがいる
- モバイル版に特化したインタラクションと UI の調整
- ギターに小さく刻まれた「Fender」のロゴ
これらのディテールを詰めていく中で気づいたのは、AI による完成度が劇的に向上したとはいえ、細部を仕上げるには人間自身が補う必要があるということだ。単に「Make it better」と指示するだけでは決して辿り着けない。では、そうした細部にどうやって気づくのか?それは経験を積み重ね、細部への観察眼を養っていくほかないのだ。
Blender も 3D モデリングもまったくの素人である僕も、プロの視点から見れば当然とされる多くのディテールを見落としていたかもしれない。
4. 成果
GPT-6 が大半の作業をこなしてくれたものの、細部をブラッシュアップする作業には丸二日近くかかった。中のテキストの推敲もそのひとつで、GPT が生成した文章は本当に目を覆いたくなるほど酷いものだった。
以下にいくつか切り取ったスクリーンショットを載せる:
この手のインタラクティブなポートフォリオを作る際、最も陥りがちな落とし穴は、派手な視覚効果に夢中になるあまり「情報を伝える」という本来の役割を疎かにしてしまうことだ。僕が一番最初に思い描いた原点は、自分の部屋を共有し、部屋にあるモノを探索してもらうことを通じて、僕がどんな人間で、どんなものに惹かれて生きているのかを少しずつ知ってもらうことだった。
感想
これは僕がずっと構想を温めながらも、なかなか手をつけられずにいたプロジェクトだった。もしかしたら Fable 5.1 の時点でも十分に実現できたのかもしれないが、以前の僕は思い至らなかった。GPT-6 のリリースを見て初めてハッと気づいたのだ。「そうだ、今ならこのプロジェクトを形にできるじゃないか」と。
2024年以降、ソフトウェア開発は劇的な変化を遂げた。特に昨年、2025年6月頃からは、モデルが更新されるたびにこれまでのやり方が根底から覆されるような感覚だった。
これほど急速に AI が進化し続ける時代において、かつての僕はすべてを投げ出して逃げ出したいと思ったこともあった。だが、今は吹っ切れた。たとえ Frontier AI Labs の一員でない開発者であっても、この巨大な AI の波に当事者として立ち会い、見届け、手探りで模索しながら何かを作り出せる。これは千載一遇のチャンスだ。みすみす船を降りてしまうなんて、あまりにもったいない。
ぜひ room.kalan.dev に僕の部屋を覗きに来てほしい!
関連記事
- フロントエンドで画像を扱う際に注意すべきこと Jake Archibaldの記事を起点に、現代のレスポンシブ画像の書き方を整理する。なぜwidth/heightを付ける必要があるのか、CSSのaspect-ratioはいつ使うべきか、AVIFとWebPの選び方、そしてpicture/source/srcsetを使ったモバイル向け画像の切り替えについて。
- CSS field-sizing — たった1行のCSSでフォーム要素を自動リサイズする かつてtextareaの自動高さ調整は、JavaScriptでscrollHeightを監視するしかなかった。しかしCSSのfield-sizing: contentなら、わずか1行で代替でき、textarea、input、selectに対応している。本記事では従来のやり方のペインポイントと、field-sizingの使い方をまとめる。
- リンクの下線をもっと見栄え良くする:text-underline-offset デフォルトでは下線と文字が近すぎて、このスタイルを好まないデザイナーもいるし、僕自身もあまり綺麗ではないと感じていた。
- なぜウェブで Pixel Perfect を追求すべきではないのか Pixel Perfect はそれが本当に重要な場合にのみ意識すべきであり、そうでなければ往々にしてお互い損をする結果に陥ってしまう。