LoginSignup
6
6

@react-three/dreiを使って様々な3D表現を行う

Posted at

この記事の続きです。

@react-three/drei(以下、dreiと呼称する。)は@react-three/fiber(以下、r3fと呼称する。)`用の便利なヘルパー関数などを提供してくれるライブラリです。このライブラリとr3fと組み合わせることで、r3fだけでは表現できなかったことが表現できるようになります。

インストール

$ npm install @react-three/drei

パーティクル

Stars

import { Stars } from "@react-three/drei";
<Stars
 radius={100} // 星の点滅(拡大)度合い
 depth={50} // 星の深さ
 count={5000} // 星の数
 factor={6} // 星の大きさ
 saturation={9} // 星の彩度
 speed={3} // 点滅のスピード
/>

docs

Points、Point

import { Points, Point } from "@react-three/drei";
const pColors = ["red", "yellow", "orange", "blue", "green", "white"];

<Points limit={2000} range={1000}>
  {/* limit : パーティクルの数, range : パーティクルの描画範囲 */}
  <pointsMaterial vertexColors size={0.1} />
  {/* lengthの値はlimitの数に合わせる */}
  {Array.from({ length: 2000 }).map((_, i) => (
    <Point
      key={i}
      position={[
        MathUtils.randFloatSpread(10),
        MathUtils.randFloatSpread(10),
        MathUtils.randFloatSpread(10)
      ]}
      color={pColors[Math.floor(Math.random() * (pColors.length - 1))]}
    />
  ))}
</Points>

docs

MathUtils

ここで、登場したMathUtilsとはなんなのか紹介します。MathUtilsはthree.js本体のあるものです。

import { MathUtils } from "three";

OrbitControls

three.jsに存在していた手軽にカメラの動きを自動的に制御する OrbitControls がdreiに存在します。

import { OrbitControls } from "@react-three/drei";
<OrbitControls />

この<OrbitControls />を使用する事によりマウスでオービット(周回軌道)できたり、マウスホイールでズームなどの操作ができます。

雲を表現する

Sky

この<Sky />を使用すると背景に「空」が描画されます。

import { Sky } from "@react-three/drei";
<Sky />

docs

Cloud

パーティクルベースの「雲」が描画されます。

import { Cloud } from "@react-three/drei";
<Cloud
  position={[0, 0, 0]} // 雲のポジショニング
  opacity={0.5} // 不透明度
  speed={0.4} // 回転速度
  width={10} // 雲全体の幅
  depth={1.5} // Z方向の深さ
  segments={20} // パーティクルの数
/>

docs

3Dモデルを表示する

blenderなどで作成した3DモデルをWeb上に描画します。
描画する際には、useGLTF()関数を使用します。

import { useGLTF } from "@react-three/drei";
const reactLogo = useGLTF(
  "https://vazxmixjsiawhamofees.supabase.co/storage/v1/object/public/models/react-logo/model.gltf"
);

useGLTF()関数の引数に任意のパスを記述します。

※モデルはここから持ってきました。

<primitive object={reactLogo.scene} position={[0, -1.3, 0.3]} scale={[1.5, 1.5, 1.5]} />
// object : useGLTF()で読み込んだモデル.scene
// position : モデルのポジショニング
// scale : モデルの拡大度合い

ContactShadows

モデルに影をつけるコンポーネント

import { ContactShadows } from "@react-three/drei";
<ContactShadows position-y={-2.0} opacity={0.7} scale={7} blur={2.4} color={"#000"} far={10} resolution={256} />
// position-y : 影の向き(y)※デフォルトでは上向き 
// opacity : 影の透過度
// scale : 影の拡大度合い
// blur : 影のぼかし具合
// color : 影の色
// far :
// resolution : 影の解像度

docs

Float

このコンポーネントを使用するとでものような浮いてるような表現ができます。

import { Float } from "@react-three/drei";
<Float
  speed={1} // 回転速度。デフォルトでは1
  rotationIntensity={1} // 回転強度。デフォルトでは1
  floatIntensity={1} // 上下の Float の強度。デフォルトでは1
  floatingRange={[1, 10]} // オブジェクトが浮動する Y 軸値の範囲。デフォルトは [-0.1,0.1]
>
  <mesh />
</Float>

Text

文字を表示するコンポーネント

import { Text } from "@react-three/drei";
<Text
 color={"black"} // 文字の色
 anchorX={"center"} //
 anchorY={"middle"} //
 position={[0, 0, 0]} //文字のポジショニング
>
  hello world!
</Text>

docs

PresentationControls

スナップバックなどを備えたSemi-OrbitControlsです。
これらのコントロールは カメラを回転させませんが、コンテンツを回転させます 。OrbitControl のように限界に達したときに突然停止するのではなく、停止位置をスムーズに予測します。

import { PresenrionControls } from "@react-three/drei";
<PresentationControls
  enabled={true} // これを false に設定するとコントロールを無効にできる。
  global={false} // これを true に設定するとグローバルに回転する。
  cursor={true} // ドラッグ時にカーソルのスタイルを切り替える。
  config={{ mass: 1, tension: 170, friction: 26 }} // スプリングの設定。
  snap={false} // 中央にスナップバックします。指定方法は config と同じ。
  speed={1} // カメラを操作した時のモデルの動きの速度。
  zoom={1} // 極最大値の半分に達したときのズーム倍率
  rotation={[0, 0, 0]} // デフォルトの回転度合い
  polar={[0, Math.PI / 2]} // 垂直方向の制限
  azimuth={[-Infinity, Infinity]} // 水平方向の制限
  domElement={events.connected} // このコントローラの DOM 要素イベントがアタッチされます。
>
  <mesh />
</PresentationControls>

docs

テクスチャ

ジオメタリに画像(テクスチャ)を貼る方法をご紹介します。useTexture()と呼ばれるものがdreiに存在するため、使用します。

import { useTexture } from "@react-three/drei";
const maping = useTexture("画像パス");

return <meshStandardMaterial map={texture} />

docs

パララックス

r3fを使えば、パララックスっぽいことも簡単に実現することができます。

useThree()

dreiではなくr3fにあるHooks。
デフォルトのレンダラー、シーン、カメラなどが含まれる状態モデルにアクセスできます。また、画面内のキャンバスの現在のサイズとビューポートの座標も表示されます。

import { useThree } from '@react-three/fiber'

function Foo() {
   const { whidth, height } = useThree((state) => state.viewport);

ビューポートの width と height を取得する例です。
docs

Image

シェーダーベースの画像コンポーネント

import { Image } from "@react-three/drei";
<Image
 url="画像パス"
 scale={[1, 1, 1]} // 画像の拡大度合い
 position={[0, 0, 0]} // 画像のポジショニング
 transport
 opacity={1} // 画像の不透明度
/>

docs

ScrollControls、Scroll

スクロールをすることが可能になるコンポーネント。

import { ScrollControls, Scroll } from "@react-three/drei";
<ScrollControls 
 pages={2} //  スクロール量。
 damping={2} // 慣性。
 horizontal={false} // true にすると横スクロール。
 infinite={false} // true にすると無限スクロール(ループ)。
 eps={0.00001} // スクロールの精度。デフォルトでは、0.00001。
 distance={0.2} // 秒単位の摩擦。デフォルトでは、0.2。
 maxSpeed={0.1} // 速度を 1 秒あたり 0.1 単位に固定
>
  <Scroll>
    <Images />
  </Scroll>
  <Scroll html>
    <h1 style={{ position: "absolute", top: "60vh", left: "1.5em" }}>
      Hello
    </h1>
    <h1 style={{ position: "absolute", top: "140vh", left: "20vw" }}>
      Would!!
    </h1>
  </Scroll>
</ScrollControls>

<Scroll />で html をラップする際は<Scroll html />とする。

docs

useScroll()

現在のスクロールなどの有用なデータを提供するフック

import { useScroll } from "@react-three/drei";
const Images = () => {
  const { height } = useThree((state) => state.viewport);
  const group = useRef({} as any);
  const data = useScroll();

  useFrame(() => {
    group.current.children[0].material.zoom = 1 + data.range(0, 1 / 3) / 3;
    group.current.children[1].material.zoom = 1 + data.range(0, 1 / 3) / 3;
    group.current.children[2].material.zoom =
      1 + data.range(1.15 / 3, 1 / 3) / 3;
    group.current.children[3].material.zoom =
      1 + data.range(1.15 / 3, 1 / 3) / 3;
  });
  return (
    <group ref={group}>
      <Image
        url="画像パス"
        scale={[4, height, 1]}
        position={[-1, 0, 1]}
      />
      <Image
        url="画像パス"
        scale={3}
        position={[2, 0, 1]}
      />
      <Image
        url="画像パス"
        scale={[1, 2.7, 1]}
        position={[-2.3, -height, -2]}
      />
      <Image
        url="画像パス"
        scale={[1.4, 2, 1]}
        position={[1.3, -height - 0.3, 1.2]}
      />
    </group>
  );
};
export default Images;

さいごに

いかがでしたか?このように、r3fとdreiを組み合わせることで表現できることが増えるので、r3fを使用する際にはdreiと一緒に使ってみてください。
また。dreiにあるメソッドの数は膨大にあるため、紹介しきれなかったものに関してはドキュメントを読むなりしながら各自で調べてみてください。

最後まで読んでいただいてありがとうございました。

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