본문 바로가기
공부/etc

Three.js and TypeScript (5)

by Piva 2024. 11. 18.
  • Udemy의 Three.js and TypeScript 강의를 듣고 정리한 내용을 기록한다.
    • 14. Object3D Hierarchy 부터 17. Common Materials 까지.

Object3D Hierarchy

  • 앞서 언급했듯 Three.js의 많은 객체들은 Object3D를 확장하는 클래스이다.
  • Scene 또한 Object3D를 확장하고 있다.
  • 일반적으로 Three.js에서 장면을 구성할 때는 Scene 객체에 다른 Object3D 객체들을 add 메서드로 추가한다.
    • 이 때, Scene은 Object3D의 확장 객체이므로 Scene 자체를 회전시키거나 이동하는 것이 가능하다(일반적으로 그럴 일이 별로 없긴 하다고).
    • 또한, Object3D 객체에 add 메서드를 사용해 다른 Object3D 객체를 추가하는 것이 가능하다.
    • 이 경우, 추가된 물체와 그 상위 물체는 일종의 ‘부모-자식 관계’를 맺게 되며, 부모 물체가 움직이면 자식 물체 또한 함께 움직이게 된다.
      • 좌표 뿐 아니라, 크기(scale)나 회전값(rotation) 또한 부모의 영향을 받는다.
    → 부모에 의해 좌표나 크기 등이 바뀌게 되면, 자식 물체의 월드 좌표는 바뀌지만 로컬 좌표는 바뀌지 않는다.
    로컬 좌표계란, 자신의 부모 물체의 상대적인 위치가 기준인 좌표계를 의미한다.
  • Object3D의 position 속성은 로컬 좌표계의 좌표를 나타낸다.
    • 월드 좌표계에서의 좌표를 알고 싶다면 별도의 메서드를 사용해서 가져올 수 있다.
import * as THREE from 'three';

const object = new THREE.Mesh(new THREE.SphereGeometry(), new THREE.MeshPhongMaterial({ color: 0xff0000 }));
const objectWorldPosition = new THREE.Vector3();
object.getWorldPosition(objectWorldPosition);

console.log(objectWorldPosition);

 

부모 물체를 움직이거나 변형시키면 자식도 같이 바뀐다

 

 

 

Geometries (기하 구조)

+) 참고

 

 

three.js docs

 

threejs.org

  • Three.js에서 3D 물체를 추가하기 위해서는 3가지의 정보가 필요하다.
    1. Geometry: 물체를 구성하는데 필요한 꼭짓점, 면 정보 등을 가지고 있는 객체이다.
    2. Material: 물체의 외관을 정의한다. 예를 들어 색상 등이 해당된다.
    3. Mesh: 위의 두 정보값을 받는다. Geometry를 받고, 그것에 Material을 적용하는 역할을 한다.
  • 이렇게 해서 하나의 큐브를 정의하는 코드는 아래와 같다.
import * as THREE from 'three';

const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);

 

 

geometry

  • Geometry 란 3D 물체의 모습을 정의하는 역할을 한다.
    • 내부에 3D 물체의 정점 정보를 가짐으로써 물체가 어떻게 생겼는지를 정의한다.
    • 이제까지의 예제에서 사용해온 SphereGeometry, CubeGeometry 등은 모두 내부적으로 구와 육면체 형상을 만들기 위한 정점들의 위치나 인덱스 정보를 가지고 있다.
  • Geometry가 저장하고 있는 꼭짓점(정점)들의 정보는 geometry 속성을 통해 확인할 수 있다.
    • 콘솔로 확인해보면 attributes.position.array에 정점들의 정보가 저장된 것을 확인할 수 있다.
    • 이 정점 정보는 물체의 크기나 위치를 바꾸어도 변하지 않는다.
      → 바뀌는 크기나 위치 정보는 ‘변환 행렬(Transformation Matrix)’에 기록된다.
import * as THREE from 'three';

const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);

console.log(cube.geometry);

크기나 위치를 바꾸어도 정점 정보는 바뀌지 않는다

변환 행렬(Transformation Matrix): 벡터에 물체 이동, 회전, 크기 변환을 위해 곱해지는 행렬을 의미한다.
(참고: 위키피디아)

 

  • 모든 Geometry 객체는 BufferGeometry 클래스를 확장한다.
  • Geometry 객체의 생성자에 패러미터를 전달함으로써 초기값을 설정해주는 것이 가능하다.
import * as THREE from 'three';

/*
  아래의 생성자에 차례대로 너비, 높이, 깊이(Z축 값), widthSegments, heightSegments, depthSegments 를 할당한다.
  widthSegments, heightSegments, depthSegments는 각각 너비, 높이, 깊이가 어느 정도로 세분화 되어있는지를 수치로 나타낸 것이다.
*/
const boxGeometry = new THREE.BoxGeometry(1, 2, 3, 4, 5, 6);
const material = new THREE.MeshNormalMaterial({
  wireframe: true,
});

const cube = new THREE.Mesh(boxGeometry, material);

 

BufferGeometry.dispose(): 메모리에서 객체를 정리한다. 현재 Scene에 존재하는 geometry를 삭제하고 싶을 때 사용한다.

 

 

+) 변환 행렬 관련 문서

 

three.js docs

 

threejs.org

  • Three.js에서 Matrix4 를 통해 직접 변환 행렬을 조작할 수 있다.

 

Material

: 3D 물체의 외관을 결정한다.

  • 모든 Material 관련 객체는 Material 클래스를 확장한다.
    • 이 Material 클래스를 직접 사용할 수는 없다. 정확히는 사용하더라도 물체가 보이지 않는다.

 

속성

  아래에는 Material에 속하는 몇 가지 속성들을 나열한다.

  • opacity: 투명도.
  • transparent: 물체가 투명한지 아닌지를 정의한다. true일 경우 opacity 속성을 통해 세세한 투명도를 지정할 수 있다.
    • 반대로 말하자면, transparent 속성이 false이면 opacity를 조작해도 변화가 일어나지 않는다.
  • alphaTest: 투명도와 관련있는 값. 정확히 어떤 값인지 세세한 설명이 안 나와서 알아보길, 렌더링의 임계값을 뜻한다고 한다. 픽셀의 알파값과 이 값을 비교하여, 픽셀의 알파값이 더 작다면 렌더링을 하지 않는 것 같다.
    • 참고로 opacity가 이 값보다 작다면 material 자체가 아예 렌더링 되지 않는다.
  • side: 어떤 면을 렌더링할지를 결정하는 값이다. 디폴트 값은 FrontSide이다.
    • Three.js는 성능 향상을 위해 카메라에 보이는 면만을 그려낸다. 즉, 카메라에 보이지 않는 부분은 그려지지 않는다.
    • side에는 총 3가지 값이 있으며 이들은 상수로 미리 정의되어있다.
// Side값에 해당하는 상수들
THREE.FrontSide
THREE.BackSide
THREE.DoubleSide

 

side가 front인 상태에서 2번째 위치한 평면이 카메라를 돌렸을 때 보이지 않는 것을 알 수 있다

 

alphaTest, transparent 등의 값을 바꾸고 난 후에는 needsUpdate를 true로 바꾸어 변경 사항을 적용하는 과정이 필요하다. 이는 이러한 값들을 바꿀 시 새로운 shader를 생성하는 과정이 필요하기 때문이다.
(참고)

 

 

Common Materials

여기에서는 Three.js 에서 잘 쓰이는 4가지 Material에 대해 알아본다.

4가지 머터리얼의 모습

MeshBasicMaterial

  • 빛에 영향받지 않는 가장 기본적인 Material이다.
  • 음영이 표현되지 않는다.
  • 그래서인지 그려내는데는 가장 빠른 Material인듯.
  • 와이어프레임(뼈대만 보이는 것)은 지원하지만 Flat shading은 지원하지 않는다.

 

MeshNormalMaterial

  • 음영이 존재하는 Material이다.
  • 이 음영은 카메라의 방향에 의해 결정된다.
    • 따라서 빛이 결정되지 않은 상태에서 사용하기 편한 Material 이라고.
  • Flat shading을 지원한다.
실제 빛의 방향에 상관 없이 카메라의 각도에 따라 음영이 바뀐다.
(어느 각도에서든 우측 하단은 핑크색, 좌측 상단은 청록색 빛깔을 띄는 것을 알 수 있다)

 

 

MeshPhongMaterial & MeshStandardMaterial

  • 위 Material처럼 음영이 존재하는 Material. 이 Material들의 음영은 실제 Scene에 존재하는 Light의 영향을 받는다.
    • 따라서 Scene에 light가 존재하지 않으면 아예 보이지 않는다!

빛이 없어지자 두 Material이 보이지 않는다

  • Flat shading을 지원한다.
  • MeshPhongMaterial과 MeshStandardMaterial은 비슷해 보이지만 이런 차이가 있다고;
    • MeshPhongMaterial이 약간 더 빠르다.
    • MeshStandardMaterial는 더 일반적으로 잘 쓰이는 Material이다.
      • 위에서 언급한대로 두 Material 모두 빛이 필요하나, MeshStandardMaterial의 경우 Scene.environment에 설정한 텍스쳐가 적용이 된다. 이 경우 빛이 없어도 Mesh를 볼 수 있다.
      • 이미 텍스쳐가 적용되어있는 모델에 쓰기 유용하다.
import * as THREE from 'three';

const scene = new THREE.Scene();
scene.environment = new THREE.CubeTextureLoader().setPath('URL').load(['px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png']);

 

빛이 꺼지고 MeshPhongMaterial은 안 보이지만, environment가 설정된 상태에서 MeshStandardMaterial은 보인다

 

 

Scene.environment: Scene.background와 비슷하게 Texture를 설정할 수 있다. 이것에 설정한 텍스쳐는 Scene에 존재하는 모든 물리적 material의 environment map에 적용된다.
  • MeshPhongMaterial과 달리 MeshStandardMaterial는 ‘Physically Based Rendering(PBR)’이라는 것을 쓴다.
PBR이란, ‘물리 기반 렌더링’을 의미하며, 현실 세계에서 ‘광학(Optics)’을 이용해 빛과 물체의 표면을 렌더링 하는 방식을 의미한다.

Three.js 공식 문서에서 언급하길, PBR이 Unity나 Unreal 같은 3D 어플리케이션에서의 기준이 되고 있다고 하며, 대중적으로 쓰이는 방식이기에 Three.js 또한 이를 지원하는 것 같다.

 

 

 

+) Dat GUI 에 컬러 피커 넣기

  • GUI에 컨트롤러를 추가하는 add 메서드 대신 addColor 메서드를 사용하면 컬러 피커를 넣을 수 있다.
import { GUI } from 'dat.gui';

const data = { color: '#FFFFFF' };
const gui = new GUI();
gui.addColor(data, 'color');

Dat GUI에 컬러 피커가 추가된 모습


  • 유니티와 컴퓨터 그래픽스 강의의 덕분인가 비교적 익숙하게 짚고 넘어갈 수 있는 개념들이 나와서 다행인 것 같다... 

'공부 > etc' 카테고리의 다른 글

Three.js and TypeScript (7)  (2) 2024.11.20
Three.js and TypeScript (6)  (0) 2024.11.19
Electron + Vite + React 환경 세팅 살펴보기  (2) 2024.11.15
Three.js and TypeScript (4)  (0) 2024.11.14
Three.js and TypeScript (3)  (0) 2024.11.13