최근에는 주로 3D asset generation 관련 일을 하다 보니, 웹에서 3D 모델을 렌더링해서 보여줄 일이 종종 생긴다. 사내 데모나 논문 프로젝트 페이지를 만들 때 유용한 두 가지 방법—Google Model Viewer와 Three.js 기반 커스텀 뷰어—를 써봤는데, 각각의 사용법과 장단점을 정리해보고, custom 구현한 model viewer 를 공유하고 싶어 글을 작성한다.
Velog에서는 마크다운만 지원해서 모델을 직접 보여줄 수 없으니, 직접 해당 방법들로 3D Model 들을 불러오고, 각종 rendering 모드를 구현하는 방법을 interactive 하게 보기 위해서는 다음 개인 github blog 포스팅을 참조하길 바란다.
<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 요소를 눈으로 확인하기가 힘들다.
대신에 제한적으로 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 Rendering | Texture Rendering |
---|---|
![]() | ![]() |
위에서 살펴본 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); },
Three.js를 사용한 커스텀 뷰어는 Google Model Viewer에 비해 훨씬 더 많은 유연성을 제공한다. 이를 통해 Diffuse, Mesh, Wireframe, Normal 등 다양한 렌더링 모드를 구현할 수 있다.
Threejs 의 Mesh Texture 는 MeshStandardMaterial 에 PBR material 형태로 정의되어 있는데, Normal, Geometry, Wireframe 등의 rendering 은 material mapping 만 적절히 해주는 것으로 구현 가능하다.
예를 들어 Normal map 의 경우에는 threejs 에서 제공하는 THREE.MeshNormalMaterial() 을 mesh material 로 설정하는 것으로 rendering 할 수 있다.
if (model) {
model.traverse((child) => {
if (child.isMesh) {
child.material = new THREE.MeshNormalMaterial();
}
});
}
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
}
});
3D Model 에 따라 이 기능들을 항상 재구현 하기엔 좀 귀찮으므로, 앞서 설명한 기능들과 더불어 성격이 다른 pre-defined skybox env map 설정 및 제거,모델의 위치와 회전을 조정할 수 있는 UI 패널 등을 추가한 SimpleModelViewer class 를 만들어보았다.
티저 이미지처럼 다양한 rendering 모드를 제공하는데, 코드와 interactive 3d model 이 궁금하면 다음 그림을 클릭하여 확인해보자!
Google Model Viewer는 빠르고 간편하게 3D 모델을 웹에 삽입할 수 있는 훌륭한 도구다. 하지만 더 세밀한 제어나 다양한 렌더링 모드가 필요할 때는 Three.js를 사용한 커스텀 뷰어가 더 적합하다.
이번 작업에서 Three.js를 활용해 Diffuse, Mesh, Wireframe, Normal 등의 렌더링 모드를 지원하는 커스텀 뷰어를 구현했으며, 모델의 위치와 회전을 조정할 수 있는 패널도 추가했다. 이를 통해 사용자는 모델을 유연하게 조작하며 다양한 시각적 효과를 탐구할 수 있다.
앞으로 필요에 따라 기능을 확장할 수 있으며, 예를 들어 조명 설정, 카메라 뷰 저장, 모델 회전 애니메이션 등을 추가할 수 있다. 이 글을 통해 3D 모델 뷰어의 구현 방법을 이해하고, 프로젝트에 맞는 최적의 방법을 선택하는 데 도움이 되길 바란다.