[리액트에 three.js를 적용하자!] (3) gltf 모델 로드

HyeKong·2023년 10월 20일
0

react-three-fiber

목록 보기
3/3
post-thumbnail

개인적으로 three.js를 활용할 때 꽃이라고 생각하는 나만의 모델 로드하기!!!!!
r3f에선 관련 자료가 찾기 힘들었고, 방법도 잘 몰랐으며 바닐라 js에서 할 때도 obj만 로드해봤지 gltf모델은 처음이라 조금 헤맸다.ㅎㅎ
그래도 ...꼬옥 필요하기에.. 깃허브를 뒤져봤다.

이건 도움 받은 문서와 깃허브!!
문서
깃허브
문서


로드 방법이다.(Canvas, Camera, Light 의 기본 세팅은 제외!)

1. glb 파일 구하기

gltf 모델을 로드할 때는 glb 확장자의 모델이 필요하다.
이 역시 찾기 힘들어서 도움 받은 깃허브에서 다운받았다.
그 후 정석대로 public 폴더 내에 옮겨주었다.

솔직히 이름이 마음에 들어서 받았다.

2. useGLTF를 import한다.

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

useGLTF는 gltf를 load해주는 훅이다.

3. 다운 받은 파일을 useGLTF를 통해 불러온다.

const groupRef = useRef();
const { nodes, materials } = useGLTF('/hamburger-draco.glb');
  

4. 로드할 mesh를 감쌀 group 태그를 생성한다.

5. group 태그 안에 배치할 mesh를 아래 순서부터 작성한다.

당연히 위에 올라오는 mesh의 순서대로일줄 알았는데, 아래에서부터 쌓이는 순서대로 작성해야 다음과 같은 에러가 안 난다.

이유가 궁금해서 실험해봤는데, 순서만 바꾸었을 때는 에러가 나지만, 아래 쌓이는 mesh(더 위에 작성)의 y 좌표를 더 낮게 조정해주면 에러가 안 나고 순서도 잘 바뀐다.
내 생각엔 순서대로 배치해야해서 높은 y좌표 => 낮은 y좌표 순으로 배치하면 해당 에러가 나는 것 같다.

5-1. mesh를 작성하며 각 mesh에 해당하는 geometry, materil을 불러와 attribute로 넣어준다.

5-2. shadow 설정을 넣으면 좀 더 예쁘다.

5-3. position 설정 역시 잘 맞춰야 한다.

<group ref={groupRef} {...props} dispose={null}>
          <mesh
            geometry={nodes.bottomBun.geometry}
            material={materials.BunMaterial}
          />
          <mesh
            castShadow
            receiveShadow
            geometry={nodes.meat.geometry}
            material={materials.SteakMaterial}
            position={[0, 2.82, 0]}
          />
          <mesh
            castShadow
            receiveShadow
            geometry={nodes.cheese.geometry}
            material={materials.CheeseMAterial}
            position={[0, 3.03, 0]}
          />
          <mesh
            castShadow
            receiveShadow
            geometry={nodes.topBun.geometry}
            material={materials.BunMaterial}
            position={[0, 1.77, 0]}
          />
        </group>

6. (선택적) useGLTF.preload

useGLTF에는 preload 옵션이 있고, 해당 옵션은 마지막줄에 실행해야 한다.

=> WebGL은 frustrum을 만날 때만 material을 컴파일 하는데, 이는 jank를 야기할 수 있기 때문에, preload 옵션을 추가하면 scene을 미리 로드해줘 이를 막을 수 있다.
관련 링크

전체 코드

import React, { useState, useRef } from 'react';
import { Canvas, useFrame } from '@react-three/fiber';
import { PerspectiveCamera, CameraControls } from '@react-three/drei';
import { useGLTF } from '@react-three/drei';

export default function LoadHBGModel(props) {
  const groupRef = useRef();
  const { nodes, materials } = useGLTF('/hamburger-draco.glb');
  return (
    <>
      <Canvas
        style={{ width: '100%', height: '100vh', background: 'orangered' }}
        camera={{ position: [20, 10, 0] }}
      >
        <CameraControls minPolarAngle={0} maxPolarAngle={Math.PI / 0.5} />
        <ambientLight intensity={0.1} />
        <directionalLight color='#FFF' position={[0, 1, 0]} />

        <PerspectiveCamera
          fov={40}
          near={10}
          far={1000}
          position={[10, 0, 50]}
        />
        <group ref={groupRef} {...props} dispose={null}>
          <mesh
            geometry={nodes.bottomBun.geometry}
            material={materials.BunMaterial}
          />
          <mesh
            castShadow
            receiveShadow
            geometry={nodes.meat.geometry}
            material={materials.SteakMaterial}
            position={[0, 2.82, 0]}
          />
          <mesh
            castShadow
            receiveShadow
            geometry={nodes.cheese.geometry}
            material={materials.CheeseMAterial}
            position={[0, 3.03, 0]}
          />
          <mesh
            castShadow
            receiveShadow
            geometry={nodes.topBun.geometry}
            material={materials.BunMaterial}
            position={[0, 1.77, 0]}
          />
        </group>
      </Canvas>
    </>
  );
}
useGLTF.preload('/hamburger.glb');

결과 사진


히히.. 내 햄버거....

내일은 여러개의 모델을 로드하고, 배치도 조정하고 애니메이션도 추가해 봐야겠다.

0개의 댓글