🌐

react-three-fiber/dreiで3Dモデルビューを手軽に実装する

2021/06/28に公開

昨今、WebGLを使用したリッチな表現が一般的になりました。
僕も現在、React×Three.jsの組み合わせでアプリケーション制作を行っていますが、この構成で開発を行う際に何か便利なライブラリは無いかと調べたところ、Three.jsをReactライクに記述するための 「react-three-fiber」 、便利な関数群をまとめた 「react-three-drei」 が存在する模様。

今回、知見共有と学習も兼ねて上記ライブラリを使用した3Dモデルビューを実装してみたいと思います。

前提

今回メインとなるライブラリの使用方法のみの解説となります。
ビルド構成や開発サーバーなどは各自でご用意ください。

バージョン情報

  • node.js ^12.18.1
  • typescript ^4.3.2
  • react ^17.0.2
  • react-dom ^17.0.2
  • @react-three/fiber ^6.2.2
  • @react-three/drei ^5.3.1

公式ドキュメント

docs

https://docs.pmnd.rs/react-three-fiber/getting-started/introduction
https://docs.pmnd.rs/drei/introduction

GitHub

https://github.com/pmndrs/react-three-fiber
https://github.com/pmndrs/drei

キャンバスを用意

まず3Dモデルをレンダリングするためのキャンバスを用意します。

DrawCanvas.tsx
import * as React from "react";
import * as Fiber from '@react-three/fiber';

const DrawCanvas: React.FC = () => {

  return (
    <React.Suspense fallback={<span>loading...</span>}>
      <Fiber.Canvas>
      </Fiber.Canvas>
    </React.Suspense>
  );
};

export default DrawCanvas;

DrawCanvasコンポーネント内に@react-three/fiberのCanvasコンポーネントをimportします。

  • canvasタグを出力
  • ウィンドウサイズに合わせたwidth・height属性の追加
  • リサイズ処理

などのThree.jsを使う上では欠かせない一連の処理をまとめて呼び出せます。
そのほかpropsとして値を渡すことで様々な設定を行うことができるようです。
https://docs.pmnd.rs/react-three-fiber/API/canvas

カメラとOrbitControlsを用意

@react-three/dreiからPerspectiveCameraコンポーネントとOrbitControlsコンポーネントをimportし、Canvasコンポーネントのchildとして渡します。

DrawCanvas.tsx
import * as React from "react";
+ import * as Fiber from '@react-three/fiber';
import * as Drei from "@react-three/drei";

const DrawCanvas: React.FC = () => {

  return (
    <React.Suspense fallback={<span>loading...</span>}>
      <Fiber.Canvas>

+     <Drei.PerspectiveCamera makeDefault />
+     <Drei.OrbitControls enablePan={true} enableZoom={true} enableRotate={true} />

      </Fiber.Canvas>
    </React.Suspense>
  );
};

export default DrawCanvas;

これでカメラとOrbitControlsが設定されました。こちらもpropsとして値を渡すことで細かい設定ができます。
https://docs.pmnd.rs/drei/controls/orbit

3Dモデルを準備する

ここで読み込みたい3Dモデルを用意しましょう。
dreiのuseGLTF関数を使用するため、ファイル形式はgltfもしくはglbとします。

以下から素材をダウンロード。
https://www.cgtrader.com/items/2911141/download-page

3Dモデルを読み込む

素材が準備できたら3Dモデルを表示してみましょう。
Modelコンポーネントを作成、useGLTF関数の引数には任意のパスを記述します。

Model.tsx
import * as React from "react";
import * as Drei from "@react-three/drei";

const Model: React.FC = () => {
    
    const { scene } = Drei.useGLTF("assets/gltf/rocket.glb");

  return (
      <group dispose={null}>
        <primitive scale={[1, 1, 1]} object={scene} />
      </group>
    )
};

export default Model;

次にDrawCanvas.tsxに以下の様にコードを追加します。

DrawCanvas.tsx
import * as React from "react";
import * as Fiber from '@react-three/fiber';
import * as Drei from "@react-three/drei";
+ import Model from "./Model";

const DrawCanvas: React.FC = () => {

  return (
    <React.Suspense fallback={<span>loading...</span>}>
      <Fiber.Canvas>

      <Drei.PerspectiveCamera makeDefault />
      <Drei.OrbitControls enablePan={true} enableZoom={true} enableRotate={true} />

+     <Drei.Stage>
+       <Model />
+     </Drei.Stage>

      </Fiber.Canvas>
    </React.Suspense>
  );
};

export default DrawCanvas;

ここではCanvasのchildとしてStageコンポーネントを追加しています。
公式ドキュメントにはStageコンポーネントの説明として以下の記載があります。

適切なスタジオ照明、コンテンツの中心と平面、シャドウ、および地面に接触するシャドウを使用して「ステージ」を作成します。

環境光の追加、陰影の追加、3Dモデル位置座標の調整をよしなにやってくれる便利なコンポーネントのようです。これは手軽でいいですね。

続いてStageのchildに先ほど作成したModelコンポーネントを追加、これで3Dモデルビューが完成したはずです。試してみましょう。

3Dモデルが表示され、OrbitControlsでカメラ移動ができるかと思います。
このようにreact-three-fiber/dreiを使うことで、通常のThree.jsでは手間のかかる実装でも手軽に実装できます。

元々ライブラリであるThree.jsをさらにラッピングしたreact-three-fiber/dreiではありますが、props経由で細かい設定ができるので痒いところにも手が届く仕様になっていますので導入もしやすいですね。

今回のコードは以下のリポジトリに記載していますので良ければ役立てて下さい〜。
https://github.com/ryotarohada/learn-three-fiber

それでは👋

Discussion