React.js

[React.js] Raect-three-fiber 알아보기

도옹건 2024. 7. 14. 19:47

3D 그래픽은 웹 개발에서 점점 더 중요한 역할을 하고 있습니다. React Three Fiber는 React 환경에서 Three.js를 쉽게 사용할 수 있게 해주는 라이브러리입니다. 이번 블로그 글에서는 React Three Fiber의 활용 방법을 알아보겠습니다.

 

설치

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

 

이제 코드를 통해 어떤 기능들이 있는지 알아보겠습니다.

 

기본적인 3D 예제 코드

import React from 'react';
import { Canvas } from '@react-three/fiber';
import { OrbitControls } from '@react-three/drei';

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

function App() {
  return (
    <Canvas camera={{ position: [2, 2, 2], fov: 75 }}>
      <ambientLight />
      <Box />
      <OrbitControls />
    </Canvas>
  );
}

export default App;

 

코드 설명

  • Canvas: React Three Fiber에서 3D 씬을 렌더링하는 기본 컴포넌트입니다. 렌더링에 필요한 기본 구성 요소인 Scene  Camera를 설정합니다 .
  • mesh: Three.js의 3D 객체입니다.
  • boxGeometry: 박스 형태의 지오메트리를 정의합니다.
  • meshStandardMaterial: 표준 재질을 적용합니다.
  • ambientLight: 씬 전체를 비추는 조명입니다.
  • OrbitControls: 마우스로 3D 씬을 조작할 수 있게 해주는 컨트롤러입니다.

위 코드는 아래 three.js를 이용한 코드와 동일합니다.

 

three.js 코드

const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000)

const renderer = new THREE.WebGLRenderer()
renderer.setSize(width, height)
document.querySelector('#canvas-container').appendChild(renderer.domElement)

const mesh = new THREE.Mesh()
mesh.geometry = new THREE.BoxGeometry()
mesh.material = new THREE.MeshStandardMaterial()

scene.add(mesh)

function animate() {
  requestAnimationFrame(animate)
  renderer.render(scene, camera)
}

animate()

 

두 코드를 비교해보니 react3fiber를 통해 three.js를 쉽게 사용할 수 있다는 것을 알아볼 수 있습니다.

 

 

결과 화면

쪼끔만한 큐브 하나가 생성된 것을 볼 수 있습니다. 

 

 

현재 이런 상태로 카메라가 큐브를 바라보고 있는 상태입니다. Canvas에서 camera의 위치나 pov 값을 조절할 수 있습니다.

<Canvas camera={{ position: [0, 0, 2], fov: 75 }}>

 

camera의 값의 기본 값은 { fov: 75, near: 0.1, far: 1000, position: [0, 0, 5] } 입니다.

 

 

애니메이션 적용하기

useFrame을 통해 큐브를 회전시켜보도록 하겠습니다.

function Box(props) {
  const ref = useRef();

  useFrame(() => {
    ref.current.rotation.x += 0.01;
    ref.current.rotation.y += 0.01;
  });

  return (
    <mesh {...props} ref={ref}>
      <boxGeometry />
      <meshBasicMaterial />
    </mesh>
  );
}

function App() {
  return (
    <Canvas camera={{ position: [0, 0, 2.5], fov: 75 }}>
      <Box />
      <ambientLight />
    </Canvas>
  );
}

 

useFrame을 통해 애니메이션 루프나 매 프레임마다 특정 작업을 수행할 수 있습니다.

 

! React-three-fiber에서 제공하는 Hooks는 컨텍스트에 의존하기 때문에 Canvas 요소 내부에서만 사용할 수 있습니다.

 

결과 화면

 

 

 

 

GLTF 모델 로드하기

이번에는 GLTF 모델을 로드하고 씬에 추가하는 방법을 알아보겠습니다. 

 

GLTF 모델 파일 준비

public 폴더에 shiba 폴더를 생성하고, 그 안에 scene.gltf 파일을 넣습니다.

 

Shiba 컴포넌트 추가

function Shiba() {
  const gltf = useLoader(GLTFLoader, '/shiba/scene.gltf');

  return <primitive object={gltf.scene} />;
}


function App() {
  return (
    <Canvas camera={{ position: [0, 0, 2.5], fov: 75 }}>
      <ambientLight />
      <Shiba />
    </Canvas>
  );
}

export default App;

 

코드설명

  • useLoader: Three.js 로더를 사용하여 GLTF 파일을 로드합니다.
  • primitive: Three.js 객체를 React Three Fiber에서 사용하기 위한 컴포넌트입니다.
  • object: 로드된 GLTF 씬 객체를 전달합니다.

 

 

결과 화면

귀여운 시바견이 생성됐습니다!

 

onClick 애니메이션 적용하기

이제 시바견을 클릭했을때 덤블링을 하는 애니메이션을 구현해보도록 하겠습니다.

function Shiba() {
  const gltf = useLoader(GLTFLoader, "/shiba/scene.gltf");
  const ref = useRef();
  const [isTumbling, setIsTumbling] = useState(false);
  const [rotationX, setRotationX] = useState(0);

  useEffect(() => {
    if (isTumbling) {
      console.log(ref.current);
      const targetRotation = ref.current.rotation.y + Math.PI * 2;
      const startTime = Date.now();

      const animate = () => {
        const elapsed = Date.now() - startTime;
        const duration = 1000; // 1 second
        const progress = Math.min(elapsed / duration, 1);
        ref.current.rotation.x = rotationX - (targetRotation + rotationX) * progress;

        if (progress < 1) {
          requestAnimationFrame(animate);
        } else {
          setIsTumbling(false);
          setRotationX(ref.current.rotation.y);
        }
      };

      requestAnimationFrame(animate);
    }
  }, [isTumbling, rotationX]);

  const handleClick = () => {
    if (!isTumbling) {
      setIsTumbling(true);
    }
  };

  return <primitive ref={ref} object={gltf.scene} onClick={handleClick} />;
}

 

코드 설명

  • useEffect 훅을 사용하여 isTumbling 상태가 true일 때 애니메이션을 시작합니다.
  • requestAnimationFrame을 사용하여 매 프레임마다 모델의 회전 상태를 업데이트합니다.
  • 애니메이션이 완료되면 isTumbling 상태를 false로 설정하여 애니메이션을 종료합니다.

 

결과 화면

 

react-three/drei 기능 알아보기

react-three/drei는 React Three Fiber를 위한 유틸리티 라이브러리로, Three.js를 React 환경에서 더 쉽게 사용할 수 있도록 다양한 기능과 컴포넌트를 제공합니다. 이 라이브러리는 많은 일반적인 3D 그래픽 작업을 간소화하고, 코드의 복잡성을 줄여줍니다. 주요 기능과 컴포넌트를 소개하겠습니다.

 

주요 기능과 컴포넌트

  1. 카메라 컨트롤 (Camera Controls)
    • OrbitControls: 마우스를 사용하여 카메라를 회전, 확대/축소할 수 있게 해줍니다.
    • FlyControls: 1인칭 비행 시뮬레이션과 같은 카메라 제어를 제공합니다.
    • TrackballControls: 자유롭게 회전, 이동, 확대/축소할 수 있는 컨트롤러입니다.
    • PointerLockControls: 마우스 커서를 숨기고, 클릭 시 카메라를 제어할 수 있게 해줍니다.
  2. 로더 (Loaders)
    • useGLTF: GLTF/GLB 파일을 로드하는 훅입니다.
    • useFBX: FBX 파일을 로드하는 훅입니다.
    • useTexture: 텍스처를 로드하는 훅입니다.
  3. 3D 객체와 도우미 (3D Objects and Helpers)
    • Sky: 하늘 배경을 생성하는 컴포넌트입니다.
    • Environment: 간단한 환경 설정을 도와주는 컴포넌트입니다.
    • Text: 3D 텍스트를 쉽게 추가할 수 있는 컴포넌트입니다.
    • Box, Plane, Sphere 등: 기본적인 3D 기하 도형을 생성하는 컴포넌트입니다.
  4. 애니메이션과 인터랙션 (Animations and Interactions)
    • useAnimations: 애니메이션 클립을 제어할 수 있는 훅입니다.
    • useDrag: 3D 객체를 드래그할 수 있게 해주는 훅입니다.
    • useGesture: 제스처 인터랙션을 쉽게 구현할 수 있는 훅입니다.
  5. 기타 유틸리티 (Miscellaneous Utilities)
    • Loader: 로딩 상태를 관리할 수 있는 컴포넌트입니다.
    • Billboard: 항상 카메라를 향하는 평면을 생성하는 컴포넌트입니다.
    • Html: 3D 씬 안에 HTML 요소를 렌더링할 수 있는 컴포넌트입니다.

 

useGLTF

const gltf = useGLTF("/shiba/scene.gltf");

 

 

OrbitControls

function App() {
  return (
    <Canvas camera={{ position: [0, 0, 2.5], fov: 75 }}>
      <ambientLight />
      <Shiba />
      <OrbitControls />
    </Canvas>
  );
}

 

결과화면

 

 

Text

function App() {
  return (
    <Canvas camera={{ position: [0, 0, 2.5], fov: 75 }}>
      <Text position={[0, 1, 0]} fontSize={0.4} fontWeight={700} color="black">
        시바견
      </Text>
      <ambientLight />
      <Shiba />
      <OrbitControls />
    </Canvas>
  );
}

 

 

결과화면

 

 

 

 

이번 포스팅에서는 React Three Fiber를 사용하여 3D 씬을 설정하고, GLTF 모델을 로드하며, 클릭 이벤트를 통해 모델에 애니메이션을 추가하는 방법에 대해 알아보았습니다. 

 

참고

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

 

React Three Fiber Documentation

React-three-fiber is a React renderer for three.js

docs.pmnd.rs

 

https://github.com/pmndrs/drei

 

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

 

https://www.youtube.com/watch?v=CojyGfCMvuU&t=49s