Three.js로 3D 웹 쉽게 구현하기

Hyeon·2022년 7월 27일
1
post-thumbnail

들어가며

왜 관심을 가지게 되었나

학교를 (드디어) 졸업했다. 요즘은 해보고 싶었던 개발을 하며 시간을 보내고 있다. 최근 노코드 툴을 사용한 게임 개발을 마치고, JS와 관련된 무언가를 해보고 싶었던 참에 회사 동료분께서 한 사이트를 공유해 주셨다. 춘식이의 관찰일기 라는 카카오에서 만든 페이지다. 마우스를 통해 춘식이를 3차원에서 움직일 수 있고, 귀여운 애니메이션도 구현되어 있다.

WebGL 기반 기술을 사용하면 위와 같이 웹 페이지에 3차원 물체를 렌더링 할 수 있다. 그리고 다양한 인터렉션도 추가할 수 있다. 3D의 영역은 유니티나 언리얼과 같은 엔진으로만 가능하다고 생각했는데 웹으로 이러한 구현이 가능하다는 것이 신선했다.

주말마다 아침 시간을 사용해서 모각코를 하고 있다. 2주 동안 Three.js를 학습하면서 간단한 프로젝트를 하는 목표를 세웠다. 나는 태양계를 만들어 보기로 했다. 작업을 하면서 Three.js의 여러 기능들을 테스트해 볼 수 있었다.

태양계 (버그 있음, 렉 있음, 행성을 눌러보세요)
깃헙 (코드 정리가 안되어 있는건 비밀)

Three.js.. 해보실래요?

사실 WebGL 관련 기술은 오래전부터 존재했지만, 아직까지는 널리 사용되고 있지 않다. 브라우저 호환성 문제, 성능(속도) 문제가 대표적인 원인으로 꼽힌다. 그럼에도 불구하고, 웹으로 3D를 구현하는 것은 매력이 있다. 단순히 2차원 평면에서 정보를 주고받는 것을 넘어 3차원에서 적극적인 인터렉션을 구성하고, 사용자에게 몰입과 색다른 경험을 선사할 수 있다. 무엇보다도 멋지다!!

장애물들

3D 개발을 하고 싶다는 생각이 들었을 때 지레 겁먹게 되는 부분이 있었다.

수학을 잘해야 하지 않나?

많이 다루어 보진 않아서 확신할 수 없지만, 아주 복잡한 3D 웹을 만들 것이 아니라면 깊은 수학적 지식은 필요 없다. cos, sin의 기초 개념 정도만 알아도 웬만한 기능은 구현할 수 있다. ammo.js, cannon-es 등 물리엔진 라이브러리도 굉장히 잘되어 있어서 물리 값에 대한 수학적 계산을 할 필요가 없다. 물리엔진을 반드시 사용해야 하는 것도 아니다.

3D 오브젝트 모델링은 어떻게 하나?

blender나 3ds max와 같은 소프트웨어를 사용해서 직접 모델을 만들 수 있다. 간단한 모델은 며칠 학습하면 만들 수 있다. 직접 만들지 않고도 텍스처, 모델을 무료 다운로드할 수 있는 사이트가 많다. 이미지 사용하는 것처럼 받아서 사용하면 된다.

https://sketchfab.com/search?type=models
https://3dtextures.me/

뭔가 3D 하니까 어려운 것 같다.

Three.js에서 개발자가 조작해야 할 핵심 요소는 mesh, light, camera 이렇게 3가지 뿐이다. 물체를 화면에 넣고, 빛을 쏘고, 그걸 카메라로 보면 된다. 끝이다. 여기에 원한다면 부수적인 것들을 하나씩 더해가면 된다.

그럼 바로 3D object를 띄워보자

우선 three.js 설치부터 하고 시작!

npm i three

실제로 '본다'라는 행위를 위해서는 다음 3가지가 필요하다. 물체, 빛, 눈이다. Three.js에서는 이것을 각각 Mesh, Light, Camera라고 부른다.

Mesh

Mesh 객체는 형상정보(Geometry)와 재료정보(Material)로 구성되어 있으며, 3D 화면을 구성하는 물체이다. Mesh 객체가 만들어지면 설정값을 통해서 3D 공간상의 위치를 결정할 수 있다.

const geometry = new THREE.BoxGeometry(1, 1, 1);//가로,세로,높이
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
cube.position.set(0,0,0)//x,y,z 위치

Light

Light 객체는 빛이다. 전체를 은은하게 비추는 AmbientLight, 한 방향으로 뻗어나가는 DirectionalLight, 특정 부분을 강조할 수 있는 SpotLight 등 많은 빛의 형태가 있다.

const ambientLight = new THREE.AmbientLight("white", 1);//색상, 강도

Camera

Camera 객체는 눈에 해당한다. Scene 객체를 촬영하여 어떻게 보여줄 것인가를 결정한다. 같은 Scene이라고 하더라도, 카메라의 위치 및 기타 설정값들을 통해서 다른 화면을 보여줄 수 있다.

const camera = new THREE.PerspectiveCamera(
  75, //시야각
  window.innerWidth / window.innerHeight,//종횡비
  0.1, //near
  1000 //far
);
camera.position.set(1, 1, 5);//x,y,z 위치

Scene

Scene 객체는 무대를 나타낸다. 생성한 물체(Mesh)와 빛(Light) 그리고 카메라(Camera)를 추가 해준다.

const scene = new THREE.Scene();
scene.add(cube);
scene.add(ambientLight);
scene.add(camera);

Renderer

<body>
	<canvas></canvas>
</body>

Renderer는 카메라 설정값을 기반으로 Scene에서 보여줄 화면을 계산하고, 브라우저에 해당 화면을 출력해준다.

const canvas = document.querySelector("canvas");
const renderer = new THREE.WebGLRenderer({canvas});
renderer.setSize(window.innerWidth, window.innerHeight);//윈도우 전체
document.body.appendChild(renderer.domElement);
renderer.render(scene, camera);


간단한 코드로 3D 오브젝트를 띄워보았다.

더욱더 멋진 기능들은 공식문서를 통해 확인할 수 있다. (한글도 지원됨)

결론

Babylon.js

생각했던 것보다 더 재미있게 개발했다. 시간이 된다면 Babylon.js 도 사용해 보고 싶다. 사실 Three.js보다 Babylon.js가 더 트렌디한 기술이긴 하다. Three.js는 WebGL 기반, Babylon.js WebGL을 발전시킨 WebGPU 기반 라이브러리이다. 아래 글들을 통해 WebGPU에 대해 알 수 있다.

https://roseline.oopy.io/dev/web-3d-graphics
https://webdoli.tistory.com/421
https://m.blog.naver.com/designju/221540082923

모델링

게임을 만들었을 때, 개발보다 사운드와 디자인을 고민하는데 더 많은 시간을 사용했다. 이번에도 같은 맥락이었다. 3D 모델링을 위해 blender를 사용해 보고자 했는데, 간단한 캐릭터 하나를 만들기도 버거웠다. 그래도 꽤 재미있어서 종종 만들어보려고 한다. blender 구루의 도넛 튜토리얼이 초심자가 보기에 괜찮아 보인다.

성능

모델이 아닌 텍스처만 로드해서 사용했는데도 불구하고 퍼포먼스가 좋지 않았다. 초기 로딩 속도는 물론이거니와 애니메이션도 끊기는 경우가 잦았다. Webpack 최적화를 잘 하면 될까? 아니면 Three.js의 한계인 걸까? 놓친 최적화 옵션이 따로있나? Ec2 프리티어를 사용해서 그런 것일까? 다음 작업은 퍼포먼스에 초점을 두고 진행해 보아야 겠다.

해보고 싶은 것

최근 시각적 이펙트가 있는 웹페이지를 구성하는 것에 관심이 가기 시작했다. 인터렉티브한 웹 개발, 웹 게임 개발을 해보고 싶다. Vampire Survivors 이라는 스팀게임이 Javascript + Electron을 사용해 만들어졌다고 한다. slack, vscode, wordpress 등도 Electron으로 빌드 되었다고 하는데 흥미가 간다.

profile
요즘 인터렉티브한 웹에 관심이 많습니다.

0개의 댓글