개발/React : React Three Fiber

【React Three Fiber】#02 카메라: Perspective Camera

고독한 쵸이 2023. 8. 27. 22:07
반응형

이번 글에서는 React Three Fiber의 카메라 중 Perspective Camera에 대해 알아보고자 한다.

 

이전 글은 아래를 참고해 주세요.

【React Three Fiber】#01 초기설정, 튜토리얼

 

【React Three Fiber】#01 초기설정, 튜토리얼

React Three Fiber를 선택한 이유 현재 일본 파견회사에서 약 4년 정도 일하고 있는데, 안 그래도 낮은 연봉이 인상도 잘 안될뿐더러, 한심한 사장을 보고 앞으로의 비전도 없다고 느꼈기 때문에 (대

solitary-choi.tistory.com

 

Perspective Camera

원근 카메라.

사람의 시야에 가장 근접한 카메라이며, 카메라에서 멀리 떨어져 있을수록 물체가 작게 보인다.

 

React Three Fiber에서 원근 카메라를 사용하기 위해서는 canvas 태그에 camera 속성을 지정하면 된다.

주로 사용되는 프로퍼티는 다음과 같다.

 

position

카메라의 위치.

x, y, z 축 순으로 설정할 수 있다.

fov

Field Of View의 줄임말로, 시야각을 의미.

카메라에서 보이는 장면의 범위. 60 ~ 90도로 설정하는 경우가 대부분이다. 

near

카메라에서 렌더링 되는 장면의 최소 거리.

0.00001 같은 이상치는 z-fighting의 원인이 되기 때문에 사용하지 말 것.

far

카메라에서 렌더링 되는 장면의 최대 거리.

999999 같은 이상치는 z-fighting의 원인이 되기 때문에 사용하지 말 것.

 

※ near, far범위를 벗어난 부분은 렌더링 되지 않는다는 점을 기억하자.

※ 이외에도 filmGauge, filmOffset 등이 있으나, 여기서는 언급하지 않겠다.

 

아래 그림을 보면 좀 더 이해하기 쉽다.

Perspective Camera
출처: mdn web docs

그러면 위에 적혀있는 프로퍼티를 실제로 적용해 보자.

const PerspectiveCamera = () => {
  return (
    <div style={{ width: sizes.width, height: sizes.height }}>
      <Canvas
        camera={{
          position: [0, 0, 3],
          fov: 75,
          near: 0.1,
          far: 100,
        }}
      >
        <Cube />
      </Canvas>
    </div>
  );
};

export default PerspectiveCamera;

위의 코드를 실행하면 다음과 같이 오브젝트가 위에서 바라보는 것처럼 나타난다.

Perspective Camera

커서 위치를 추적해 카메라 움직이기

이번에는 마우스가 움직인 위치를 추적해, 카메라를 움직여보자.

일단 App.tsx에 커서의 초기값과 커서의 상태 값을 업데이트하는 함수를 선언한 후, PerspectiveCamera 컴포넌트에 인자로 넘겨준다.

커서의 좌표는 React.PointerEvent의 clientX와 clientY를 사용해 취득할 수 있다.

 

// TypeScript를 사용할 경우, 타입도 제대로 설정하는 것이 바람직하다.
const [cursor, setCursor] = useState<Cursor>({ x: 0, y: 0 });
// 커서의 상태값을 업데이트하는 함수
const changeCursorHandler = (event: React.PointerEvent<HTMLDivElement>) => {
    setCursor({
      // 최소값: -0.5, 최대값: 0.5가 되도록 -0.5를 붙여준다.
      x: event.clientX / sizes.width - 0.5,
      y: event.clientY / sizes.height - 0.5,
    });
};

return (
    <PerspectiveCamera
      sizes={sizes}
      cursor={cursor}
      onChangeCursor={changeCursorHandler}
    />
);

PerspectiveCamera에서는 캔버스 내에서 마우스가 움직였을 경우, App.tsx에서 넘겨받은 changeCursorHandler를 실행하는 함수를 실행시키도록 한다.

그리고 오브젝트에서는 커서의 상태 값을 넘겨받아, 카메라 위치에 커서 좌표 * 10을 설정한다.

 

/* eslint-disable react/no-unknown-property */

import * as THREE from "three";

import { Canvas, useFrame } from "@react-three/fiber";
import { Cursor, Sizes } from "../../Common";
import React, { useRef } from "react";

interface Props {
  sizes: Sizes;
  cursor: Cursor;
  onChangeCursor: (event: React.PointerEvent<HTMLDivElement>) => void;
}

// 마우스를 움직였을 경우 실행할 함수
const MoveObject = (
  event: React.PointerEvent<HTMLDivElement>,
  onChangeCursor: (event: React.PointerEvent<HTMLDivElement>) => void
) => {
  onChangeCursor(event);
};

const Cube: React.FC<{ cursor: Cursor }> = ({ cursor }) => {
  const cubeRef = useRef<THREE.Mesh>(null);

  useFrame((state) => {
    if (!cubeRef.current) {
      return;
    }

    // 커서 상태값 * 10의 값을 카메라 위치에 설정한다.
    state.camera.position.x = cursor.x * 10;
    state.camera.position.y = cursor.y * 10;
  });

  const object = (
    <mesh ref={cubeRef}>
      <boxGeometry args={[1, 1, 1, 5, 5, 5]} />
      <meshBasicMaterial color="#e91e63" />
    </mesh>
  );
  return object;
};

/**
 * @param {object} sizes 화면 사이즈
 * @param {object} cursor 커서 상태값
 * @param {function} onChangeCursor 커서 상태값 변경 함수
 * @return PerspecticeCamera
 */
const PerspectiveCamera = ({ sizes, cursor, onChangeCursor }: Props) => {
  return (
    <div style={{ width: sizes.width, height: sizes.height }}>
      <Canvas
        camera={{
          position: [0, 0, 3],
          fov: 75,
          near: 0.1,
          far: 100,
        }}
        // 마우스가 움직였을 경우 아래 함수를 실행한다.
        onPointerMove={(event) => MoveObject(event, onChangeCursor)}
      >
        // 커서 상태값을 인자로 넘겨준다.
        <Cube cursor={cursor} />
      </Canvas>
    </div>
  );
};

export default PerspectiveCamera;

코드를 실행하면 아래와 같이 커서 위치에 따라서 카메라가 이동하는 것을 볼 수 있다.

커서의 위치에 따라 움직이는 카메라

다음에는 Orthographic Camera, OrbitControls에 대해 작성해보고자 한다.

 

つづく

반응형