FrontEnd/3D Web

[R3F] About R3F's Hooks

Indigochi1d 2024. 8. 22. 19:49

 

GitHub - Indigochi1d/IntroduceWith3Dweb: R3F로 구현한 Dancing Scroll Introduce 3D Web

R3F로 구현한 Dancing Scroll Introduce 3D Web. Contribute to Indigochi1d/IntroduceWith3Dweb development by creating an account on GitHub.

github.com

🔎서론

위의 프로젝트를 R3F로 구현하면서 사용했던 Hooks들을 자세히 다뤄보려고 한다.

다뤄볼 Hooks들은 아래와 같다.

  1. useThree
  2. useFrame
  3. useGLTF
  4. useAnimations
  5. useProgress
  6. useScroll

1️⃣useThree

 

useThree | React Three Fiber

React Three Fiber is a React reconciler for Threejs on the web and react-native.

gracious-keller-98ef35.netlify.app

📌제공하는 것

① 기본 객체(renderer, scene, camera 등)에 대한 접근. 

② 화면 또는 뷰포트에서 현재 canvas의 사이즈

import { useThree } from "react-three-fiber";

const {
  gl, /* WebGL renderer */
  scene, /* Default scene */
  camera, /* Default camera */
  raycaster, /* Default raycaster */
  size, /* Bounds of the view (which stretches 100% and auto-adjusts) */
  viewport, /* Bounds of the viewport in 3d units + factor (size/viewport) */
  aspect, /* Aspect ratio (size.width / size.height) */
  mouse, /* Current, centered, normalized 2D mouse coordinates */
  clock, /* THREE.Clock (useful for useFrame deltas) */
  invalidate, /* Invalidates a single frame (for <Canvas invalidateFrameloop />) */
  intersect, /* Calls onMouseMove handlers for objects underneath the cursor */
  setDefaultCamera, /* Sets the default camera */
} = useThree();

 

✏️사용법

import { useThree } from "@react-three/fiber";

export const useThreeExample = () => {
	const three = useThree();
    useEffect(() => {
    	three.scene.background = new THREE.Color("black");
    },[three.scene])
}

2️⃣useFrame

 

useFrame | React Three Fiber

React Three Fiber is a React reconciler for Threejs on the web and react-native.

gracious-keller-98ef35.netlify.app

📌기본 형태

useFrame((callback: (state, delta) => void), (renderPriority: number = 0));

 

📌주요 기능

이 Hook는 매 프레임마다 실행된다.

따라서 효과 실행이나 컨트롤 업데이트와 같은 기민하게 렌더링되어야하는 요소사항에 적합하다.

📌매개변수

매개변수로는 아래의 두 가지를 가진다.

  • 콜백함수
    • 필수 매개변수
    • (state, delta)
    • state: 현재 렌더링 상태를 포함하며, 카메라, 시간, Three.js의 주요 객체들을 다룸.
    • delta: 이전 프레임 이후 경과된 시간으로, 애니메이션 속도를 시간에 맞춰 조정할 수 있음
  • renderPriority
    • 선택적 매개변수
    • number
    • css의 z-index속성과 결은 비슷하지만 이 값이 작을수록 우선순위를 가진다.
    • 여러개의 useFrame 콜백이 있을때 이 우선순위대로 적용된다.
import { useFrame } from "react-three-fiber";

const controls = useRef();
useFrame((state) => controls.current.update());
return <orbitControls ref={controls} />;

3️⃣useGLTF

 

GitHub - pmndrs/drei: 🥉 useful helpers for react-three-fiber

🥉 useful helpers for react-three-fiber. Contribute to pmndrs/drei development by creating an account on GitHub.

github.com

📌기본 형태

const { scene, nodes, materials, animations } = useGLTF('/path/to/model.glb');

useLoader와 GLTFLoader를 편리하게 쓰기위해 묶은 Hook이다.

📌주요 기능

GLB 파일 형식의 3D 모델을 R3F 애플리케이션에 쉽게 로드하고 사용할 수 있게 해준다.

  • GLTF 파일로드
    • useGLTF는 주어진 URL경로에서 GLTF파일을 비동기적으로 로드한다.
    • 이 때 ①모델 데이터 ②메쉬 ③애니메이션 등을 자동으로 파싱하여 반환한다.
  • 로컬 및 원격 파일 지원
    • useGLTF는 로컬에 저장된 GLTF파일과 원격 서버에서 제공하는 파일도 쉽게 로드할 수 있다.

📌매개변수

const { scene, nodes, materials, animations } = useGLTF(
    '/path/to/model.glb',  /* GLTF 파일 경로 */
    '/draco-gltf/',        /* Draco 압축 해제를 위한 경로 */
    (loader) => {          /* 확장 기능 적용 */
      const dracoLoader = new DRACOLoader()
      dracoLoader.setDecoderPath('/draco-gltf/')  /* Draco 디코더 경로 설정 */
      loader.setDRACOLoader(dracoLoader)          /* GLTFLoader에 DracoLoader를 추가 */
    }
  )

 

  • path
    • useGLTF 훅의 첫 번째 인수로, 로드할 GLTF 파일의 경로(URL)를 문자열로 전달한다.
  • extensions (선택적)
    • GLTF 파일 로드 시 사용할 확장 프로그램(예: DRACOLoader 등)을 설정할 수 있다.
  • draco (선택적)
    • Draco 압축을 해제하기 위한 옵션으로, 압축된 GLTF 파일을 로드할 때 사용된다.

📌반환값

아래에 있는 속성들을 포함할 수 있는 객체를 반환한다. 모든 속성들이 객체안에 반드시 적히지 않아도 된다는 뜻

 

  • scene: 로드된 GLTF 모델의 기본 Scene 객체다. Three.js의 Scene 객체로 반환
  • nodes: Scene 안에 포함된 모든 노드를 객체 형태로 반환한다. 각 노드는 메쉬, 카메라, 라이트 등 다양한 3D 요소를 포함
  • materials: Scene에 사용된 모든 재질(Material)을 객체 형태로 반환한다.
  • animations: 모델에 포함된 모든 애니메이션 클립을 배열 형태로 반환한다. 이 클립들은 useAnimations 훅과 함께 사용됨.
  • cameras: Scene에 포함된 카메라들을 배열 형태로 반환한다.
  • extensions: GLTF 파일에 적용된 확장 기능들을 포함한 객체다.

✏️사용법

import { useGLTF } from '@react-three/drei'
import { useAnimations } from '@react-three/drei'
import { useEffect } from 'react'

function AnimatedModel() {
  const { scene, animations } = useGLTF('/model-path.glb')
  const { actions, names, mixer } = useAnimations(animations, scene)

  useEffect(() => {
    /* 특정 애니메이션을 실행 */
    const action = actions['AnimationName']
    action.play()

    /* 컴포넌트가 언마운트될 때 애니메이션 정지 */
    return () => {
      action.stop()
    }
  }, [actions])

  return <primitive object={scene} />
}

 

 


4️⃣useAnimations

 

GitHub - pmndrs/drei: 🥉 useful helpers for react-three-fiber

🥉 useful helpers for react-three-fiber. Contribute to pmndrs/drei development by creating an account on GitHub.

github.com

📌기본 형태

const { actions, names, mixer } = useAnimations(animations, scene)

📌주요 기능

이 Hook은 GLTFLoader를 사용해 로드한 3D 모델에 포함된 애니메이션을 다루는데 유용하다.

  • 애니메이션 클립 관리: useAnimations는 GLTF 모델에서 로드된 여러 애니메이션 클립을 관리한다.
  • 애니메이션 재생 및 중지: 특정 애니메이션 클립을 선택해서 재생하거나 중지할 수 있다.
  • 애니메이션의 상태 관리: 각 애니메이션의 진행 상태를 관리하고 제어한다.

📌매개변수

매개변수로는 아래의 두 가지를 가진다.

const { actions, names, mixer } = useAnimations(animations, root)
/*
	root의 예 : scene
*/
    • animations
      • useAnimations Hook의 첫 번째 인수이다.
      • GLTF 모델에서 로드한 애니메이션 클립 배열을 전달한다.
    • root
      • useAnimations Hook의 두 번째 인수이다.
      • 애니메이션이 적용될 Root Object를 전달한다.

📌반환값

  • actions: 애니메이션 클립들을 key-value 쌍으로 반환한다.
    • key는 애니메이션 이름이고, value은 THREE.AnimationAction 객체이다.
    • 이를 통해 특정 애니메이션을 재생, 정지, 일시 중지, 속도 조절 등의 작업을 할 수 있다.
  • names: 로드된 애니메이션 클립의 이름들을 배열 형태로 반환한다.
  • mixer: THREE.AnimationMixer 객체를 반환한다. 애니메이션 혼합 및 조절을 담당하는 Three.js의 핵심 클래스다.

✏️사용법

import { useGLTF } from '@react-three/drei'
import { useAnimations } from '@react-three/drei'
import { useEffect } from 'react'

function AnimatedModel() {
  const { scene, animations } = useGLTF('/model-path.glb')
  const { actions, names, mixer } = useAnimations(animations, scene)

  useEffect(() => {
    /* 특정 애니메이션을 실행*/
    const action = actions['AnimationName']
    action.play()

    /* 컴포넌트가 언마운트될 때 애니메이션 정지*/
    return () => {
      action.stop()
    }
  }, [actions])

  return <primitive object={scene} />
}

 

  1. useGLTF Hook으로 GLTF모델을 로드한다.
  2. useAnimations Hook에 로드된 animations와 scene을 전달해서 애니메이션을 초기화한다.
  3. useEffect를 사용해서 컴포넌트가 마운트될때 특정 애니메이션을 재생하고 언마운트 될때 애니메이션을 정지한다.

5️⃣useProgress

 

Loading Models - React Three Fiber

3D Software to the web!

r3f.docs.pmnd.rs

useProgress는 3D모델을 로드하는 동안 진행상태를 추적하는데 사용된다.

📌기본 형태

function Loader() {
  const { progress } = useProgress()
  return <Html center>{progress.toFixed(2)}% loaded</Html>
}

📌주요 기능

 

  • 로딩 진행 상태 제공
    • useProgress는 현재 로드 중인 리소스의 진행률을 백분율로 제공한다.
  • 로드된 항목과 남은 항목 추적
    • 로드가 완료된 항목의 개수와 남은 항목의 개수를 확인할 수 있다.
  • 오류 처리
    • 로딩 중에 발생한 오류를 추적할 수 있다.

📌반환값

 

  • progress: 현재 로딩 진행 상태를 백분율(%)로 나타낸 값.
  • total: 로드해야 할 전체 항목의 개수
  • loaded: 현재까지 로드된 항목의 개수
  • errors: 로드 중에 발생한 오류
  • item: 현재 로드 중인 항목의 이름
  • active: 현재 로딩이 활성화되어 있는지 여부를 나타내는 boolean값.

✏️사용법 ①

import { Canvas } from '@react-three/fiber'
import { useProgress, Html } from '@react-three/drei'

function Loader() {
  const { progress } = useProgress()
  return <Html center>{progress.toFixed(2)}% loaded</Html>
}

function MyScene() {
  return (
    <Canvas>
      {/* 로더 컴포넌트 */}
      <Loader />
      {/* 여기서 로드할 모델이나 3D 요소를 추가 */}
      {/* <MyModel /> */}
    </Canvas>
  )
}

export default MyScene

 

 

useProgress는 여태껏 정리했던 것처럼 로딩상태에 따라 UI의 업데이트를 관장할 수 있다.

 

하지만 기본적으로 ThreeJS는 (HTML태그로 봤을때)canvas요소위에 그려지기 때문에 3D Scene내부에서 HTML태그요소를 사용하지 못한다.


이 때 사용되는 것이 HTML 컴포넌트이다.
HTML 컴포넌트를 사용하면 3D Scene내부에서 HTML 태그를 사용할 수 있다.

 

✏️사용법 ②

function Loader() {
  const { progress, loaded, total, item } = useProgress()
  return (
    <Html center>
      <div>
        <p>{item}</p>
        <p>{progress.toFixed(2)}% loaded</p>
        <p>{loaded}/{total} items loaded</p>
      </div>
    </Html>
  )
}

 

이렇게 하면 현재 로드 중인 파일의 이름과 전체 진행 상태를 포함한 정보를 사용자에게 제공할 수 있다.


6️⃣useScroll

 

GitHub - pmndrs/drei: 🥉 useful helpers for react-three-fiber

🥉 useful helpers for react-three-fiber. Contribute to pmndrs/drei development by creating an account on GitHub.

github.com

📌기본 형태

const scroll = useScroll();

📌주요 기능

  • scroll 위치 감지
    • useScroll은 페이지에서의 현재 위치offset0~1사이의으로 반환한다.
    • 예를 들어, 페이지의 50% 지점에 스크롤이 도달하면 scroll.offset 값이 0.5

✏️사용법 

import { Canvas } from '@react-three/fiber';
import { ScrollControls, useScroll } from '@react-three/drei';

function Box() {
  const scroll = useScroll();

  useFrame(() => {
    /* 예시: 스크롤에 따라 박스의 y 위치를 변경 */
    const y = scroll.offset * 10;
    meshRef.current.position.y = y;
  });

  return (
    <mesh ref={meshRef}>
      <boxGeometry />
      <meshStandardMaterial color="orange" />
    </mesh>
  );
}

export default function App() {
  return (
    <Canvas>
      <ScrollControls pages={3}>
        <Box />
      </ScrollControls>
    </Canvas>
  );
}