[R3F] 2주차 정리_R3F에서 중요한 3가지!

Chaejung·2023년 12월 26일
0

3D_JavaScript

목록 보기
3/6
post-thumbnail

이번 포스트는 React Three fiber(R3F)로 배우는 인터렉티브 3D 웹 개발을 수강한 뒤 정리하는 포스트입니다.

공부한 것

R3F에서 중요한 세 가지 객체

  1. Scene
    : 관찰 당하는 객체
  2. Camera
    : Scene을 관찰하는 추상 객체
  3. Renderer
    : Camera가 보는 view

Scene

객체를 렌더하기 위해서는 mesh가 필요하다.
mesh는 geometry와 material이란 property로 이루어져 있다.

  • geometry: 객체의 모양
  • material: 객체의 색, 텍스쳐

geometry는 HTML, material은 CSS로 비유 가능하다.

R3F는 Three.js의 개념을 기본적으로 따르는데, React에서 렌더하는 방식에서 차이가 나다보니 같은 객체를 렌더하더라도 아래와 같이 코드베이스의 차이가 난다.

// Three.js
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshBasicMaterial( { color: 0xffffff } );
const mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
// R3F
export default function ThreeElement() {

  return (
      <mesh>
        <boxGeometry />
        <meshStandardMaterial color="white" />
      </mesh>
  );
}

Camera

객체를 공간에 두었다면, 이를 렌더할 frame이 필요하다.
그 frame을 어디서, 얼마만큼 둘 건지 정의하는 추상적인 개념이 바로 camera이다.

ThreeJS에는 총 다섯 가지 카메라가 있는데 이 중에서 보편적으로 쓰이는 것은 아래 두 가지이다.

  • PerspectiveCamera
    : 원근감이 있는 카메라
    • 일반적으로 인간이 보는 방식을 그대로 가져가는 투시법이며 가장 일반적인 카메라.
  • OrthographicCamera
    : 원근감이 없는 카메라
    • 카메라 거리와 상관없이 항상 일정한 이미지를 렌더하며 2D scene과 UI 요소를 렌더하는 데에 유용한 카메라.
  • <주요 파라미터>
    • near, far: 카메라로부터 떨어진 위치
      • near부터 far까지 렌더하기 된다.
    • fov: 카메라 각도
      • orthographic에는 없는 개념
    • position: 카메라 위치

Renderer

Renderer는 ThreeJS를 React에 렌더하기 위해 필요한 개념이다.
이는 ThreeJS의 Scene을 Canvas에 그리면서 동시에 React의 상태, hook, prop, event를 이용한다.
대표적으로 쓰는 훅으로 useThree(), useFrame()이 있고,
주의할 점은 Canvas 태그 하위에서만 쓸 수 있다.

useThree()

This hook gives you access to the state model which contains the default renderer, the scene, your camera, and so on. It also gives you the current size of the canvas in screen and viewport coordinates.
.
기본 renderer, scene, camera 등을 포함한 상태 모델에 접근하는 훅이다. 현재 스크린과 viewport 좌표계에서의 canvas 크기도 전달 가능하다.

const { size, gl, scene, camera } = useThree();
  • size: canvas 크기(pixel)
  • gl: renderer

useFrame()

This hook allows you to execute code on every rendered frame, like running effects, updating controls, and so on. You receive the state (same as useThree) and a clock delta. Your callback function will be invoked just before a frame is rendered. When the component unmounts it is unsubscribed automatically from the render-loop.
.
이 훅은 실행 효과, 제어 업데이트 등 매 렌더 프레임마다 실행된다. useThree와 같은 상태와 시간 delta를 갖는다. 콜백 함수는 프레임이 렌더되기 전에 호출된다.

  //...
  const boxRef = useRef<THREE.Mesh>(null);

  useFrame((state, delta) => {
    boxRef.current.rotation.x += delta;
    boxRef.current.position.y -= 0.01;
    boxRef.current.scale.z += 0.01;
  });
  return (
    <>
      <mesh
        ref={boxRef}
      >
        <boxGeometry />
        <meshStandardMaterial color={boxColor.color} />
      </mesh>
    </>
  );
//...

Control, Helper

  • @react-three/drei에 있는 기능으로, scene와 인터렉티브하게 작용하도록 하기 위해 필요한 도구들 중 scene의 기준(축, grid)에 관한 것들이다.
  • OrbitControls
    scene의 기준인 축에 의해 움직일 수 있는 범위를 정할 수 있는 control

    <OrbitControls
     minAzimuthAngle={-Math.PI / 4}
     maxAzimuthAngle={Math.PI / 4}
     minPolarAngle={Math.PI / 6}
     maxPolarAngle={Math.PI - Math.PI / 6}
    />
    • azimuth angle: x-z 평면각
    • polar angle: y축 포함 평면각
  • axesHelper
    x, y, z 축 가이드라인을 보여주는 helper

    <axesHelper args={[5]} />
    • args={[축 길이]}
  • gridHelper
    grid인 바닥에 규격에 맞추어 보여주는 helper

    <gridHelper args={[20, 20, 0xff0000, 'teal']} />
    • args={[grid 한 변 길이, grid 한 변 segment 갯수, grid center 색, grid 색]}

threeJS에서 단위는 기본적으로 meter이다!
ex. <gridHelper args={[20, 20, 0xff0000, 'teal']} />에서 grid 한 변 길이는 20m가 되고, 한 변의 segment 갯수가 20개이니, 한 segment의 한 변 길이는 1m가 된다.

leva

  • scene, camera의 설정을 개발 화면에서 직접 GUI로 조정할 수 있는 툴

다음과 같이 노란색 테두리로 감싸져 있는 부분이 leva로 생성한 GUI component이다.

해당 스크린샷의 예시 코드는 아래와 같다.

관련 자료

느낀 점

drei, leva와 같은 라이브러리 의존성이 높은 것 같다. drei에서도 React 18이면 사용 시 console error를 뱉을 것이라고도 얘기한다.
아직 불안정한 오픈 소스를 쓰는 게 과연 괜찮을까 싶으면서도 이렇게 한 번 세게 부딪혀보면서 이해도를 높이면 언젠가 직접 컨트리뷰트도 할 수 있지 않을까 싶다.

그나저나 지금은 기본적인 정육면체, 구로 하지만 나중에 직접 렌더하고 싶은 디자인이 있으면 Maya나 3D Max로 직접 그려야 하나 싶다. 궁금해!

profile
프론트엔드 기술 학습 및 공유를 활발하게 하기 위해 노력합니다.

0개의 댓글