코딩 없는 게임 엔진 이야기 3 - 효율적인 렌더링

렌더링은 2차원 또는 3차원 장면을 바탕으로 컴퓨터를 이용해 사진이나 영상을 만들어내는 과정 또는 그러한 기법을 말한다. 게임 월드에 존재하는 오브젝트들을 화면에 표시될 수 있도록 2차원의 화면, 즉 화면 프레임으로 변환하는 것을 의미한다. 화면에 존재하는 모든 픽셀에 대한 색의 정보를 계산해야되는, 직관적으로 이해하기 어려운 복잡한 과정을 거치기 때문에 여기서 자세한 설명은 넘어간다.

게임은 다른 영화와 같이 이미 렌더링 된 파일을 실행하는 것이 아닌 그때 그때 달라지는 오브젝트들의 상태를 실시간으로 렌더링해야하기 때문에 렌더링이 유저의 컴퓨터에서 일어나게 된다. 하지만 유저마다 컴퓨터 환경이 다르기 때문에 각각의 컴퓨팅 환경에 맞춰 개발을 하는 것은 비효율적이다. 이 때문에 그래픽 API를 사용해서 실시간 렌더링을 개발한다.

그래픽 API는 DirectX, OpenGL 그리고 Vulkan 같이 컴퓨팅 환경에 상관 없이 같은 메서드 호출로 동일한 동작을 보장하도록 도와주는 API를 말한다. 각각의 그래픽 API는 조금씩 다르긴 하지만 공통적으로 사용하는 개념은 버텍스, 폴리곤 그리고 UV라는 개념이다.

2D든 3D든 컴퓨터 그래픽을 통해 렌더링 되는 모든 오브젝트들은 폴리곤을 통해 그려진다. 폴리곤은 각 모서리의 세 점인 버텍스로 구성되며 이 때문에 버텍스는 모델링의 기본 단위로 사용된다. 폴리곤과 버텍스가 형태에 대한 정보를 나타낸다면 UV는 각 버텍스가 텍스처 이미지에서 맵핑되는 정보를 나타내며 폴리곤에 이미지를 입힌다.

rendering-optimization-01

폴리곤의 각 점은 버텍스로 이뤄지고, UV를 통해 로드된 텍스처 이미지를 맵핑한다.


스프라이트 아틀라스

폴리곤의 수를 줄이는 것도 중요하지만 메모리 측면에서 봤을 때 중요한 것은 로드되는 텍스처 파일의 크기를 줄이는 것이다. 텍스처 파일은 메모리에 로드될 때 2의 제곱수 크기의 이미지로 로드된다. 때문에 작은 텍스처를 여러개 로드할 경우 쓸데없이 사용되는 메모리의 영역이 많아진다. 이미지가 로드될 때 낭비되는 공간에 이미지를 로드하도록 하면 메모리의 사용량을 줄일 수 있다.

rendering-optimization-02

적은 메모리를 사용하면서도 더 많은 텍스처를 로드할 수 있다.


한가지 주의해야할 것은 이미지가 로드될 때 아틀라스 단위로 로드가 되기 때문에 게임에 존재하는 모든 이미지를 아틀라스로 묶을 경우 해당 장면에서 필요하지 않는 이미지가 로드될 수 있다. 때문에 한 장면에서 연관이 있는 이미지를 아틀라스 이미지로 만들어서 사용하는 것을 권장한다.

그래픽 배치 처리

화면에 출력되는 폴리곤은 그래픽 API를 사용하여 버텍스를 통해 폴리곤을, UV를 통해 텍스처를 렌더링한다. 화면에 오브젝트를 렌더링 하기 위해선 버텍스와 UV 좌표 리스트를 그래픽 API인 렌더링 메서드의 파라메터로 전달해야한다. 렌더링 처리는 가벼운 처리는 아니다. 때문에 렌더링 메서드를 한 게임 프레임 안에서 많이 호출하게 될 경우 프레임이 차지하는 시간이 길어지게 된다.

때문에 렌더링 메서드를 최소한으로 호출하도록 한번에 최대한 많은 버텍스, UV 정보를 파라메터로 넘겨 줘야한다. 이렇게 렌더링에 필요한 정보를 일괄(Batch)처리 하는 것을 그래픽 배치처리하고 하며 2D 렌더링에선 스프라이트 배치라고 표현한다. 문제는 UV 정보가 로드가 된 텍스처들 중 하나의 텍스처만을 타겟으로 한다는 것이다.

UV에는 좌표값만 있을 뿐 어느 텍스처를 타겟으로 한다는 정보는 포함되어있지 않다. 때문에 렌더링 메서드를 호출하기 전 텍스처를 지정하는 메서드를 호출하여 렌더링 메서드가 호출 되었을 때 어떤 텍스처를 사용할지 지정하는 과정을 거친다. 때문에 오브젝트마다 다른 텍스처를 사용한다면 텍스터 지정 메서드와 함께 오브젝트 마다 렌더링 메서드가 호출되게 되어 성능에 영향을 주게 된다.

이를 해결하는 방법은 이미 앞서 다뤘던 스프라이트 아틀라스를 사용하는 것이다. 각각의 오브젝트에 필요한 텍스처들이 하나의 텍스처 파일에 들어있기 때문에 다른 오브젝트를 렌더링하기 위해 텍스처 지정 메서드를 호출할 필요가 없고, 이는 렌더링 메서드가 어쩔 수 없이 여러번 호출되는 일을 막을 수 있다.

연관글

코딩 없는 게임 엔진 이야기 1 - 게임 루프

코딩 없는 게임 엔진 이야기 2 - 멀티코어 게임 루프

코딩 없는 게임 엔진 이야기 3 - 효율적인 렌더링