Skip to content

브라우저에서 오픈 월드 만들기, 11부: 하드코딩 모드가 아닌 정책 모드

글쓴이 Oleg Sidorkin, Cinevva CTO이자 공동 창업자

처음 오셨나요? 시리즈 가이드를 보세요. spike가 무엇인지 설명하고 모든 부분을 링크해 둡니다.

이음매 혼돈 챕터가 끝난 뒤, 우리는 반응하기를 멈추고 다스리기를 시작해야 했습니다.

Spike 23은 즉흥적인 동작을 명시적인 정책 규칙으로 바꿨습니다. chunk가 각자의 로컬 상태가 시키는 대로 아무렇게나 움직이는 대신, 이제 중앙 정책 시스템이 결정을 내립니다. 이 chunk는 어떤 LOD 레벨을 받을까? heightmap으로 렌더링될까, marching cubes로 렌더링될까? 전환 cell이 필요할까, 그렇다면 어느 면에서? 그 답은 카메라까지의 거리, 편집 이력, 이웃의 해상도 상태를 평가하는 정책 함수에서 나왔습니다.

새 탭에서 Spike 23 열기 ↗ · 소스 보기

거리 기반 LOD 할당은 카메라를 중심으로 한 동심원 링을 사용했습니다. clipmap 개념과 비슷하지만 chunk 그리드에 적용한 것이죠. 링 0의 chunk는 전체 해상도 MC를 받습니다. 링 1은 절반 해상도 MC를 받습니다. 링 2 이상은 heightmap 모드로 갑니다. 인접 제약이 핵심이었습니다. 이웃한 두 chunk에 대해 우리는 |LiLj|1을 요구합니다. 한 면을 가로지르는 해상도 비율은 2|LiLj|이고, Transvoxel 전환 테이블은 2:1 경우(|LiLj|=1)에 대해서만 정의되어 있습니다. 2레벨 점프는 테이블이 표현할 수 없는 4:1 전환이 필요하므로, 정책은 제약이 충족될 때까지 더 낮은 디테일의 chunk를 업그레이드하도록 강제합니다.

HM/MC 전환 로직은 각 chunk의 편집 비트맵을 확인했습니다. chunk에 볼류메트릭 편집(동굴, 터널, 지형 조각)이 하나라도 있으면, 거리와 관계없이 MC 모드에 남았습니다. 편집되지 않은 chunk는 충분히 멀어지면 heightmap 모드로 내려갈 수 있었습니다. 이 하이브리드 방식 덕분에 중요한 곳에서는 볼류메트릭 자유를, 그렇지 않은 곳에서는 효율을 얻었습니다.

이 spike는 밖에서 보기엔 이전의 몇몇보다 작아 보였습니다. 실제로는 개발 편의성에서 큰 개선이었습니다.

시스템이 chunk가 왜 모드를 바꿨는지 설명할 수 있으면, 추측에 쓰는 시간이 줄어듭니다. 우리는 색상으로 구분한 오버레이를 추가했습니다. heightmap chunk는 녹색, MC chunk는 파란색, 전환이 활성화된 면은 주황색입니다. 이음매 가시성에 전용 렌더 제어가 있으면, 시각적 디버깅의 모호함이 줄어듭니다. draw 범위가 정책 시스템의 활성 정점 수에 명시적으로 묶여 있으면, 오래된 지오메트리 잔상이 오후 시간을 갉아먹는 일이 사라집니다.

이 spike에서 우리는 카메라 동작도 대폭 손봤습니다. 이전 spike들의 단순한 orbit 컨트롤은 스크린샷에는 괜찮았지만 버그 재현에는 쓸모가 없었습니다. Spike 23은 속도 조절이 가능한 WASD 비행 카메라, 고도 잠금 토글, 위치 표시를 추가했습니다. 사소하게 들립니다. 하지만 이것은 "저 능선 근처 어딘가에서 버그를 봤다"와 "버그는 북서쪽을 바라보는 위치 (142, 12, -67)에서 나타난다"의 차이를 의미했습니다.

이 챕터의 핵심 통찰은 정책이 복잡도를 줄이지 않았다는 것입니다. 정책은 복잡도를 조직했습니다. 같은 수의 엣지 케이스가 그대로 존재했습니다. 하지만 이제 각 엣지 케이스에는 이름이 있고, 트리거 조건이 있고, 브레이크포인트를 걸 수 있는 코드상의 자리가 있습니다. 이것은 다른 종류의 승리이고, 시스템이 계속 진화할 수 있는지 아니면 제 무게에 짓눌려 무너지는지를 결정하는 요소입니다.

Spike 23이 끝날 무렵, 우리에게는 상호작용 버그에 대한 끊임없는 두려움 없이 원거리 clipmap 링 전략에 연결할 수 있을 만큼 예측 가능한 근거리 동작 레이어가 생겼습니다.

12부에서는 Spike 24를 다룹니다. 링 전환, 스카이박스 안개, Three.js 버전 수준의 셰이더 통합이 이 프로젝트의 이 챕터를 마무리합니다.

이 챕터에서 언급한 기술

거리 기반 LOD 정책. 카메라까지의 거리, 편집 이력, 이웃 상태를 바탕으로 각 chunk에 LOD 레벨과 렌더링 모드를 할당하는 중앙 함수입니다. 동심 거리 링이 기본 LOD를 결정합니다. 링 0 = 전체 해상도 MC, 링 1 = 절반 해상도 MC, 링 2+ = heightmap 모드. 정책 함수는 카메라가 움직임에 따라 프레임마다 실행되며 chunk 전환을 트리거합니다. 이것은 즉흥적인 chunk별 결정을 예측 가능하고 디버깅 가능한 규칙 시스템으로 바꿉니다. compute shader 등가물은 GPU 기반 LOD 선택을 보세요.

인접 제약. Transvoxel 알고리즘은 2:1 해상도 비율만 처리합니다. 이웃한 두 chunk가 한 LOD 레벨을 초과해 차이 나면(예: LOD 0 옆에 LOD 2), 전환 테이블이 유효한 이음매 지오메트리를 만들 수 없습니다. 정책 시스템은 LOD 차이가 1을 넘을 때 더 낮은 디테일의 chunk를 업그레이드해 이를 강제합니다. 이 제약 전파는 연쇄될 수 있습니다. 한 chunk를 업그레이드하면 그 이웃들도 업그레이드를 강제할 수 있습니다. 구현은 단순한 반복 패스이며, 일반적인 그리드 구성에서 2-3회 반복이면 수렴합니다.

모드 선택을 위한 편집 비트맵. 각 chunk는 볼류메트릭 SDF 편집(동굴, 터널, 조각)을 포함하는지 기록하는 비트맵을 유지합니다. 편집이 하나라도 있는 chunk는 거리와 관계없이 marching cubes 모드에 남아 창작자의 수정을 보존합니다. 편집되지 않은 chunk는 카메라에서 충분히 멀어지면 heightmap 모드로 내려가 연산과 메모리를 아낍니다. 비트맵은 chunk당 단일 플래그이지만, 더 세분화된 모드 결정을 위해 편집 밀도를 추적하도록 확장할 수 있습니다.

디버그 시각화 오버레이. 색상으로 구분한 chunk 렌더링으로, 녹색 = heightmap 모드, 파란색 = MC 모드, 주황색 = 전환이 활성화된 면입니다. LOD 레벨 숫자, 모드 라벨, wireframe 토글이 달린 chunk별 오버레이도 있습니다. 이것들은 출시 기능이 아니라 개발 도구이지만, LOD 전환과 이음매 아티팩트를 디버깅할 때 거듭 본전을 뽑습니다. 정확한 월드 위치를 알려주는 WASD 비행 카메라와 결합하면, "어딘가에서 버그를 봤다"가 "버그는 이 LOD 구성에서 (142, 12, -67)에 나타난다"로 바뀝니다.


12부 중 11부.
이전: 10부 - 이음매 혼돈과 코너 보스전
다음: 12부 - 링, 하늘 안개, 그리고 다시 한다면 할 일
시리즈 가이드: /ko/blog/2026-02-25-open-world-browser-series-guide