>ase를 카툰랜더로 출력해볼려고하는데..
>책 같은데 봐두 넘 어렵게만 나와서 접근할수가 없어요...
>어셈블만 나오면  ㅠ_ㅠ 울고싶고...  
>접근방법과 책이나 참고자료같은것 추천좀 해주세요.....
>부탁드립니다..

요즘 '카툰렌더' 방식에 대한 관심이 부쩍 높아지고 있습니다. 트루판타지라이브 온라인, 드래곤 퀘스트8, 다크크로니클2 등 외국게임과 천랑열전, 마비노기, 씰 온라인등 국산 게임들에도 카툰렌더링이 활발하게 쓰이고 있습니다.

우선 카툰렌더에 대한 정확한 정의를 해둘 필요가 있습니다. 카툰렌더링은 비사실적인 렌더링 방식(Non-photo realistic rendering = NPR 기법)중의 하나로써, 어떤 게임이 '카툰렌더링을 이용했다' 라고 말하려면 최소한 다음 2 가지 조건중 하나를 갖추어야 합니다

   - 불연속적인 쉐이딩 표현
   - 실루엣 외곽선의 묘사

다크 크로니클2 나 드래곤 퀘스트 8 같은 게임은 실루엣 외곽선의 묘사만 사용하고, 내부 쉐이딩 표현은 일반적인 기법을 사용한 반면, 게임큐브용 젤다같은 경우는 실루엣 외곽선의 묘사는 생략하는 대신 불연속적인 쉐이딩 표현방식을 이용하였습니다. 트루판타지 라이브 같은 경우는 두가지 방식을 모두 이용한 예입니다.

그림자를 표현하는데에 여러가지 방식이 있는 것처럼 카툰렌더링을 실제로 구현하는데에는 여러가지 방식이 있습니다. 그럼 각각의 방식에 대해 간단히 알아보도록 합시다.

1. 불연속적인 쉐이딩 표현
보통 게임에서 쉐이딩을 표현할때, Ambient term (일정한 상수값), Diffuse term (빛의 각도와 표면의 각도에 의해 표현되는 값), Specular Term (시선의 각도와 빛의 각도, 표면의 각도에 의해 표현되는 하일라이트 값) 의 3 가지 요소의 복합에 의해서 물체를 나타냅니다. (자세한 사항은 DirectX SDK 문서의 'Mathematics of Lighting' 항목을 참조하시기 바랍니다.)

쉐이딩 표현에 있어서 가장 큰 영향을 미치는 요소는 Diffuse term 인데, 이것은 빛의 각도와 표면의 각도에 의해서 결정됩니다. 빛이 표면에 정확하게 직각으로 비추게 되면 100% 의 밝기로 보이고 (cos 90' = 1) 빛이 45 도로 비스듬하게 비추게 되면 약 70%의 밝기 (cos 45' = 0.707) 로, 빛이 표면에 평행하게 지나가거나 반대쪽에서 비추게 되면 0% 의 밝기 (검은색) 으로 표현하는 것입니다.
이 방식에 의하면 동그란 구형의 물체에 빛을 쬐면, cos 의 그래프에 맞춰서 스무스하게 밝은부분부터 어두운 부분으로 변하는 쉐이딩을 보게 됩니다.

반면에 불연속적인 쉐이딩 표현인 카툰렌더링을 이용할 경우에는 스무스하게 쉐이딩이 표현되는 것이 아니라, 2 단계나 3 단계로 매우 간략화된 표현방식을 사용하게 됩니다. 이 경우에는 밝기가 100% 부터 70% 까지는 무조건 100% 로 그냥 색상을 정하고, 70%~ 40%까지는 무조건 70%, 40%~0% 까지는 무조건 40% 로 찍는 등의 방법을 이용해서 색상을 뚝뚝 끊어놓는 것입니다.

이것을 구현하는데에는 2 가지 방법이 있습니다. 첫째는 Diffuse term 을 계산 (표면의 법선벡터와 빛의 법선벡터의 내적을 계산) 한 다음에 위의 예와 비슷하게 판단문을 사용해서 결과값을 조절하는 방식이 있습니다. 두번째는 별도의 lookup table 용으로 1 차원 텍스춰를 이용해서 diffuse term 을 넣으면 수정된 결과값이 나오는 절차를 추가하는 것입니다.

두번째 방식의 경우에는 더 다양한 효과를 줄 수 있다는 장점이 있습니다. 예를 들면 쉐이딩이 바뀌는 경계부분을 완전 날카롭게 처리하지 않고 약간 부드럽게 뭉개주는 효과를 줄 수 있습니다. 이것은 예전에 게시판에 올라온 일본 동인 카툰렌더링 격투게임에서 사용한 방식입니다.

2. 실루엣 외곽선의 묘사

또 하나의 특징은 실루엣 외곽선을 묘사하는 것입니다. 이것에는 더 많은 구현방법이 있는데, 크게 4 가지로 나눌 수 있습니다.

첫째, 환경맵이나 버텍스 쉐이더를 사용해서, 시점과 표면의 각도가 거의 평행이 되는 (즉, 모서리에 근접한) 쪽의 폴리곤을 어둡게 칠해주는 방식입니다. 이것은 계산이 매우 간략하지만, 세가지 단점이 있습니다. 모서리쪽에 폴리곤의 크기가 큰 경우에는 표현이 부드럽지 않게 나온다는 점, 그리고 외곽선이 모델의 바깥쪽으로 가는 것이 아니라 모델의 안쪽으로 그려지는 것이기 때문에 외곽부위의 디테일 표현이 가려진다는 단점이 있습니다. 또한 외곽선의 굵기가 균일해지지 않는다는 것도 단점입니다. 장점은 모델을 한번 찍는 것만으로 표현되기 때문에 속도가 빠르다는 점입니다. 보통 directX SDK 예제나 nVidia SDK 예제에 있는 toon-shading 은 이 방식을 사용한 것입니다.

둘째, 모델을 두번 찍는 방식입니다. 모델을 일반적인 방식으로 한번 찍고, 모델을 단색으로 어둡게 하고 약간 확대를 한 다음에 그 자리에 다시 찍으면 확대된 것과 보통상태의 차이만큼이 단색으로 어둡게 묘사되는 것입니다. 어떤 책에서는 단색으로 어둡게 찍을때 front-face 대신 back-face 로 찍으라고 권하기도 하는데 둘 사이에 어떤 차이점이 있는지는 제가 직접 해보지 않아서 모르겠습니다. 이 방식의 장점은 vertex-shader 나 기타 특별한 처리가 필요하지 않다는 장점이 있습니다. 그냥 모델을 약간 크게 단색으로 한번 더 찍어주기만 하면 되기 때문입니다. 단점은 모델을 2 번찍기 때문에 속도가 2 배로 든다는 점이 있습니다. 외곽선용 모델을 찍을때, 대부분의 픽셀은 찍히지 않고 외곽부분만 찍게 되므로 낭비가 생기게 됩니다만 보통 모델을 먼저 찍게 되면 Hyper-Z 같은 구조를 사용할 경우에는 시간을 절약할 수 있습니다.. 또 한가지 단점은 모델 내부에 있는 외곽선이 잘 표현되지 않는다는 점입니다. 예를 들어서 사람의 정면 얼굴을 찍는다고 할때 얼굴과 목 사이에 있는 부분은 선으로 표현되지 않을 수 있습니다. 이것은 그림자부분을 찍을때 얼마나 뒷쪽에 찍어주느냐에 따라서 달라질 수 있습니다. 다크 크로니클2 가 이 방법을 사용한 것으로 보입니다.

셋째, 외곽 edge 선을 직접 계산해서 선으로 찍어주는 방식입니다. 어떤 edge 가 외곽선인가 아닌가를 판별할때에는 그 edge 에 접하고 있는 2 개의 면 법선벡터와 시점의 벡터의 곱한 값 2 개의 부호가 서로 다른가, 같은가를 갖고 판별합니다. 다시 말하면 edge 를 기준으로 한 면은 front-facing 이고 다른 면은 back-facing 이면 그 edge 는 확실히 실루엣 edge 라고 볼 수 있다는 것입니다. 그렇게 구한 edge 들을 line-rendering 방식으로 그려주면 됩니다.
이 방식은 가장 깨끗한 외곽선을 그릴 수 있고, 외곽선의 두께를 프로그래머가 직접 정할 수 있다는 장점, 외곽선 만큼만 pixel-rendering 이 필요하다라는 장점이 있습니다만, edge 판별을 위해서 CPU 연산이 필요하다는 점, 그리고 edge-line 과 모델사이의 z-buffer 값에 의한 깨짐현상을 해결하기 위해는 다소 복잡한 절차를 거쳐야 한다는 단점이 있습니다.
CPU 연산을 줄이기 위한 방법의 하나로는 vertex-shader 를 이용해서 fur-shading 기법을 응용하는 방법이 있습니다. 이것은 fur-rendering 을 할때처럼 각 edge 마다, 늘어날 수 있는 면을 추가로 심어놓고 edge 로 판별된 면에 대해 그 edge 를 extrude 해주는 것입니다. 이렇게 하면 cpu 의 부담을 줄일 수 있고, vertex-buffer 의 변동을 줄일 수 있지만, 각 edge 마다 일일이 fur 를 심어주느라고 vertex-buffer 가 커지는 단점이 있습니다.

넷째, 이미 모델들이 모두 렌더링된 화면을 분석해서 픽셀단위로 외곽선 검출을 하고 외곽선으로 판단된 픽셀에 외곽선 색상을 그려주는 방식이 있습니다. 크게 2 가지 방법이 있는데, 화면상의 한 점의 z 버퍼값을 읽어서, 그 주변 점들과의 z 값을 비교했을때 어느 일정 정도(threshold) 이상 z 값이 차이가 나면 외곽선으로 판단하게 되는 방식이 있고, 또 하나는 화면의 픽셀당 노말맵을 별도의 버퍼에 그려놓고, 역시 노말값이 급격하게 변하는 부분을 외곽선으로 판단하는 방식이 있습니다. 경우에 따라서는 깊이값 검출과 노말값 검출을 조합해서 (and 또는 or 로) 쓰면 더욱 깨끗한 외곽선을 검출할 수 있습니다.
이 방법의 장점은 모델의 갯수에 관계없이 한번의 화면 크기만큼의 후처리를 하는 것으로 전체적인 외곽선을 뽑아서 그려줄 수 있다는 점입니다. 하지만 픽셀쉐이더가 반드시 있어야 한다는 점과, 화면에 카툰렌더링된 캐릭터가 얼마 표시안되더라도 화면 전체크기만큼의 후처리를 하는데 시간이 소요된다는 점이 단점으로 생각할 수 있습니다.

3. 결론

간단하게 초보적인 방법부터 접근을 하신다면, 비선형적인 쉐이딩방법과 모델 2 번 찍어주기 방법을 조합해보시길 권합니다.

imcgames 의 김학규입니다