꽃미남 프로그래머 김포프가 창립한 탑 프로그래머 양성 교육 기관 POCU 아카데미 오픈!
절찬리에 수강생 모집 중!
프로그래밍 언어 입문서가 아닌 프로그래밍 기초 개념 입문서
문과생, 비전공자를 위한 프로그래밍 입문책입니다.
jobGuid 꽃미남 프로그래머 "Pope Kim"님의 이론이나 수학에 치우치지 않고 실무에 곧바로 쓸 수 있는 실용적인 셰이더 프로그래밍 입문서 #겁나친절 jobGuid "1판의내용"에 "새로바뀐북미게임업계분위기"와 "비자관련정보", "1판을 기반으로 북미취업에 성공하신 분들의 생생한 경험담"을 담았습니다.
Posted by 조진현

유저에 의해서 한번만 생성되어져서 
지속적으로 게임 속에서 사용되어져야 하는 텍스쳐가 있다면 어떻게 구현해야 할까요?
예를 들어서 문신과 같은 유사한 기능을 구현할 때, 어떻게 해야할까요?

문신의 경우 유저에 의해서 선택되어지고, 
이후에는 지속적으로 문신이 적용된 상태로 텍스쳐링이 되어야 할 것입니다.
이를 적용할 수 있는 방법은 몇 가지가 있습니다. 

- 멀티 텍스쳐링
- 픽셀 쉐이더 상에서 혼합
- 텍스쳐에 락(Lock)을 걸어서 직접 연산


사실 위의 방법들은 실시간으로 텍스쳐 데이터를 생성해서,
텍스쳐링을 하는 것입니다.
이러한 작업을 매프레임 실행하는 것은 당연히 범죄이겠지요.^^

그래서 이를 단 한번만 수행하기 위해서
렌더타겟을 텍스쳐로 설정해서 각각의 텍스쳐를 파이프라인에 연결해서
픽셀쉐이더에서 연산하는 방법이 사용되기도 합니다.
물론 더 좋은 방법이 있으시면, 언제든지 알려주시기 바랍니다..^^

저도 물론 이렇게 해서 문제를 해결했었는데,
문제가 하나 있었습니다.
렌더타겟을 지원하지 않는 그래픽카드의 경우가 바로 그것입니다.
쉐이더를 지원하지 않는 그래픽카드라고도 할 수 있습니다. ^^
최근에는 이런 오래된 그래픽카드 유저가 거의 없지만,
해외에 나가면 또 얘기가 다릅니다.

또 하나의 미세한 문제가 있는데,
렌더타겟은 압축 포맷이 아니라는 것입니다.
즉, 일반적으로 사용되는 RGBA 포맷입니다.
결국 렌더타겟은 DDS 파일보다 메모리 점유가 클 수 밖에 없습니다.

제가 이 문제를 고민했던 시기가 2007~2008년도 사이였으니
좀 오래된 얘기이기도 합니다.
어쩌면 이제는 필요없는 것일수도.......

이렇게 GPU 활용에 제약이 있다는 얘기인데,
이렇게 되면 CPU를 활용할 수 밖에 없습니다.
일반적인 이미지 포맷( JPG, PNG... ) 등의 경우라면,
아래와 같은 방법으로 텍스쳐 이미지 픽셀의 정보를 얻어올 수 있습니다.

 
단순히 이미지의 높이와 폭만큼 접근하면서
반복적으로 이미지 픽셀 데이터에 접근하는 로직을 구성하면 됩니다.

그런데, DDS 파일 포맷은 이런 식으로 접근하면 안됩니다.
이 DDS에서 이미지 픽셀을 다루는 방법이 DirectX API 에는 존재하지 않습니다.
정확히 모든 이미지 포맷에 대해서 픽셀을 제어하는 DirectX API는 존재하지 않습니다.
즉, 이것은 개발자의 몫입니다.

DDS의 경우에는 압축 포맷입니다.
즉, DDS 파일은 이미지 픽셀 데이터가 실제 데이터와 1:1로 매칭되지 않습니다.

혼란을 피하기 위해서 용어를 명확히 하자면
DDS는 파일 포맷이고, DXT는 이미지의 픽셀 포맷입니다.
그런데, 다들 아시듯이 DXT는 1~5번까지의 압축 방법들이 있습니다.
DXT 는 결국 압축되어진 이미지 블럭에서 해당 이미지 픽셀을 추출할 수 있어야
GetPixel(...), SetPixel( ... ) 을 구현할 수가 있습니다.

DDS와 DXT에 대한 상세한 설명은 인터넷에 많은 자료들이 있으니,
저는 다루지 않겠습니다.^^

DXT 픽셀 포맷에서 이미지 픽셀 데이터를 추출하는 작업은
좀 처럼 쉬운 문제는 아닙니다.( 적어도 제게는 아주 어려운 작업이였습니다~ )
직접 데이터를 추출하셔도 되지만,
저는 라이브러리를 사용하라고 얘기드리고 싶습니다.
그 중에 하나가 오늘 소개드릴 squish 라이브러리입니다.

http://code.google.com/p/libsquish/

다운로드를 받으셔서,
헤더파일과 라이브러리를 프로젝트에 연결시켜주기만 하시면 됩니다.
그리고 아래에 한줄만 선언해 주시기 바랍니다.
#include <squish.h>

아래는 실제 사용 예입니다.



위의 예처럼 squish::DecompressImage( ... ) 만 해주시면,
RGBA 데이터가 자동적으로 풀려서 저장됩니다.
이 두 DDS 텍스쳐를 서로 혼합하는 것은 다음과 같이 하면 될 것입니다.



편의상 DXT1 만 사용해 보았습니다.
squish 라이브러리는 DXT 1, 3, 5 번 압축만 현재 지원을 하고 있습니다.
최적화도 굉장히 잘 되어 있다고 합니다.
( 홈페이지에 나와 있어서....ㅎㅎ )

그리고 보통 이미지 작업을 위해서 DevIL 많이들 사용하시는데,
DevIL 의 내부에서도 DXT 부분은 이 squish 라이브러리를 사용합니다.
( 옵션으로 squish와 Nvidia 모듈을 설정할 수 있습니다.^^ )






댓글을 달아 주세요

  1. Favicon of https://gamedevforever.com cagetu 2012.01.05 15:53 신고  댓글주소  수정/삭제  댓글쓰기

    와우~... 좋은데요?! ㅎㅎ

  2. Favicon of https://gamedevforever.com Silverchime 2012.01.06 14:01 신고  댓글주소  수정/삭제  댓글쓰기

    이 이거 알려줘야겠네요... 감사합니다

  3. Favicon of https://gamedevforever.com ozlael 2012.01.06 23:08 신고  댓글주소  수정/삭제  댓글쓰기

    오오 신기한 라이브러리군요

  4. Favicon of https://gamedevforever.com 김포프 2012.01.09 08:29 신고  댓글주소  수정/삭제  댓글쓰기

    전 그냥 NVTT(NVidia Texture Tool)씁니다. 오픈소스 프로젝트가 되었는데 저도 기능 하나(generic convolution filter) contribution했구요. NVTT 내부적으로 squish라이브러리를 쓸수있게 해주는 컴파일러 스위치도 있구요..

    CUDA지원이 가장 큰 장점이라고 하는데... NVidia에서 이거 관리하던 이그나시오 아저씨(예전엔 렐릭에 있었음)가 엔비디아 떠나서 다른 겜 회사 간뒤로... 오픈소스가 되었고.. 그뒤로 좀 유지보수가 뜸한게 문제라면 문제...


  5. Favicon of https://gamedevforever.com 대마왕J 2012.01.13 09:09 신고  댓글주소  수정/삭제  댓글쓰기

    헐 우리는 어떻게 하고 있지...? 우리한테도 필요한지 알려줘야겠습니다. 잘 읽었습니다 :)

  6. Favicon of https://gamedevforever.com zinzza 2012.01.13 10:14 신고  댓글주소  수정/삭제  댓글쓰기

    게임할때마다 저런건 어떻게 만들지? 하고 생각했었는데 여러가지 방법이 있군요.
    관련 라이브러리도 있고 ㅎ

  7. Favicon of https://gamedevforever.com denoil 2012.01.13 10:43 신고  댓글주소  수정/삭제  댓글쓰기

    와우 DXT를 직접 건들 수 있는 라이브러리가 있다니
    좋은 정보 감사합니다. ^^

  8. 디치리 2012.01.13 16:20  댓글주소  수정/삭제  댓글쓰기

    옹옹 멋져염.. 감사합니다.

  9. Favicon of http://sumnomm.blog.me sumnomm 2012.01.13 17:00  댓글주소  수정/삭제  댓글쓰기

    저도 동적으로 텍스쳐를 생성해야 한다면 DevIL을 사용해서 텍스쳐를 미리 생성해서 사용해 볼까 생각했었는데
    DevIL도 squish를 사용해서 하는거였군요.
    좋은내용 배워갑니다!!

  10. Hybrid 2012.01.14 22:53  댓글주소  수정/삭제  댓글쓰기

    전 이 라이브러리 쓰면서,
    '아, 남들이 쉽게 할 수 있는걸 내가 잘 몰라서 괜히 복잡하게 하는건가?' 싶었는데,
    딱히 편한 방법은 없나보군요. 흠....