SungJin Kang

SungJin Kang

hour30000@gmail.com

© 2024

Dark Mode

텍스쳐 압축을 위한 힘든 여정

지금까지는 텍스쳐를 압축없이 png 그대로 가져다 써왔다. 언젠가는 텍스쳐 압축을 해야겠다는 생각은 하였는 데 때가 된 것 같다.
텍스쳐 압축은 해본 적이 없어서 인터넷 검색을 통해서 대충 어떻게 할지 정하였다.
간단하게 설명하자면 에디터 단계에서 각 게임 내에 사용되는 모든 텍스쳐를 DXT 포맷으로 압축 후 dds파일로 저장한다.
그럼 빌드된 파일을 실행하면 이 dds파일을 런타임에 임포드해서 바로 GPU에 올린다. dds파일(dxt 포맷)은 compressed 타입이지만 decompress 과정 없이 바로 GPU에 올릴 수 있다는 장점 때문에 현재는 거의 표준에 가깝게 쓰이고 있다.

우선 일반 png나 jpg파일을 dxt 포맷으로 compress할 필요가 있었다. 한번 만들어 볼까도 생각하였지만 SIMD지원이나 파일 export 등 내가 직접하기에는 확실히 한계가 있어서 외부 라이브러리를 사용하기로 하였다.
여러 라이브러리를 연구하였지만 대부분의 dxt라이브러리들이 업데이트도 안되고 관리가 잘 되지 않고 있었다.
또한 나는 이미지 파일을 미리 빌드 단계에서 dds파일로 저장해두어서 게임 시작시 이 dds파일을 임포드 하여야 했는 데 dds 파일 import, export 할 수 있는 라이브러리가 많이 않았다.
삽질을 너무 많이 했다. compressonator라는 amd에서 나온 라이브러리도 실험하고 sdl_image도 해보고, opengl의 ktx 포맷도 실험해보았다.
너무 힘들었다. 여러 가지 라이브러리를 시험해보느라.
결국에는 마이크로소프트에서 만든 DirextXTex를 사용하기로 하였다. 기본적으로 dxt라는 포맷자체가 direct x에서 사용하기 위해 개발되었고 이 라이브러리가 관리도 잘되어 있었고 document도 풍부했기 때문에 DirectXTex를 사용하기로 정하였다. 마소 짱짱….
DirextXTex가 direct x에서 사용하기 위해 개발되었지만 OpenGL에서도 dxt 포맷을 지원하니 상관없다.

당연히 에셋들은 멀티스레드로 동시에(?) 임포트된다. 다만 GPU에 올리는 것도 멀티스레딩으로 구현하려 했으니 OpenGL의 경우 각 스레드별 공유할 수 있는 자원이 제한되어 있고 텍스쳐는 당연히 안된다. 그냥 main thread에서 gpu에 올리기로 하였다. ( 어차피 gpu band width가 한정되어 있어 여러 스레드에서 gpu buffer call을 날려도 속도에는 큰 차이가 없다고 한다. )

삽질을 하면서 느낀점이 똑같은 포맷을 의미하면서도 directx, opengl이 다른 용어를 사용하고 라이브러리마다 용어를 조금 다르게 사용한다는 것이다. DXT도 마소에서는 D3, D6 처럼 다른 이름으로 사용하는 것 처럼 보였다. 이런 것 때문에 너무 너무 고생을 많이 헀다. 왜 이렇게 했는지 알 수가 없다.

모든 dds파일들을 압축알고리즘으로 한 파일로 통으로 압축할까도 생각하였다. 하지만 이렇게 통으로 압축해버리면 게임 시작 시 decompress를 해야해서 로딩시간이 늘어나게 되는 문제가 생긴다. 그리고 PC플랫폼에서 게임 파일 사이즈가 문제될 일은 거의 없을거라 생각해서 그냥 하지 않기로 했다.

이렇게 dds파일로 로드해서 바로 gpu에 올려버리니 로딩 시간이 놀라울 정도로 빨라졌다.

현재는 에셋의 종류에 상관없이 전부 서브 스레드에 맡기는 데 이렇게 되는 경우 간단한 text파일 같은 것들은 크기가 작으니 서브 스레드에 맡기는 것이 더 느릴 수 있다. 그러니 크기가 작은 파일들은 그냥 메인 쓰레드에서 처리할 예정이다.