2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

はじめてのアドベントカレンダーAdvent Calendar 2023

Day 8

【React】react-three-fiberで自作の3Dモデルを手軽にWebサイトに表示する

Last updated at Posted at 2023-11-11

背景

背景が変化するリッチなWebサイトをよく見かけます。
Three.jsでは3DモデルをWeebページ上に表示できるので、2Dでは表現できないようなリッチな背景をWebサイトに実装する事ができます。
ReactでもThree.jsのようなライブラリがないか調べたところ、three.js の React レンダラーであるreact-three-fiberがありました。
本記事では、react-three-fiberを使用し、Blenderで制作した3Dモデルをwebページ上に表示してみます。

◆完成イメージ図

image.png

  • react-three-fiber

  • drei

前提

本記事では、React×TypeScript環境を使用します。
また、Blenderで作成した3Dモデルの準備が必要です。
Blenderで設定したブルームの表現については触れず、
3DモデルをWebサイト上に表示させるところに絞っています。

環境

  • Blender:3.4
  • Typescript:4.9.5
  • React:18.2.0
  • React-three-drei:9.88.11
  • React-three-fiber:8.15.9

準備する3Dモデル

今回は桜をイメージした次の3Dモデルを表示させてみます。

scherry_blossom_night.png

Blender側ではgltf形式でエクスポートしました。
設定は以下の通りです。

image.png

1. プロジェクトの作成

--template typescriptを付けて、TypeScriptを使用するプロジェクトのひな形を作成します。
コマンドは以下の通りです。

npx create-react-app プロジェクト名 --template typescript

2. ライブラリインストール

react-three-fiberとdreiを以下のコマンドでインストールします。

npm i three @react-three/fiber @react-three/drei

以下のコマンドでthreeの型定義モジュールをインストールします。

npm i -D @types/three

3. フォルダ構成

一部分のみですがフォルダ構成は、以下の通りです。
assetsフォルダにBlenderでエクスポートした3Dモデル(sakura_tree.glb)を追加しています。

┬public
│ └assets
│ └sakura_tree.glb
└ src
  ├css
  │ └index.css
  ├App.tsx
  └index.tsx

4. GLTF形式の3Dモデルを読み込み

以下のコード部分では、useGLTFフックを使用してGLTF形式の3Dモデルを読み込み、
そのモデルのsceneを作成しています。
<primitive>コンポーネントを使用して、作成したシーンを描画しています。

App.tsx
function Model() {
  const { scene } = useGLTF("assets/sakura_tree.glb")
  return <primitive object={scene} />
}

5. キャンバスの描画

以下のコード部分では、<Canvas> コンポーネントを使用して3Dモデルをキャンバス内に描画しています。
キャンバスの背景色はstyle={{ background: "#001122" }でネイビー色を指定しています。
cameraプロパティを使用してカメラの初期位置を指定しています。

App.tsx
export default function App() {
  return (
    <>
      <Canvas camera={{ position: [2, 1, 2], near: 0.05 }}
       style={{ background: "#001122" }>
        {/* ~ */}
      </Canvas>
    </>
  )
}

6. 3Dモデルの描画

<OrbitControls>コンポーネントによりマウス操作でカメラの回転やズームを制御できます。
autoRotateプロパティが設定されているためカメラは水平方向に自動で回転します。
また、<group>コンポーネント内にModelコンポーネントを配置し3Dモデルを描画しています。

App.tsx
export default function App() {
  return (
    <>
      <Canvas camera={{ position: [2, 1, 2], near: 0.05 }}
       style={{ background: "#001122" }>
        {/* 3Dモデルの表示 */}
        <group>
          <Model />
        </group>
        {/* 自動横回転 */}
        <OrbitControls autoRotate />
        {/* フレームレート情報 */}
        <Stats />
      </Canvas>
    </>
  )
}

補足
Statsコンポーネントを使用する事で、画面にフレーム レート情報を表示できます。
必要ない場合は削除してください。

・App.tsxのコード全体

以上を踏まえたApp.tsx全体のコードです。

App.tsx
import { Canvas } from '@react-three/fiber'
import { Stats, OrbitControls, useGLTF } from '@react-three/drei'


function Model() {
  const { scene } = useGLTF("assets/sakura_tree.glb")
  return <primitive object={scene} />
}

export default function App() {

  return (
    <>
      <Canvas camera={{ position: [2, 1, 2], near: 0.05 }}>
        <group>
          <Model />
        </group>
        <OrbitControls autoRotate />
        <Stats />
      </Canvas>
    </>
  )
}

・index.tsxのコード全体

root.renderメソッドを使用してidがrootのDOM要素にレンダリングします。

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import "./css/index.css";

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

・index.cssのコード全体

ページ全体にコンポーネントを描画します。

body {
  margin: 0;
  overflow: hidden;
}

#root {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

7. 描画結果

ここまでできたら以下のコマンドで、次のコマンドで起動します。

npm start

実行すると以下画像のように3Dモデルをwebサイト上に表示出来ていました。
しかし、Blenderでの見え方と異なっており、3Dモデルに影がなく花びら部分がのっぺりとしたボールのようになっています。。

image.png

8. 改善:ライトの設置

ライトを設置していなかったため、影が投影されていなかった可能性がありました。
以下のコードをApp.tsxファイルのCanvas部分に記載し、平行光源を追加します。

  • directionalLight:平行光源
  • position={[x, y, z]}:ライトの位置
  • castShadowプロパティ:影の投影
{/* ライト */}
<directionalLight position={[5, 5, 5]} castShadow />

ライトを追加したApp.tsxは以下の通りです。

App.tsx
  <Canvas camera={{ position: [2, 1, 2], near: 0.05 }} style={{ background: "#001122" }}>
    {/* 3Dモデルの表示 */}
    <group>
      <Model />
    </group>
    {/* 自動横回転 */}
    <OrbitControls autoRotate />
    {/* 統計情報 */}
    <Stats />
    {/* ライト */}
    <directionalLight position={[5, 5, 5]} castShadow />
  </Canvas>

平行光源を追加した事で、追加前に比べて花びら1枚1枚がよりはっきり見えるようになりました。

image.png

上記改善よりましにはなりましたが、
Blenderで3Dモデルに設定していたブルーム感がまだ反映されません。。
本記事では、react-three-fiberで3DモデルをWebサイト上に表示する事が目的でだったので、
一端ここまでとします。
ブルーム感を出す方法については、次の記事に続きます。

  • 次の記事:react-three-fiberで表示した3Dモデルに発光感(ブルーム)を付ける

参考

2
2
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?