웹에서 3D Model Viewer 구현하기: Google Model Viewer vs Three.js

Hwan Heo·2025년 3월 10일
1

Neural Rendering

목록 보기
22/22

들어가며

최근에는 주로 3D asset generation 관련 일을 하다 보니, 웹에서 3D 모델을 렌더링해서 보여줄 일이 종종 생긴다. 사내 데모나 논문 프로젝트 페이지를 만들 때 유용한 두 가지 방법—Google Model ViewerThree.js 기반 커스텀 뷰어—를 써봤는데, 각각의 사용법과 장단점을 정리해보고, custom 구현한 model viewer 를 공유하고 싶어 글을 작성한다.

Velog에서는 마크다운만 지원해서 모델을 직접 보여줄 수 없으니, 직접 해당 방법들로 3D Model 들을 불러오고, 각종 rendering 모드를 구현하는 방법을 interactive 하게 보기 위해서는 다음 개인 github blog 포스팅을 참조하길 바란다.

👉 3D Model Viewer in Web

Google Model Viewer

<script type="module" src="https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js"></script>

<model-viewer 
    src="your_3d_model.glb" >
</model-viewer>

위처럼 간단하게 import 후 model src 만 제공하면 바로 webpage 에서 3D Model 을 보여줄 수 있다.

하지만 model viewer 는 기본 shader 를 수정하기가 힘들고, 기본 texture rendering 외에 다른 타입 (Normal, Geometry, Wireframe) 등을 지원하지 않아서, texture 외의 detail 한 mesh 요소를 눈으로 확인하기가 힘들다.

  • gradient environment

대신에 제한적으로 texture 를 지우고 enviroment 에 gradient equirectangular image 를 사용하여, PBR rendering 으로 gradient environment 를 반사하는 rendering 을 만들어서 mesh geometry 를 rendering 하는 듯한 효과를 낼 수 있다.

var window_state = {};
function show_geometry(){
    let modelViewer = document.getElementById('model');
    if (modelViewer.model.materials[0].pbrMetallicRoughness.baseColorTexture.texture === null) return;
    window_state.textures = [];
    for (let i = 0; i < modelViewer.model.materials.length; i++) {
        window_state.textures.push(modelViewer.model.materials[i].pbrMetallicRoughness.baseColorTexture.texture);
    }
    window_state.exposure = modelViewer.exposure;
    modelViewer.environmentImage = '<img src="gradient.jpg" width="100%" />';
    for (let i = 0; i < modelViewer.model.materials.length; i++) {
        modelViewer.model.materials[i].pbrMetallicRoughness.baseColorTexture.setTexture(null);
    }
    modelViewer.exposure = 3;
}
Geometry RenderingTexture Rendering

Three.js Custom Viewer

위에서 살펴본 model viewer 만으로 rendering 할 수 없는 normal, wireframe rendering 등을 구현하기 위해서는 threejs 를 사용해서 직접 model viewer class 를 구현해야 한다.

<script type="importmap">
    {
        "imports": {
            "three": "https://unpkg.com/three@0.150.0/build/three.module.js",
            "three/addons/": "https://unpkg.com/three@0.157.0/examples/jsm/"
        }
    }
</script>

Model Viewer 와 마찬가지로 cdn 으로 import 해서 쓸 수 있지만, threejs 자체는 기본적인 설정이 model viewer 보다 훨씬 복잡하다.

scene, camera, renderer 등을 모두 직접 설정해줘야 하는데, jacascript 에서 다음과 같이 필요한 최소 패키지들을 import 한 후, scene 과 camera 를 새로 정의하고 다음과 같이 gltf 3D model 을 load 하여 scene 에 불러올 수 있다.

import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';

scene = new THREE.Scene(); 
camera = new THREE.PerspectiveCamera(50, 1, 0.1, 1000);
renderer = new THREE.WebGLRenderer({ antialias: true });
controls = new OrbitControls(this.camera, this.renderer.domElement);

loader = new GLTFLoader();
loader.load('your_3d_model.glb', (gltf) => { scene.add(gltf.scene); },

Custom Settings

Three.js를 사용한 커스텀 뷰어는 Google Model Viewer에 비해 훨씬 더 많은 유연성을 제공한다. 이를 통해 Diffuse, Mesh, Wireframe, Normal 등 다양한 렌더링 모드를 구현할 수 있다.

Threejs 의 Mesh Texture 는 MeshStandardMaterial 에 PBR material 형태로 정의되어 있는데, Normal, Geometry, Wireframe 등의 rendering 은 material mapping 만 적절히 해주는 것으로 구현 가능하다.

Normal Map

예를 들어 Normal map 의 경우에는 threejs 에서 제공하는 THREE.MeshNormalMaterial() 을 mesh material 로 설정하는 것으로 rendering 할 수 있다.

if (model) {
    model.traverse((child) => {
        if (child.isMesh) {
            child.material = new THREE.MeshNormalMaterial();
        }
    });
}

Wireframe

Wireframe 의 경우에는 THREE.MeshNormalMaterial() 에서 wireframe: true 로 설정하면 wireframe mesh 가 나오긴 하지만, 이 모드는 원본 texture 랑 geometry 가 사라져서 가시성이 떨어진다.

대신에 wireframemesh 를 복사본으로 선언한 후, original mesh 의 child 로 추가하여 mesh 의 original texture, geometry 와 함께 wireframe 을 렌더링하여 볼 수 있다.

model.traverse((child) => {
    if (child.isMesh) {
        const wireframeMesh = new THREE.Mesh(child.geometry, new THREE.MeshBasicMaterial({
            wireframe: true,
            color: 0xaaaaaa, // light gray
            depthTest: true,
            transparent: true,
            opacity: 0.8 // transparency
        }));
        model.add(wireframeMesh); // add as child 
    }
});

Custom Model Viewer

3D Model 에 따라 이 기능들을 항상 재구현 하기엔 좀 귀찮으므로, 앞서 설명한 기능들과 더불어 성격이 다른 pre-defined skybox env map 설정 및 제거,모델의 위치와 회전을 조정할 수 있는 UI 패널 등을 추가한 SimpleModelViewer class 를 만들어보았다.

티저 이미지처럼 다양한 rendering 모드를 제공하는데, 코드와 interactive 3d model 이 궁금하면 다음 그림을 클릭하여 확인해보자!
click to project page

마치며

Google Model Viewer는 빠르고 간편하게 3D 모델을 웹에 삽입할 수 있는 훌륭한 도구다. 하지만 더 세밀한 제어나 다양한 렌더링 모드가 필요할 때는 Three.js를 사용한 커스텀 뷰어가 더 적합하다.

이번 작업에서 Three.js를 활용해 Diffuse, Mesh, Wireframe, Normal 등의 렌더링 모드를 지원하는 커스텀 뷰어를 구현했으며, 모델의 위치와 회전을 조정할 수 있는 패널도 추가했다. 이를 통해 사용자는 모델을 유연하게 조작하며 다양한 시각적 효과를 탐구할 수 있다.

앞으로 필요에 따라 기능을 확장할 수 있으며, 예를 들어 조명 설정, 카메라 뷰 저장, 모델 회전 애니메이션 등을 추가할 수 있다. 이 글을 통해 3D 모델 뷰어의 구현 방법을 이해하고, 프로젝트에 맞는 최적의 방법을 선택하는 데 도움이 되길 바란다.

profile
기타치는AI Researcher

0개의 댓글

관련 채용 정보