0
0

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.

Three.jsとReactThreeFiberの実装の違い(サンプル)

Last updated at Posted at 2023-09-27

サンプル

image.png
正方形をマウスドラッグで回転させることができるプログラム

Three.js

Three.jsを用いると以下の書き方になります。

/** @jsxImportSource @emotion/react */
import * as React from 'react';
import * as THREE from "three";
import { OrbitControls } from "three-stdlib";
import { Vector3 } from "three";
import { css } from '@emotion/react';

const styles = {
  container: css({
    height: "90vmin",
    width: "100%",
    flexDirection: "column",
    alignItems: "center",
  }),
  canvas: css({
    width: "100%",
    height: "100%",
    touchAction: "auto",
  }),
};

const ThreejsCube = () => {
  const canvasRef = React.useRef<HTMLCanvasElement>(null);

  React.useEffect(() => {
    const canvas = canvasRef.current;
    if (canvas === null) {
      return;
    }

    const width = canvas.clientWidth;
    const height = canvas.clientHeight;

    const renderer = new THREE.WebGLRenderer({
      canvas: canvas
    });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(width, height);
    renderer.setClearColor(0x000000);

    const scene: THREE.Scene = new THREE.Scene();

    const camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera(90, 1.0);
    camera.aspect = width / height;
    camera.position.set(0, 0, 10);
    camera.updateProjectionMatrix();

    let oribitControls = new OrbitControls(camera, canvas);
    oribitControls.target = new Vector3(0, 0, 0);
    oribitControls.minDistance = 2.0;
    oribitControls.maxDistance = 50.0;

    const geometry = new THREE.BoxGeometry( 2, 2, 2 );
    const material = new THREE.MeshBasicMaterial( {color: 0xff0000} );
    const cube = new THREE.Mesh( geometry, material );
    scene.add( cube );

    const glRender = () => {        
      oribitControls.update();
      renderer.render(scene, camera);
      requestAnimationFrame(glRender);
    };

    glRender();
  }, []);

  return (
    <div css={styles.container}>
      <canvas css={styles.canvas} ref={canvasRef} />
    </div>
  );
};

export default ThreejsCube;

内容を細かくみていきます。
まず、以下の部分でWebgl用のレンダラを作成します。

const renderer = new THREE.WebGLRenderer({
  canvas: canvas
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
renderer.setClearColor(0x000000);

シーンを作成します。

const scene: THREE.Scene = new THREE.Scene();

次にカメラを作成します。

const camera: THREE.PerspectiveCamera = new THREE.PerspectiveCamera(90, 1.0);
camera.aspect = width / height;
camera.position.set(0, 0, 10);
camera.updateProjectionMatrix();

カメラを制御するコントローラを作成します。

let oribitControls = new OrbitControls(camera, canvas);
oribitControls.target = new Vector3(0, 0, 0);
oribitControls.minDistance = 2.0;
oribitControls.maxDistance = 50.0;

Cubeオブジェクトを追加します。

const geometry = new THREE.BoxGeometry( 2, 2, 2 );
const material = new THREE.MeshBasicMaterial( {color: 0xff0000} );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );

最後に描画を行います。

const glRender = () => {        
    oribitControls.update();
    renderer.render(scene, camera);
    requestAnimationFrame(glRender);
};

glRender();

ReactThreeFiber

ReactThreeFiberを用いると以下の実装になります。

/** @jsxImportSource @emotion/react */
import React from "react";
import * as Fiber from '@react-three/fiber';
import * as Drei from '@react-three/drei';
import { css } from '@emotion/react';

const styles = {
  container: css({
    height: "90vmin",
    width: "100%",
    flexDirection: "column",
    alignItems: "center",
  }),
  canvas: css({
    width: "100%",
    height: "100%",
    touchAction: "auto",
  }),
};

const R3FCube = () => {
  return (
    <div css={styles.container}>
      <Fiber.Canvas css={styles.canvas} onCreated={state => state.gl.setClearColor("black")} >
        <Drei.PerspectiveCamera makeDefault fov={90} position={[0, 0, 10]}/>
        <Drei.Box args={[2, 2, 2]}>
          <meshBasicMaterial color="red" />
        </Drei.Box>
        <Drei.OrbitControls makeDefault minDistance={2.0} maxDistance={50.0}/>
      </Fiber.Canvas>
    </div>
  );
};

export default R3FCube;

内容を細かく見ていきます。
以下の部分でCanvasを作成しています。

<Fiber.Canvas css={styles.canvas} onCreated={state => state.gl.setClearColor("black")} >

カメラを作成します。

<Drei.PerspectiveCamera makeDefault fov={90} position={[0, 0, 10]}/>

Cubeオブジェクトを追加します。

<Drei.Box args={[2, 2, 2]}>
    <meshBasicMaterial color="red" />
</Drei.Box>

カメラを制御するコントローラを追加します。

<Drei.OrbitControls makeDefault minDistance={2.0} maxDistance={50.0}/>

Three.jsとReactThreeFiberの実装の違い

サンプルプログラムを比較し、ReactThreeFiberではシーン設定やカメラ設定などをライブラリの内部でやってくれていることが分かります。そのため、Threejsで実装するよりコード量が少なくなります。ReactThreeFiberはReactコンポーネントのようにThree.jsが書けるライブラリです。Reactの宣言的な記述で、WebGLの3Dモデル作成が簡単実装できる点が特徴だと思います。

参考

0
0
0

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?