Game Dev – Voxel Horizon – 자동 최적화 기능 구현

메모리를 절약하고 처리 성능을 높이기 위한 자동 최적화 기능을 구현했다.

복셀 오브젝트는 8x8x8(최소 복셀 크기 50cm^3)에서 1x1x1(최소복셀 크기 1m^3)까지 가변적인 사이즈를 가진다.

복셀 오브젝트는 모양과 색칠된 상태를 유지한다는 전제하에 최적화 될 수 있다.

  • 8x8x8 -> 4x4x4로
  • 4x4x4 -> 2x2x2로
  • 2x2x2 -> 1x1x1로

당연히 8x8x8오브젝트가 1x1x1짜리 오브젝트에보다 메모리를 더 먹는다. 복셀 데이터 스트리밍할때 패킷량도 더 크다. 렌더링할때도 버텍스 프로세싱 부하가 더 걸린다.
단 충돌처리쪽은 처음부터 성능에 민감했던 부분이라 8x8x8정밀도일 경우에도 내부적으로 충돌처리용 삼각형은 최적화된 형태로 생성된다.
이와는 별도로 이번 최적화는 8x8x8 = 512 bits테이블을 (이상적인 경우) 1x1x1 bit짜리 테이블로 최적화하기 위함이다. 결과적으로 메모리 사용량, 패킷량, 렌더링되는 삼각형 수를 줄일 수 있다.

로켓탄을 맞고 일부가 파괴되거나 하면 가장 조밀한 정밀도(8x8x8)로 자동 변환된다. 1x1x1짜리 오브젝트가 로켓을 맞고 움푹 패이면 패인 모양을 이쁘게 구현하기 위해 8x8x8로 바뀐다.

대부분의 경우 복셀 오브젝트가 변형된 경우 8x8x8 -> 4x4x4로 최적화하려고 하면 모양과 색칠된 상태를 유지할 수 없다고 판단했기 때문에 자동 최적화 기능은 넣지 않았다.

그러다가 복셀오브젝트가 로켓으로 파괴되는 경우 외에도 편집기능에 의한 변형도 적지 않을것이란 생각이 들었다.
로켓 폭발 이벤트와는 달리 복셀들을 편집하다보면 최적화 가능한 때가 제법 있을수도 있다. 플레이어가 꼭 50cm x 50cm x 50cm단위로만 편집을 한다는 보장은 없으니까.
오히려 편의상 1m x 1m x 1m단위로 편집할 가능성이 높을것이다. 그렇다면 8x8x8오브젝트가 4x4x4오브젝트로 최적화 될 수 있는 상황도 생각보다 많이 발생할 수 있다.
그리고 이후 테스트중에 깨달았는데 무기에 의해서 복셀 오브젝트가 파괴되는 경우도 꼭지점쪽에 작은 조각 하나만 떨어져있는 경우 이 조각이 파괴되면 최적화될 수 있다.
OK. 복셀 오브젝트가 변형되는 이벤트가 발생할때마다 자동 최적화를 해주기로 결심했다.

문제는 속도인데…
클라이언트에선 상관없지만 서버에서는 성능저하에 민감할수 밖에 없다.
변형 이벤트 발생 횟수에 비해서 실제로 최적화가 가능한 케이스는 훨씬 적을 것이다.
그렇다면 대부분은 쓸데없이 복셀들을 탐색하는게 된다. 단 쓸데없는 탐색시간이라도 아주 짧은 시간이면 무시해도 좋을것이다. 그럼 빠르게 만들면 되겠네.

  1. 일단 8x8x8오브젝트가 여건이 맞으면 1x1x1까지 최적화 하도록 하는 함수를 하나 작성했다.
  2. 작동을 확인한후 나름대로 최적화 했다. 여기서 30%정도 성능향상을 얻었다.
  3. 테스트 해보니 2.4GHz – 3GHz CPU기준 평균적으로 오브젝트 한개당 0.00037ms가 소모된다.
  4. 로켓탄이 한번 터질때마다 평균적으로 4-8개 정도 오브젝트가 영향을 받으니까 8개 영향 받는다치고 면 0.003ms정도 걸린다.
  5. 서버의 한 프레임에 영향을 줄 정도의 시간을 1ms로 가정하면 한 프레임당 33번의 로켓폭발 이벤트를 처리할 수 있다.

음… 이 정도면 괜찮은것 같다.

기본적인 기능 구현으로 가능성 여부를 타진하고 일주일을 더 투자해서 자동 최적화 기능을 완료했다.

무기에 의한 복셀 파괴, 또는 복셀 편집 이벤트가 발생하면 자동으로 최적의 복셀 정밀도를 설정한다. 이것은 엔진에 포함된 기능이다. 따라서 동일한 엔진을 사용하는 서버와 클라이언트 모두에 적용된다.

데모에선 클라이언트에서 서버 접속 없이 기능을 테스트하고 있다. 실제 게임 플레이 상황에선 복셀지형이 변경되는 모든 작업은 서버에서 처리한 후 클라이언트에 통보해준다.
패킷량을 줄이기 위해 변경된 복셀 오브젝트의 데이터 그 자체를 보내는것이 아니라 이벤트를 보내준다.
‘어느 위치에서 반지름 얼마로 복셀이 파괴된 이벤트가 발생했고 서버에서는 무사히 처리했다. 그러니까 클라이언트 너도 이 이벤트를 처리해라.’
이렇게 보내준다.

검증을 위해서 패킷에 최대 128bits(16 bytes)짜리 데이터를 추가했다. 변형이 일어난 오브젝트들(최대64개)의 정밀도를 각 2bits로 압축한 데이터다.
클라이언트에서 복셀 오브젝트 변형 이벤트를 처리한 후 클라이언트측의 복셀 오브젝트의 정밀도가 서버가 보내준 리스트와 일치하는지를 확인한다.
패킷에 16bytes 추가하는건 네트웍 트래픽이 아까우므로 충분히 검증됐다고 판단하면 제거한다.

데모 설명

  1. 1x1x1짜리 오브젝에 로켓탄이 충돌한다.
  2. 로켓이 폭발하고 로켓 폭발 흔적을 이쁘게 구현하기 위해 1x1x1짜리 오브젝트의 정밀도는 8x8x8로 바뀐다.
  3. 이후 편집 이벤트에 의해 자동 최적화가 이루어지고 1x1x1로 다시 바뀐다.
  4. 단계적으로 편집용 브러쉬의 정밀도에 따라 1x1x1 -> 2x2x2 -> 4x4x4 -> 8x8x8로 변경되는 것을 확인할 수 있다.

Game Dev – Voxel Horizon – 자동 최적화 기능 구현”에 대한 답글 1개

답글 남기기

댓글을 게시하려면 다음의 방법 중 하나를 사용하여 로그인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중