불규칙한 형태의 사실적인 포보스 만들기

0

지금까지 지구, 태양, 토성과 같은 천체를 거의 완전한 구형으로 표현했다. 이들은 매끄러운 구형을 이룰 만큼 충분히 큰 중력을 가지고 있다. 하지만 화성의 위성 중 하나인 포보스(Phobos)는 질량이 작아 울퉁불퉁한 표면을 매끄럽게 만들 만큼 중력이 강하지 않기 때문에 불규칙한 형태를 가진다. 이 글에서는 포보스의 울퉁불퉁한 형상을 렌더링하는 방법을 설명한다.

이 글은 태양계 시뮬레이터 시리즈의 일부다:

  1. Three.js 좌표계 기초
  2. Three.js PBR (물리 기반 렌더링) 재질 기초
  3. 사실적인 지구 만들기
  4. 사실적인 태양 만들기
  5. 고리가 있는 행성 만들기
  6. 불규칙한 형태의 위성 만들기
  7. 태양을 빛나게 하기
  8. 은하수 스카이박스 만들기
  9. 타원 궤도 계산하기

이전 글들1에서는 산, 계곡, 구름을 표현했지만, 이들은 구의 표면에 텍스처로 표현된 것이며, 그 그림자가 구를 복잡한 모델처럼 보이게 했다. 지구 표면의 고도 변화는 그 반지름에 비해 무시할 만큼 작기 때문에 이전 방법들로 충분히 표현할 수 있었다. 그러나 포보스의 고도 변화는 그 반지름에 비해 충분히 작지 않으므로, 지구와는 다른 geometry를 사용해야 한다. 아래 코드를 보자.

uniform sampler2D u_dispTexture;
uniform float u_dispScale;

varying vec2 vUv;
varying vec3 vNormal;
varying vec3 vPosition;
varying mat3 vTbn;

attribute vec4 tangent; // "geometry.computeTangents()" is needed.

void main() {
  vUv = uv;
  vNormal = normalize(mat3(modelMatrix) * normal);
  vPosition = mat3(modelMatrix) * position;

  float displacement = texture2D( u_dispTexture, vUv ).r;
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position + u_dispScale * (displacement - 0.5) * normal, 1.0);

  vec3 t = normalize(tangent.xyz);
  vec3 n = normalize(normal.xyz);
  vec3 b = normalize(cross(t, n));

  t = mat3(modelMatrix) * t;
  b = mat3(modelMatrix) * b;
  n = mat3(modelMatrix) * n;
  vTbn = mat3(t, b, n);
}

기존의 (지구, 태양, 토성 등의) 정점 셰이더 코드와 비교하면, 변경된 부분은 다음과 같다.

gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);

에서

float displacement = texture2D( u_dispTexture, vUv ).r;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position + u_dispScale * (displacement - 0.5) * normal, 1.0);

로 바뀌었다. 변위(displacement) 텍스처 맵의 값은 평균 반지름이 0인 정규화된 고도로 주어지며, 정점의 위치는 법선 벡터 방향으로 u_dispScale * (displacement - 0.5)만큼 확장된다. u_dispScale의 값은 직접 선택할 수 있다.

작은 스케일 큰 스케일