브라우저 오픈 월드를 위한 동적 LOD와 스트리밍 지형 생성
Perlin 노이즈를 입힌 하이트맵은 절차적 지형의 기본 출발점입니다. fBm을 몇 옥타브 쌓고 컬러 그라디언트를 적용하면 지형처럼 보이는 무언가가 나옵니다. 거의 모든 튜토리얼이 여기서 끝납니다. 하지만 진짜 풍경은 쌓아 올린 노이즈처럼 보이지 않습니다. 진짜 풍경에는 물이 깎아낸 강 계곡, 응력 균열이 빚어낸 절벽면, 수백만 년의 침식이 만든 동굴과 아치가 있습니다. 또한 지오메트리를 빚어낸 바로 그 물리 과정에서 함께 나오는 상관된 텍스처(평지의 풀, 가파른 경사의 바위, 수목한계선 위의 눈)도 있습니다.
이 가이드는 노이즈 다음에 오는 것을 다룹니다. 물리에 기반한 생성 방법, 동굴과 오버행을 다루는 볼류메트릭 표현, 디퓨전 기반 뉴럴 지형 합성, 그리고 이 모든 것을 브라우저 탭에서 60fps로 렌더링하는 데 필요한 GPU 구동 LOD와 스트리밍 파이프라인입니다.
여기 나오는 모든 내용은 우리의 구체적인 제약을 겨냥합니다. WebGL 2 / WebGPU에서 동작하고, 네트워크로 스트리밍되며, 크리에이터가 편집할 수 있는 멀티플레이어 오픈 월드입니다.
하이트맵으로 충분하지 않은 이유
하이트맵은 격자점마다 높이 값 하나를 저장합니다. 2D 함수입니다. (x, z)가 주어지면 y를 돌려줍니다. 이 표현은 작고, GPU 친화적이며, 렌더링이 빠릅니다. 하지만 크리에이터 월드에 중요한 근본적 한계가 있습니다.
동굴이나 오버행이 없습니다. 하이트맵은 한 점이 서로 다른 두 높이를 갖는 지형을 표현할 수 없습니다. 동굴, 아치, 절벽 오버행, 터널, 떠 있는 섬은 모두 불가능합니다. Minecraft, No Man's Sky, Deep Rock Galactic이 모두 이 때문에 볼류메트릭 지형을 필요로 합니다.
수직 피처가 없습니다. 하이트맵에서 수직 절벽면은 거의 무한대에 가까운 경사라서 극단적인 텍스처 늘어짐과 충돌 아티팩트를 만듭니다. 진짜 절벽에는 하이트맵이 표현할 수 없는 수평 피처(턱, 틈새)가 있습니다.
노이즈는 노이즈처럼 보입니다. fBm을 8옥타브 쓰고 도메인 워핑을 더해도 지형에는 인공적인 느낌이 남습니다. 진짜 지질의 방향성 구조, 즉 능선, 배수망, 퇴적층, 구조 습곡이 빠져 있습니다. 이런 패턴은 물리 과정에서 나오는 것이지 노이즈 함수에서 나오는 것이 아닙니다.
크리에이터 편집이 제한됩니다. 크리에이터가 높이만 수정할 수 있다면 터널을 파거나, 동굴을 만들거나, 지하 공간을 지을 수 없습니다. 크리에이터가 진짜로 빚을 수 있는 월드라면 지형 표현이 더하기뿐 아니라 빼기도 지원해야 합니다.
해결책은 하이트맵을 완전히 버리는 것이 아닙니다. 단순한 표면인 90%의 지형에는 하이트맵이 여전히 최선의 표현입니다. 해결책은 하이브리드 방식입니다. 하이트맵 기반 지형에, 복잡한 지오메트리가 필요한 곳에는 볼류메트릭 오버레이를 얹고, 사실적인 지형을 위해 물리적으로 정확한 생성을 쓰고, 노이즈로는 얻을 수 없는 다양성을 위해 뉴럴 합성을 더합니다.
빠른 답: 우리가 실제로 만들 것
깊이 들어가기 전에 의사결정 프레임워크를 먼저 제시합니다. 글의 나머지는 각 부분을 설명합니다.
지형 표현
하이브리드 하이트맵 + SDF 시스템을 씁니다. 하이트맵은 월드 전체를 덮습니다(싸고, 작고, 검증됨). SDF 볼륨은 동굴, 오버행, 또는 크리에이터가 깎아낸 피처가 필요한 곳에만 존재합니다(아마 청크의 5-10%). 이렇게 하면 월드의 90%는 하이트맵 비용으로 유지하면서, 필요한 곳에서는 임의의 지오메트리를 지원합니다.
생성 파이프라인
서버 측에서 연쇄 프로세스로 실행합니다.
- Terrain Diffusion(또는 텍스트 프롬프트용 MESA)이 시드로부터 기반 하이트맵을 생성합니다. 노이즈를 실제 고도 데이터로 학습한 지질적으로 사실적인 지형으로 대체합니다.
- 해석적 침식(stream power law)이 강 네트워크와 능선으로 하이트맵을 밀리초 단위로 다듬습니다.
- TerraFusion 또는 Geodiffussr가 하이트맵으로부터 상관된 텍스처를 생성합니다(또는 WebGL 2 폴백에서는 절차적 경사/고도 규칙 사용).
- 생태계 시뮬레이션이 식생 밀도 맵을 만듭니다.
- Arenite 스타일 침식이 지형이 요구하는 곳에 절벽면, 아치, 동굴을 위한 SDF 볼륨을 생성합니다.
- 청크로 나누고, 압축하고, CDN에 업로드합니다. 평균 청크: 2-8 KB. 볼류메트릭 데이터가 있는 복잡한 청크: 20-100 KB.
크리에이터는 파라미터를 조정하거나("더 습하게", "더 산악으로", "동굴 추가"), 의도를 스케치하거나, 브러시와 SDF 도구로 직접 조각하며 이 파이프라인과 상호작용합니다.
LOD 전략
| 브라우저 역량 | 하이트맵 LOD | 볼류메트릭 LOD | 식생 LOD |
|---|---|---|---|
| WebGPU | GPU 구동 쿼드트리(CDLOD) + compute 컬링 + 간접 드로우 | 다해상도 SDF + compute marching cubes + Transvoxel | ComputeInstanceCulling + 간접 드로우 |
| WebGL 2 | CPU 측 링 업데이트가 있는 geometry clipmap | 2-3개 LOD 레벨로 미리 생성한 메시, 캐시됨 | CPU 프러스텀 컬링, InstancedMesh |
두 경로 모두 팝 없는 전환을 위해 버텍스 셰이더에서 geomorphing을 씁니다. 둘 다 멀리 있는 식생에는 빌보드 임포스터를 씁니다. WebGPU 경로가 더 빠르지만(지형 예산 3.5ms) WebGL 2 경로도 쓸 만합니다(6.5ms).
스트리밍
점진적 로딩: 지형 지오메트리 먼저(<100ms), 텍스처 다음(<300ms), 식생 셋째(<1s), 볼류메트릭 데이터 넷째(<3s). 플레이어 속도를 기준으로 미리 가져옵니다. 메모리 예산: 지형 전체 256 MB.
편집
표면 조각을 위한 하이트맵 브러시(올리기, 내리기, 부드럽게, 침식). 볼류메트릭 편집을 위한 SDF 프리미티브(동굴 깎기, 아치 추가). 둘 다 로컬에서는 즉시 반영되고, 100-300ms 안에 서버로 동기화되며, 델타 업데이트로 다른 플레이어에게 전파됩니다.
무엇을 어떤 순서로 만들까
1-2개월차: geometry clipmap이 적용된 하이트맵 지형. WebGL 2만. CDN에서 스트리밍. 절차적 경사/고도 머티리얼. 이렇게 하면 모든 브라우저에서 지형이 화면에 나옵니다. 생성에는 노이즈 + 해석적 침식을 씁니다(Terrain Diffusion은 나중에 해도 됨).
3-4개월차: 식생과 대기. 밀도 맵에서 나오는 GPU 인스턴스 풀과 나무. 낮/밤 사이클이 있는 절차적 하늘. 대기 안개. 캐스케이드 섀도 맵. 월드가 하나의 장소처럼 느껴지기 시작합니다.
5-6개월차: 크리에이터 편집. 하이트맵 브러시 도구. 멀티플레이어 지형 편집을 위한 델타 기반 동기화. 동시 편집을 위한 공간 잠금. 이때 크리에이터가 월드를 빚기 시작합니다.
7-9개월차: 볼류메트릭 지형과 WebGPU 경로. 동굴과 오버행을 위한 SDF 오버레이. WebGPU compute의 marching cubes. LOD 경계를 위한 Transvoxel. SDF 조각 도구. 이것으로 완전한 창작 도구 모음이 열립니다.
10-12개월차: 뉴럴 생성과 다듬기. 기반 하이트맵을 위한 Terrain Diffusion 또는 MESA. 텍스처를 위한 TerraFusion/Geodiffussr. 마이크로 디테일을 위한 phasor noise. 반복 방지를 위한 hex-tiling. 가상 텍스처링. 라플라시안 블렌딩. 지형이 프로덕션 품질에 도달합니다.
이 순서대로면 2개월 후에는 플레이 가능한 것이, 4개월 후에는 아름다운 것이, 6개월 후에는 편집 가능한 것이, 12개월 후에는 최신 수준의 것이 존재하게 됩니다.
글의 나머지는 각 결정 뒤에 있는 리서치입니다.
하이트맵을 넘어선 지형 표현
부호 있는 거리장(SDF)
부호 있는 거리장은 3D 공간의 모든 점에서 가장 가까운 표면까지의 거리를 저장합니다. 양수는 바깥, 음수는 안쪽이며, 영교차점이 곧 표면 자체입니다. SDF는 동굴, 아치, 떠 있는 지오메트리를 포함한 임의의 3D 형상을 표현합니다.
SDF를 메시로 렌더링하려면 marching cubes(또는 그 변형)를 실행해 영교차점을 삼각형으로 추출합니다. 메시 해상도는 격자 해상도에 따라 달라집니다. 256x256x256 SDF 격자는 1미터 해상도에서 대략 청크 하나 분량의 지형을 만듭니다.
브라우저 구현: WebGPU marching cubes는 compute 셰이더를 통해 전적으로 GPU에서 돌아갑니다. Will Usher의 webgpu-marching-cubes 구현은 브라우저에서 256^3 격자를 실시간으로 처리하며 네이티브 속도를 냅니다. 알고리즘은 당황스러울 만큼 병렬적이라(각 셀이 독립적으로 처리됨) GPU compute에 이상적입니다.
@compute @workgroup_size(4, 4, 4)
fn marchingCubes(@builtin(global_invocation_id) id: vec3<u32>) {
let sdfValues = sampleSDF(id);
let caseIndex = classifyCell(sdfValues);
if (caseIndex == 0u || caseIndex == 255u) { return; }
let triangles = lookupTriangulation(caseIndex);
let vertices = interpolateEdges(sdfValues, triangles);
appendToMeshBuffer(vertices);
}저장 비용: 8비트 양자화 정밀도의 256^3 SDF는 압축하지 않으면 16 MB입니다. 하지만 볼륨 대부분은 비어 있습니다(표면에서 멀리 떨어져 있음). 런렝스 인코딩이나 희소 옥트리 저장을 쓰면 보통 청크당 100-500 KB로 줄어드는데, 이는 하이트맵 지형과 비슷합니다.
편집: SDF 지형은 본질적으로 편집 가능합니다. 머티리얼을 더하는 것은 거리장에 대한 min() 연산입니다. 머티리얼을 제거하는 것(파기)은 부호를 뒤집은 형상에 대한 max()입니다. 형상 사이의 부드러운 블렌딩은 smoothMin()을 씁니다. 이 연산들은 compute 셰이더에서 인터랙티브한 속도로 돌아갑니다.
Dual Contouring
Marching cubes는 정점을 격자 모서리에 놓아 부드러운 표면을 만들지만 날카로운 피처(절벽 모서리, 바위 모서리)를 잃습니다. Dual contouring은 셀마다 그 셀 안의 표면을 가장 잘 대표하는 위치에 정점 하나를 놓아 날카로운 모서리와 코너를 보존합니다.
이 알고리즘은 각 격자점에서 거리장 값과 표면 법선(SDF의 그래디언트)을 모두 필요로 합니다. 셀마다 작은 최소제곱 문제를 풀어 최적 정점 위치를 찾습니다. 결과는 부드러운 지형과 날카로운 암석 피처를 모두 담아내는 메시입니다.
Neural Dual Contouring(Chen et al., 2022, arXiv:2202.01999)은 최소제곱 솔버를 최적 정점 위치와 모서리 교차점을 예측하는 신경망으로 대체합니다. 특히 복잡한 자연 암석 형성에서 더 나은 표면 재구성 정확도와 피처 보존을 달성합니다.
Transvoxel 알고리즘
볼류메트릭 지형에서 가장 어려운 문제는 메시 생성이 아닙니다. LOD 전환입니다. 고해상도 청크가 저해상도 청크 옆에 놓이면 경계에서 메시가 맞지 않아 눈에 보이는 균열이 생깁니다.
Eric Lengyel이 설계한 Transvoxel 알고리즘(transvoxel.org)은 해상도 간 경계에 특수 전환 셀을 끼워 넣어 이를 해결합니다. 이 셀들은 양쪽을 정확히 맞추는 추가 삼각형으로 해상도 차이를 잇습니다. 알고리즘은 복잡한 경계 문제를 73개의 등가 클래스로 줄입니다(무차별 대입 방식의 약 120만 가지와 대조됨).
Transvoxel은 복셀 데이터가 동적으로 바뀌는(크리에이터 편집, 침식, 채굴) 실시간 응용을 위해 특별히 설계되었습니다. 특허가 없고 출시된 게임(Space Engineers, Astroneer)에서 쓰였습니다. 편집 가능한 볼류메트릭 지형이 있는 브라우저 월드에서 Transvoxel이 곧 LOD 해법입니다.
하이브리드: 하이트맵 기반 + 볼류메트릭 오버레이
브라우저 오픈 월드를 위한 실용적인 방식은 레이어로 나눈 시스템입니다.
레이어 1: 하이트맵 지형이 월드 전체를 덮습니다. 완만한 언덕, 계곡, 산을 위한 싸고 작은 표현입니다. 청크당 작은 하이트맵 패치로 스트리밍됩니다(각각 2-4 KB). 렌더링은 GPU 비용이 일정한 geometry clipmap을 씁니다.
레이어 2: 볼류메트릭 오버레이는 복잡한 지오메트리가 필요한 청크에만 존재합니다. 동굴, 절벽면, 아치, 크리에이터가 깎은 터널, 지하 공간이 희소 SDF 볼륨으로 저장됩니다. 볼류메트릭 데이터가 있는 청크만 SDF 저장과 marching cubes 비용을 치릅니다.
레이어 3: 크리에이터 수정은 기반 레이어 위의 SDF 편집으로 저장됩니다. 터널을 파는 크리에이터는 그 터널의 SDF 형상을 저장합니다. 렌더링 시스템은 하이트맵 표면을 볼류메트릭 빼기/더하기와 합쳐 최종 메시를 만듭니다.
이 하이브리드는 평지에는 거의 비용이 들지 않고(하이트맵만), 복잡함이 존재하는 곳에서만 확장됩니다. 전형적인 월드에서는 아마 청크의 5-10%만 볼류메트릭 데이터가 필요합니다.
물리적으로 정확한 지형 생성
노이즈는 무작위 지형을 만듭니다. 물리는 사실적인 지형을 만듭니다. 차이는 눈에 보입니다. 노이즈 지형은 구조가 없지만(어디나 무작위로 울퉁불퉁함), 물리 지형에는 침식과 지각 운동에서 나오는 강 네트워크, 능선, 충적 선상지, 절벽 띠가 있습니다.
수력 침식: 기초
물은 경사를 따라 흐르고, 퇴적물을 들어 올리고, 느려지면 그것을 내려놓습니다. 수백만 가상 년에 걸쳐 시뮬레이션되는 이 단일 과정이 특징 없는 노이즈를 알아볼 수 있는 지질 피처가 있는 지형으로 바꿉니다.
입자 기반 방식은 하이트맵에 시뮬레이션된 빗방울을 떨어뜨립니다. 각 방울은 경사를 따라 흐르며(그래디언트를 따라), 속도와 경사에 따라 물질을 침식하고, 퇴적물을 용해 부하로 운반하며, 속도가 줄거나 용량을 초과하면 퇴적물을 내려놓습니다. 20만-50만 개의 입자가 지난 뒤 지형은 다음을 발달시킵니다.
- 최대 수류 경로를 따르는 강 계곡
- 배수 분지를 나누는 능선
- 가파른 계곡이 평원으로 열리는 곳의 충적 선상지
- 산악 지형의 V자 계곡, 빙하 지형의 U자 계곡
GPU 구현: 입자 시뮬레이션은 병렬화할 수 있습니다. 각 입자는 독립적입니다(근사가 입자 간 상호작용을 무시하는데, 침식에는 문제없음). WebGPU compute 셰이더는 60fps에서 프레임당 1만 개의 입자를 처리해, 실제 시간으로 약 3초 만에 20만 개를 완료합니다.
Sebastian Lague의 오픈소스 구현(GitHub)이 표준 출발점입니다. C#에서 단일 스레드로 돌아가며 1024x1024 하이트맵을 몇 초 만에 처리합니다. GPU 버전은 50-100배 빠릅니다.
열 침식
물만이 침식력은 아닙니다. 온도 변화는 암석을 갈라지고 부서지게 합니다(열 풍화). 두 지형 점 사이의 경사가 물질의 안식각을 넘으면 물질이 높은 점에서 낮은 점으로 떨어집니다. 이것은 다음을 만듭니다.
- 절벽 밑의 테일러스 사면(떨어진 바위 더미)
- 시간이 지나며 부드러워진 능선
- 물질에 따른 단면(단단한 암석은 가파른 경사를 유지하고, 무른 흙은 완만한 각도로 무너짐)
열 침식은 수력 침식보다 단순합니다. 국소 연산입니다. 각 셀마다 이웃과의 높이 차이를 비교합니다. 경사가 임계값을 넘으면 물질을 경사 아래로 옮깁니다. 반복마다 단일 compute 셰이더 패스로 돌아가며 50-100회 반복 만에 수렴합니다.
수력과 열 침식을 합치면 어느 한쪽만 쓸 때보다 훨씬 자연스러워 보이는 지형이 나옵니다. 물은 계곡을 깎고, 열 침식은 그 사이의 능선을 부드럽게 하며 계곡 바닥을 잔해로 채웁니다.
Stream Power Law: 해석적 침식
최근 연구는 입자 기반 시뮬레이션의 대안을 제시합니다. stream power law(침식률을 배수 면적과 경사에 연결하는 지형학 방정식)는 반복적으로 시뮬레이션하는 대신 해석적으로 풀 수 있습니다.
Cordonnier et al. (2024, HAL)은 해석적 stream power law를 산사태 및 사면 확산 과정과 결합합니다. 그 결과는 물리에 기반하면서도 시간 시뮬레이션이 아니라 수학 함수로 돌아가는 지형 생성입니다. 노이즈 기반 하이트맵과 파라미터(강수율, 암석 경도, 지각 융기율)를 입력하면 밀리초 단위로 침식된 지형을 얻습니다.
이 해석적 방식은 브라우저 월드에 이상적입니다. 반복적으로가 아니라 지형 생성 중 서버 측에서 한 번 돌기 때문입니다. 파라미터는 크리에이터가 조정할 수 있습니다("이 지역을 더 산악으로"는 융기율을 올리고, "더 습하게"는 강수를 늘려 계곡을 깊게 합니다).
Arenite: 다중 물리 침식 (SIGGRAPH 2025)
Arenite(프로젝트 페이지)는 단순한 초기 조건으로부터 아치, 알코브, 후두, 뷰트를 생성하는 물리 기반 사암 시뮬레이터입니다. 사용자가 침식성 맵(무른 암석 대 단단한 암석 층)과 식생을 칠하면, 시스템이 다음을 시뮬레이션합니다.
- 암석 기둥을 통한 응력 분포
- 노출된 무른 물질을 우선 제거하는 풍식
- 수류로 인한 하천 침식
- 새 형성을 만드는 입자 퇴적
GPU 구현은 데스크톱 GPU에서 복잡한 형성을 5분 이내에 처리합니다. 실시간 브라우저 사용에는 너무 느리지만 서버 측 생성에는 충분히 빠릅니다. 크리에이터가 무른/단단한 암석 층이 있는 절벽면을 정의하면 몇 분 안에 사실적인 아치 형성을 얻을 수 있습니다.
출력은 3D 복셀 필드이며, 이는 우리의 SDF/marching cubes 파이프라인에 바로 들어맞습니다.
표현을 넘나드는 유연한 침식
IRIT-STORM의 2024년 논문("Flexible Terrain Erosion," Springer)은 실용적인 문제를 해결합니다. 대부분의 침식 방법은 하이트필드에서만 동작합니다. 지형이 복셀, SDF, 또는 층상 머티리얼을 쓴다면 각각에 별도의 침식 코드가 필요합니다.
유연한 침식 방법은 침식을 두 개의 독립적인 과정으로 분해합니다. 지형 변경(표면에서 물질 제거)과 물질 운반(기본 물리에 따라 움직이는 입자로 퇴적물 이동)입니다. 각 입자는 크기, 밀도, 반발 계수, 퇴적 용량을 설정할 수 있습니다. 선택적 벡터 필드가 사실적인 유체 역학을 위해 입자 운동을 제어합니다.
입자가 통합된 물질 변경 인터페이스를 통해 지형과 상호작용하기 때문에, 같은 시뮬레이션이 하이트필드, 복셀 격자, 음함수 표면, 층상 머티리얼 스택에서 모두 동작합니다. 우리의 하이브리드 지형(하이트맵 기반 + SDF 오버레이)에서는 침식 시스템 하나가 두 표현을 모두 처리한다는 뜻입니다. 입자 시뮬레이션은 GPU에서 병렬로 돌아갑니다.
강 네트워크와 배수 분지
침식은 강을 깎지만, 설득력 있는 강 네트워크를 생성하려면 물을 경사 아래로 흘리는 것 이상이 필요합니다. 두 가지 접근이 더 나은 결과를 냅니다.
배수 우선 생성(Amit Patel, Red Blob Games, 프로젝트)은 고도를 배정하기 전에 강 네트워크를 구축합니다. 그래프(보로노이 또는 삼각형 메시)로 시작합니다. 모서리를 능선(흐름 없음), 입구(물이 흘러 들어옴), 출구(물이 흘러 나감)로 분류합니다. 이렇게 하면 작은 지류가 큰 수로로 모이는 사실적인 배수 위계가 만들어지며, 서로 다른 강 유형에 대한 Rosgen 분류 체계(평지의 망상 하도, 산악의 좁은 협곡)를 따릅니다.
흐름 누적은 각 지형 셀을 얼마나 많은 물이 지나가는지 추적합니다. 시뮬레이션된 비를 고르게 떨어뜨리고, 경사 아래로 흘리고, 셀당 방문 횟수를 셉니다. 누적이 높은 셀은 강 하도입니다. 누적이 중간인 셀은 계절성 개울입니다. 누적 맵은 침식 강도(물이 많을수록 침식이 많음)와 식생 분포(강둑이 더 습해 다른 식물 종을 지지함)도 좌우합니다.
크리에이터 월드에서는 강 네트워크가 지형 생성 중 서버 측에서 생성되어 청크당 2D 흐름 방향 맵과 물 누적 맵으로 저장됩니다. 브라우저 클라이언트는 이 맵들을 써서 물 표면(강 하도에서 올바른 높이의 평평한 평면)을 렌더링하고 식생 분포(물가가 더 무성함)를 좌우합니다.
해안과 해안선 생성
해안선은 지형이 물과 만나는 곳이며, 표준 침식이 만들지 못하는 특징적인 피처가 있습니다. 해식애, 해변 퇴적물, 갯벌, 시 스택, 파식대입니다.
NEWTS1.0 (2024, MIT)은 두 가지 침식 메커니즘으로 암석 해안선의 진화를 모델링합니다. 균일 후퇴(일정한 침식률)와 파도 구동 침식(취송 거리와 입사 파각의 함수로서의 침식률)입니다. 모델은 수천 시뮬레이션 년에 걸쳐 돌아가며 실제 해안 지형과 일치하는 곶, 만, 시 스택, 아치를 만듭니다.
브라우저 월드에서는 해안 피처가 월드 생성 중 미리 생성됩니다. 파라미터(우세 파향, 해안을 따른 암석 경도 변화)로 크리에이터가 자기 해안선의 성격을 제어합니다. "노르웨이 피오르드" 설정은 가파른 입구를 만듭니다. "열대 환초" 설정은 석호가 있는 낮은 모래 해안을 만듭니다.
동굴과 지하 생성
동굴은 완전한 볼류메트릭 지형(SDF 또는 복셀)을 필요로 합니다. 하이트맵은 폐쇄 공간을 표현할 수 없기 때문입니다. 생성 방식은 다음과 같습니다.
3D 노이즈 임계화가 가장 단순한 방법입니다. 복셀마다 3D Perlin 또는 심플렉스 노이즈를 샘플링합니다. 임계값 아래는 고체, 위는 빈 공간입니다. 임계값과 노이즈 파라미터를 조정해 터널 직경, 연결성, 챔버 크기를 제어합니다. 이것은 Minecraft를 연상시키는 유기적이고 벌레 굴 같은 동굴 시스템을 만듭니다.
PLUME (Procedural Layer Underground Modeling Engine) (2024, arXiv:2508.20926)은 층상 절차적 규칙을 써서 사실적인 동굴과 용암 동굴 환경을 생성합니다. 원래 우주 탐사 연구를 위해(화성 용암 동굴 시뮬레이션) 만들어졌으며, 종유석, 기둥, 챔버 시스템이 있는 지질적으로 그럴듯한 지하 구조를 만듭니다.
메타볼 조각이 적용된 L-system 터널은 L-system 문법으로 지형을 통과하는 분기 터널 경로를 키운 뒤, 메타볼 음함수 표면으로 실제 터널 지오메트리를 깎습니다. 메타볼은 부드럽고 둥근 동굴 벽을 만듭니다. 서로 다른 파라미터로 여러 패스를 돌리면 주 통로, 측면 챔버, 좁은 연결 터널이 생깁니다.
크리에이터 월드에서는 동굴 생성이 SDF 오버레이 시스템에 연결됩니다. 기반 지형은 하이트맵입니다(동굴 없음). 청크에 동굴이 필요할 때(절차적 생성이든 크리에이터 설계든) 기반 지형에서 동굴 지오메트리를 빼는 SDF 볼륨이 생성됩니다. marching cubes 파이프라인이 합쳐진 표면을 렌더링합니다.
물리 과정으로서의 식생
게임의 식생은 보통 "2000m 아래는 풀, 1500m 아래는 나무, 3000m 위는 눈" 같은 규칙으로 절차적으로 배치됩니다. 이건 빠르지만 균일하고 비현실적인 분포를 만듭니다.
물리에 기반한 식생 시뮬레이션은 각 식물을 자원(빛, 물, 토양 양분)을 두고 경쟁하는 것으로 모델링합니다. 시뮬레이션은 이렇습니다.
- 씨앗이 지형 전체에 뿌려집니다
- 각 식물은 가용 자원에 따라 자랍니다(물은 수력 침식 시뮬레이션에서 흐르고, 햇빛은 경사와 향에 달려 있으며, 토심은 침식 이력에 달려 있음)
- 식물이 경쟁합니다. 나무가 풀을 그늘로 덮고, 빽빽한 수관이 새 묘목을 막습니다
- 시뮬레이션 시간이 지나며 생물군계가 자연스럽게 나타납니다. 물이 있는 계곡에는 숲, 바람 부는 능선에는 성긴 식생, 물이 고이는 곳에는 습지
Deussen et al.의 생태계 시뮬레이션(논문)은 실세계 생태 패턴과 일치하는 숲 분포를 생성합니다. 시뮬레이션은 2D 격자에서 돌아가며(지형 청크당 셀 하나) 렌더링 시스템이 GPU 인스턴스 식생 배치에 쓰는 밀도 맵과 종 배정을 만듭니다.
브라우저 월드에서는 식생 시뮬레이션이 월드 생성 중 한 번(서버 측) 돌아갑니다. 출력은 청크당 밀도 맵 세트입니다. 나무 밀도, 풀 밀도, 꽃 밀도, 바위 잔해 밀도. 브라우저 클라이언트는 이 맵들을 GPU 인스턴싱과 함께 써서 런타임에 식생을 뿌립니다.
디퓨전 기반 지형 합성
이 분야는 여기서 가장 빠르게 움직이고 있습니다. 디퓨전 모델(이미지용 Stable Diffusion 뒤에 있는 바로 그 기술)이 지형 생성에 적용되고 있으며, 결과는 노이즈 기반 방법보다 상당히 더 사실적입니다.
Terrain Diffusion: Perlin 노이즈의 후계자
Terrain Diffusion (Goslin, 2025, arXiv:2512.08309, 프로젝트 페이지)은 1985년 Perlin 노이즈 이래 절차적 지형 생성에서 가장 의미 있는 진전입니다. 이 연구는 이후 SIGGRAPH 2026에 채택되었고, 정식 arXiv 제목은 이제 "InfiniteDiffusion: Bridging Learned Fidelity and Procedural Utility for Open-World Terrain Generation"입니다. InfiniteDiffusion 알고리즘과 Terrain Diffusion 프레임워크는 같은 논문의 두 절반입니다.
핵심 혁신은 InfiniteDiffusion으로, 디퓨전 샘플링을 무한 도메인에 맞게 재정식화한 알고리즘입니다. 전통적인 디퓨전 모델은 고정 크기 출력(예: 512x512 하이트맵)을 생성합니다. InfiniteDiffusion은 다음을 갖춘 무한 범위의 지형을 생성합니다.
- 시드 일관성: 같은 시드는 항상 같은 지형을 만듭니다. Perlin 노이즈처럼요.
- 상수 시간 랜덤 액세스: 이웃 영역을 먼저 생성하지 않고도 임의의 점에서 높이를 질의할 수 있습니다.
- 경계 아티팩트 없음: 눈에 보이는 이음매나 반복 없는 무한 생성.
이 시스템은 디퓨전 모델의 위계적 스택을 씁니다. 최상위 레벨은 행성 규모 피처(대륙, 산맥)를 잡아냅니다. 이후 각 레벨은 더 미세한 디테일(개별 봉우리, 계곡, 소규모 거칠기)을 더합니다. 작은 라플라시안 인코딩이 해수면에서 히말라야 봉우리에 이르는 거대한 동적 범위에 걸쳐 출력을 안정화합니다.
성능: 생성이 실시간 탐험과 보조를 맞춥니다. 논문은 궤도 속도(약 7,700 m/s)라는 이론적 극단에서도 지형 합성이 소비자용 GPU에서 이동보다 9배 빠르게 돌아간다고 보고합니다. 프로젝트에는 실시간 지형 합성을 시연하는 Minecraft 통합이 포함됩니다.
이것이 우리에게 중요한 이유: Terrain Diffusion은 실세계 고도 데이터(지구의 실제 지형)로 학습한 풍경을 만듭니다. 출력에는 손으로 조정한 노이즈 파라미터가 아니라 학습 데이터에서 나오는 강 네트워크, 산맥, 해안 피처, 고원 구조가 있습니다. 크리에이터가 "스코틀랜드 고지대 같은 지형을 생성해"라고 말하면 디퓨전 모델이 올바른 지질 성격을 가진 무언가를 만들어 냅니다.
모델은 월드 생성 중 서버 측에서 돌아갑니다. 출력은 다른 지형 데이터처럼 브라우저로 스트리밍되는 표준 하이트맵입니다. 생성 방법은 클라이언트에게 보이지 않습니다.
TerraFusion: 지오메트리와 텍스처 동시 생성
TerraFusion (2025, arXiv:2505.04050)은 하이트맵과 지형 텍스처를 동시에 생성하며 한 걸음 더 나아갑니다. 핵심 통찰은 지형 지오메트리와 표면 외형이 상관되어 있다는 것입니다(강바닥은 모래, 절벽면은 바위, 평지는 풀). 따로 생성하면 불일치가 생깁니다.
TerraFusion은 하이트맵과 텍스처용 별도 VAE를 가진 잠재 디퓨전 모델을 써서 그것들의 결합 분포를 모델링하도록 학습됩니다. 시스템은 다음을 지원합니다.
- 무조건 생성: 일치하는 텍스처가 있는 무작위의 그럴듯한 지형
- 스케치 조건 생성: 크리에이터가 대략적인 맵(여기 계곡, 저기 능선, 이 가장자리를 따라 절벽)을 그리면 모델이 스케치에 맞는 상세한 지오메트리와 텍스처를 생성
크리에이터 월드에서 이건 강력합니다. 크리에이터가 자기 부지의 전반적 배치를 스케치하면 시스템이 적절한 표면 머티리얼이 있는 지질적으로 그럴듯한 지형을 채워 넣습니다. 하이트맵 페인팅도, 텍스처 스플래팅도, 수동 머티리얼 배정도 없습니다.
MESA: 텍스트에서 지형으로
MESA (2025, arXiv:2504.07210, CVPR 2025 Workshop)는 텍스트 설명으로부터 지형을 생성합니다. Copernicus 프로그램의 글로벌 원격탐사 데이터로 학습되어 모든 유형의 육상 풍경에 노출되어 있습니다.
"가파른 화강암 벽을 가진 피오르드가 바위투성이 해안으로 열린다" 같은 프롬프트는 적절한 지질 구조를 가진 하이트맵을 만듭니다. "완만한 언덕과 넓은 강 계곡이 있는 굽이치는 농지"는 완전히 다른 것을 만듭니다.
MESA는 위성 이미지를 전 세계 디지털 고도 모델과 짝짓는 Major TOM Core-DEM 확장 데이터셋을 도입합니다. 이 학습 데이터는 모델에게 실제 지형이 모든 규모와 모든 기후대에서 어떻게 보이는지에 대한 이해를 줍니다.
Geodiffussr: 텍스트로 안내하는 지형 텍스처링
Geodiffussr (2025, arXiv:2511.23029)는 기존 하이트맵을 받아 고도 데이터를 존중하면서 텍스트 설명으로 안내하는 텍스처를 생성합니다. "가을 숲"은 중간 경사에 주황과 금빛 단풍을, 가파른 면에는 맨바위를 만듭니다. "열대 해안"은 낮은 지대에 야자 식생을, 해수면에는 산호 모래를 만듭니다.
이 시스템은 다중 스케일 콘텐츠 집계를 써서 텍스처 배정이 고도를 존중하도록 합니다. 눈은 물리적으로 그럴듯한 고도 이상에서만 나타나고, 물 피처는 움푹한 곳에 앉으며, 식생은 고도에 따라 성겨집니다.
크리에이터 월드에서는 지오메트리를 바꾸지 않고도 텍스트 프롬프트로 지형 텍스처를 다시 생성할 수 있다는 뜻입니다. 크리에이터가 원하는 지형을 조각한 뒤 분위기를 설명하면("어두운 화산 황무지" 또는 "무성한 온대림") 시스템이 적절한 표면 머티리얼을 생성합니다.
브라우저 지형을 위한 동적 LOD
큰 지형을 어디서나 풀 해상도로 렌더링하는 것은 브라우저에서 불가능합니다. 4 km x 4 km 월드를 1미터 해상도로 하면 지형만 1600만 정점입니다. 동적 LOD는 이것을 월드 크기와 무관하게 일정하고 다룰 만한 정점 수로 줄입니다.
Geometry Clipmaps
Geometry clipmap (Losasso and Hoppe, SIGGRAPH 2004, 논문)은 하이트맵 지형 LOD의 황금 표준으로 남아 있습니다. 아이디어는 지형을 카메라를 중심으로 한 동심 정사각형 링들의 집합으로 렌더링하는 것입니다. 각 링은 이전 링의 두 배 면적이지만 절반 해상도입니다.
카메라 가까이(가장 안쪽 링): 풀 해상도, 1미터 격자 간격. 한 링 바깥: 2미터 간격, 4배 면적 커버. 다음 링: 4미터 간격, 16배 면적 커버. 이런 식으로 6-8 레벨, 가장 바깥 링이 가시 거리 전체를 덮을 때까지 이어집니다.
총 정점 수는 일정합니다. 대략 N^2 * 레벨 수이며, N은 링 너비(정점 단위)입니다. N=256에 8 레벨이면 총 약 50만 정점입니다. 월드가 1 km든 100 km든 똑같이 렌더링됩니다.
브라우저 구현: Geometry clipmap은 표준 버텍스 버퍼 업데이트만 필요해서(compute 셰이더 없음) WebGL 2에서 동작합니다. 카메라가 움직이면 CPU가 각 링의 하이트맵 데이터를 적절한 해상도로 지형을 샘플링해 업데이트합니다. 버텍스 셰이더는 텍스처에서 높이 값을 읽어 평평한 격자를 변위시킵니다.
모핑: LOD 레벨 사이 전환은 순진하게 처리하면 눈에 보이는 "팝핑"을 만듭니다. Geomorphing(아래 별도 절에서 자세히)은 버텍스 셰이더에서 전환 구간에 걸쳐 레벨 간 정점 위치를 블렌딩해, 추가 드로우 콜 비용 없이 부드럽고 팝 없는 전환을 만듭니다.
CDLOD: 쿼드트리 적응형 Clipmap
CDLOD (Strugar, 2014, 논문)는 고정된 동심 링 대신 쿼드트리를 써서 geometry clipmap을 개선합니다. 쿼드트리는 지형에 적응합니다. 평지는 거친 노드를 쓰고, 디테일이 높은 영역(절벽, 능선)은 더 세밀한 분할을 받습니다.
이건 크리에이터 월드에 중요합니다. 청크마다 복잡도가 다르기 때문입니다. 평평한 초원은 최소 해상도면 됩니다. 절벽과 동굴이 있는 산악 지역은 최대 디테일이 필요합니다. CDLOD는 해상도를 중요한 곳에 할당합니다.
CPU 측 쿼드트리 순회는 가볍고(노드 수백 개) 어떤 지형 패치를 어떤 해상도로 그릴지 결정합니다. GPU는 각 패치를 패치별 LOD 유니폼이 있는 인스턴스 격자로 렌더링합니다.
Concurrent Binary Trees: 행성 규모 테셀레이션
Concurrent Binary Trees(CBT)는 적응형 지형 테셀레이션을 위한 GPU 친화적 자료구조로, Benyoub과 Dupuy가 제시했습니다(Intel, HPG 2024, 논문, GitHub).
핵심 아이디어는 지형을 각 노드가 삼각형인 이진 트리로 표현하는 것입니다. 적응형 분할은 카메라에 가까운 삼각형을 쪼개고 멀리 있는 삼각형을 병합합니다. 이진 트리는 1D 배열(이진 힙)로서 전적으로 GPU 메모리에 존재하며, 분할/병합 연산은 compute 셰이더로 돌아갑니다.
2024년 논문은 CBT를 정사각형 하이트맵 도메인에서 임의의 다각형 메시로 확장합니다. 즉, 구(행성 렌더링용)나 임의의 기반 메시(비사각형 경계가 있는 게임 월드용)를 테셀레이션할 수 있습니다. 핵심 개선은 CBT를 암시적 인코딩 대신 메모리 풀 관리자로 쓰는 것으로, 훨씬 높은 분할 레벨을 허용합니다.
성능: 콘솔급 하드웨어에서 0.2ms 미만에 행성 규모 지형 테셀레이션. 알고리즘은 프로세서 수에 따라 선형으로 확장됩니다. WebGPU에서는 이것이 브라우저에서 행성 규모 지형 렌더링으로 가는 경로를 제공하지만, 구현 복잡도는 높습니다.
WebGPU를 활용한 GPU 구동 LOD
WebGPU는 LOD 결정에서 CPU 개입을 없애는 완전 GPU 구동 지형 파이프라인을 가능하게 합니다.
Compute 패스 1: 프러스텀 및 오클루전 컬링. compute 셰이더가 각 지형 패치의 바운딩 박스를 뷰 프러스텀과 오클루전 버퍼(이전 프레임의 다운샘플링된 깊이 버퍼)에 테스트합니다. 보이지 않는 패치는 통째로 버립니다.
Compute 패스 2: LOD 선택. 보이는 패치에 대해 화면 공간 크기를 계산하고 적절한 LOD 레벨을 선택합니다. LOD 레벨과 패치 ID를 간접 드로우 버퍼에 씁니다.
Compute 패스 3: 메시 생성(볼류메트릭 지형용). SDF 데이터가 있는 청크에 대해 선택된 LOD 해상도로 marching cubes를 실행해 메시를 생성합니다.
간접 드로우. 단일
drawIndexedIndirect()호출이 모든 지형 패치를 렌더링합니다. GPU가 모든 것을 결정합니다. 무엇을, 어떤 해상도로, 어떤 순서로 그릴지를요.
이 파이프라인은 월드 크기나 복잡도와 무관하게 CPU 비용이 일정합니다(compute 셰이더 디스패치와 간접 드로우 콜). GPU가 모든 패치별 결정을 처리합니다.
@compute @workgroup_size(64)
fn lodSelection(@builtin(global_invocation_id) id: vec3<u32>) {
let patchIdx = id.x;
let bounds = patchBounds[patchIdx];
if (!frustumTest(bounds, viewProjection)) { return; }
if (occlusionTest(bounds, depthPyramid) == OCCLUDED) { return; }
let screenSize = projectedSize(bounds, viewProjection, screenDimensions);
let lod = clamp(u32(log2(maxScreenSize / screenSize)), 0u, MAX_LOD);
let drawIdx = atomicAdd(&drawCount, 1u);
drawArgs[drawIdx] = DrawArgs(patchIdx, lod, indexCount[lod], indexOffset[lod]);
}Geomorphing: 팝 없는 LOD 전환
지형 LOD에서 가장 큰 시각적 아티팩트는 팝핑입니다. 패치가 LOD 레벨을 바꿀 때 정점이 갑자기 새 위치로 점프하는 것입니다. Geomorphing은 전환 구간에 걸쳐 LOD 레벨 사이 정점 위치를 부드럽게 보간해 이를 없앱니다.
구현은 전적으로 버텍스 셰이더에 있습니다. 각 정점은 현재 LOD 위치와 다음 더 거친 LOD 위치를 모두 저장합니다. 카메라 거리가 전환 임계값을 넘으면 모프 팩터가 둘 사이를 블렌딩합니다.
float morphFactor = smoothstep(lodNear, lodFar, distanceToCamera);
float morphedHeight = mix(fineLodHeight, coarseLodHeight, morphFactor);
gl_Position = viewProjection * vec4(worldPos.x, morphedHeight, worldPos.z, 1.0);Hoppe의 geometry clipmap 논문(GPU Gems 2, 2장)이 clipmap 링에 대한 전체 구현을 설명합니다. 모프 구간은 각 링의 바깥쪽 20%입니다. 이 구간 안에서 정점들이 다음 링의 해상도로 부드럽게 수렴합니다. 시각적 효과는 지형 지오메트리가 디테일 레벨 사이를 끊기듯 바뀌는 게 아니라 "녹아내리는" 것입니다. 보통의 카메라 속도에서 전환은 보이지 않습니다.
이미지 공간 블렌딩(Scherzer et al., 논문)은 두 LOD 레벨의 렌더링된 이미지를 화면 공간에서 블렌딩하는 대안입니다. 더 극단적인 LOD 차이(예: 메시-빌보드 전환)를 다루지만 전환 구간에 대해 추가 렌더 패스 비용이 듭니다.
GPU 구동 식생 컬링
식생(나무, 풀, 바위)은 오픈 월드에서 흔히 드로우 콜의 가장 큰 원천입니다. 순진한 방식은 매 프레임 모든 식생 인스턴스를 그립니다. 이제 WebGPU를 통해 Three.js에서 쓸 수 있는 GPU 구동 컬링은 보이지 않는 인스턴스가 래스터라이저에 도달하기 전에 제거합니다.
Three.js의 ComputeInstanceCulling(문서)은 인스턴스 메시에 프러스텀 및 LOD 컬링을 제공하며, 인스턴스 수가 많을 때 10-100배 성능 향상을 냅니다. 파이프라인은 이렇습니다.
- compute 셰이더가 모든 인스턴스 바운딩 구를 읽습니다
- 각각을 카메라 프러스텀에 테스트합니다(6평면 테스트)
- 거리 기반 LOD를 적용합니다. 임계값 너머의 인스턴스는 낮은 디테일로 전환되거나 통째로 컬링됩니다
- 살아남은 인스턴스는 버퍼로 압축되어
drawIndirect로 그려집니다
CPU는 인스턴스별 작업을 전혀 하지 않습니다. 초기 설정 이후 비용은 식생 유형당 compute 디스패치 하나에 간접 드로우 콜 하나이며, 인스턴스 수와 무관합니다.
더 빽빽한 식생에는 Three.js의 IndirectBatchedMesh(문서)가 여러 지오메트리 유형(나무, 덤불, 바위)을 단일 버퍼에 묶어 multi-draw indirect로 그립니다. 청크 안의 모든 식생에 대해 드로우 콜 하나입니다.
우리 식생 시스템의 밀도 맵 기반 산포와 결합하면 이렇게 됩니다. 밀도 맵이 compute 셰이더에서 5만 개의 풀잎 위치를 생성하고, 컬링 패스가 화면 밖이거나 너무 먼 70%를 제거하고, 간접 드로우 콜 하나가 살아남은 1만 5천 개의 잎을 렌더링합니다. 총 CPU 비용은 무시할 만합니다.
볼류메트릭 지형을 위한 LOD
볼류메트릭 지형(SDF + marching cubes)은 메시가 미리 만들어진 게 아니라 생성되기 때문에 자체 LOD 시스템이 필요합니다. 방식은 이렇습니다.
다해상도 SDF 저장. SDF를 밉맵 같은 위계로 여러 해상도에 저장합니다. 레벨 0은 풀 해상도(1미터 복셀)입니다. 레벨 1은 2미터 복셀(데이터 8배 적음)입니다. 레벨 2는 4미터 복셀입니다. 각 레벨에서 SDF는 최소 절댓값 거리를 취해 다운샘플링됩니다.
LOD 선택형 marching cubes. 원하는 LOD에 맞는 SDF 레벨에서 marching cubes를 실행합니다. 가까운 청크는 레벨 0을 씁니다. 먼 청크는 레벨 2나 3을 씁니다. Transvoxel 알고리즘이 서로 다른 레벨 사이 경계를 처리합니다.
캐싱. 생성된 메시는 SDF가 바뀌거나(크리에이터 편집) LOD 레벨이 바뀔 때까지(카메라가 크게 이동) 캐시됩니다. 정적 지형에서는 메시가 한 번 생성되고 재사용됩니다.
지형을 위한 스트리밍 아키텍처
청크 데이터 포맷
각 지형 청크(64x64미터)는 작은 바이너리 패키지로 스트리밍됩니다.
ChunkPacket {
header: {
chunkX: i16, chunkZ: i16,
version: u32,
flags: u8 // hasHeightmap | hasVolumetric | hasVegetation
}
heightmap: {
resolution: u8, // 풀은 65x65, 절반은 33x33, 1/4은 17x17
quantizedHeights: u16[resolution * resolution], // 델타 인코딩, zlib 압축
splatMap: u8[4 * resolution * resolution] // RGBA 블렌드 가중치, LZ4 압축
}
volumetric?: { // flags.hasVolumetric일 때만 존재
sdfResolution: u8, // 보통 32 또는 64
sparseOctree: bytes // 런렝스 인코딩된 희소 SDF
}
vegetation?: { // flags.hasVegetation일 때만 존재
treeDensityMap: u8[16 * 16], // 4m 해상도 밀도 격자
grassDensityMap: u8[32 * 32], // 2m 해상도 밀도 격자
rockDensityMap: u8[16 * 16]
}
creatorObjects: {
count: u16,
objects: PlacedObject[] // assetId + 트랜스폼 + 속성, 각각 ~40바이트
}
}전형적인 크기:
- 하이트맵만 있는 청크(평지): 압축 2-4 KB
- 하이트맵 + 식생: 4-8 KB
- 하이트맵 + 볼류메트릭 + 식생(복잡한 청크): 20-100 KB
- 5x5 풀 디테일 이웃: 총 50-500 KB
점진적 청크 로딩
청크는 거리, 이동 방향, 데이터 유형에 따른 우선순위 순서로 로드됩니다.
우선순위 1(즉시, <100ms): 플레이어가 막 들어가려는 청크의 하이트맵 지오메트리. 지형 표면이 먼저 나타납니다. 가장 낮은 해상도(청크당 17x17)에서도 땅은 거기 있습니다.
우선순위 2(빠름, <300ms): 스플랫 맵과 지형 텍스처. 땅에 색이 입혀집니다.
우선순위 3(스트리밍, <1s): 풀 해상도 하이트맵 업그레이드. 식생 밀도 맵. GPU 인스턴싱이 나무와 풀을 생성합니다.
우선순위 4(백그라운드, <3s): 동굴/오버행이 있는 청크의 볼류메트릭 SDF 데이터. marching cubes가 Web Worker에서 메시를 생성하고 버퍼를 메인 스레드로 전송합니다.
우선순위 5(지연, <10s): 크리에이터가 배치한 오브젝트. 구조물의 고해상도 텍스처. 꽃, 작은 바위, 잔해 같은 디테일 오브젝트.
예측 선반입
플레이어가 청크에 들어갈 때까지 기다렸다가 로드하지 마세요. 속도를 기준으로 어디로 갈지 예측해 미리 로드합니다.
- 걷기 속도(5 km/h): 2 청크 앞(128m)을 미리 가져옵니다. 전형적인 광대역 지연에서 이건 200-400ms의 여유 시간입니다.
- 달리기/탈것(15 km/h): 4 청크 앞을 미리 가져옵니다. 로드 링이 속도 방향에 따라 이동합니다.
- 비행/빠른 이동: 전환 중 렌더링을 멈춥니다. 목적지 청크를 최고 우선순위로 스트리밍합니다. 첫 프레임에 충분한 데이터가 존재하면 렌더링을 재개합니다.
선반입 시스템은 어떤 청크가 캐시에 있는지, 어떤 게 전송 중인지(요청했으나 아직 도착 안 함), 어떤 게 필요한지 추적합니다. 우선순위 큐가 대기 중 요청을 긴급도순으로 정렬합니다. 플레이어가 멀어진 청크의 요청은 취소합니다.
메모리 예산과 축출
브라우저 탭은 데스크톱에서 2-4 GB를 받습니다. 지형 시스템은 그 일부 안에서 살아야 합니다(나머지는 렌더링, 물리, 네트워킹, JavaScript 힙용).
목표 예산: 모든 지형 데이터에 256 MB.
전형적인 청크 크기로 보면 이렇습니다.
- 풀 디테일 캐시 청크: 약 100개(10x10 이웃), 각 5-100 KB = 원시 데이터 5-10 MB
- GPU 지형 지오메트리: 약 50 MB(가시 지형의 버텍스 버퍼, 인덱스 버퍼)
- 지형 텍스처: 약 100 MB(KTX2 압축, 아틀라스 패킹)
- 식생 인스턴스 버퍼: 약 50 MB(GPU 인스턴싱용 위치, 회전, 스케일)
- SDF 볼륨과 캐시된 marching cubes 메시: 약 50 MB
가시 범위 너머의 청크는 GPU 메모리에서 먼저 축출되고(텍스처, 버텍스 버퍼), 그다음 CPU 캐시에서 축출됩니다. 원시 하이트맵 데이터는 가장 마지막에 사라집니다. 유지 비용이 가장 싸고, 플레이어가 돌아설 때 가지고 있는 게 가장 중요하기 때문입니다.
생물군계 전환과 타일링 방지
부드러운 생물군계 경계
진짜 풍경은 생물군계 사이에 딱딱한 가장자리가 없습니다. 숲이 한 선에서 멈추고 사막이 되지 않습니다. 그라디언트가 있습니다. 빽빽한 숲이 흩어진 나무로 성겨지고, 다음엔 관목지, 다음엔 성긴 사막 식생입니다. 이걸 제대로 하면 월드가 타일처럼이 아니라 연속적으로 느껴집니다.
AutoBiomes(Kötter et al., 논문)는 절차적 지형 생성을 단순화된 기후 시뮬레이션과 결합합니다. 온도, 습도, 고도가 각 점의 생물군계 유형을 결정합니다. 생물군계 사이에서 머티리얼 가중치와 식생 밀도가 전환 구간(보통 50-100미터 너비)에 걸쳐 보간됩니다. 전환 너비는 생물군계 쌍에 따라 달라집니다. 숲-초원은 넓고 점진적이고, 절벽-물은 좁고 급격합니다.
크리에이터 월드에서는 생물군계 배정이 거친 격자에서 돌아갑니다(16x16미터 영역당 생물군계 샘플 하나). 지형 셰이더가 현재 프래그먼트와 이웃의 생물군계 값을 읽어 전환 구간에서 머티리얼 가중치를 보간하고 텍스처를 그에 맞게 블렌딩합니다. 식생 산포도 같은 보간 밀도 값을 쓰므로 숲 가장자리에서 나무 밀도가 점진적으로 옅어집니다.
크리에이터 제어: 크리에이터가 자기 부지에 생물군계 오버라이드를 칠하게 합니다. 시스템은 지형 속성에서 기본 생물군계를 생성하지만, 크리에이터가 그것을 오버라이드할 수 있습니다. 낮은 지대에 "늪"을 칠하면 머티리얼이 탁한 물, 이끼, 죽은 나무로 바뀝니다. 생물군계 페인트 맵은 청크당 16x16 생물군계 ID 격자(256바이트)이며 절차적 배정을 오버라이드합니다.
Hex-Tiling: 텍스처 반복 제거
지형 렌더링에서 가장 흔한 시각적 아티팩트는 텍스처 반복입니다. 1미터 풀 텍스처를 100미터 초원에 타일링하면 눈에 보이는 격자 패턴이 생깁니다. 두 기법이 이를 해결합니다.
Hex-tiling(Mikkelsen, 데모)은 정사각형 타일링 격자를 육각형 격자로 대체합니다. 각 육각형 타일은 무작위 오프셋과 회전으로 텍스처를 샘플링합니다. 육각형 경계는 이음매를 숨기도록 블렌딩됩니다. 결과는 타일처럼이 아니라 균일하게 무작위로 보이는 표면입니다. 비용: 프래그먼트당 약 3번의 추가 텍스처 샘플. 이 기법은 프로덕션 게임에서 널리 쓰이며 어떤 프래그먼트 셰이더에서든 돌아갑니다.
확률적 텍스처 필터링(Pharr et al., NVIDIA, 2024, 논문)은 셰이딩 전이 아니라 후에 확률적 샘플링을 써서 필터링을 적용합니다. 확률적 샘플링의 오차는 미미하며 시공간 디노이징으로 잘 처리됩니다. 이것은 더 정확한 필터링 결과를 내고 압축/희소 텍스처와 함께 동작합니다. 지형에서는 타일링 아티팩트와, hex-tiling이 때때로 전환부에 도입하는 필터링 아티팩트를 모두 없앱니다.
브라우저 월드에서는 hex-tiling이 실용적인 선택입니다(어떤 셰이더에서든 동작함). 확률적 필터링은 더 많은 인프라가 필요하지만 시간적 디노이징이 가용하다면(TAA가 있는 WebGPU 경로에서는 그럴 것) 더 나은 결과를 냅니다.
지형 머티리얼 시스템
Triplanar 매핑
표준 UV 매핑 텍스처는 가파른 경사에서 끔찍하게 늘어납니다. UV 좌표가 압축되기 때문입니다. Triplanar 매핑은 세 축(X, Y, Z)을 따라 텍스처를 투영하고 표면 법선에 따라 블렌딩합니다.
vec3 blending = abs(normal);
blending = normalize(max(blending, 0.00001));
blending /= (blending.x + blending.y + blending.z);
vec4 xaxis = texture(material, worldPos.yz * scale);
vec4 yaxis = texture(material, worldPos.xz * scale);
vec4 zaxis = texture(material, worldPos.xy * scale);
vec4 color = xaxis * blending.x + yaxis * blending.y + zaxis * blending.z;절벽면은 X 또는 Z 투영을 받습니다(늘어남 없음). 평지는 Y 투영을 받습니다. 블렌딩은 부드럽고 자동입니다. UV 언래핑이 필요 없습니다.
Babylon.js에는 내장 TriPlanar Material이 있습니다. Three.js는 커스텀 셰이더가 필요하지만 구현은 GLSL 약 30줄입니다.
PBR 지형에서는 모든 채널에 triplanar 매핑을 적용합니다. 알베도, 노멀, 러프니스, 앰비언트 오클루전. 같은 블렌딩 가중치가 각 채널에 적용됩니다.
경사 및 고도 기반 머티리얼 배정
스플랫 맵을 손으로 칠하는 대신 지형 속성에 따라 절차적으로 머티리얼을 배정합니다.
float slope = acos(dot(normal, vec3(0, 1, 0)));
float altitude = worldPos.y;
float grassWeight = smoothstep(0.3, 0.0, slope) * smoothstep(2000.0, 1500.0, altitude);
float rockWeight = smoothstep(0.2, 0.5, slope);
float snowWeight = smoothstep(2500.0, 3000.0, altitude) * smoothstep(0.4, 0.1, slope);
float sandWeight = smoothstep(5.0, 0.0, altitude) * smoothstep(0.15, 0.0, slope);낮은 고도의 평지는 풀을 받습니다. 가파른 경사는 바위를 받습니다. 높은 고도는 눈을 받습니다(단, 눈이 쌓일 만큼 평평한 표면에서만). 해수면 근처는 모래를 받습니다. 전환은 부드럽고 물리적으로 동기 부여됩니다.
크리에이터 월드에서는 고도 임계값과 블렌드 구간을 청크당 칠할 수 있는 파라미터로 노출합니다. 크리에이터는 수목한계선을 위아래로 옮기거나, 눈 덮임을 확장하거나, 자기 부지의 머티리얼 규칙을 조정해 풀 언덕을 모래 사막으로 바꿀 수 있습니다.
GPU 친화적 라플라시안 텍스처 블렌딩
표준 텍스처 블렌딩(레이어 간 선형 보간)은 눈에 보이는 이음매나 흐릿하고 대비가 낮은 결과를 만듭니다. 라플라시안 피라미드 블렌딩이 이를 해결하지만 전통적으로 비싼 사전 계산이 필요합니다.
Wronski (NVIDIA, 2025, JCGT)는 사전 계산도 추가 메모리도 없이 실시간 셰이더에서 동작하는 GPU 친화적 변형을 제시합니다. 이 기법은 표준 밉맵 체인을 라플라시안 피라미드의 근사로 씁니다. 텍스처를 현재 밉 레벨과 더 거친 레벨에서 모두 샘플링하고, 그 차이(라플라시안)를 계산하고, 각 레이어의 라플라시안 기여를 블렌딩합니다.
결과는 날카로운 국소 피처(개별 풀잎, 바위 균열)를 보존하면서 더 큰 스케일에서 부드럽게 블렌딩합니다. 비용은 프래그먼트당 몇 번의 추가 텍스처 탭입니다. 픽셀당 4개 이상의 머티리얼 레이어를 블렌딩하는 지형에서는 선형 블렌딩보다 눈에 띄게 나은 결과를 냅니다. 특히 풀, 바위, 모래 사이의 전환부에서요.
침식 디테일을 위한 Phasor 노이즈
표준 지형은 가까이서 보면 종종 평평해 보입니다. 침식 시뮬레이션이 하이트맵 해상도(1미터 격자)에서 동작하기 때문입니다. 진짜 지형에는 센티미터 규모의 미세한 침식 패턴(릴, 거얼리, 풍화 균열)이 있습니다.
Grenier et al. (2024, CGF)은 phasor 노이즈를 써서 지형 마이크로 디테일을 실시간으로 더합니다. Phasor 노이즈는 주기 함수에 입력되는 확률적 위상장을 정의해 구조화된 패턴을 합성합니다. 지형에 적용하면 공간적으로 변하는 침식 패턴을 만듭니다.
- 좁은 릴을 스케일에 걸쳐 더 큰 거얼리로 단계적으로 발전시킵니다
- 지형 경사에 자동으로 정렬됩니다(침식 패턴이 최대 경사선을 따름)
- 최대 32배 증폭을 달성합니다(하이트맵 해상도의 32배로 디테일 추가)
- 전적으로 프래그먼트 셰이더에서 인터랙티브한 프레임 속도로 돌아갑니다
브라우저 월드에서는 phasor 노이즈가 지형 셰이더에서 디테일 레이어로 돌아갑니다. 하이트맵이 큰 스케일 형태를 제공합니다. Phasor 노이즈는 지오메트리 복잡도를 늘리지 않고 프래그먼트 셰이더에서 설득력 있는 미세 침식을 더합니다. 파라미터(패턴 빈도, 진폭, 방향)는 생물군계마다 달라질 수 있습니다. 맨바위의 깊은 릴, 모래언덕의 잔잔한 물결, 마른 진흙의 거친 나무껍질 같은 질감입니다.
지형을 위한 가상 텍스처링
큰 스케일에서는 지형 텍스처 아틀라스가 다루기 힘들어집니다. 4 km x 4 km 월드를 센티미터당 1텍셀로 하면 400,000 x 400,000 픽셀 텍스처가 필요합니다. 당연히 불가능합니다.
가상 텍스처링(메가텍스처라고도 하며, id Software의 Rage에서 유래)은 지형 텍스처를 페이지화된 구조로 다뤄 이를 해결합니다. 전체 텍스처는 개념적으로 존재하지만 화면에 보이는 타일만 GPU 메모리에 로드됩니다.
파이프라인은 이렇습니다.
- 피드백 패스: 각 픽셀이 어떤 텍스처 타일을 필요로 하는지(타일 ID와 밉 레벨) 출력하는 셰이더로 지형을 렌더링합니다. 이것을 CPU로 읽어 옵니다(또는 compute 셰이더로 처리합니다).
- 타일 로딩: 요청된 타일을 CDN에서 로드하거나 스플랫 맵 데이터에서 절차적으로 생성합니다.
- 인디렉션 텍스처: 작은 텍스처가 가상 타일 좌표를 텍스처 아틀라스의 물리 타일 좌표로 매핑합니다.
- 렌더 패스: 지형 셰이더가 인디렉션 텍스처를 조회해 올바른 물리 타일을 찾은 뒤 아틀라스에서 머티리얼 텍스처를 샘플링합니다.
WebGPU의 compute 셰이더는 피드백 분석과 페이지 테이블 관리를 전적으로 GPU에서 처리할 수 있습니다. CPU는 타일 I/O만 관리합니다.
결과: 텍스처 메모리 폭발 없이 임의의 해상도로 고유 텍스처가 입혀진 지형. 카메라에서 먼 타일은 낮은 해상도로 로드됩니다. 가까운 타일은 높은 해상도로 로드됩니다. 총 메모리 사용량은 고정 예산 안에 머뭅니다(보통 128-256 MB의 텍스처 아틀라스).
동적 지형 효과
물웅덩이와 젖음
비는 그냥 내리기만 하지 않습니다. 쌓입니다. 움푹한 곳에 물웅덩이를 만듭니다. 표면에 젖은 윤기를 만듭니다. 가파른 경사에서는 흘러내립니다. 이걸 시뮬레이션하면 날씨가 순전히 시각적 오버레이가 아니라 지형과 연결된 것처럼 느껴집니다.
셰이더 기반 방식은 유체 역학을 시뮬레이션하지 않습니다. 지형 하이트맵을 써서 물이 고이는 곳을 결정합니다.
float concavity = heightCenter * 4.0 - heightLeft - heightRight - heightUp - heightDown;
float puddleDepth = max(0.0, concavity * rainIntensity - evaporationRate * timeSinceRain);
float wetness = smoothstep(0.0, 0.02, puddleDepth);
vec3 wetColor = baseColor * 0.7;
float wetRoughness = baseRoughness * 0.3;
vec3 finalColor = mix(baseColor, wetColor, wetness);
float finalRoughness = mix(baseRoughness, wetRoughness, wetness);오목한 영역(하이트맵의 음의 라플라시안)이 물을 모읍니다. 오목함이 깊을수록 물웅덩이가 큽니다. 젖은 표면은 어두워지고 더 반사적이 됩니다(러프니스 낮아짐). 효과는 비가 멈춘 뒤 시간이 지나며 옅어집니다.
완전한 물웅덩이 반사를 위해서는 물웅덩이 표면에 평면 반사 패스를 더합니다. 또는 더 싸고 Three.js와 Babylon.js 후처리 스택에 이미 있는 화면 공간 반사(SSR)를 씁니다.
물웅덩이 표면의 빗방울은 피드백 텍스처에서 단순한 2D 파동 방정식을 씁니다(Saurel, 2026, 블로그). 각 빗방울은 바깥으로 퍼지며 감쇠하는 잔물결을 만듭니다. 파동 텍스처가 물웅덩이 노멀 맵을 변조해 60fps로 설득력 있는 잔물결 패턴을 만듭니다.
발자국과 지형 변형
플레이어가 무른 지형(모래, 눈, 진흙)을 걸을 때 발자국은 물리적 존재감을 더합니다. 기법은 이렇습니다. 청크당 작은 변형 텍스처(64x64 픽셀 = 4 KB)를 유지해 높이 오프셋을 저장합니다. 캐릭터가 무른 지형을 밟으면 발자국 형상을 변형 텍스처에 찍습니다.
지형 버텍스 셰이더가 변형 텍스처를 읽어 높이에서 오프셋을 뺍니다. 지형 프래그먼트 셰이더가 발자국 영역을 어둡게 하고(다져진 흙은 더 어두움) 러프니스를 높입니다(흐트러진 표면).
발자국은 변형 텍스처를 점진적으로 0으로 만들어 시간이 지나며 옅어집니다(눈이 메우고, 비가 진흙 자국을 씻어 냄). 옅어지는 속도는 날씨에 달려 있습니다. 비 올 때는 빠르고, 건조할 때는 느립니다.
멀티플레이어 월드에서 발자국 데이터는 일시적이고 로컬입니다. 각 클라이언트가 보이는 플레이어를 위해 발자국을 생성합니다. 변형 텍스처는 클라이언트 간 동기화가 필요 없습니다(누구나 자기 버전의 일시적 발자국을 봄). 이렇게 하면 모든 발걸음을 브로드캐스트하는 네트워킹 비용을 피합니다.
절차적 하늘과 낮/밤 사이클
하늘은 어떤 오픈 월드에서든 가장 큰 가시 표면입니다. 지형 전체의 분위기를 정합니다.
Three.js에는 절차적 해/달, 낮/밤 사이클, 구름, 별, 렌즈 플레어를 포함하는 완전한 하늘 시스템이 있습니다. Three.js 내장 Sky 예제(WebGPU에서도 가용)는 Preetham의 해석적 하늘 모델을 구현합니다.
물리적으로 더 정확한 결과를 위해서는 webgpu-sky-atmosphere가 Hillaire의 대기 모델을 WebGPU 후처리로 구현합니다. 다중 산란 위상 함수를 지원하며 올바른 공중 원근(먼 지형이 더 뿌옇게 보임), 해/일몰 색, 하늘 그라디언트를 제1원리에서 만듭니다.
TerrainView7은 사전 계산된 대기 산란으로 WebGPU에서 전체 규모 행성 렌더링을 시연하며, 물리적으로 정확한 대기 렌더링이 브라우저에서 돌아간다는 것을 증명합니다.
크리에이터 월드에서는 하늘 파라미터(해 위치, 구름 덮임, 안개 밀도)가 서버의 월드 시계로부터 모든 클라이언트에 동기화됩니다. 하늘 셰이더는 각 클라이언트에서 로컬로 돌아가며 모든 플레이어에 걸쳐 일관된 조명을 만듭니다.
지형 조명: 간접 조명
직사 햇빛은 섀도 맵이 처리합니다. 하지만 그늘에 있는 지형의 색과 밝기(앰비언트/간접광)도 시각적 품질에 똑같이 중요합니다. 순수한 검정 그림자는 잘못 보입니다. 그림자는 하늘 색으로 물들어야 합니다(맑은 날엔 파랑, 흐린 날엔 회색).
브라우저 월드에서 실용적인 방식은 이렇습니다.
가시성 비트마스크를 사용한 화면 공간 간접 조명(Jimenez et al., 2023, 논문)은 픽셀당 32개의 방향성 가시성 섹터를 추적해 표준 SSAO를 개선합니다. 이것은 한 점이 얼마나 가려졌는지뿐 아니라 가림의 방향성도 잡아냅니다. 얇은 표면은 반대편에서 빛이 올바르게 통과하도록 합니다. 결과는 전역 조명 인프라 없이 주변 지오메트리에 반응하는 간접 조명입니다.
비용은 SSAO와 비슷합니다(1-2ms). 시각적 개선은 상당합니다. 협곡의 지형이 협곡 벽에서 반사광을 받습니다. 오버행의 아랫면이 지면 반사로 밝아집니다. 이 효과는 하늘 셰이더의 대기 산란과 결합해 물리적으로 동기 부여된 앰비언트 조명을 만듭니다.
지형 물리 통합
Rapier 하이트필드 콜라이더
Rapier의 WASM 물리 엔진은 지형에 최적화된 네이티브 하이트필드 콜라이더를 제공합니다. 지형 콜라이더를 만드는 건 간단합니다.
const heights = new Float32Array(65 * 65);
// 하이트맵 데이터로 채우기...
const groundCollider = RAPIER.ColliderDesc.heightfield(
64, 64, heights, new RAPIER.Vector3(64.0, 100.0, 64.0)
);
world.createCollider(groundCollider);하이트필드 콜라이더는 효율적인 브로드페이즈 질의를 위해 구조화된 격자를 씁니다. 하이트필드에 대한 레이캐스팅은 삼각형 메시의 O(n)이 아니라 O(log n)입니다. 65x65 청크에서 충돌 질의는 마이크로초 단위로 해결됩니다.
볼류메트릭 지형이 있는 청크(SDF 오버레이)에서는 marching cubes 출력에서 삼각형 메시를 생성하고 trimesh 콜라이더를 씁니다. 이건 하이트필드 콜라이더보다 비싸지만 임의의 지오메트리를 처리합니다. 플레이어에게 가장 가까운 3-5개 청크에만 trimesh 콜라이더를 생성합니다. 먼 청크는 물리가 필요 없습니다.
성능: 65x65 청크에 대한 Rapier의 하이트필드 콜라이더는 캐릭터 컨트롤러 질의에 물리 스텝당 약 0.1ms를 더합니다. 하이트필드 콜라이더가 있는 활성 청크 5개: 0.5ms. 볼류메트릭 청크용 trimesh 콜라이더 하나: 0.2-0.5ms. 총 지형 물리 예산: 1ms 미만으로, 월드 전체의 2-3ms 물리 예산에 충분히 들어갑니다.
지형 인식 캐릭터 컨트롤러
캐릭터 컨트롤러는 지형 속성에 반응해야 합니다.
- 경사 제한: 캐릭터는 최대 45도 경사까지 걸을 수 있습니다. 더 가파른 경사는 미끄러짐을 일으킵니다. 이것은 캐릭터 위치의 지형 법선을 씁니다(하이트맵 그래디언트에서 싸게 계산됨).
- 표면 머티리얼 반응: 바위 위를 걷는 것은 모래나 진흙 위를 걷는 것과 다른 발소리와 이동 속도를 냅니다. 지형의 스플랫 맵이 임의의 점에서 표면 머티리얼을 제공합니다.
- 단 오르기: 캐릭터는 최대 0.5미터의 턱을 오를 수 있습니다. Rapier의
KinematicCharacterController가 설정 가능한 단 높이로 이를 자동으로 처리합니다.
브라우저에서의 인터랙티브 지형 편집
크리에이터 월드에서 지형은 생성되기만 하는 게 아닙니다. 플레이어가 조각하고, 수정하고, 다시 빚습니다. 편집 도구는 반응적이어야 하고(즉각적인 시각 피드백) 네트워크화되어야 합니다(다른 플레이어가 몇 초 안에 변화를 봄).
WebGPU SDF Editor
Reinder Nijhoff의 WebGPU SDF Editor는 풀 기능 SDF 모델링이 오늘날 브라우저에서 동작함을 시연합니다. 이 에디터는 다음을 지원합니다.
- 여섯 가지 프리미티브 형상(구, 박스, 원뿔, 원기둥, 캡슐, 토러스)과 위치, 회전, 스케일
- 불리언 연산(합집합, 차집합, 교집합)과 부드러운 블렌딩 및 설정 가능한 블렌드 반경
- 위계적 씬 그래프와 그룹 및 중첩 연산
- 실시간 렌더링, 다중 GPU compute 셰이더 단계, 16,384개 격자 셀에 걸친 옥트리 기반 공간 분할, marching cubes 또는 surface nets를 통한 표면 추출 사용
- 시간적 안티에일리어싱과 앰비언트 오클루전, 섀도 맵을 통해
각 프리미티브는 단일 GPU 버퍼에 28개의 float(112바이트)로 저장됩니다. 이 작은 표현은 복잡한 지형 편집(동굴 입구, 아치, 깎은 절벽면을 정의하는 수십 개의 SDF 프리미티브)이 5 KB 미만이고 다른 플레이어에게 즉시 동기화됨을 뜻합니다.
크리에이터 월드에서 SDF 편집 워크플로는 이렇게 보입니다.
- 크리에이터가 조각 도구를 선택합니다(구 추가, 박스 빼기, 부드러운 블렌드)
- 월드에서 클릭/드래그해 SDF 프리미티브를 배치하고 크기를 정합니다
- 클라이언트가 즉시 수정된 SDF에 marching cubes를 돌려 로컬 메시를 업데이트합니다(피드백 <16ms)
- SDF 편집(프리미티브 유형 + 트랜스폼 + 블렌드 모드, ~100바이트)이 서버로 전송됩니다
- 서버가 편집을 검증하고(크리에이터 부지 안인지, 보호 구역과 겹치지 않는지) 주변 플레이어에게 브로드캐스트합니다
- 다른 플레이어의 클라이언트가 SDF 편집을 적용하고 로컬 메시를 다시 생성합니다
편집이 다른 사람에게 보이기까지의 총 왕복: 네트워크 지연에 따라 100-300ms. 크리에이터는 서버 확인 전에 로컬에서 적용되므로 자기 편집을 즉시 봅니다.
브러시 기반 하이트맵 편집
하이트맵 레이어(볼류메트릭 피처가 필요 없는 90%의 지형)에는 더 단순한 편집 모델이 동작합니다. 크리에이터가 브러시로 높이 수정을 칠합니다.
- 올리기/내리기: 감쇠가 있는 반경 안에서 높이를 더하거나 뺍니다
- 부드럽게: 반경 안의 높이를 평균 내어 날카로운 피처를 제거합니다
- 평탄화: 반경 안의 모든 높이를 목표 값으로 설정합니다
- 침식 브러시: 브러시 반경 안에서 수력 침식 몇 단계를 로컬로 적용합니다
하이트맵 편집은 델타입니다. 기반 지형 위에 얹히는 작은 높이 변화 패치입니다. 델타 패치는 아주 작고(16비트 높이 오프셋 32x32 격자 = 2 KB) 단일 메시지로 다른 플레이어에게 동기화됩니다. 여러 델타 패치가 청크당 누적되며 주기적으로 서버 측에서 청크의 영구 하이트맵으로 병합됩니다.
협업 편집 제약
여러 크리에이터가 같은 청크를 동시에 편집할 때 시스템에는 규칙이 필요합니다.
- 공간 잠금: 한 번에 한 크리에이터만 주어진 8x8미터 하위 영역을 편집할 수 있습니다. 크리에이터가 편집 스트로크를 시작하면 잠금을 얻고 브러시를 떼면 풉니다. 잠금은 10초 비활동 후 만료됩니다.
- 겹치지 않는 편집: 두 크리에이터가 같은 청크의 다른 부분을 편집하면 두 편집 모두 충돌 없이 적용됩니다(서로 다른 하이트맵 셀이나 SDF 영역을 수정함).
- 겹치는 편집: 두 크리에이터가 같은 위치를 편집하면 서버가 도착 순서로 편집을 직렬화합니다. 두 클라이언트는 조정 후 같은 최종 결과를 봅니다.
이것은 배치된 오브젝트에 쓰는 완전한 CRDT 방식보다 단순합니다. 지형 편집이 이산적 오브젝트 상태가 아니라 연속장(높이, SDF 거리)에 대한 가산 연산이기 때문입니다.
WebGPU의 Nanite 스타일 가상 지오메트리
언리얼 엔진 5의 Nanite는 빌드 타임에 클러스터 DAG(방향성 비순환 그래프)를 만들고 런타임에 화면 공간 오차를 기준으로 클러스터별로 올바른 LOD를 선택해 수십억 개의 삼각형을 렌더링합니다. 전체 파이프라인이 GPU에서 돌아갑니다. 이 방식이 WebGPU로 이식되었습니다.
Nanite WebGPU
Scthe의 Nanite WebGPU(GitHub 1.1k+ 스타)는 Nanite 핵심 아키텍처의 완전한 브라우저 구현입니다.
- meshoptimizer의 클러스터 생성으로 오프라인에서 구축한 Meshlet LOD 위계
- WGSL compute 셰이더로 구현한 소프트웨어 래스터라이저(하드웨어 래스터화가 클러스터별 드로우를 효율적으로 할 수 없는 WebGPU의 제약 안에서 동작)
- 프러스텀 및 오클루전 테스트를 쓰는 인스턴스별 및 meshlet별 컬링
- 극히 먼 오브젝트를 위한 빌보드 임포스터
- 텍스처 및 정점별 노멀 지원
파이프라인: 메시가 약 128개 삼각형의 클러스터로 나뉩니다. 이웃 클러스터가 그룹화되고, 각 그룹은 공유 경계를 보존하면서(meshoptimizer를 써서) 단순화됩니다. 이것은 전체 메시가 단일 클러스터로 붕괴할 때까지 재귀합니다. 런타임에 compute 셰이더가 DAG를 순회하며 현재 화면 해상도에서 1픽셀 미만의 오차를 내는 그룹별 가장 거친 클러스터를 선택합니다.
THREE-Nanite는 떠오르는 Three.js 구현으로, 수십만 개의 삼각형을 다루면서 내장 그래픽 하드웨어에서 20-40fps를 달성합니다. Nanite 스타일 렌더링이 저사양 브라우저 하드웨어에서도 쓸 만함을 보여 줍니다.
meshoptimizer: LOD 파이프라인의 기초
meshoptimizer(Arseny Kapoulkine 제작)는 대부분의 브라우저 호환 LOD 파이프라인 뒤에 있는 라이브러리입니다. 1.0 버전(2025)이 제공하는 것은 이렇습니다.
- 오차 지표가 있는 메시 단순화(형상이 얼마나 바뀌었는지, LOD 선택에 사용)
- Nanite 스타일 meshlet 위계를 위한 클러스터 생성
- GPU 친화적 삼각형 정렬을 위한 버텍스 캐시 최적화
- 픽셀 셰이더 비용을 줄이는 오버드로 최적화
- 더 작은 다운로드를 위한 버텍스 양자화 및 압축
meshoptimizer 1.0(2025년 12월 출시)은 Nanite 스타일 연속 LOD를 직접 구현하는 새로운 단일 헤더 clusterlod.h를 제공합니다. 점진적으로 그룹화되고 단순화되는 클러스터 위계를 만들며, 그대로 쓰거나 커스텀 파이프라인의 참조로 쓸 수 있습니다. 이것이 바로 지형 파이프라인이 SDF/marching-cubes 메시 LOD에 필요로 하는 클러스터 DAG 프리미티브입니다.
우리 지형 파이프라인에서는 meshoptimizer가 SDF 지형의 marching cubes 출력을 LOD 위계가 있는 최적화된 클러스터 메시로 처리합니다. 오프라인 처리는 서버 측에서 돌아갑니다. 브라우저는 미리 클러스터화된 메시를 받아 런타임에 GPU 구동 LOD 선택을 수행합니다.
LOD 생성을 위한 meshoptimizer와 런타임 선택을 위한 WebGPU compute의 조합은 브라우저 지형에 Nanite와 같은 아키텍처 패턴을, 웹 제약에 맞게 적응시켜 제공합니다.
지형 인식 레벨 디자인
지형은 그저 위를 걷는 표면이 아닙니다. 그 형태가 플레이어 이동을 안내하고, 주의를 끌고, 탐험의 감정적 리듬을 만듭니다. 최고의 오픈 월드는 지형을 디자인 도구로 씁니다.
시선과 랜드마크
The Level Design Book의 길찾기 장은 지형 고도가 플레이어가 무엇을 보고 어디로 가는지를 어떻게 제어하는지 기록합니다. 능선은 그 너머를 숨겨 호기심을 만듭니다. 계곡은 이동을 가장 낮은 지점으로 깔때기처럼 모읍니다. 멀리서 보이는 높은 랜드마크(탑, 산봉우리, 특이한 나무)는 플레이어에게 걸어갈 목표를 줍니다.
크리에이터 월드에서 이건 지형 생성이 자연스러운 길찾기 피처를 만들어야 한다는 뜻입니다. 능선은 시선을 끊어 플레이어가 언덕을 넘어 새 영역을 볼 때 "드러나는 순간"을 만들어야 합니다. 계곡은 흥미로운 위치로 모여야 합니다. 크리에이터가 멀리서 보이는 랜드마크를 배치할 수 있는 높은 지점이 존재해야 합니다.
호기심 주도 탐험
퍼듀 대학교의 연구(논문)는 네 가지 공간 탐험 트리거를 밝혀냅니다.
- 극단 지점 도달(가장 높은 봉우리, 가장 먼 가장자리, 가장 깊은 동굴). 지형은 도달을 보상하는 명확한 극단을 가져야 합니다.
- 시각적 가림 해소(저 절벽 뒤에 뭐가 있지? 저 동굴 안에는?). 시야를 막는 지형은 숨겨진 것을 찾도록 이동을 유발합니다.
- 어울리지 않는 오브젝트(황야의 구조물, 어둠 속의 빛). 자연 지형에 대비되는 크리에이터 배치 오브젝트가 주의를 끄는 대비를 만듭니다.
- 공간적 연결 이해(이 계곡이 저 해안과 어떻게 이어지지?). 읽기 쉬운 지리를 만드는 지형은 지도 읽기와 경로 계획을 장려합니다.
PlotMap: AI 보조 POI 배치
PlotMap(arXiv:2309.15242)은 서사 요구사항(이 퀘스트는 강 근처에 마을이 필요하고, 저 퀘스트는 언덕 위에 폐허가 필요함)을 받아 공간 제약을 만족하는 지형 위치를 찾아 관심 지점 배치를 자동화합니다. 크리에이터 월드에서는 비슷한 시스템이 지형 속성에 따라 구조물 배치를 제안할 수 있습니다. "이 언덕 정상은 망루에 좋은 시선을 가졌다", "이 아늑한 계곡은 마을에 어울린다".
흐르는 물과 폭포
강과 폭포는 시각적 매력을 환경음 및 게임플레이 어포던스(장벽, 자원, 경로로서의 물)와 결합하는 지형 피처입니다.
강 렌더링
오픈 월드의 강은 보통 지형 표면을 따르는 텍스처 스트립으로 렌더링됩니다. 스트립 메시는 강 스플라인(컨트롤 포인트로 저장됨)에서 생성되어 지형 하이트맵에 투영됩니다. 강 셰이더는 다음을 적용합니다.
- 강 방향으로 스크롤하는 흐름 정렬 UV, 흐르는 물의 외형을 만듭니다
- 강이 둑과 만나는 곳의 가장자리 거품(깊이 기반, 해안선 거품과 유사)
- 하도 너비에 따른 속도 변화(좁은 구간은 빠르게 흐르고, 넓은 구간은 느려짐)
- 깊이 기반 색이 있는 투명도(얕으면 맑고, 깊으면 어두움)
브라우저 월드에서 강 데이터는 작습니다. 스플라인(강 구간당 20-50개 컨트롤 포인트, ~400바이트)에 너비와 흐름 속도 파라미터를 더합니다. 클라이언트는 스플라인을 자기 지형 표면에 투영해 강 메시를 로컬로 생성합니다.
폭포 렌더링
강이 절벽면에서 떨어지는 곳에서는 폭포 파티클 시스템이 평평한 강 표면을 대체합니다. 실시간 물 시뮬레이션 연구의 하이브리드 방식(EG): 높이장으로 표현할 수 없는 영역(폭포, 물보라)이 유체 시뮬레이션과 질량 및 운동량을 교환하는 물보라, 튀김, 거품 파티클로 변환됩니다.
브라우저 월드에서 폭포는 더 단순합니다. 강 스플라인이 지형 높이 불연속을 가로지르는 곳을 감지해, 그 지점에 하향 속도를 가진 파티클 시스템을 생성하고, 밑부분에 거품 튀김을 더합니다. 파티클은 스크롤하는 알파 텍스처가 있는 GPU 인스턴스 쿼드입니다. 폭포당 500개 파티클, 드로우 콜 하나. 떨어지는 물소리는 거리 감쇠가 있는 Web Audio API를 씁니다.
먼 지형 피처를 위한 임포스터
나무, 바위, 건물, 그 밖의 지형 피처는 멀리서 아주 작아집니다. 이것들을 완전한 3D 메시로 렌더링하는 것은 GPU 사이클을 낭비합니다. 임포스터는 먼 오브젝트를 카메라를 향하는 미리 렌더링된 평평한 이미지로 대체합니다.
팔면체 임포스터 아틀라스
팔면체 임포스터는 3D 오브젝트의 외형을 여러 시야각에서 포착해 텍스처 아틀라스에 저장합니다. 런타임에 셰이더가 현재 시야 방향을 기준으로 아틀라스를 샘플링하며, 가장 가까운 두 포착 각도 사이를 보간합니다.
반팔면체 아틀라스(나무를 아래에서 볼 일이 드물어 위쪽 반구 시야만)는 같은 텍스처 크기로 완전한 팔면체 아틀라스의 두 배 각도 해상도를 제공합니다. Unity의 임포스터 시스템은 1,600개의 나무 인스턴스를 실제 메시(각 14만 삼각형)에서 임포스터로 전환할 때 프레임 시간이 111ms에서 5.78ms로 떨어진다고 보고합니다.
브라우저 월드에서 임포스터 파이프라인은 이렇습니다.
- 서버 측: 각 에셋을 16-32개 시야각에서 렌더링해 색, 노멀, 깊이를 포착합니다
- 아틀라스 텍스처로 패킹합니다(에셋당 아틀라스 하나, ~256x256 픽셀, KTX2로 <100 KB)
- 런타임: 임포스터 거리 너머의 인스턴스(보통 100-200m)는 아틀라스를 샘플링하는 빌보드로 렌더링됩니다
- 전환을 숨기기 위해 20m 전환 구간에 걸쳐 메시와 임포스터를 크로스페이드합니다
빌보드 스플래팅 (BBSplat)
빌보드 스플래팅(2024, arXiv:2411.08508)은 학습 가능한 텍스처 평면 프리미티브를 써서 한 걸음 더 나아갑니다. 미리 렌더링된 시야 대신, BBSplat은 어떤 각도에서든 3D 오브젝트를 가장 잘 표현하도록 빌보드 위치와 텍스처를 최적화합니다. 이것은 시야 의존적 외형을 유지하면서 3D Gaussian Splatting 대비 최대 17배 압축을 달성합니다. 브라우저 월드의 먼 지형 피처에서 BBSplat은 각도 커버리지를 개선하면서 에셋당 임포스터 저장량을 줄일 수 있습니다.
전문 지형 도구와 그것이 가르치는 것
지형 파이프라인을 맨바닥부터 만들기 전에, 전문 오프라인 도구가 무엇을 하는지 이해할 가치가 있습니다. 이 도구들은 수십 년의 지형 생성 연구를 프로덕션 워크플로로 증류한 것입니다.
Gaea(QuadSpinner)는 GPU 가속이며 변화에 거의 즉각적인 피드백을 줍니다. 변당 최대 200만 픽셀까지의 타일 빌드, 자동 LOD 메시 익스포트, 그리고 각 노드가 물리 과정(침식, 퇴적, 융기, 열 풍화)인 노드 기반 그래프를 지원합니다. Gaea의 침식 노드는 손으로 조각한 듯 보이는 지형을 만듭니다. 일반적인 노이즈가 아니라 구체적인 물리 과정을 모델링하기 때문입니다. 핵심 통찰: Gaea는 단일 침식 알고리즘을 쓰지 않습니다. 하천 침식(강 깎기), 열 침식(절벽 부서짐), 해안 침식(파도 작용), 풍식(모래언덕 형성)에 별도의 노드를 제공합니다. 이것들을 그래프에서 조합하면 특정 기후의 지질 성격을 가진 지형이 나옵니다.
World Machine은 지형 거시 구조에 초점을 둔 비슷한 그래프 방식을 취합니다. "레이아웃 제너레이터"는 아티스트가 지형 피처의 대략적 형태(여기 산, 저기 계곡, 이 가장자리를 따라 해안선)를 스케치하면 시스템이 물리적으로 그럴듯한 디테일을 채워 넣게 합니다. 이것이 바로 우리가 원하는 크리에이터 워크플로입니다. 의도를 스케치하면 지질을 얻습니다.
World Creator는 편집 중 실시간 미리보기와, 지형을 분석해 배수 분석을 기준으로 흐름 경로를 자동 계산하는 내장 강 생성으로 차별화합니다.
이 도구들에서 우리가 가져가는 것: 물리 과정을 조합하는 노드 그래프 방식은 어떤 단일 알고리즘보다 강력합니다. 우리의 서버 측 생성 파이프라인은 연쇄를 지원해야 합니다. 노이즈 기반 > 지각 융기 > 수력 침식 > 열 풍화 > 해안 침식 > 식생. 크리에이터가 각 단계의 파라미터를 제어합니다. 파이프라인은 서버 측에서 몇 초 안에 돌아가 하이트맵, 스플랫 맵, 식생 밀도 맵을 만듭니다.
SoilMachine: 오픈소스 지형학
SoilMachine은 여러 침식 시스템(수력, 열, 바람)을 퇴적물 운반 및 퇴적과 결합하는 오픈소스 모듈식 지형학 시뮬레이터입니다. C++와 GPU compute로 만들어졌으며, 전문 도구가 쓰는 다중 과정 침식 방식의 참조 구현을 제공합니다.
관련된 soillib(C++20, MIT 라이선스)는 바탕 지형학 시뮬레이션 프리미티브를 재사용 가능한 라이브러리로 제공합니다. 그리고 hydro-gen은 OpenGL compute 셰이더에서 격자 기반(천수)과 입자 기반(빗방울) 수력 침식을 모두 구현하며 실시간 파라미터 조정을 지원합니다.
이 오픈소스 도구들은 우리의 서버 측 생성 파이프라인에 적응시킬 수 있습니다. compute 셰이더 구현은, 실시간 크리에이터 피드백을 위해 브라우저에서 침식을 돌리고 싶어진다면, WebGPU로 바로 옮겨집니다.
다층 지형 머티리얼
진짜 지형은 단일 표면이 아닙니다. 층입니다. 바닥의 기반암, 그 위의 토양, 표면에 쌓이는 눈이나 모래. 동적 레이어링은 계절, 날씨, 크리에이터 행동에 따라 지형의 시각적 성격을 바꿉니다.
층상 하이트필드 표현
단일 하이트맵 대신 격자 셀당 여러 높이 레이어를 씁니다.
Cell {
bedrock_height: f16, // 영구 암석 표면
soil_height: f16, // 기반암 위에 쌓인 토양/퇴적물
snow_height: f16, // 동적 눈 누적
water_height: f16 // 고인 물 깊이
}합계: 셀당 8바이트(단일 하이트맵의 2바이트 대비). 65x65 청크면 압축 전 34 KB입니다. 여전히 작습니다.
시각적 표면은 bedrock + soil + snow입니다. 지형 셰이더가 모든 레이어를 읽어 머티리얼을 그에 맞게 블렌딩합니다. 토양이 얇은 곳은 바위가 비쳐 나옵니다. 눈이 쌓인 곳은 표면이 하얗습니다. 물이 고인 곳은 물웅덩이나 호수가 됩니다.
동적 누적
눈은 강설 동안 평평하고 위를 향한 표면에 쌓입니다. 누적률은 표면 법선(가파른 경사는 눈을 머금지 못함), 온도(고도 의존적), 차폐(오버행 아래 영역은 깨끗하게 유지됨)에 달려 있습니다. compute 셰이더 패스가 날씨 틱당 한 번(몇 초마다) 눈 레이어를 업데이트합니다.
모래 누적도 바람 구동 퇴적으로 비슷하게 동작합니다. 바람이 노출된 표면에서 입자를 운반해 장애물 뒤와 차폐된 영역에 퇴적합니다.
크리에이터 월드에서 동적 누적은 지형이 날씨마다 다르게 보인다는 뜻입니다. 눈보라 동안 눈이 월드를 덮고 맑은 시기에 녹습니다. 비가 움푹한 곳을 물로 채웁니다. 이렇게 하면 크리에이터가 아무것도 하지 않아도 월드가 반응적으로 느껴집니다.
다층 침식
2024년 논문 "3D Real-Time Hydraulic Erosion Simulation using Multi-Layered Heightmaps"(EG)는 침식을 레이어를 가로질러 동작하도록 확장합니다. 물은 토양을 기반암보다 빠르게 침식합니다. 퇴적물은 새 토양 레이어로 쌓입니다. 시뮬레이션은 레이어 무결성을 유지하면서(기반암이 토양 아래에 머묾) 오버행 같은 복잡한 피처(기반암이 아래 침식된 토양 위로 돌출)를 가능하게 합니다.
성능: RTX 3070에서 2048x2048 해상도로 시뮬레이션 스텝당 약 6ms. 이건 서버 측 생성에는 충분히 빠르지만 프레임당 브라우저 시뮬레이션에는 너무 느립니다. 층상 표현은 정적 지형 생성에 동작하고, 동적 눈/물 누적은 더 싼 프레임당 셰이더로 돌아갑니다.
풀, 바위, 디테일 렌더링
풍경은 지형 지오메트리와 텍스처 이상이 필요합니다. 바람에 흔들리는 풀잎, 경사에 흩어진 바위, 그리고 가까이서 봤을 때 자연스러워 보이게 하는 꽃, 자갈, 떨어진 나뭇가지 같은 작은 디테일이 필요합니다.
GPU 인스턴스 풀
브라우저 기반 풀 렌더링은 Three.js에서 잘 검증되어 있으며 GPU 인스턴싱으로 동작합니다. al-ro의 풀 데모의 방식은 InstancedBufferGeometry를 써서 10만 개의 풀잎을 단일 드로우 콜로 렌더링합니다.
각 풀잎은 단순한 쿼드(4-8 삼각형)입니다. 인스턴스별 속성이 위치, 높이, 휘는 방향, 색 변화, 바람 위상을 정의합니다. 버텍스 셰이더는 이렇습니다.
- 인스턴스별 트랜스폼을 읽습니다
- 월드 위치와 시간에 맞춘 사인파로 바람 애니메이션을 적용합니다
- 바람 세기에 따라 잎을 휩니다(끝은 더 많이, 밑은 안 휨)
- 색 그라디언트를 적용합니다(밑은 더 어둡고, 끝은 표면하 산란을 위해 더 밝음)
Codrops의 풍성한 풀 튜토리얼(2025, 튜토리얼)은 셸 텍스처링 방식을 시연합니다. 지면을 점점 커지는 오프셋으로 여러 번 렌더링하고, 각 레이어가 노이즈 텍스처를 샘플링해 빽빽한 풀 볼륨의 외형을 만듭니다. 이건 아주 빽빽한 커버리지에는 개별 잎 인스턴싱보다 싸지만 가까이서는 덜 사실적입니다.
크리에이터 월드에서 풀 밀도는 청크당 식생 밀도 맵에서 나옵니다. GPU가 렌더 타임에 밀도 맵에서 잎 위치를 뿌립니다. 잎별 데이터는 저장하거나 스트리밍하지 않습니다. 밀도 맵은 청크당 32x32 격자(1 KB)이며, GPU가 거기서 수천 개의 잎 인스턴스를 생성합니다.
절차적 바위와 절벽 디테일
절벽면과 바위 지형은 기반 하이트맵이나 SDF가 합리적인 해상도로 제공할 수 없는 기하학적 디테일이 필요합니다. 두 방식이 서로 보완합니다.
GPU 메시 셰이더 재표면화(Raad et al., Eurographics 2025, 논문)는 렌더 타임에 거친 컨트롤 메시에서 절차적 지오메트리를 생성합니다. 메시 셰이더가 기반 지형 표면을 읽어 디테일 지오메트리를 메모리에 저장하지 않고 변위, 균열, 돌출을 더합니다. 이것은 VRAM 사용을 줄이고 동적 LOD를 가능하게 합니다.
인스턴스 바위 산포는 GPU 인스턴싱을 써서 가파른 경사와 절벽 가장자리에 미리 만든 바위 메시를 배치합니다. compute 셰이더가 지형 법선과 경사를 읽어 경사가 임계값을 넘는 곳에 바위 인스턴스를 뿌립니다. 각 인스턴스는 무작위 회전과 스케일이 있는 작은 메시(200-500 삼각형)입니다. 1만 개의 흩뿌린 바위는 인스턴싱으로 무시할 만한 렌더링 비용을 더합니다.
도로와 길
크리에이터가 배치한 도로, 오솔길, 길은 지형에 맞추고 표면 머티리얼을 수정(풀을 흙이나 돌로 대체)해야 합니다.
모든 주요 게임 엔진이 쓰는 방식: 길을 스플라인(일련의 컨트롤 포인트)으로 정의합니다. 스플라인을 지형 표면에 투영합니다. 스플라인을 따르며 지형보다 약간 위에 앉는 스트립 메시를 생성합니다. 스트립에 도로 텍스처를 적용합니다. 지형 셰이더에서 투영 텍스처나 데칼을 써서 지형 머티리얼을 스플라인 너비 안의 도로 머티리얼로 블렌딩합니다.
브라우저 월드에서는 크리에이터가 지형에 길을 그립니다. 클라이언트가 컨트롤 포인트를 생성해 서버로 보냅니다(수십 개의 vec3 값). 서버가 스플라인을 저장합니다. 모든 클라이언트가 스플라인을 자기 지형 메시에 투영해 도로 스트립을 로컬로 렌더링합니다. 도로 데이터는 작지만(길 스플라인 포인트, 아마 200바이트) 시각적 영향은 큽니다. 크리에이터 건물을 잇는 길은 월드가 사람이 사는 곳처럼 느껴지게 합니다.
지형을 위한 그림자
지형 그림자는 가독성(지형 형태 이해)과 분위기(시간대 무드)에 핵심입니다. 오픈 월드에서 태양은 가시 지형 전체에 그림자를 드리웁니다.
캐스케이드 섀도 맵 (CSM)
CSM은 뷰 프러스텀을 3-4개 거리 범위(캐스케이드)로 나눕니다. 각 캐스케이드는 그 거리에 맞는 해상도로 태양 시점에서 섀도 맵을 렌더링합니다. 가까운 캐스케이드: 고해상도(나무와 건물 아래의 상세한 그림자). 먼 캐스케이드: 저해상도(넓은 산 그림자).
Three.js와 Babylon.js 모두 CSM을 지원합니다. 지형의 핵심 최적화: 섀도 맵에는 지형만 렌더링하고 개별 풀잎이나 작은 디테일은 렌더링하지 않습니다. 풀은 자기 것이 아니라 지형의 섀도 맵을 써서 자기 그림자를 만듭니다.
성능 예산: 각 1024x1024인 3-4개 섀도 캐스케이드. 섀도 맵에 지형을 렌더링하는 비용은 0.5-1ms입니다(지형 지오메트리는 이미 GPU 메모리에 있음). 지형 셰이더에서 4개 캐스케이드를 샘플링하는 것은 0.2-0.3ms를 더합니다.
하이트맵에서의 지형 자기 그림자
CSM이 비싸지는 아주 큰 지형에서는 지평선 맵을 사전 계산합니다. 각 지형 셀마다 8개 나침반 방향의 최대 고도각을 저장합니다. 렌더 타임에 태양 각도를 지평선 맵과 비교해 한 점이 그림자 안에 있는지 판단합니다. 이것이 Skyrim이 먼 지형(CSM 범위 너머)의 지형 자기 그림자를 처리하는 방식입니다.
지평선 맵은 하이트맵에서 서버 측으로 계산되고(몇 초의 처리) 청크당 128x128 텍스처로 스트리밍됩니다(압축 16 KB). 시각적 영향은 상당합니다. 산골짜기가 극단적인 시야 거리에서도 사실적으로 어두워집니다.
스트리밍을 위한 지형 데이터 압축
네트워크가 브라우저 월드의 병목입니다. 지형 데이터에서 아낀 모든 바이트가 더 빠른 로드 시간입니다.
하이트맵 압축
원시 16비트 하이트맵은 인접 셀이 비슷한 값을 가져 잘 압축됩니다. 파이프라인은 이렇습니다.
- 델타 인코딩: 각 셀과 그 예측값(이웃의 평균)의 차이를 저장합니다. 델타 값은 작고 0 근처에 모입니다.
- 양자화: 먼 청크에는 정밀도를 16비트에서 12비트나 8비트로 줄입니다. 500미터 떨어진 곳에서 8비트 높이 정밀도(100m 높이 범위에서 0.4m 해상도)는 16비트와 구별할 수 없습니다.
- 엔트로피 코딩: 델타 인코딩된 스트림에 zlib나 brotli 압축을 적용합니다. 전형적인 압축률: 4-8배.
결과: 16비트 65x65 청크가 원시 8.4 KB에서 압축 1-2 KB로 줄어듭니다. 8비트 축소 정밀도에서는 0.5-1 KB입니다.
점진적 하이트맵 스트리밍
지형을 먼저 낮은 해상도로 보낸 뒤 정제합니다. 17x17 하이트맵(4m 셀 간격의 64m 청크에 대한 최소값)은 원시 578바이트, 압축 200바이트 미만입니다. 지형이 즉시 보입니다. 그다음 33x33 정제(홀수 행/열 샘플 추가)를 스트리밍합니다. 그다음 65x65 풀 해상도. 각 레벨은 이전 데이터를 대체하지 않고 디테일을 더합니다.
이것은 geometry clipmap LOD 링에 매핑됩니다. 먼 지형은 저해상도 버전(17x17)을, 중거리는 중간(33x33)을, 가까운 곳은 풀(65x65)을 씁니다. 스트리밍 우선순위가 렌더링 LOD와 일치합니다.
SDF 볼륨 압축
희소 SDF 볼륨은 대부분의 복셀이 표면에서 멀리(빈 공간) 떨어져 있어 극적으로 압축됩니다. 옵션은 이렇습니다.
런렝스 인코딩: 같은 값(빈 복셀)의 런을 인코딩합니다. 전형적인 SDF 볼륨은 95% 이상이 비어 있어 RLE가 10-50배 압축을 달성합니다.
희소 옥트리: 표면 교차 복셀을 포함하는 옥트리 노드만 저장합니다. 빈 공간에는 노드가 없습니다. 동굴 터널 하나가 있는 64^3 SDF 볼륨은 점유 노드가 2,000-5,000개뿐일 수 있으며(총 262,144 복셀 대비), 각각 1-2바이트로 저장됩니다.
엔트로피 주도 점진적 압축(2024, HAL)은 엔트로피 최적화 평면과 적응형 양자화로 공간을 재귀적으로 분할해 3D 공간 데이터에 적용됩니다. 이것은 레이트-디스토션 트레이드오프에 최적화된 정제 스트림을 만들며, 특히 네트워크 스트리밍의 낮은 비트레이트에서 유익합니다.
종합하기: 브라우저 지형 파이프라인
이 글 맨 위의 전략 개요는 빠른 의사결정 프레임워크와 단계별 빌드 계획을 줍니다. 이 절은 서버 측 생성 파이프라인과 브라우저 렌더링 파이프라인 모두에 대한 완전한 기술 디테일을 제공합니다.
생성 파이프라인 (서버 측)
생성 파이프라인은 Gaea와 World Machine의 노드 그래프 방식에서 영감을 받아 물리 과정의 방향성 그래프로 돌아갑니다. 각 단계는 이전 단계의 출력을 받아 정제합니다. 크리에이터가 각 단계의 파라미터를 제어합니다.
| 단계 | 입력 | 과정 | 출력 | 시간 |
|---|---|---|---|---|
| 1. 기반 지형 | 시드 또는 텍스트 프롬프트 | Terrain Diffusion / MESA / 노이즈 + fBm | 16비트 하이트맵 | 1-5s |
| 2. 침식 | 하이트맵 | 해석적 stream power + 열 침식 | 침식 하이트맵, 흐름 누적 맵, 퇴적 맵 | 0.5-2s |
| 3. 강 | 침식 하이트맵, 흐름 맵 | 배수 네트워크 추출, 하도 깎기 | 강 스플라인, 수위 맵 | 0.5s |
| 4. 해안 | 해수면 근처 하이트맵 | NEWTS 스타일 파도 침식 | 해안선 피처(절벽, 해변, 스택) | 1-3s |
| 5. 볼류메트릭 | 하이트맵 + 크리에이터 의도 | Arenite 침식 / 동굴 생성 / SDF 조각 | 영향받은 청크의 희소 SDF 볼륨 | 1-60s |
| 6. 머티리얼 | 하이트맵 + 침식 맵 | TerraFusion / Geodiffussr / 절차적 규칙 | 스플랫 맵, 지형 텍스처 | 1-5s |
| 7. 식생 | 하이트맵 + 흐름 맵 + 머티리얼 | 생태계 경쟁 시뮬레이션 | 생물군계별 청크별 밀도 맵 | 1-3s |
| 8. 지평선 맵 | 최종 하이트맵 | 8방향 최대 고도각 | 청크당 자기 그림자 텍스처 | 2-5s |
| 9. 청킹 | 모든 출력 | 슬라이스, 델타 인코딩, 압축, 해시 | CDN의 청크 패키지 | 5-10s |
| 합계 | 15-90s |
새 4x4 km 월드는 15-90초 만에 생성됩니다. 크리에이터 편집(조각, 파라미터 변경)은 영향받은 청크에 대해 영향받은 단계만 다시 돌리며, 보통 5초 미만에 완료됩니다.
렌더링 파이프라인 (브라우저)
| 단계 | WebGPU 경로 | WebGL 2 폴백 | 프레임 예산 |
|---|---|---|---|
| 1. 스트리밍 | 우선순위 큐, 예측 선반입 | 동일 | 해당 없음(비동기) |
| 2. 하이트맵 지형 | GPU 구동 CDLOD 쿼드트리, compute 컬링, 간접 드로우 | Geometry clipmap, CPU 링 업데이트 | 0.5-1ms |
| 3. 볼류메트릭 메시 | Compute marching cubes + Transvoxel | Web Worker의 미리 생성한 메시, 2-3개 캐시 LOD | 0.5-2ms |
| 4. LOD 전환 | 버텍스 셰이더의 geomorphing | 동일 | 위에 포함됨 |
| 5. 머티리얼 | Triplanar PBR + 라플라시안 블렌딩 + phasor 노이즈 디테일 + 가상 텍스처링 | Triplanar PBR + 선형 블렌딩 + 사전 베이크 스플랫 맵 | 1-1.5ms |
| 6. 식생 | ComputeInstanceCulling + IndirectBatchedMesh, hex-tiled 지면 덮개 | CPU 프러스텀 컬링 + InstancedMesh | 1-1.5ms |
| 7. 물 | 흐름 정렬 강 스트립, 깊이 기반 해안 거품 | 동일(더 단순한 반사) | 0.5ms |
| 8. 그림자 | 3-4 캐스케이드 CSM + 지평선 맵 자기 그림자 | 2 캐스케이드 CSM | 0.5-1ms |
| 9. 대기 | Hillaire 하늘 모델 + 볼류메트릭 안개 + 날씨 파티클 | Preetham 하늘 + 거리 안개 | 0.5ms |
| 10. 동적 효과 | 물웅덩이 누적, 발자국 변형, 눈/비 | 물웅덩이 누적, 비 파티클 | 0.3ms |
| 지형 합계 | 3.5-6.5ms |
60fps(프레임당 16.6ms)에서 지형 시스템은 WebGPU에서 프레임 예산의 21%, WebGL 2에서 39%를 씁니다. 나머지는 플레이어 아바타, 크리에이터 오브젝트, UI, 네트워킹, 후처리에 가용합니다.
이것이 브라우저에서 동작하는 이유
전체 파이프라인은 세 가지 브라우저 제약을 중심으로 설계되었습니다.
메모리(최대 2-4 GB): 256 MB 지형 예산이 들어맞습니다. 하이트맵 청크가 각 2-8 KB(델타 인코딩)이고, SDF 볼륨이 희소하며(볼류메트릭 청크당 100-500 KB), 식생이 1 KB 밀도 맵에서 런타임에 생성되고, 텍스처가 KTX2 압축(1024x1024당 150 KB)을 쓰기 때문입니다. 어느 순간이든 브라우저에 보이는 월드는 총 50-200 MB입니다.
디스크 접근 없음: 모든 것이 네트워크로 스트리밍됩니다. 점진적 로딩은 플레이어가 <100ms에 지형(저해상도 하이트맵)을, <300ms에 텍스처가 입혀진 지형을, <3s에 풀 디테일을 본다는 뜻입니다. 속도 기반 선반입이 보통의 탐험 중 로드 시간을 숨깁니다.
GPU가 천차만별: WebGPU 경로는 고사양 데스크톱을 다룹니다. WebGL 2 폴백은 모바일을 포함한 그 밖의 모든 것을 다룹니다. 같은 청크 데이터가 두 경로를 모두 구동합니다. 차이는 렌더링 기법이지 데이터 포맷이 아닙니다. WebGL 2를 돌리는 Chromebook은 WebGPU를 돌리는 RTX 4090과 같은 월드를 봅니다. 단지 디테일이 낮고 시야 거리가 짧을 뿐입니다.
연구 논문
지형 표현과 메시 생성
"Marching Cubes: A High Resolution 3D Surface Construction Algorithm" -- Lorensen and Cline (SIGGRAPH 1987). DOI. 볼류메트릭 데이터에서 삼각형 메시를 추출하는 기초 알고리즘. 38년이 지난 지금도 가장 널리 쓰이는 등치면 추출 방법입니다. GPU 병렬 구현은 WebGPU compute 셰이더에서 실시간으로 돌아갑니다.
"Dual Contouring of Hermite Data" -- Ju, Losasso, Schaefer, Warren (SIGGRAPH 2002). DOI. marching cubes가 둥글려 버리는 날카로운 피처(절벽 모서리, 바위 코너)를 보존하는 메시를 만듭니다. 거리 값에 더해 표면 법선을 필요로 합니다.
"Neural Dual Contouring" -- Chen et al. (2022). arXiv:2202.01999. dual contouring의 최소제곱 정점 배치를 학습된 예측기로 대체합니다. 복잡한 자연 피처에 더 나은 표면 품질.
"The Transvoxel Algorithm" -- Lengyel (2009, 2024 갱신). transvoxel.org. 복셀 지형을 위한 이음매 없는 LOD 전환. 73가지 전환 셀 유형으로 해상도 경계의 균열을 없앱니다. 특허 없음, 실시간 응용을 위해 설계됨.
지형 LOD와 렌더링
"Geometry Clipmaps: Terrain Rendering Using Nested Regular Grids" -- Losasso and Hoppe (SIGGRAPH 2004). 논문. 동심 LOD 링으로 일정 비용 지형 렌더링. 40 GB 지형을 인터랙티브한 속도로 처리합니다. 대부분의 브라우저 지형 렌더러의 기초.
"CDLOD: Hybrid LOD for Terrain Rendering" -- Strugar (2014). 논문. geometry clipmap에 대한 쿼드트리 적응형 개선. 거리만이 아니라 지형 복잡도에 따라 해상도를 할당합니다.
"GPU-Driven Rendering Pipelines" -- Ubisoft (SIGGRAPH 2015), Wihlidal and Hoppe. compute 셰이더가 컬링, LOD 선택, 드로우 콜 생성을 처리하는 GPU 구동 방식을 정식화했습니다. 우리 WebGPU 지형 파이프라인의 아키텍처 패턴.
물리 지형 생성
"Physically-Based Analytical Erosion for Fast Terrain Generation" -- Cordonnier et al. (2024). HAL. 반복 시뮬레이션을 피하는 해석적 stream power law 침식. 밀리초 단위로 물리적으로 그럴듯한 지형을 생성합니다.
"Fast Hydraulic Erosion Simulation and Visualization on GPU" -- Mei, Decaudin, Hu (2007). HAL. 천수 시뮬레이션을 쓰는 GPU 병렬 수력 침식. 대부분의 게임 엔진 침식 구현의 기반.
"Arenite: A Physics-Based Sandstone Simulator" -- SIGGRAPH 2025. 프로젝트. 응력과 침식 시뮬레이션으로 아치, 후두, 알코브를 생성하는 다중 물리 침식. 데스크톱 GPU에서 5분 미만에 돌아갑니다.
"Efficient Debris-flow Simulation for Steep Terrain Erosion" -- Purdue CGVLAB (2024). 논문. 사실적인 산악 지형 피처를 만드는 GPU 가속 토석류 및 급경사 침식.
"Flexible Terrain Erosion" -- IRIT-STORM (2024). Springer. 통합 인터페이스로 하이트필드, 복셀 격자, 음함수 표면, 층상 머티리얼을 가로질러 동작하는 입자 기반 침식. 하이브리드 지형 표현을 위한 단일 침식 시스템을 가능하게 합니다.
지형 디테일과 텍스처링
"GPU-Friendly Laplacian Texture Blending" -- Wronski (NVIDIA, 2025). JCGT. 사전 계산 없는 지형 머티리얼 실시간 라플라시안 피라미드 블렌딩. 이음매 아티팩트를 없애면서 날카로운 피처를 보존합니다. 프래그먼트당 몇 번의 추가 텍스처 탭.
"Real-time Terrain Enhancement with Controlled Procedural Patterns" -- Grenier et al. (2024). CGF. 최대 32배 하이트맵 해상도의 phasor 노이즈 기반 미세 침식 디테일. 경사 정렬 패턴이 전적으로 프래그먼트 셰이더에서 돌아갑니다.
적응형 테셀레이션
"Concurrent Binary Trees for Large-Scale Game Components" -- Benyoub and Dupuy (Intel, HPG 2024). 논문. 적응형 지형 테셀레이션을 위한 GPU 친화적 이진 트리 자료구조. 행성 규모 지오메트리를 0.2ms 미만에 렌더링합니다. 정사각형 도메인에서 임의의 다각형 메시로 확장됨.
동굴과 지하 생성
"PLUME: Procedural Layer Underground Modeling Engine" -- 2024. arXiv:2508.20926. 층상 절차적 규칙으로 사실적인 동굴과 용암 동굴 환경을 생성하는 오픈소스 프레임워크. 원래 우주 탐사 로보틱스를 위해 만들어졌습니다.
뉴럴 지형 합성
"InfiniteDiffusion: Bridging Learned Fidelity and Procedural Utility for Open-World Terrain Generation" -- Goslin (2025, SIGGRAPH 2026). arXiv:2512.08309. 라플라시안 인코딩이 있는 위계적 디퓨전 모델을 쓰는 무한, 시드 일관 지형 생성. 소비자용 GPU에서 베이스라인보다 9배 빠름.
"TerraFusion: Joint Generation of Terrain Geometry and Texture" -- 2025. arXiv:2505.04050. 스케치 조건이 있는 동시 하이트맵 및 텍스처 합성을 위한 잠재 디퓨전.
"MESA: Text-Driven Terrain Generation" -- CVPR 2025 Workshop. arXiv:2504.07210. Copernicus 원격탐사 학습 데이터를 쓰는 텍스트에서 지형으로.
"Geodiffussr: Generative Terrain Texturing with Elevation Fidelity" -- 2025. arXiv:2511.23029. 흐름 매칭을 써서 고도 데이터를 존중하는 텍스트 안내 지형 텍스처 생성.
"Sketch2Terrain: AI-Driven Real-Time Terrain Sketch Mapping" -- 2025. 프로젝트. 증강 현실에서의 스케치에서 지형으로. 수동 매핑 대비 38% 효율 향상.
식생과 생태계 시뮬레이션
"GPU-Based Real-Time Procedural Distribution of Vegetation on Large-Scale Virtual Terrains" -- SBGames 2018. 논문. GPU에서 생물/비생물 인자를 쓰는 쿼드트리 기반 식생 산포.
"Procedural Generation and Rendering of Forests" -- 2022. 논문. 사실적인 숲 분포를 위한 L-system 나무 생성과 생태계 경쟁 시뮬레이션의 결합.
"Real-Time Procedural Generation with GPU Work Graphs" -- AMD GPUOpen 2024. 논문. 7.9만 개 이상의 식생 인스턴스를 4ms 미만에 생성하는 GPU work graph.
브라우저 GPU 기술
"GSWT Renderer" -- SIGGRAPH Asia 2025. GitHub. 동적 LOD와 스트리밍이 있는 무한 3D 지형을 위해 Gaussian Splatting Wang Tiles를 쓰는 WebGPU + Rust/Wasm 렌더러.
"GPU Compute in the Browser at the Speed of Native: WebGPU Marching Cubes" -- Usher (2024). 블로그. WebGPU compute가 병렬 메시 생성 알고리즘에 네이티브 속도 성능을 달성함을 시연합니다.
복셀 렌더링과 대규모 씬
"Aokana: A GPU-Driven Voxel Rendering Framework for Open World Games" -- 2025. arXiv:2505.02017. 수백억 개의 복셀이 있는 씬을 위한 LOD와 스트리밍이 있는 희소 복셀 DAG. 이전 최신 기술 대비 9배 메모리 감소와 4.8배 빠른 렌더링. 게임 엔진 통합을 위해 설계됨.
절차적 지오메트리와 재표면화
"Real-time Procedural Resurfacing using GPU Mesh Shaders" -- Raad et al. (Eurographics 2025). 논문. 메시 셰이더를 써서 렌더 타임에 거친 컨트롤 메시에서 상세한 기하학적 표면을 생성합니다. 고해상도 지오메트리를 메모리에 저장하지 않는 동적 LOD를 가능하게 합니다.
지형 그림자
"Optimizing Terrain Shadows" -- AMD GPUOpen. 블로그. 대규모 지형을 위한 실용적 CSM 최적화. 캐스케이드 분할, GPU 효율적 섀도 맵 렌더링, 지형 특화 최적화를 다룹니다.
가상 지오메트리와 메시 최적화
"Nanite WebGPU" -- Scthe (2024). GitHub, Demo. UE5 Nanite 아키텍처의 완전한 브라우저 구현: meshlet LOD 위계, WGSL의 소프트웨어 래스터라이저, meshlet별 컬링, 빌보드 임포스터.
"Billions of Triangles in Minutes" -- Kapoulkine (2025). 블로그. 위계적 클러스터 LOD 생성을 위한 Meshoptimizer v1.0. 대규모 메시를 Nanite 스타일 클러스터 DAG로 효율적으로 처리합니다.
"Billboard Splatting (BBSplat)" -- 2024. arXiv:2411.08508. 신규 시야 합성을 위한 학습 가능한 텍스처 평면 프리미티브로 3D Gaussian Splatting 대비 17배 압축 달성.
지형 조명과 전역 조명
"Global Illumination in Once Human" -- GDC 2025. Session. 16km 오픈 월드를 위한 하이브리드 GI: 신경망 압축 프로브(69:1 비율), ML 기반 실내/실외 누출 해결, 동적 프로브 반응.
"GI with AMD FidelityFX Brixelizer" -- GDC 2024. 논문. 화면 공간 프로브가 있는 compute 기반 희소 거리장 캐스케이드. 하드웨어 레이트레이싱 불필요.
"Radiance Cascades" -- 2024. 블로그. 시간 누적 없이 캐스케이드 라디언스 구조를 쓰는 노이즈 없는 실시간 전역 조명.
레벨 디자인과 탐험
"PlotMap: Automated Layout Design for Building Game Worlds" -- 2023. arXiv:2309.15242. 지형에서 서사 공간 제약을 만족하는 AI 보조 POI 배치.
"Spatial Exploration Triggers" -- Purdue University (FDG 2022). 논문. 플레이어 탐험을 이끄는 네 가지 디자인 패턴: 극단 지점, 시각적 가림, 어울리지 않는 오브젝트, 공간 연결.
데이터 압축과 스트리밍
"Entropy-driven Progressive Compression of 3D Point Clouds" -- SGP 2024. 논문. 적응형 양자화가 있는 재귀적 공간 분할을 쓰는 레이트-디스토션 최적화 점진적 압축. 가변 대역폭 네트워크 스트리밍에 맞는 정제 스트림을 만듭니다.
인터랙티브 편집
"WebGPU SDF Editor" -- Nijhoff (2026). 프로젝트. 실시간 marching cubes, 불리언 연산, 부드러운 블렌딩, 옥트리 공간 분할이 있는 브라우저 풀 기능 SDF 모델링. 프리미티브당 112바이트.
강과 해안 생성
"Procedural River Drainage Basins" -- Patel (Red Blob Games). 프로젝트. 보로노이/삼각형 메시 모서리 분류를 쓰는 배수 우선 강 생성. 지형 고도를 배정하기 전에 강 위계를 구축합니다.
"NEWTS1.0: Numerical Model of Coastal Erosion by Waves and Transgressive Scarps" -- MIT (2024). 논문. 균일 후퇴와 파도 구동 침식을 쓰는 단순화된 해안 침식 모델. 실제 지형과 일치하는 곶, 만, 시 스택, 아치를 생성합니다.
더 읽을거리
- 브라우저 3D 오픈 월드 기술은 브라우저에서 멀티플레이어 크리에이터 월드의 전체 아키텍처를 다룹니다
- 2026년 Web 게임 기술 스택은 WebGL, WebGPU, WebAssembly 기초를 다룹니다
- Three.js + USDC 기술 보고서는 브라우저에서 3D 에셋 로딩에 관한 것입니다
- 프런티어 오픈소스 생성 AI 모델은 AI 생성 파이프라인을 위한 것입니다
- WebGPU 시작하기 -- GPU 구동 지형을 위한 compute 셰이더
- 게임 로직을 위한 Web Workers -- 지형 생성을 Worker로 오프로딩하기
- 게임 물리 라이브러리 -- 지형 상호작용과 하이트필드 콜라이더를 위한 물리
- 무료 게임 에셋을 찾는 곳 -- 지형 렌더링을 위한 텍스처와 머티리얼 소스




