텍스처

텍스처는 비트맵 이미지이다. 즉 Unity 프로젝트에 포함된 모든 이미지 파일은 텍스처로 인식된다.

그럼 Unity의 텍스처에 대해 알아보기 전 비트맵에 대한 간단한 정리를 먼저 해보자

 

* 비트맵(Bitmap)

레스터 그래픽으로도 불리며 서로 다른 픽셀들에 저장된 비트 정보 집합을 사용하는 이미지 표현 방식이다.

가로 픽셀의 수 * 세로 픽셀의 수가 비트맵 이미지의 크기가 되며 색 표현을 위한 픽셀당 비트 수인 bpp (Bit Per Pixel)를 지정할 수 있다.  

에시로 4bpp의 경우 2^4인 16가지 색을, 8pp를 지정한다면 2^8인 256가지 색을 지정할 수 있다

 

16bpp의 경우 하이 컬러, 24bpp 경우 16,777,216개의 색상을 사용할 수 있으며 사람이 볼 수 있는 색이라는 뜻에서 트루 컬러라고 부른다.

빛의 3원색인 빨간색, 녹색, 파란색의 채널로 이루어진 것을 RGB채널이라 부른다. 24bpp인 트루컬러의 경우 각 채널에 8비트씩 할당된다.

이때 투명도 값을 의미하는 알파 채널이 더해져 32bpp를 사용하는 것을 RGBA채널이라 부른다.

 

* 비트맵 그래픽 파일 형식

이러한 배트맵을 파일로 저장하는 과정에서 파일의 크기를 줄이기 위해 비트맵을 압축하여 저장하는데 압축 방식과 지원하는 기능에 따라 다양한 표준 형식이 있다. 그중 대표적인 표준 형식 몇 가지의 간단한 특징만 정리했다.

 

BMP

일반적으로 픽셀당 24비트를 저장하며 압축되지 않는 파일 형식이다.

 

GIF

GIF는 무손실 압축 포맷이기 때문에 압축과정에서 정보의 손실이 발생하지 않는다. GIF의 한 색을 투명으로 저장할 수 있으며 픽셀당 최대 8비트까지 저장되므로 256색으로 제한된다.

 

PNG

GIF 파일과 마찬가지로 PNG 파일은 정보 손실 없이 압축된다. 픽셀당 256색으로 제한되던 GIF와는 달리 트루 컬러인 1,600만 개의 색상을 지원한다.

또한 GIF처럼 한 가지 색을 투명값으로 사용하는 것이 아닌 별도의 알파 채널을 사용하여 완벽한 불투명도를 지정할 수 있다.

 

JPEG

JPEG는 손실 압축 방식으로 파일이 압축될 때 이미지의 일부 데이터가 영구적으로 삭제된다. PNG와 마찬가지로 1,600만 개 이상의 색을 표시할 수 있다. 단 크기는 PNG에 비해 파일 크기가 작다는 장점이 있다. 스캔한 사진 혹은 자연 장면에 잘 작동하는 압축 체계. 선, 단색 블록, 날카로운 경계 표현에 경우 다소 약하다. PNG와의 가장 큰 차이는 JPEG는 투명한 배경을 지원하지 않는 점이다.

 

* 비트맵(레스터 그래픽)과 반대되는 벡터(Vector) 그래픽도 존재한다. 이는 점과 점을 연결해 수학적 원리로 그림을 그리는 이미지 표현 방식이다.

 

즉 Unity는 흔히 사용하는 이미지 파일(GIF, PNG, JPG)들을 통해 게임에서 사용하는 텍스처로 이용할 수 있다는 뜻이다.

그럼 게임에서 텍스처를 어떻게 활용하는지 알아보자.

3D 모델의 경우 모델 표면에 이미지를 매핑하기 위해 텍스처를 사용한다.

3D 게임의 오브젝트는 MeshRenderer 컴포넌트를 통해 렌더링 되는데 이때 필요한 리소스로 모델의 형태 정보인 Mesh와 표면의 색을 결정하는 Material 두 가지 에셋이 필요하다.

Material은 텍스처와 셰이더가 합쳐진 에셋으로 즉 3D 모델의 표면 색을 지정하려면 Material 에셋에 원하는 텍스처를 연결하면 된다.

 

2D 게임 오브젝트는 SpriteRenderer, UI 이미지의 경우 Image컴포넌트를 통해 렌더링 되는데 이때 사용할 리소스 이미지로 Sprite가 필요하다.

프로젝트 창의 텍스처파일을 클릭하면 인스펙터 창에 표시되는 Import Settings에서 Texture Type을 Sprite(2D and UI)로 변경하면 해당 텍스처를 Sprite로 인식하고 2D 게임 오브젝트나 UI 이미지에 사용할 수 있다.

 

텍스쳐 압축

JPG, PNG과 같이 비트맵 데이터를 이미지 압축 방식을 통해 데이터 사이즈를 줄여 디스크 용량을 절약할 수 있었지만 런타임 시 게임 그래픽에서 그대로 사용할 수 없다. JPG나 PNG는 GPU가 읽어 들일 수 있도록 비디오 메모리에 올리면 압축한 상태가 아닌 압축이 풀린 상태로 올라간다.

2048 * 2048 크기의 알파 채널을 포함한 PNG 파일의 경우 압축된 원본 크기가 2~3MB였을지라도 그래픽 메모리에 올라갈 때는 16MB로 올라간다는 것이다.

 

따라서 Unity 에디터에서 JPEG 또는 PNG 같은 비트맵 이미지 포맷의 텍스쳐 소스 파일을 가져올 수 있지만 GPU는 런타임 시 이러한 포맷을 직접 사용하지 않는다. 대신 Unity 에디터에서 빌드 타겟에 따라 적합한 다양한 전문 포맷으로 변환하여 사용한다. 즉 GPU에서 사용하기 위한 픽셀 포맷이 별도로 존재한다는 것인데 이러한 포맷으로 변환하는 것을 텍스쳐 압축이라 한다. Unity 빌드 결과물 또한 프로젝트 폴더에 있는 이미지 파일이 아닌 텍스처 압축을 통해 전문 포맷으로 변환된 파일이 빌드에 포함된다.

 

게임에서 사용하는 텍스처 압축 포맷들은 다음 사항을 만족해야 한다.

- 디코딩 속도가 빨라야 한다

압축된 텍스처는 메모리에 로드될 때 압축이 풀려서 적재되는 것이 아니라 압축된 데이터 그대로 메모리에 적재되어야 한다. 그 후 렌더링 퍼포먼스에 발목을 잡히지 않기 위해 압축 해제가 고속으로 이루어져야 한다. 압축의 디코딩은 하드웨어에 구현되어 있으므로 따라서 텍스처 압축 포맷은 어떤 하드웨어를 사용하느냐에 따라 지원 여부가 의존적이다. 

 

- 랜덤 액세스가 가능해야 한다

랜덤 액세스(Random Access)는 직접 액세스로도 불리며 논리적, 물리적인 순서가 아닌 한번에 단 하나의 블록만을 접근하는 방식이며 이와 반대로 시퀀셜 액세스는 논리적 혹은 물리적으로 연결된 순서에 따라 차례대로 블록을 읽는 방식이다.

즉 랜덤 엑세스가 가능한 경우 시퀀셜 액세스보다 더욱 빠르게 메모리를 읽을 수 있다.

 

도형 표면에 텍스처가 입혀지려면 보통 uv 혹은 st라 부르는 텍셀 좌표가 필요한데 이는 현재 그려지는 픽셀이 어느 지점의 컬러를 가져와야 하느냐의 정보가 담긴 죄표이다. GPU는 특정 위치의 텍셀을 바로 읽어와야 하기 때문에 랜덤 액세스가 필수적이다.

 

JPG, PNG와 같은 이미지 압축에 사용되는 가변 비율 압축은 랜덤 액세스에 적합하지 않다. 따라서 텍스처 압축은 반드시 고정 비율 압축이어야 한다.

가변 비율 압축은 데이터가 중복된 단위를 기준으로 압축한다. 동일한 해상도의 이미지라도 이미지 복잡도에 따라 압축률이 달라지는 방식이다.

고정 비율 압축의 경우 4:1, 8:1, 16:1과 같이 고정된 비율로 압축하며 모든 결과물의 압축률이 같아진다. 압축률이 같다면 어느 위치의 데이터를 읽어야 하는지 충분히 예측 가능해지기 때문에 랜덤 액세스가 가능하다.

 

텍스처 압축은 손실 압축이다. 압축된 텍스처를 디코딩 하는 과정이 너무 어렵거나 복잡하다면 그만큼의 연산이 많이 필요하고 성능 효율이 떨어진다. 그렇기 때문에 압축 효율이 높으면서 디코딩이 너무 복잡하지 않은 손실 압축 알고리즘을 채용하고 있다.

 

[참고]

https://docs.unity3d.com/kr/current/Manual/ImportingTextures.html

https://www.youtube.com/watch?v=BeEjoTa9sSo&t=689s 

https://learn.microsoft.com/ko-kr/dotnet/desktop/winforms/advanced/types-of-bitmaps?view=netframeworkdesktop-4.8

 

'Unity' 카테고리의 다른 글

[Unity] Behavior Tree  (0) 2023.03.20
[Unity] FSM - 유한 상태 기계  (2) 2023.03.13
[Unity] Normal Map  (0) 2023.01.30
[Unity] 텍스처 타입  (0) 2023.01.24
[Unity] 텍스처 압축 포맷  (0) 2023.01.16

+ Recent posts