절차적 섬 생성 (III)
요약
절차적 섬 생성 시리즈의 세 번째 파트로, 페인트 맵을 기반으로 다중 스케일 노이즈 레이어를 적용하여 지형의 디테일을 높이는 방법을 다룹니다. 해안선에 고주파수 노이즈를 집중시키는 강화 기법과 산악 지형 구현을 위한 거리 필드(Distance Field) 계산 원리를 설명합니다.
핵심 포인트
- 페인트 맵을 통해 육지와 해양의 기본적인 분포와 흐름을 정의합니다.
- 다양한 주파수를 가진 Simplex 노이즈 레이어를 중첩하여 지형의 디테일을 생성합니다.
- 해안선 영역에만 고주파수 노이즈를 적용하여 내륙의 형태를 유지하면서 해안 디테일을 강화합니다.
- BFS를 활용한 거리 필드 계산을 통해 산봉우리 주변의 산악 지형을 구현합니다.
이 포스트는 페인트 맵 (paint map) 기초와 산맥 능선 시스템을 구축했던 Part II에서 이어집니다. 이제 상세한 노이즈 레이어 (noise layers), 거리에 기반한 산봉우리 (distance-based mountain peaks)를 추가하고, 블렌딩 (blending)을 수행하여 최종적인 지형 고도 (terrain elevation)를 생성할 것입니다.
페인트 맵 (Paint Map) (요약)
노이즈 레이어를 적용하기 전에, Part I에서 구축한 기초인 기본 육지/해양 분포를 정의하는 페인트 맵 (paint map)부터 시작합니다:
이 포스트 전반에 걸친 시각화를 위해 matplotlib의 magma 팔레트를 사용할 것이며, 해안선을 강조하기 위해 해양 영역을 인위적으로 어둡게 패치(patch)했습니다:
우리는 Delaunay 삼각형당 (각 삼각형의 무게 중심에서) 페인트 맵을 샘플링할 것임에 유의하십시오:
페인트 맵은 큰 흐름을 제공한다는 점을 기억하십시오. 양수 값은 육지, 음수 값은 해양을 나타내며 그 사이에는 부드러운 전환이 존재합니다. 이제 노이즈 레이어를 사용하여 이를 강화하고 현실적인 지형 디테일을 만들어 보겠습니다.
다중 스케일 노이즈 레이어 (Multi-Scale Noise Layers)
페인트 맵이 제공하는 큰 흐름 위에 서로 다른 주파수 (frequencies)를 가진 여러 옥타브 (octaves)의 Simplex 노이즈를 레이어링할 것입니다. 각 레이어는 최종 지형에 서로 다른 디테일 스케일을 기여합니다.
특히 @redblobgames의 mapgen4는 6개의 레이어를 사용합니다:
| 레이어 | 주파수 | 설명 |
|---|---|---|
| n₀ | 1x | 가장 낮은 주파수 |
| ... | ||
| 번호 매기기에서 간격이 있음에 유의하십시오 (n₃가 누락됨). 이는 우리가 사용하지 않는 주파수 8x에 해당합니다. |
해안 노이즈 강화 (Coastal Noise Enhancement)
mapgen4는 해안 노이즈 강화로 시작합니다. 이는 내륙 고도에는 영향을 주지 않으면서 해안선의 변화를 제어할 수 있게 해줍니다:
[e = \text{Part I의 페인트 맵}]
[e_{coast} = e + \alpha \cdot (1 - e^4) \cdot \left(n_4 + \frac{n_5}{2} + \frac{n_6}{4}\right)]
[(1 - e^4)] 항은 (e=0) (해안선)에서 정점을 찍고 (|e| > 0)일 때 급격히 감소하는 종 모양 곡선 (bell curve)을 생성합니다. 이는 우리의 세 가지 가장 높은 주파수 노이즈 레이어의 fBm (fractional Brownian motion) 유사 조합을 변조합니다.
여기서 중요한 것은 정확한 공식이나 진폭 (amplitudes)이 아니라, 핵심 원리입니다. 즉, 육지와 물이 만나는 지점에 구체적으로 고주파수 디테일 (high-frequency detail)을 적용하는 것입니다.
[e_{tmp} = \begin{cases} e & \text{if } e_{coast} > 0 \ e_{coast} & \text{if } e_{coast} \leq 0 \end{cases}]## 산악 거리 필드 (Mountain Distance Field)
산악 지형에는 특별한 전처리 (pre-processing)가 필요합니다. 제1부 (Part I)에서 기억하신다면, 씨앗 포인트 (seed points)의 무리 중에서 일부를 산봉우리로 태깅했습니다. 여기서는 모든 일반 씨앗 포인트로부터 가장 가까운 산봉우리 포인트까지의 *거리 필드 (distance field)*를 미리 계산할 것입니다.
우리는 BFS (breadth-first search, 너비 우선 탐색)를 사용하여 Delaunay 삼각측량 (Delaunay triangulation)의 메쉬 토폴로지 (mesh topology)를 통해 거리를 계산합니다. 즉, 유클리드 거리 (Euclidean distance)를 사용하지 않습니다. 이는 지형의 자연스러운 연결성을 따르는 더 유기적인 산악 형태를 만들어냅니다.
알고리즘은 산봉우리로부터 바깥쪽으로 퍼져 나갑니다:
- 산악 씨앗 포인트를 포함하는 삼각형에서 시작합니다 (거리 = 0)
- 인접한 삼각형을 방문하며, 거리를 무작위 양만큼 증가시킵니다
- 이 무작위성은 완벽한 원뿔 형태 대신 자연스러운 능선 패턴을 생성합니다
다음은 각 단계에서 거리 증가에 사용되는 마법의 공식입니다:
[\Delta = s \cdot (1 + j \cdot r)]여기서:
- (s) = 삼각형 사이의 간격 (설정된 Poisson disk separation 사용)
- (j) = 거칠기 (jaggedness) 파라미터 (0 = 실제 토폴로지 거리, 1 = 매우 불규칙함)
- (r \in [-1,1]) = 삼각형 분포 (triangular distribution)를 사용하는 무작위 요소
삼각형 분포 rand() - rand()는
가끔 발생하는 큰 변동은 허용하면서 값을 0 근처로 밀집시킵니다. 이는 균등 무작위성 (uniform randomness)보다 더 자연스럽게 보입니다.
인접 삼각형을 방문할 때 Fisher-Yates 셔플링 (shuffling)을 구현했습니다. 이웃을 고정된 순서로 처리하는 대신 (이는 방향성 편향을 생성할 수 있습니다), 매번 순서를 무작위로 섞습니다. 이를 통해 산맥의 능선이 예측 가능한 패턴을 따르지 않고 모든 방향으로 유기적으로 뻗어 나가도록 보장합니다.
이런 방식으로 거리를 계산한 후, 우리는 이를 정규화합니다 (예를 들어, 최대 거리로 나누어):
고도 블렌딩 (Elevation Blending)
최종 고도 (elevation)는 가중치 블렌딩 (weighted blending)을 통해 모든 구성 요소를 결합합니다:
[e_{final} = \begin{cases} \text{lerp}(e_{hill}, e_{mountain}, e_{coast}^2) & \text{if } e_{coast} > 0 \ e_{coast} \cdot (\rho + n_1) & \text{if } e_{coast} \leq 0 \end{cases}]
여기서:
- (e_{hill} = h \cdot \bigl(1 + \text{lerp}(n_2, n_4, \tfrac{1 + n_0}{2})\bigr)) => 노이즈로 변조된 높이를 가진 언덕 고도 (hill elevation)
- (e_{mountain} = 1 - \frac{\mu}{2^\sigma} \cdot d_m) => 거리 필드 (distance field)로부터의 산 고도 (mountain elevation)
이차식 블렌딩 가중치 (quadratic blend weight)는 해안 근처의 언덕에서부터 중간 고도의 혼합 지형을 거쳐 정점의 순수 산악 지형에 이르기까지 부드러운 전이를 생성합니다.
(수정 가능한) 파라미터 (parameters):
- (\alpha): 해안 노이즈 강도 (Coastal noise strength) (0.01)
- (h): 언덕 높이 스케일 (Hill height scale) (0.02)
- (\rho): 해양 깊이 승수 (Ocean depth multiplier) (1.5)
- (\mu): 산 사면 (Mountain slope) (17.6)
- (\sigma): 산의 날카로움 (Mountain sharpness) (9.8)
대화형 파라미터 탐색 (Interactive Parameter Exploration)
영역 (vs. 삼각형) 고도 (Region (vs. Triangle) Elevation)
지금까지 우리는 삼각형에 대한 고도를 계산했습니다. 하지만 (제1부에서 다룬) 보로노이 영역 (Voronoi regions) 또한 본 시리즈의 나머지 단계들을 위해 특정 고도가 필요합니다.
각 시드 포인트 (seed point)는 보로노이 영역을 정의하며, 여러 델로네 삼각형 (Delaunay triangles)의 정점 (vertex) 역할을 합니다. 보로노이 영역에 고도를 할당하기 위해, 해당 영역의 시드 포인트를 정점으로 공유하는 모든 삼각형의 고도를 평균냅니다.
다음 단계 (Next Steps)
고도 계산이 완료됨에 따라, 우리의 섬은 형태를 갖추었으나 물에 의해 깎여 나간 결정적인 특징들은 부족한 상태입니다. 제4부에서는 수문 순환 (hydrological cycle)을 시뮬레이션할 것입니다: 지형의 영향을 받는 강우 패턴, 정점에서 해양으로 흐르는 강, 그리고 침식 (erosion)에 의해 형성된 계곡 등이 포함됩니다.
유용한 리소스 (Valuable Resources)
- Terrain from Noise - 지형을 위한 노이즈 레이어링에 관한 Amit Patel의 Red Blob Games 가이드
- Polygonal Map Generation - 보로노이 기반 지형에 관한 Red Blob Games의 글 (mapgen4의 영감)
- Distance Fields for Terrain - 지형 생성에서 거리 필드를 사용하는 법에 관한 Red Blob Games의 글
AI 자동 생성 콘텐츠
본 콘텐츠는 HN Game Dev의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기