Home

Gabriel's Blog

<맨 위로>

rTexLoader 개발 관련 주절주절

개요

지난번에 고안한 아틀라스 데이터 운용방식이 상당히 마음에 들어서, 이걸 간단히 라이브러리로 만들어보려고 했다. 이름은 rTexLoader다. 몇 가지 시행착오를 겪으면서 떠올랐던 생각들을 어디엔가 늘어놓고 싶어졌다. 이런 얘기 해도 들어줄 사람이 없으니 대충 끄적여서 블로그 구석에라도 냅두려는 생각이다.


배경 지식

어딘가(주로 화면)에 텍스쳐를 그리기 위해서는 일반적으로 GPU를 거치게 된다. 현대 GPU의 렌더링 파이프라인은 다소 독특하다. 서로 다른 두 개의 텍스쳐를 순서대로 그리면, 총 두 번의 드로우 콜(draw call)이 발생한다. 그러나 하나의 텍스쳐를 여러 번 그려도 한 번의 드로우 콜 내에 처리된다.

따라서 개별 이미지를 따로 올리는 대신, 이들을 이어붙여서 만든 커다란 아틀라스를 올린 뒤 잘라서 그리는 편이 효율적이다.

rTexPacker는 이런 아틀라스 이미지와 개별 스프라이트의 위치, 크기 정보 등을 생성해주는 도구다. 이 스프라이트 정보는 외부 파일로 생성할 수도 있지만, png 청크 데이터에 심어놓을 수도 있다. 결과물이 매우 깔끔하므로 이 방법을 채택했다.


라이브러리 종속성 제거

지난번에는 rpng 라이브러리를 사용해 이 정보를 불러왔었다. 외부 라이브러리 종속성을 제거하고자, rpng 소스코드를 분석해 청크 로딩 코드를 새로 짰다.

rpng는 C 라이브러리이기 때문에 주인장이 극도로 싫어하는 mallocfree가 양껏 담겨있다. 올바른 C++ 코드로 변환하지 않으면 오렌지병으로 세상을 떠날 것이 분명했다.

여기서 문제가 발생하는데, unsigned char[] 타입에 대응되는 RAII 컨테이너로 std::string을 쓸 것인지, std::vector<unsigned char>를 쓸 것인지를 결정해야만 했다. 문자열에 바이너리 데이터를 담는 아이디어가 상당히 마음에 들어 처음에 이 방식으로 구현했었으나, 이 만행을 지켜보던 한 사나이의 꾸중을 들은 뒤 벡터 방식으로 변경했다.

한편 고정 길이를 갖는 전역 상수 배열에는 벡터 대신 constexpr std::array<unsigned char>를 썼다.


단일 헤더

외국에서는 single-header 라이브러리라고 부르는 모양이다. 헤더 파일에 구현을 모조리 집어넣는 건데, 그냥 써 버리면 링킹 과정에서 redefinition error를 마주하게 된다. 함수 인라이닝을 통해 해결할 수 있는데, 그중 static 함수도 있고 해서 다른 방법을 사용했다.

들어 보면 충격과 공포 그 자체인 발상인데, #ifdef LIB_IMPLEMENTATION 위쪽으로는 함수 선언을 몰아놓고, 아래쪽으로는 함수 구현을 두는 것이다. 그리고 이 헤더파일을 참조하는 변환 단위 중 단 하나의 파일에서 헤더 임포트 직전에 #define LIB_IMPLEMENTATION를 적어주면 된다. 이러면 해당 변환 단위에서만 매크로가 활성화되어 함수 정의가 삽입된다.

할 말이 매우 많지만 여백이 부족해 하지 않겠다. 기생충 마냥 다른 소스파일에 지싯지싯 붙어 제 삶을 연명하는 꼴을 보라! 단일 헤더 라이브러리가 뭐라고 이토록 전처리기를 학대하는가! 이런, 이미 해버렸군. 뭐, 이러니 저러니 해도 상당히 영리한 트릭임은 인정해야겠다. 결국 사용하기 편하면 된 게 아닐까.


개발방식

라이브러리를 개발하면서 점진적 최적화 방식(Incremental Otimization Approach, IOA)를 사용했다. 검색하지 마세요, 방금 제가 만든 단어랍니다(!).

  1. rpng 에서 필요한 코드를 만들고 있는 라이브러리 파일에 모조리 붙여넣는다.
  2. 내 주적인 mallocfree를 무슨 수를 써서라도 없앤다. RAII를 만족하는 자료형을 사용하면 된다.
  3. 전체 코드를 모던 C++ 스타일로 바꾼다.
  4. 함수들을 알맞게 병합하고 이름을 바꾼다.
  5. 코드를 목적에 맞게 재배치하고 불필요한 코드를 제거한다.
  6. 이쁘게 주석을 단다.

끝내고 보니 처음 코드는 아무것도 남아 있지 않았다. 백지 상태에서 개발하는 게 훨씬 빨랐겠다 싶었다.


회의감

README.md를 비롯해 example과 각종 빌드 파일을 제작해 깃허브에 올려놓고 보니 문득 회의감이 들었다. 정작 중요한 건 헤더파일 하나인데, 라이브러리 설명하고 보조하기 위한 곁다리 파일은 수십 개에 달했다. 정작 라이브러리 사용할 때는 파일 하나만 쏙 빼서 쓸 텐데 말이다. 보기에는 좋지만, 생산성이 바닥을 기어다닌다.

이에 관해서는 조금 더 고민해 봐야겠다.


여담

이렇게 또 쓸모없는 뻘글이 탄생하고야 말았구나. 심지어는 나조차도 다시 열어보지 않을, 재미도 없고 감동도 없는 글들이 하루하루 블로그를 채워 간다. 뭐 아무렴 어때.

그럼 다음에,
Gabriel-Dropout at 14:08

scribble