
게임 최적화의 기본, 안 보이는 건 그리지 않기
마인크래프트 같은 블록 게임을 떠올려 보세요. 세상이 전부 블록으로 이루어져 있어서 한 화면에 그려야 할 면이 어마어마하게 많아요. 그런데 가만히 생각해보면 대부분은 실제로 눈에 안 보여요. 산 뒤에 있는 동굴, 땅속 깊은 광맥, 벽 너머의 방 같은 것들이요. 이런 걸 GPU에 다 그리라고 보내면 성능이 쓸데없이 낭비되겠죠.
이번에 소개할 글은 개인 개발자가 만들고 있는 복셀 게임 Block Game의 개발 블로그 글이에요. 주제는 소프트웨어 오클루전 컬링, 즉 GPU 대신 CPU에서 직접 가려진 물체를 골라내는 기법이에요. 게임 개발을 안 하더라도 성능 최적화의 사고방식을 배우기 좋은 주제라 풀어볼게요.
컬링이 뭐냐면
컬링(culling)은 원래 솎아낸다는 뜻이에요. 그래픽스에서는 그릴 필요 없는 걸 미리 걸러내는 작업을 말해요. 대표적으로 세 가지가 있어요.
- 백페이스 컬링: 물체의 뒷면은 어차피 안 보이니까 안 그려요.
- 프러스텀 컬링: 카메라 시야 범위(원뿔처럼 생긴 영역) 밖에 있는 건 안 그려요. 내 뒤에 있는 건 볼 필요가 없죠.
- 오클루전 컬링: 시야 안에 있긴 한데 다른 물체에 가려진 건 안 그려요.
GPU로 하면 되지 않나요?
GPU에도 오클루전 쿼리라는 기능이 있어요. 물체를 그려보고 실제로 화면에 찍힌 픽셀이 몇 개인지 물어보는 방식이에요. 문제는 GPU와 CPU 사이의 시간차예요. GPU는 CPU보다 한두 프레임 늦게 일하는 경우가 많아서, 결과를 바로 기다리면 전체가 멈춰버려요. 그렇다고 이전 프레임 결과를 쓰면 카메라를 빠르게 돌릴 때 물체가 한 박자 늦게 뿅 나타나는 팝핑 현상이 생겨요.
그래서 나온 대안이 CPU에서 작은 깊이 버퍼를 직접 그려보는 방식이에요.
소프트웨어 오클루전 컬링의 원리
아이디어는 생각보다 단순해요.
1. 큰 벽이나 지형처럼 가리는 역할을 할 만한 물체(오클루더)를 골라요.
2. 이걸 CPU에서 아주 낮은 해상도의 깊이 버퍼에 래스터화해요. 깊이 버퍼는 픽셀마다 카메라에서 가장 가까운 물체까지의 거리를 적어둔 표예요. 해상도는 실제 화면보다 훨씬 작게 잡아서 계산량을 줄여요.
3. 그 다음 각 물체의 경계 상자를 같은 버퍼에 비춰보고, 상자가 차지하는 모든 픽셀에서 이미 더 가까운 뭔가가 있으면 완전히 가려진 거라고 판단해서 그리기 목록에서 빼요.
비유하자면, 본 공연 전에 종이에 대충 스케치를 그려보고 스케치에서 완전히 가려지는 배우는 무대에 올리지 않는 거예요. 스케치가 대충이어도 보이는 걸 안 보인다고 판단하지만 않으면 화면은 정확하게 나와요. 그래서 보통 보수적으로, 애매하면 그리는 쪽으로 설계해요.
복셀 게임과 궁합이 좋은 이유
블록 게임은 이 기법과 특히 잘 맞아요. 세계가 청크라는 덩어리로 나뉘어 있어서 청크 단위로 가려짐을 판단하면 되고, 불투명한 블록은 그 자체로 완벽한 오클루더거든요. 지형이 대부분 꽉 찬 땅이라서 한 번 걸러내면 줄어드는 양도 엄청나요. 특히 동굴 속이나 건물 안에 있을 때 효과가 극적이에요.
업계 맥락
이 기법은 AAA 게임에서도 오래 써왔어요. 배틀필드 시리즈의 프로스트바이트 엔진이 소프트웨어 오클루전 컬링을 적극 활용한 것으로 유명하고, 인텔은 SIMD 명령어로 이걸 빠르게 하는 Masked Software Occlusion Culling 라이브러리를 오픈소스로 공개했어요. 마인크래프트는 조금 다른 방식으로, 청크 내부의 빈 공간이 어느 면과 어느 면을 이어주는지 그래프로 만들어서 플러드 필로 보이는 청크를 찾는 방법을 써왔어요. 최근에는 GPU에서 컴퓨트 셰이더로 컬링을 전부 처리하는 GPU 드리븐 렌더링도 주목받고 있고요. 개인 개발자가 이런 선택지 사이에서 자기 게임에 맞는 방식을 직접 구현하고 기록했다는 점에서 읽어볼 가치가 커요.
한국 개발자에게 주는 시사점
게임이나 그래픽스 쪽이라면 당연히 도움이 되고, 그렇지 않더라도 배울 점이 있어요. 핵심은 정밀한 계산 전에 싸고 대략적인 계산으로 후보를 걸러낸다는 사고방식이에요. 이건 데이터베이스 인덱스, 블룸 필터, 검색 엔진의 1차 후보 추출에서도 똑같이 쓰이는 패턴이거든요. 그리고 CPU와 GPU 사이의 지연을 이해하는 건 웹의 메인 스레드와 워커, 서버와 클라이언트 사이의 비동기 문제를 이해하는 데도 도움이 돼요.
마무리
한 줄 정리: 안 보이는 걸 안 그리는 게 최고의 최적화고, CPU에서 작은 깊이 버퍼를 그려보는 건 그걸 해내는 오래되고 검증된 방법이에요.
여러분이 작업하는 분야에서는 비싼 계산 전에 싸게 걸러내는 컬링 같은 기법을 어디에 쓰고 계신가요? 게임 개발자분들은 오클루전 컬링을 GPU와 CPU 중 어느 쪽에서 처리하는 게 낫다고 보시는지도 궁금해요.
🔗 출처: Hacker News