[Three.js] 03) 3D 모델 불러오기 (GLTF Loader)

GLTF

Unity에서는 보통 fbx나 obj 파일을 임포트해서 사용하지만, 웹 환경에서는 GLTF(GL Transmission Format)가 사실상의 표준이라고 한다. GLTF는 웹에 최적화 되어있어 대표적으로 함께 사용되는 GLB 포맷과 함께 아래와 같은 특성을 가지고 있다.

구분 glTF(.gltf) GLB(.glb)
파일 구조 여러 파일로 분리 (.gltf + .bin + 텍스쳐...) 단일 바이너리 파일
기반 형식 JSON 텍스트 기반 바이너리
웹 로딩 속도 상대적으로 느림 (여러 파일 요청 필요) 빠름 (단일 파일 요청)
주요 사용처 개발, 디버깅, 3D 모델 데이터 수정 단계 웹 배포, 실시간 렌더링, 최종 앱

 


 

GLTFLoader와 비동기 로딩

Three.js에서 GLTF 모델을 불러오려면 GLTFLoader가 필요하다. 모델을 불러오는 동안 중요한 포인트는 모델 로딩 시 비동기 방식으로 처리 된다는 것이다. 파일의 위치가 로컬이던, 원격 서버에 있던 브라우저가 파일을 읽고 처리하는 동안 웹페이지 전체가 멈추는 블로킹 현상을 막기 위함이다. 따라서 모델을 다루는 코드는 로딩이 완료된 후 실행되는 콜백함수 내부에 작성해야한다.

 

// main.js

// 1. GLTFLoader를 import한다.
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

// 2. 로더 인스턴스를 생성한다.
const gltfLoader = new GLTFLoader();

// 3. .load() 메소드를 호출한다.
gltfLoader.load(
    './models/scene.gltf',  // 모델 파일 경로

    // 로드 성공 시 실행될 콜백 함수
    (gltf) => {
        const model = gltf.scene; // 실제 모델은 gltf.scene에 담겨 있다.
        scene.add(model); // 씬에 모델을 추가한다.
        
        // 모델의 Transform(위치, 크기, 회전)을 여기서 제어해야 한다.
        model.scale.set(0.25, 0.25, 0.25);
        model.position.y = 0;
    },

    // 로드가 진행되는 동안 실행될 콜백 (선택 사항)
    undefined,

    // 로드 실패 시 실행될 콜백
    (error) => {
        console.error('모델 로드 중 에러 발생', error);
    }
);

 

gltfLoader.load()는 모델 파일 로드에 대한 요청만 보낸 뒤 로딩이 끝나기를 기다리지 않고 바로 다음 코드를 실행한다. 로딩이 끝나면 이후의 콜백함수 (gltf) => {실행될 내용}  가 실행되는 구조이다.

 


 

traverse : 불러온 모델에 그림자 적용

GLTF 모델은 여러 개의 자식 Mesh로 구성된 그룹인 경우가 많기 때문에 traverse 메서드를 사용해 모델의 모든 자식 요소를 순회하며 그림자 속성을 켜줘야 한다.

// main.js - gltfLoader.load() 콜백 함수 내부

gltfLoader.load(
    './models/scene.gltf',
    (gltf) => {
        const model = gltf.scene;

        // 모델의 모든 자식 Mesh를 순회하며 그림자 속성을 설정
        model.traverse((child) => {
            // 자식이 Mesh 타입인 경우에만 그림자 속을 적용
            if (child.isMesh) {
                child.castShadow = true;      // 이 Mesh가 그림자를 만들도록 설정
                child.receiveShadow = true;   // 이 Mesh가 다른 그림자를 받도록 설정
            }
        });

        model.scale.set(0.25, 0.25, 0.25);
        model.position.y = 0;
        scene.add(model);
    }
);

 

model.traverse()는 Unity에서 GetComponentsInChildren<MeshRenderer>()를 호출해 모든 자식 렌더러에 접근하는 것과 유사한 개념이다.

 


 

결과물

 

 

 

 


 

다음에는 임포트한 모델에 다른 재질을 입히거나 텍스처를 설정하는 내용을 다뤄보려고 한다.

 

전체 코드 GitHub 링크

https://github.com/sgho0915/threejs-learn/tree/master/03-model-loader

 

threejs-learn/03-model-loader at master · sgho0915/threejs-learn

웹 3D 라이브러리인 Three.js를 학습하고, 최종적으로 두 개의 포트폴리오 프로젝트를 완성하는 과정을 기록하는 공간입니다. - sgho0915/threejs-learn

github.com

 

반응형