컨텐츠 바로가기

z buffer test 를 조작해서 phantom shader 를 만들어 보자

http://lwsoft.egloos.com/5860193

phantom.shader


[ 서론 ]

유튜브를 배회하다 우연히 본 동영상.

보다시피 돈주고 사야하는 Asset임.    

공식적인 명칭인지는 모르겠지만 팬텀 쉐이더 (phantom shader) 를
오늘 한번 만들어 보겠음.

[ 본론 ]
  
    1.어떻게 구현했을까?
        -시선(카메라) 에서 캐릭터를 향하는 Ray test 후 캐릭터 쉐이더 교체?
          구현이 간단하지만 모든 배경오브젝트를 per frame 테스트 하는건 큰 부담이될듯
          캐릭터에 쉐이더 하나 넣자고 bounding volume을 설정하는건 배보다  배꼽이 더큰상황.
          더군다나    모든 ray test 대상이 되는 배경오브젝트에 tag 나 component 로  
          힌트를 심어줘야 하는데 이건 아무리 생각해도 노가다고 비효율적이다.
         
        - 동영상을 보면  pro 버젼의 post image Effect 기반임을 알수있다.
        - 캐릭터가 차폐물에 가려진 부분만 pixel 단위로 phantom effect 가 나온다.
           실시간으로 가려진 부위를 검출하여 그부분의 material 을 찾아낸뒤
           shader 를 교체한다는건 정말 무책임한 brutal force (무대포) 라는 이야기다.
            따라서 쉐이더 교체는 아닐 확률이 높으므로 최후의 보루로 남겨두자.
        
     
    2. 눈에보이는것만 얘기하자
        - phantom 은  알파블랜딩 되고있다.
        - 가려진부분만 phantom 이 pixel 단위로 렌더링된다
            - 통상적으로 우리가 사용하는 z-buffer test 는 less 이고 
                통과한 픽셀에 한해서 z값이 버퍼에 기록된다. 
               엇 그럼 z-buffer test 를 less 가 아닌 greater  로 바꾼다면 ?
               그리고 2pass로 나눠서 캐릭터와 phantom 을 각각 1pass씩 쓴다면? 

    3. 만들어보자.
        - 총 2pass로 나누어서 첫번째 pass 에서는 캐릭터를 간단히 렌더링하고
           두번째 pass 는 phantom 을 렌더링하자.

        - 어? 그런데 이게 뭐지?
           




































                 장갑하박쪽과 손가락쪽 그리고 다리부분이 뭔가 이상하다.
                 사진을 자세히 보면 겹치는곳이 2번이상 z-buffer 연산이 일어나는 convex 한 부분들이다.  
                 언뜻이해가 안간다면 중간이 뚫린 donut 과 sphere 의 차이를 생각해보면 된다
                 노가다 아저씨의 몸통이나 허벅지부분은 문제가 없지만 
                 손가락이나 장화부분처럼 z test를 두번이상 하게되면 
                 시선과 제일 먼 픽셀을  렌더링 하게 되므로 
                 꼬이게 되버린다.  
                   
                 이를 해결하기위해 pass간  stencil buffer test 를 넣었다.
                 
                  shader code만 옮기자면 
                 // pass character
                 stencil {
                         ref 18
                         comp always 
                         pass   replace //비교에 성공하면 스텐실 버퍼 에 ref 값을 기록해라
                 }
                 
                 // pass phantom 
                 stencil {
                        ref 18
                        comp notequal     
                        pass   keep // 비교에 성공하면 스텐실버퍼값을 유지해라
                 }
                 캐릭터 패스에서 18로 기록 하고 
                 팬텀 패스에서는 18이 아닌곳만 랜더링하게 해놨기때문에
                 겹칠 수가 없다.
                 그리고 early ztest 를 하기때문에 
                 ztest 에 성공한 부위만 stencil test 를 하게된다.
                 
                 

  










































이제 잘나온다.




  3. 만들었다!
       - 원리만 심플하게 보이기 위해 유니티 스탠다드 에셋에 있는 
           노가다아저씨의 디폴트 메트리얼에 쉐이더만 바꿔꼈다.
           phantom pass에서는 unity shader tutorial 에 있는 rim lighting 처리 방식으로 
           아주아주 간단히 phantom느낌이 나게 처리해봤다. 
        
           


[ 결론 ]
   - phantom shader 를 어디다 써야할까?
      
      - 병원이나 공항검색대 같은곳에 x-ray 를 연출
      - 동영상에 나온것처럼 던젼이나 벽에 가려졌을때 실루엣 표시
      - fps 게임등에서 유료 아이템 구매시 벽뒤에 가려진 enemy를 표시

[ 개선사항 ]
     - stencil buffer 에 masking처리후   테스트를 사용해서 
        특정 오브젝트에서만 phantom이 나올수있게  처리하는것도 좋겠다.
        캐릭터를 가리는 모든 오브젝트에 phantom 효과가 렌더링 되면 그건 더이상할테니..

    - 장기적으로 보면 post image effect 로 가는게 좋다.
       보통은 주인공이 가장화려하기 때문에 material 도 많이 사용하고 shader 도 따로 만들어서 쓰는 경우가 많다.
       기존에 만들어 놓은 shader 를 조금이라도 수정해서 쓴다는건 부담스러운 일일수 밖에 없다.
       따라서 phantom 효과가 필요한 오브젝트에 한해 component를 추가하고  
       카메라에 attach 된 post image process script 에서 한방에 처리해주는게 제일 심플할듯싶다.

쉐이더는 첨부파일이나 링크 참조.


덧글|덧글 쓰기|신고