Unity/Shader & VFX

URP 14 - SimplePostBlur

CatDarkGame 2024. 7. 30. 21:02
반응형

 

개요

  • 모바일 성능을 고려한 블러 포스트프로세싱입니다.
  • 다운 샘플링 방식으로 블러를 표현하여 GPU 성능을 최대한 사용하지 않습니다.
  • 마스킹 텍스처를 활용해 블러 영역 제어 가능합니다.
  • Unity 2022.3.38f1 / URP 14.0.3 버전 기준으로 제작되었습니다.
    • URP 14의 최신 RendererFeature API를 적극 활용했습니다.

https://github.com/CatDarkGame/SimplePostBlur/tree/main?tab=readme-ov-file

 

GitHub - CatDarkGame/SimplePostBlur

Contribute to CatDarkGame/SimplePostBlur development by creating an account on GitHub.

github.com

 

 

사용법

1. RendererFeature 추가

URP Renderer Data에 PostBlurRendererFeature를 추가합니다.

Filter Mode 다운 샘플링 과정에서 RT 필터 모드를 선택합니다.
성능 차이 거의 없으며, 원하는 비주얼에 맞게 세팅합니다.
Sample Count 다운 샘플 드로우콜 횟수를 의미합니다.
숫자가 높을 수록 다운 샘플링 횟수가 많아지며 성능에 좋지 않습니다.
런타임 도중 유동적으로 값을 바꾸는 것은 성능에 좋지 않습니다.
숫자에 따라 비주얼이 느낌이 다르기 때문에 원하는 방향에 맞게 세팅합니다.
Render Pass Event 후처리 실행 구간을 세팅합니다.
일반적으로 기본 값을 사용하지만 프로젝트 상황에 맞게 세팅합니다.

 

 

2. Post Volume 추가

씬에 Post Volume 배치 후, Post Blur Component를 추가합니다.

Blur Amount Blur 효과 반영 수치를 제어합니다, 0으로 세팅하면 후처리 기능이 완전 비활성화됩니다.
Blur Offset 블러 퍼짐 수치를 제어합니다, 원하는 블러 비주얼 방향에 맞게 조절합니다.
RendererFeature의 Sample Count와 다르게 런타임에서 유동적으로 값 제어해도 문제 없습니다.
Blur Mask 마스크 텍스처를 통해 블러 영역을 제어 가능합니다.
R채널만 사용하기 때문에 싱글 채널 무압축 포맷 사용을 권장합니다.
마스크 텍스처 사이즈는 성능을 위해 최대한 작게 사용을 권장합니다.
Blur Mask Tilling Offset 마스크 텍스처의 Tiling Offset 제어합니다. 응용 예시는 아래 설명합니다.

 

 

3. 사용 예제 : TiltShift 세팅

 

TiltShift 블러를 세팅한 예제는 github 샘플 프로젝트에서 확인 가능합니다.

TiltShift는 화면 위 아래를 블러 처리하여 간단히 표현 가능하며, 주로 Fov가 낮은 미니어처 느낌을 낼때 사용합니다.

사용한 블러 마스크는 8x256 사이즈의 그라디언트 텍스처이며 Wrap Mode를 Mirror로 세팅하여 텍스처 사이즈 대비 더 높은 품질을 내도록 했습니다.

 

후처리에 사용하는 텍스처 사이즈 관련해서

후처리 특성상 전체 해상도만큼 픽셀 쉐이더가 돌아가야하기 때문에 픽셀 연산 및 샘플링 비용에 민감할 필요가 있습니다.

특히 Shared 메모리를 사용하는 모바일 디바이스 특성상 텍스처 샘플링 캐시 히트율이 낮으면 쉐이더 연산 상관 없이 성능 저하가 쉽게 발생하기 때문에 주의할 필요가 있습니다.

 

 

 

구현 & 원리 설명

1. 쉐이더 구현

 

1개의 쉐이더의 각 역할이 다른 2개의 Pass가 구현되어 있습니다.

  • Pass 0 : 최종 블러 결과물 출력을 담당, 블러 처리된 RT와 Lerp 블랜딩 구현됨.
  • Pass 1 : 다운 & 업 샘플링 Pass이며, 단순히 4방향 Box 블러가 구현됨. 

 

2. RenderPass - RenderTexture 세팅

기본적으로 화면 버퍼 카피(sourceTexture) & 출럭 버퍼(destTexture) RTHandle을 선언합니다.

그리고 다운 샘플링 버퍼를 저장하는 RTHandle을 SampleCount 만큼 배열로 선언합니다.

URP 14에서 한번 메모리에 생성한 버퍼를 재활용하기 때문에 고정 배열 형태로 선언하여 Sample Count가 변하지 않는 이상 추가 동적 할당이 발생하지 않습니다.

 

RT 생성하는 코드입니다. 다운 샘플링 -> 업 샘플링해야하기 때문에 >> 비트 시프트 연산자로 2배로 줄어들고 2배로 증가하도록 구현했습니다.

 

다음은 커맨드버퍼에 드로우콜 구현 내용입니다.

URP 14에서 권장하는 Triangles 메쉬로 화면 전체에 출력하는 방식으로 구현되었습니다.

그 외 Material에 값을 직접 세팅하지 않고 MaterialPropertyBlock을 사용했는데, Blitter.BlitTexture 함수를 사용할 때 Material에 직접 값을 세팅해서 사용하면 세팅한 값이 초기화되지 않는 현상이 있어 이와 같이 구현했습니다.

URP 내장 코드에서도 이와 같이 구현된 것을 보면 MaterialPropertyBlock 사용이 권장 사항 같습니다.

 

3. 결과 & 구현 특징 해설

 

앞서 설명한대로, 쉐이더에서는 박스 블러 외에 특별한 구현 내용이 없으며, 블러 효과는 다운 & 업 샘플링에 의존도가 높은 것이 특징입니다. 따라서 쉐이더 연산에 의한 GPU 성능보다는 RT 생성 & 드로우콜 처리에 의한 CPU 성능을 더 사용합니다.

최대 장점은 높은 해상도에 의한 성능 저하 부담이 적으며, RenderPass에서 프레임 스킵 구현을 통해 추가 최적화 작업이 가능합니다.

 

 

 

반응형