이전 포스팅에서 RenderObjects 를 이용한 2Pass 방식의 알파처리를 다루었습니다.

 

동작과정에 대해 설명하기 전에 기본적인 파이프라인 개념이 있다고 가정하고 진행하도록 할게요.

 

먼저 URP 에 대한 개념부터 짚어보자

 

유니티에서 만든 스크립터블 렌더 파이프라인의 일종으로 가볍고 고성능을 지향해서 모바일 환경에서 주로 쓰는데,

이전의 빌트인 파이프라인에서는 그래픽스 API를 직접 접근할 수 없었고, OnRenderImage 함수 안에서 제한적인 기능만 쓸 수 있었다.

대표적인 함수가 Graphics.Blit

 

아래 이미지는 빌트인과 스크립터블 렌더 파이프라인 (이제부터 SRP 라고 명명하겠다) 의 차이를 설명한 것

빌트인 파이프라인
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

URP 를 공부하며, 기존 레거시 쉐이더에서 자주 쓰이는 2Pass 방식을 어떻게 적용할지 고민하고 있다.

 

URP 는 기본적으로 싱글패스만 지원하기 때문에 멀티패스를 쓰기 위해선 별도 처리가 필요한데, 이를 위해 유니티에서 마련해준 기능이 RenderFeature 중 RenderObjects 이다.

(물론 이 RenderFeature 또한 직접 구현이 가능하며, RenderObjects 는 유니티에서 편하게 쓰라고 만들어준 RenderFeature 의 일종이다)

 

어떻게 쓰느냐에 따라 활용방법이 무궁무진 한데, 멀티패스 구현 또한 가능하다.

 

여기서는 알파 블렌딩 시 가려지는 뒷쪽 메시들이 부분부분 보이는 문제를 해결하기 위한 RenderFeature 사용 방식을 설명할 것이다.

이런 Convex 한 반투명 메시들은 뒷 메시가 보여져버렷..

 

먼저 우리의 가장 중요한 ForwardRenderer 를 보자

 

이녀석은 ScriptableRenderer 를 상속받아 유니티에서 마련해놓은 포워드렌더링 방식의 파이프라인이다.

여기에 Add RenderFeature 가 보일것이다.

버튼을 눌러보면 Render Objects(Experimental) 이라는 항목이 하나 있을텐데 그걸 선택한 뒤 다음처럼 셋팅하자

아 참, 아래 ZWriteOnly 메테리얼은 새로 만든 셰이더로서 이렇게 셋팅하면 된다

ZWriteOnly 메테리얼의 Inspector

중요한 부분은 Base Map 의 알파를 0 으로 셋팅해서 안보이게 해야 한다는 것이다 (추후 설명하겠지만 Z 버퍼에 쓰기만 할 용도임)

 

아래 부분이 Render Object 에 대한 설정값

각 셋팅에 대한 설명은 아래에..

그 후 반투명 처리할 물체의 메시에 적용해줄 메테리얼을 하나 만들고 다음과 같이 셋팅한다

URP 기본 쉐이더로 셋팅 (원한다면 lit 을 해도 상관 없지만, Surface Type, Blending Mode 는 꼭 저대로 셋팅해야 반투명 오브젝트로 인식하고, 알파 블렌딩도 적용된다.)

Base Map 항목에 컬러값을 셋팅할 수 있는걸 볼 수 있는데 여기에서 알파를 조절하면, 씬뷰에서 반투명 처리되는 메시를 볼 수 있을 것이다.

이 메시의 Layer 도 위 값에 셋팅된 대로 ZTestTransparent 라는 걸로 만들어서 적용하면, 아래처럼 깔끔히 알파처리된 메시를 볼 수 있다.

왼쪽이 깔끔처리된 메시, 오른쪽이 알파 블렌딩 문제 메시

 

위 코드는 저의 깃헙에서도 확인할 수 있습니다. (Assets/Scenes/ConvexMeshAlphaScene.unity 를 열어서 확인가능함)

https://github.com/SeonHwan/ShaderExample

 

SeonHwan/ShaderExample

Contribute to SeonHwan/ShaderExample development by creating an account on GitHub.

github.com

 

자 이제 어떻게 이렇게 구현이 되는지 하나하나 따져볼 시간이지만 포스팅이 길어지므로 다음 포스팅에 자세히 설명하겠습니다.

 

Universal RP 패키지의 몇몇 버전에서 제대로 동작하지 않는 버그가 있습니다. (7.2.0 ~ 7.4.3 쯤에서 비정상 동작하는거 같음)

각 유니티 버전에 verified 된 버전을 사용하거나 최신 유니티 버전을 사용하세요

'Unity > Universal Render Pipeline' 카테고리의 다른 글

알파 블렌딩 (2)  (0) 2020.12.10

+ Recent posts