이전 포스팅에서 RenderObjects 를 이용한 2Pass 방식의 알파처리를 다루었습니다.
동작과정에 대해 설명하기 전에 기본적인 파이프라인 개념이 있다고 가정하고 진행하도록 할게요.
먼저 URP 에 대한 개념부터 짚어보자
유니티에서 만든 스크립터블 렌더 파이프라인의 일종으로 가볍고 고성능을 지향해서 모바일 환경에서 주로 쓰는데,
이전의 빌트인 파이프라인에서는 그래픽스 API를 직접 접근할 수 없었고, OnRenderImage 함수 안에서 제한적인 기능만 쓸 수 있었다.
대표적인 함수가 Graphics.Blit
아래 이미지는 빌트인과 스크립터블 렌더 파이프라인 (이제부터 SRP 라고 명명하겠다) 의 차이를 설명한 것
저기 빨간 네모를 통해 CPU 메인쓰레드에서 GPU 렌더쓰레드로 명령이 전달되는데 GPU 에게 그려라는 명령을 내리기 위한 전반적인 프로세스인 저 빨간박스 영역을 우리는 파이프라인이라고 한다.
차이가 보이는가?
빨간색 박스가 게임로직 박스 옆으로 이동되었다. 이게 아주 중요한 부분이다.
유니티께서 우리에게 그래픽스 API에 바로 명령을 전달할 수 있게 스크립트로 빼준 것
저렇게 바뀜으로서 우리는 어떻게 어떻게 그려라 라는 값들을 C# 스크립팅을 통해 잘 정리하고 패킹해서 SRP에 전달할 수 있게 된것.
다시 말하자면 예전엔 빨간색 상자에 전달할 수 있는 명령이 몇개 없었는데, 지금은 대부분의 것을 빨간색 상자에 전달하면 빨간색 상자는 그대로 그려준다는 것이다. (여기서 빨간색 상자는 SRP)
단! 저 빨간색 상자에 어떤 값을 전달해줘야 하는지 알기 위해선 그래픽스에 대한 이해가 필요하다.
비유하자면 21단 자전거를 사줬지만 기어변경을 할 줄 모르면 쓸모가 없다는 것
이제 기존 빌트인 파이프라인과의 차이에 대해 이해하겠는가?
그래도 모르겠다면, 유니티 코리아에서 자세한 개념설명 해주셧으니 해당 영상을 참고하기 바란다
https://www.youtube.com/watch?v=QRlz4-pAtpY&list=PL412Ym60h6utrWNnHpZYSlG_pwRafryMO&index=15
차이에 대해 이해했다고 가정하고, 자 그럼 어떠 어떤걸 SRP 에 넘겨줘야 하는거지?
이를 위해 SRP 는 Pass 개념을 도입했는데 SRP 는 여러개의 패스로 구성된 렌더러를 가지고 있다.
DOD 스타일로 다루어져서 이 렌더러를 바꿔끼기만 하면 다른 렌더링 방식으로 렌더링이 가능하다.
우리는 이 Pass, Pass, Pass 를 잘 구성하기만 하면 되는 것이다.
그래서 ForwardRenderer.cs 파일을 열어보면 이 패스들을 정해진 순서대로 그리고 있는것을 확인할 수 있다.
이 패스를 지지고 볶고 추가하고 삭제하고 하는 방식으로 SRP 와 상호작용 할 수 있다.
자 개념도 알겠고 내가 Pass 를 전달해줘야 하는 것도 알겠다.
그런데 어떻게 스크립팅 하라고?
그럴걸 대비해서 유니티는 친절하게도 예제 소스를 친히 제공해주는데, 그게 바로 RenderObjects 라는 클래스 되시겠다.
얘를 까보면 코드 몇줄 없고, 실질적으로 RenderObjectsPass 생성하고, Renderer에 패스 추가하는 역할이 끝
renderObjectsPass = new RenderObjectsPass(settings.passTag, settings.Event, filter.PassNames,
filter.RenderQueueType, filter.LayerMask, settings.cameraSettings);
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
renderer.EnqueuePass(renderObjectsPass);
}
요 Pass (위 코드에서는 RenderObjectsPass) 에다가 잘 셋팅하는 것. 이게 URP 를 다루기 위한 핵심이다.
이전 포스팅에서의 작동 방식에 대해 설명하기 위해 먼길을 돌아왔다.
저번에 ForwardRenderer 에다가 Add RenderFeature 를 한 것을 기억하는가?
바로 이 패스를 추가하기 위함이었던 것이다.
이제 이러한 개념을 바탕으로 2패스 알파블렌딩에 대해 고찰해보자
URP 는 기본적으로 멀티 패스 렌더링을 지원하지 않는다.
하지만, Universal Render Pipeline 관련 쉐이더를 까보면 아닌데? SubShader 에 쉐이더 Pass 여러갠데?
이건 오브젝트 하나 그릴때 여러개의 패스를 다 탄 다음에 그려라는 내용이 아니다.
URP 는 쉐이더 Pass 의 LightMode 태그를 통해 동일한 객체를 여러번 그리게 되는데,
뎁스쓰기용 태그를 가지고 있는 오브젝트를 다 갖고와서 뎁스만 설정하고 (이게 Depth 패스)
불투명 태그를 가지고 있는 오브젝트를 다 갖고와서 불투명 오브젝트만 그리고 (이게 Opaque 패스)
투명 태그를 가지고 있는 오브젝트를 다 갖고와서 투명 오브젝트 그리고 (Transparent 패스)
이런 식으로 하나의 쉐이더를 가지고 각 패스마다 여러번 참조하기 때문에 쉐이더 패스를 여러번 참조당한다 라는 개념이 맞을것이다.
다 알겠다. 그래서 2 Pass 어떻게 처리하는데요?
이제 결론을 얘기할 때가 된 것 같다.
우리는 이 Pass 사이사이마다 임의로 패스를 추가할수도 있기 때문에 중간 어디쯤에 패스를 밀어넣어주면 결과적으로 멀티 패스를 구현할 수 있는 것이다.
Event 항목이 이 패스를 어디에 끼워넣을건지 설정할 수 있는 부분이며,
이 패스를 어떤 오브젝트에 적용할건지 필터 설정도 할 수 있다.
Override 항목에는,
어떤 재질로 덧 그릴것인지,
뎁스버퍼를 어떻게 설정할 것인지, (ZTest, ZWrite 모두 저 항목으로 설정 가능)
스텐실버퍼를 어떻게 설정할 것인지
자주쓰는 기능들이 모두 마련되어 있다.
2 Pass 알파 처리의 핵심은 뎁스버퍼를 먼저 채우고 난 다음 반투명을 덧그리는 것이기 때문에,
반투명 오브젝트를 그리기 전에 뎁스버퍼를 채우는 Pass 를 추가하면 해결이 되는 것이다.
2 Pass 쉐이더를 자주 이용했던 프로젝트에서 URP로 넘어갈때 어떻게 해야 하는지 감이 안잡히셨던 분들에게 조금이나마 도움이 됬으면 하는 바램이다.
'Unity > Universal Render Pipeline' 카테고리의 다른 글
알파 블렌딩 (1) (0) | 2020.12.09 |
---|