css를 공부하다 보니 자연스레 WebGL에 관심이 생겨 기본 개념을 익힐 겸 공식 문서를 따라 만들어 보았다(openGL은 일단 조금 나중에 다시 보는 걸로..). 사실 문서가 너무 잘 돼있어 예제를 단순히 따라 하면서 react로 구현한 거 이외에는 별다른 게 없기 때문에 이 글에서는 쓸 내용은 많지 않았다. 하지만 시작한 기록을 남기기 위해 조금만 적어본다.
Three.js란?
Three.js는 웹에 3D 객체를 쉽게 렌더링하도록 WebGL을 근간에 둔 자바스크립트 3D 라이브러리이다. 사실상 WebGL이지만, WebGL의 경우 점, 섬, 삼각형만 그리는 단순한 자바스크립트 API이기 때문에, 3D 객체를 조금 더 편하고 효율적으로 짤 수 있게 도움을 주는 Three.js 같은 라이브러리를 사용한다.
위 그림은 three.js를 앱을 만들기 위한 다양한 객체를 도식화 한 것이다. 이것에 대한 설명은 중요하면서도 이미 문서에서 "한글"로 자세하게 적어 놓았다. 아직은 그 글보다 더 쉽게 이해하지 못하여, 아래 글을 그대로 가져왔다.
-
먼저 Renderer가 있습니다. Three.js의 핵심 객체이죠. Renderer는 Scene과 Camera 객체를 넘겨 받아 카메라의 절두체(frustum) 안 3D 씬의 일부를 평면(2차원) 이미지로 렌더링 합니다.
-
씬 그래프(Scene graph)는 Scene 또는 다수의 Mesh, Light, Group, Object3D, Camera로 이루어진 트리 구조와 유사합니다. Scene은 씬 그래프의 최상위 노드로서 배경색(background color), 안개(fog) 등의 요소를 포함합니다. Scene에 포함된 객체들 또한 부모/자식의 트리 구조로 이루어지며, 이는 각 객체의 유래와 방향성을 나타냅니다. 쉽게 말해 자식 객체의 위치(position)와 방향(orientation)이 부모 기준이라는 거죠. 예를 들어 자동차의 바퀴가 자동차 객체의 자식 객체라면, 자동차 객체의 방향을 움직일 때, 바퀴 객체의 방향 또한 같이 움직입니다(더 자세한 내용은 씬 그래프에 관한 글에서 확인할 수 있습니다)
Camera가 도표에서 반쯤 나간 것이 보이나요? 이는 의도된 것으로, 다른 객체와 달리 Camera는 굳이 씬 그래프에 포함될 필요가 없음을 보여주기 위함입니다. 물론 다른 객체와 마찬가지로 Camera 또한 다른 객체의 자식 객체가 될 수 있습니다. 이러면 부모 객체에 따라 Camera 또한 움직이겠죠. 씬 그래프에 관한 글 마지막에 여러 개의Camera를 넣는 예제가 있으니 참고하시기 바랍니다.
-
Mesh는 어떤 Material로 하나의 Geometry를 그리는 객체입니다. Material, Geometry는 재사용이 가능하여 여러 개의Mesh가 하나의 Material 또는 Geometry를 동시에 참조할 수 있습니다. 파란색 정육면체 2개를 그린다고 해보죠. 일단 두 정육면체의 위치가 달라야 하니, 2개의 Mesh가 필요합니다. 그리고 정점(vertext, 꼭짓점) 데이터를 가진 한 개의 Geometry와 채색을 위한 하나의 Material이 필요하겠죠. 이때 각 Mesh는 객체를 복사할 필요 없이, 같은 Geometry 그리고 Material을 참조할 수 있습니다.
-
Geometry는 기하학 객체의 정점 데이터입니다. 구(sphere), 정육면체(cube), 면(plane), 개, 고양이, 사람, 나무, 건물 등 아주 다양한 것이 될 수 있죠. Three.js는 기본적으로 몇 가지의 내장(built-in) 기하학 객체를 제공합니다. 물론 직접 기하학 객체를 만들 수도 있고, 파일에서 기하학 객체를 불러올 수도 있죠.
-
Material은 기하학 객체를 그리는 데 사용하는 표면 속성입니다. 색이나 밝기 등을 지정할 수 있죠. 하나의 Material는 여러 개의Texture를 사용할 수 있습니다. 기하학 객체의 표면을 이미지로 덮어씌울 때 주로 사용하죠.
-
Texture는 이미지나 파일에서 로드한 이미지, canvas로 생성한 이미지 또는 다른 Scene 객체에서 렌더링 한 결과물에 해당합니다.
-
Light는 여러 종류의 광원에 해당합니다.
설치
yarn add three
코드
실제 코드는 깃허브에 모두 공개하였습니다.
const scene = new Scene();
const camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
ref.current!.appendChild(renderer.domElement);
const geometry = new BoxGeometry(1, 1, 1);
const material = new MeshBasicMaterial({ color: 0x00ff00 });
const cube = new Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
const animate = () => {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
};
animate();
Storybook으로 동작 확인
vercel로 빌드된 스토리북 주소: css-collection-git-main.jungkyuhyun.vercel.app/?path=/story/threejs-by-jacob-basicscene--basic-css
추가적으로 지원 브라우저 체크
모던한 브라우저와 기기에서는 대부분 사용할 수 있지만, 아직도 사용할 수 없는 환경이 존재할 수도 있다. Doc에서 제공한 스크립트를 가져와서 이 부분을 한번 더 체크해 준다. https://github.com/mrdoob/three.js/blob/master/examples/jsm/WebGL.js
'React' 카테고리의 다른 글
React로 Threejs 예제 따라 구현하기 2 (0) | 2021.01.31 |
---|---|
React로 줄바꿈에 따라 늘어나는 textarea 구현하기(+ caret 색상 변경) (0) | 2021.01.29 |
[React] 간단하게 예제 코드로 구현해 보는 Drag and Drop (드래그앤드롭) (0) | 2021.01.10 |
[React Dot Notation] 리액트 컴포넌트 점 표기법 (0) | 2020.12.25 |
[React Dynamic Component] 동적으로 컴포넌트를 보여주는 방법 (0) | 2020.12.22 |