Z 버퍼의 Read / Write 개념 (4부. 개악마 알파 블렌딩3편) by 김윤정

우하하 . 어느덧 4부입니다.
제길 이거 진짜 힘든 강의잖아 OTL

익숙해 지고 나니 별 게 아니긴 한데, 잘 설명하려니까 얽히고 설킨 것들이 너무 많습니다 OTL

어쨌건 지난줄거리 요약

- 불투명인 것들은 Z 버퍼만으로 앞뒤구별이 가능하니, 대충 찍어도 된다.
- 반투명인 것들이 끼어 버리면 문제가 되니, 불투명한 것 먼저 찍고 반투명한걸 나중에 모아서 찍는다.
- 반투명인 것들끼리도 먼저찍히냐 나중에 찍히냐에 따라 문제가 생기기 때문에 반투명한 것들은 순서를 판정해서 뒤에서부터 앞으로 찍어온다.


라는 것입니다.
자 그럼 이번 시간에는...

바로 그 마지막 방법. 반투명한 것들끼리 찍을때 뒤에서 부터 찍는다는 그것 말입니다. 
그게 잘 될것 같지만, 생각만큼 잘 되지를 않는단 말입니다 (...)  

자아 예를 들어 봅시다.
아래의 모든 오브젝트는 이제부터 반투명이라고 생각하세요.

그리고 이제 격자 같은거 안그려도 앞뒤 판정은 하실 수 있으시겠죠?


네에 이건 뭐 쉽습니다. 당연히 앞에 있는 노란 공이 제일 나중에 그려지겠고,
맨 뒤에 있는 튜브가 제일 먼저 그려지겠죠 하하하.
뭐 이렇게 쉬운걸 문제라고..

하하하 아주 쉽네요

좋습니다. 잘 하셨습니다.
그런데 이 물체들이 누가 앞에 있고 누가 뒤에 있는지를 무엇을 기준으로 판단하는 것입니까?

모든 오브젝트에는 각자가 가지고 있는 피봇(pivot)이라 불리는 포인트가 있지요.
이 포인트와 카메라의 거리로 거리판정을 하는 겁니다. 과연. 뭐 그래픽 하시는 분들이라면 다들 알고 있는 내용.

각자 중심이나 아래쪽에 축 하나씩을 가지고 있는데, 그게 피봇점.




그치만 말입니다. 그치만 말예요. 그렇지만 말입니다.

이게 이런 경우도 나온단 말이지요.



아래쪽에 넓은 판 하나가 생겼습니다. 주로 '반투명의 물' 을 만들때 사용되는 방식이지요.
자아 위의 그림처럼 반투명의 물과 오브젝트가 있다 칩시다.  그리고 이 반투명들은 모두 Z Read와 Write 를 하고 있습니다.  

카메라는 정직하지요... 반투명인 물체들이 모였으니까 , 뒤에서 부터.. 즉 "카메라로부터 피봇점이 먼 것부터" 그리기 시작합니다.

슬쩍 상식적으로 생각해 봅시다. 어떤게 가장 '카메라부터 멀리 있어서 제일 먼저 그려야 할 것' 인가요?

당연히 상식적으로 생각하면 5-4-3-2-1 순서입니다.
반투명인 물 (연두색이지만!) 이 가장 먼저 그려지고 그다음에 4-3-2-1 순으로 그려야 겠지요. 

하지만 정말 컴퓨터도 그렇게 생각할까요? 

자 언제나 공정하고 냉정한 그래픽연산장치님의 눈으로 쳐다봅시다. 
위 그림에서 가장 먼 피봇 점은 5번인가요? 
전혀 그렇지 않습니다. 카메라와 피봇 점만 냉정하게 따져보면 , 사실 가장 멀리 있는 것은 4번입니다! 
그리고 그 다음이 5번... 아니 3번인가요?

그다음은 2번, 1번. 이건 뭐 평이하네요. 
자 이제  컴퓨터가 그리듯 카메라 뷰에서 그려봅시다.






먼저 가장 멀리 있다고 생각한 4번을 먼저 그립니다.
그 다음에 멀리 있다고 판단되었던 물을 그립니다.
그런데 물을 그리려다 보니, 이미 누군가가 물보다 앞쪽에 Z 값을 써 놓았습니다.
그렇습니다. 나뭇잎 4번입니다!! 4번은 피봇으로 따져보면 더 멀리 있지만, 픽셀로 따져보면 더 가까이 있는 것이니까요!!

아아아악 개악마 알파의 저주가 시작되었습니다.


게다가 여기서 끝난 것도 아닙니다. 3번과 5번처럼 거리가 애매한 녀석은, 프레임에 따라, 카메라 각도에 따라 서로 우선순위가 엎치락 뒤치락 합니다. 엔진의 거리버퍼가 정밀하지 못하면 더더욱 말입니다.
가끔 절묘하게 동일한 선상에 있다고 판단될때는 여지없이 깨지기도 합니다.
(아래의 그림이 현재 상태에서 정확하지는 않습니다. 보통 아래와 같이 깨지는 경우는 주로 두 평면이 서로 바짝 붙어 있을때입니다)


으아아아아악.

나머지 두 개는 문제가 없다고 해도 이미 저 두 잎이 다 망쳐 버렸습니다. 더 해봤자 희망이 없네요.

그렇습니다. 바로 아래와 같은 경우 발생입니다.
물도 반투명, 배에서 나오는 이펙트도 반투명이었습니다.
물의 plan은 꽤 크기 때문에, 카메라는 물보다 이펙트가 멀리 있다고 판단해 버린 것이었습니다 (!!)

이런 경우만 있으면 차라리 괜찮기나 하죠.

아래와 같은건 어쩔껍니까?

반투명 안에 반투명이 있습니다.
피봇축이 동일합니다. 어쩔까요 이거?

머리카락의 경우도 위험합니다. 저렇게 덮개 모양으로 만드는 데다가, 두꺼워 보이게 하기 위해 여러 겹을 겹치곤 합니다.
저런 머리카락 형태의 문제는, 머리카락의 앞이마 부분은 안쪽머리가 가장 뒷쪽이지만, 
뒤통수 부분은 안쪽머리가 가장 앞쪽이라는 겁니다. 엉망이죠. 
알파 블렌딩을 충분히 사용하면 저 머리카락은 차마 볼 수 없을만큼 엉망이 됩니다.
 

게다가 머리카락의 텍스쳐는 주로 끝부분이 부드럽게 빠지게 하기 위해 알파 블렌딩을 사용하기 때문에, 어쩔 수 없이 머리카락 전체는 반투명(알파 블렌딩) 을 사용할 수 밖에 없게 됩니다.
그래서 이 문제를 해결하기 위해 주로 쓰는 방법은, 알파 블렌딩을 사용하는 부분을 최소화 하는 겁니다.
아래 그림에서 보면, 머리카락이 제대로 나오지 않은 것을 알 수 있지만, 쉽게 눈치채지 못할 만큼의 면적으로 블렌딩을 했기 때문에 눈속임으로 넘어갈 수 있을 정도가 됩니다.

(좀 더 좋은 예제 있었는데.. 찾으면 업데이트 하겠습니다)


결론은, 실무에서 사용하면 뒤죽박죽이 될 수 밖에 없다는 겁니다.
그래픽 디자이너가 결벽증을 가지고 있는 친구가 아닌 담에야 피봇축을 일일히 가운데에 맞출리도 만무하고,
위와같이 오브젝트가 크거나 덮고 있는 형태면 방법도 없습니다.

네, 방법이 없습니다. 개악마 알파 블렌딩의 패악질을 이길 방법이 없습니다.


사실상 대부분의 게임들이 이런 문제로 골머리를 앓고 있습니다.
그리고 프로그램적으로 완벽히 해결하는 방법은 이제 없습니다.(DX11이 나오면 어찌 될까나..) 
나머지는 이 단점을 가지고 어떻게 응용해 나가냐는 거지요.
그리고 그 모든 방법에는 장점이 있고 단점이 있기 때문에,
해결하는 방법은 여러 개이고 그 방법을 때에따라 적절히 섞어가면서 사용합니다. 
여기서 그래픽 디자이너와 프로그래머와의 궁합이 얼마나 되느냐 - 커뮤니케이션이 잘 되느냐 - 에 따라 결과물이 판가름나게 됩니다.



일단 위의 경우를 피하기 위해 그래픽팀에서 많이 사용하는 방법은 다음과 같습니다.

- 물체를 잘게 쪼갭니다 :
어찌보면 완벽한 방법입니다. 쪼개면 쪼갤수록 피봇축이 정밀해져서, 앞뒤 판정이 정확해 질 테니까요.
하지만 그런 식으로 가다가는 모든 폴리곤을 쪼개야 할겁니다 OTL
이것도 적절한 수준으로 쪼개는 수 밖에 없지요.

- 알파 부분을 최소화해서 그립니다. :
상당히 소극적인 방법입니다. 잎을 그릴 때 잎 모양으로 아예 모델링 해 버린다던가, 머리카락을 그릴 때에는 정말로 머리카락의 '맨 끝만' 알파 블렌딩을 사용하는 방법입니다. 소극적이지만 효과적입니다.

- 알파 테스팅을 사용합니다. :
이건 다음 시간에 설명하지요.

- Z Write를 사용하지 않습니다. :
역시 다음 시간에 설명하겠습니다.



그리고 프로그램팀에서 많이 사용하는 방법은 다음과 같습니다.

- 렌더링 레이어를 만듭니다 :
강제로 그리는 순서를 그룹화 시켜서 제어하는 겁니다. 예를 들어 반투명이라고 하더라도 'water' 속성인 녀석들은 무조건 반투명 중 제일 먼저 그린다 - 라는 식으로 제어하는 것입니다.
그런 식으로 이펙트나 기후 등 종류에 따라 그리는 순서를 제어합니다. 완벽하진 않지만 크게 제어가 가능한 방법입니다.

- 여러 Pass를 사용하여 그립니다 :
머리 카락등에서 방향에 따라 여러 번에 나누어 그리는 방법입니다. 그래픽에서 얼마나 잘 쪼개주느냐에 따라 다른 결과가 나올 수 있습니다. 때문에 매우 고난이도의 방법이지요.





자아 . 일단 성급하게 결론내려보면 다음과 같습니다.
- 불투명인 것들은 Z 버퍼만으로 앞뒤구별이 가능하니, 대충 찍어도 된다.
- 반투명인 것들이 끼어 버리면 문제가 되니, 불투명한 것 먼저 찍고 반투명한걸 나중에 모아서 찍는다.
- 반투명인 것들끼리도 먼저찍히냐 나중에 찍히냐에 따라 문제가 생기기 때문에 반투명한 것들은 순서를 판정해서 뒤에서부터 앞으로 찍어온다.
- 그래도 피봇으로 앞뒤를 판정하기 때문에, 완벽하게 앞뒤를 구분하는것은 사실상 불가능하다.


이것이 프로그래머와 그래픽 디자이너의 머리를 싸매게 만드는 알파 블렌딩의 저주입니다.

자 그럼 다음 시간에는, 이 문제의 해결책들중 하나인 알파 테스팅과 Z Read/Write 에 대해 좀 더 자세히 설명해 보겠습니다.
5부, 알파 테스팅과 Z Read/Write 에서 뵙지요. (아아 슬슬 지쳐간다...)

핑백

덧글

  • makio 2010/03/16 10:09 #

    덧글보고 4부에서 알파 블렌딩 설명 해주시는줄 알았는데ㅜ 다음 회를 기대해야겠네요~
  • 김윤정 2010/03/16 10:45 #

    알파 블렌딩은 지금까지 얘기해 왔던 것이고... 알파 테스트가 다음 시간입니다 >_<
  • 2010/03/16 10:46 # 비공개

    비공개 덧글입니다.
  • 김윤정 2010/03/16 10:46 #

    :)
    졸려서...
  • 2010/03/16 11:39 # 비공개

    비공개 덧글입니다.
  • 김윤정 2010/03/16 16:41 #

    헤헤 어차피 다 아시는내용이면서...
    틀린거 있으면 지적많이 해 주세요.
    저도 원래는 그래픽디자이너라서 빈틈이 많습니다.
  • 그레이오거 2010/03/16 19:57 #

    고생 많으십니다.
    보여주고 싶은 사람들이 여럿 되는데 링크좀 퍼갈 수 있도록 허락 해 주시면 감사하겠습니다. m(_ _)m

    횟수로 치자면 클라이언트가 3D 디자인팀으로부터 받는 질문의 절반 이상이 alpha 관련 문제죠. 만약 겜브료를 쓴다면 99%는 맥스에서 해결 가능합니다만... 더 이상 alpha 쪽 트러블이 나오지 않게 '패턴별로 주입'하는데 대충 1년 좀 넘게 걸린 것 같습니다.
    원리를 알면 자체해결이 가능하지만 '와이어프레임 안쪽의 세계는 디자이너의 영역이 아니다!'라고 인식하는 분들이 많은 것이 현실이죠. 쉽지 않은 길, 근성으로 걸어나가시는 모습에 박수를 보냅니다.
  • 김윤정 2010/03/16 20:15 #

    출처 밝히시면 퍼가셔도 상관 없겠습니다 (_ _)
    저야말로 그래픽 디자이너면서 엔진팀에 소속되어 있는지라, 이런 문제로 쓸데없는 프로그래머들의 자원과 시간이 낭비되는것을 수없이 봐 왔었지요. 그래픽 디자이너들이 조금만 이해하면 효율이 극대화 될텐데 말입니다. 회사 내부 교육용으로 제작한 문건이지만, 필요하신 분들께 같이 공유하고 싶었습니다.
  • 기기묘묘한 2010/03/22 16:15 #

    궁금한게 있어서 질문드립니다. 게임브리오 도움말을 보면 SORTING_OFF 를 사용해서 아티스트가 화면에 나오는 거의 모든 알파블렌딩 되는것의 순서를 결정할 수 있다고 써있는데요.... 막상 보면 안쓰더라고요 위에도 빼놓으신거 같고 이유를 여쭤봐도 될까요?
  • 김윤정 2010/03/22 17:13 #

    뭐 전 범용적인 일반론을 얘기하고 있기 때문에 그 부분을 빼놓긴 했습니다 ;; 그리고 그 기능에 대한 부분은 실제로 깊게 사용하던 분들의 경험에 의한거라 정확한 답이 될지는 모르겠는데요;;(범용이라기 보다 엔진기능이기도 하고) 그게 소팅을 모두 off 해버리면 또 곤란한게 생기니까요. 지금 예가 생각이 안 납니다만 소팅은 경우에 따라 off를 해야 하는거지 언제나 off하면 더 문제가 커집니다. 그리고 그 경우에는 소팅을 off 하고 수동으로 sort adjust node로 제어 하는 것 같은데, 그렇게 되면 게임에서 만든 node 구조와 상충될 수도 있기 때문에 여러모로 곤란하지요. 즉 겜브리오 내의 몇몇 오브젝트나 일부 효과등에서 사용할 수는 있겠습니다만 게임 전체로 봐서는 sort 구조를 없애버릴 수는 없으니까요 :) 답이 되었나 모르겠네요;;
※ 로그인 사용자만 덧글을 남길 수 있습니다.


MyADD

<script> (adsbygoogle = window.adsbygoogle || []).push({}); </script>