이진호의 개발 블로그

[유니티] 유니티 그래픽스 최적화 : 텍스처 본문

Unity/최적화

[유니티] 유니티 그래픽스 최적화 : 텍스처

l__j__h 2024. 2. 27. 16:32

텍스처

텍스처란?

텍스처는 게임 렌더링에 있어서 필수적인 리소스 중 하나이다.

오브젝트를 렌더링할 때 텍스처를 이용하여 질감을 묘사한다 (= 텍스처 맵핑)

 

대역폭 (Bandwidth)

대역폭이란?

프로세서가 메모리에서 데이터를 가져올 때, 한 번에 가져올 수 있는 데이터의 크기

 

모바일에서는 대역폭이 좁은 편이다.

(이유 : 모바일은 데탑과 달리 항상 전원이 연결돼있는게 아니므로 성능보다는 전력을 중요시하고, 휴대가 용이해야 하므로 칩셋도 작아지기 때문)

이 작은 대역폭 때문에, 데이터 사이즈가 커지면 병목이 발생하게 되고 성능에 악영향을 미치게 된다. GPU가 GPU 메모리에서 데이터를 불러올 때에도 속도의 한계가 있기 때문에, 데이터 각각의 사이즈가 커질수록 병목이 발생하고, 핸드폰에 발열이 일어나고, 쓰로틀링 상태로 진입해서 성능 저하로 이어질 수 있다는 것이다.

 

그래서 텍스처의 해상도가 성능에 큰 영향을 미친다.

예를 들어, 텍스처의 해상도가 1024일 경우에는 성능 문제가 없다가, 2048일 경우 성능 하락이 발생할 수도 있다.

1024 -> 2048은 2배가 아니다. 텍스처는 2D 이미지이기 때문에, 면적으로 따져야 한다. 

즉, 1024x1024 에서 2048x2048이 되었으므로, 용량이 4배로 늘어난 것이다.

 

만약 메모리 대역폭이 병목의 원인이라면, 게임에서 사용하고 있는 텍스처의 용량을 줄일 필요가 있다.

 

텍스처 압축의 필요성

텍스처 압축은 디스크의 용량과 메모리의 크기를 모두 절약할 수 있다. 또, 만약 메모리 대역폭이 병목을 일으킨다면 성능 개선도 노릴 수 있다.

주의할 점은, 게임에서 사용되는 텍스처 압축은 우리가 흔히 알고 있는 PNG, JPEG과는 다른 방식이라는 것이다!!!!

텍스처는 수많은 비트로 이루어진 이미지 데이터이다. 그래서  GPU가 이 데이터를 이용하려면 대역폭이 필요하고, 성능 문제가 발생한다.

따라서, 렌더링 시 사용되는 텍스처는 고정된 비율을 가진 '블럭 형태의 손실 압축 기법'을 사용한다.

 

BPP (Bit Per Pixel)

일반적인 컴퓨터 모니터에서는 한 픽셀 당 R, G, B 3가지 색상으로 표시하게 된다. R, G, B에서 채널 1개 당 8비트를 저장하므로, 한 픽셀 당 8*3 = 24비트를 사용하고 있다고 할 수 있다. 이를 트루 컬러라고 부른다.

흔히 사용하는 이미지도 마찬가지이다. 이미지는 알파 채널이 없는 경우는 위와 동일하게 24비트, 알파 채널이 있는 경우에는 8*4 = 32비트를 사용한다.

 

만약 이미지 A 가 알파채널을 포함하는 2048x2048 의 해상도를 가진다고 가정하면, 이 이미지 A의 용량은

32bpp (한 픽셀당 r,g,b,a 4개 채널을 가지므로, 8bit*4를 했다) * 2048 * 2048 = 134,217,728 비트 이다......


단, 이미지 A에서 알파채널을 제외한다면??

24bpp (한 픽셀당 r,g,b 3개 채널을 가지므로, 8bit*3을 했다) * 2048 * 2048 = 100,663,296 비트이다.

 

위와 같이, 한 픽셀 당 비트 수(=bpp)만 줄여도 용량이 감소하는 것을 알 수 있다.

따라서 이미지 데이터 사이즈는 해상도뿐만 아니라 bpp도 영향을 미친다.

 

bpp와 색의 범위

이미지 데이터의 사이즈를 줄이는 가장 간단한 방법은, 이미지의 정밀도, 즉 bpp를 줄이는 것이다.

알파 없이 RGB 채널만 사용하는 이미지가 있다고 가정하자.

한 채널 당 8비트를 사용하는 32bpp의 이 이미지를 한 채널 당 4비트인 16bpp로 줄이면, 용량은 절반으로 줄어든다.

 

단!!! 용량이 1/2로 줄어드는 것이지, 사용하는 색상 개수가 1/2이 되는 것이 아니다. 오히려 색상 수는 더더 줄어든다.

왜냐면??

 

R 채널에 8비트를 쓴다는 말은, R 컬러를 256(=2^8)단계의 밝기로 표현 가능하다는 것이다.

그럼, R,G,B 3색상을 쓴다는 말은 256*256*256 = 16,777,216개의 컬러를 사용할 수 있다는 말이다.

그런데, 만약 한 채널에 4비트밖에 안 쓴다면, 한 컬러를 16(=2^4)단계의 밝기로 표현한다는 말이다.

그럼, R,G,B 3색상을 모두 사용해도 16*16*16 = 4,096개의 컬러만 사용할 수 있게 된다.

용량은 절반으로 줄어들었지만, 사용 색상 수는 매우매우 줄어들었다.

물론 품질(또는 성능)과 용량은 Trade-off 관계이지만 현저한 품질 저하는 문제가 될 수 있으므로 주의해야 한다.

 

 

이미지 파일 용량 압축 포맷

우리가 흔히 아는 JPEG, PNG 등은 이미지를 압축하는 확장자 포맷이다. 이 포맷들은 디스크 용량을 절약하기 위해서 고안되었다.

 

하지만 "디스크"의 용량을 절약하기 위해 고안된 것이지, GPU가 텍스처로 사용하기 위해 고안된 포맷이 아니다.

왜냐하면, 텍스처는 폴리곤의 표면에 uv 매핑되어야 하고, 하나의 텍스처 안에 밉맵 텍스처들도 존재하는 경우가 있다. 그래서 특정 위치에 바로 접근할 수 있는 랜덤 액세스가 가능해야 한다.

그런데 PNG는 가변비율 압축이라서, 원하는 데이터가 어디있는지 알기 위해선 처음부터 압축을 풀어가며 일일이 찾아야 한다.

이게 무슨 말이냐면, 어떤 이미지가 5A3B7A 라고 가변비율 압축되어있다고 가정하자.

그런데 10번째 A를 읽으라고 하면, 그게 어디 있는지 알기 위해선 5A8B7A를 AAAAABBBAAAAAAA로 압축 해제하고, 그래서 10번째 A가 어디 있다는 건지 일일이 찾아야된다는 것이다. 텍스처 매핑은 신속하게 이루어져야 하므로 이 방식은 적합하지 않다.

그래서 아무리 JPEG, PNG로 이미지를 압축한 뒤 리소스로 사용해도, GPU가 읽을 수 있도록 메모리에 올라가면 압축이 해제된 상태로 올라가게 된다.

따라서 GPU가 실시간으로 텍스처를 읽을 수 있도록 텍스처를 위한 별도의 압축 방식이 존재한다.

유니티에서는 Project 창에서 텍스처를 클릭한 후 인스펙터창을 보면, Format 이라는 이름의 드롭다운 태그가 있을 것이다. 드롭다운을 누르면 보이는 것들이 이미지를 텍스처로 Import할 때 사용되는 압축 포맷들이다. 

 

유니티의 플랫폼별 텍스처 압축 형식 ⬇️⬇️

https://docs.unity3d.com/kr/2021.2/Manual/class-TextureImporterOverride.html

 

플랫폼별 권장, 기본 및 지원 텍스처 압축 포맷 - Unity 매뉴얼

이 페이지는 다음에 관한 정보를 제공합니다.

docs.unity3d.com

 

텍스처 압축 방법 과정이 어떻게 되는지, 왜 블록 단위 손실 압축이라고 하는지는 아래 블로그에서 잘 설명해두셨다.

https://blog.naver.com/tigerjk0409/221235264616

 

텍스처 압축 알고리즘

2012년에 크로노스가 만들고 2014년부터 유니티가 지원하는 ASTC를 드디어 회사들이 쓰는걸 고려하는 ...

blog.naver.com

 

읽어보니, 왜 이 책에서 텍스처 압축을 "블록 단위 손실 압축" 이라고 하는지 알 수 있었다.

블록 단위인 이유 :

ASTC 4x4 압축일 경우, 한 블럭 당 4x4픽셀을 포함하고 있다는 말. 즉, 이미지에서 4x4 픽셀을 1개의 블럭으로 묶어서 처리.

손실 압축인 이유 :

픽셀 n개를 블럭단위로 묶은 후, 블럭 당 대표 색을 뽑아, 팔레트처럼 만들어 인덱스와 웨이트를 부여하므로, 원본의 색과 달라질 가능성이 높아서.

 

 

728x90