유니티 엔진 (Unity Engine)

유니티 그래픽스 최적화 - 5.라이팅 (Lighting)

원생계 2019. 9. 16. 03:08

.

.

라이트의 모든 걸 다루진 않고, 성능에 포커싱해서 유의점들을 다룬다.

라이팅 전반은 유니티 매뉴얼

https://docs.unity3d.com/kr/current/Manual/LightingOverview.html

5-1 포워드 렌더링 vs 디퍼드 렌더링

카메라 컴포넌트에서 포워드 렌더링과 디퍼드 렌더링 두 가지 방식 중 선택 가능. Rendering Path 에서 Forward, Deferred 선택.

Use Graphics Settings 로 두면 포워드 혹은 디퍼드를 강제하지 않고 디바이스마다 다른 렌더링 파이프라인 설정 가능. Edit > Project Settings > Graphics 선택, GraphicsSettings 인스펙터 오픈. Tier Setting 에서 플랫폼 티어별로 설정. 디바이스별로 다르게 설정 가능. 낮은 등급의 Tier 에서는 포워드 렌더링을, 높은 등급 Ier 에서는 디퍼드 렌더링 하도록 설정 가능. 쉐이더 퀄, 디테일 노말맵 등등.

유니티 엔진이 구동될 때 디바이스의 GPU를 자동 탐지.

Tier 1

안드 : OpenGL ES 3 미지원

iOS : 5, 아이패드 4세대, 미니 1세대, 이전

Tier 2

안드 : OpenGL ES 3 이상

iOS : 5S, 패드 에어, 미니 2세대, 이후

Tier 3

자동탐지 안됨. 강제로 바꿔줘야함.

위 티어 설명은 바뀔 수 있음.

https://docs.unity3d.com/ScriptReference/Rendering.GraphicsTier.Tier1.html

https://docs.unity3d.com/ScriptReference/Rendering.GraphicsTier.Tier2.html

https://docs.unity3d.com/ScriptReference/Rendering.GraphicsTier.Tier3.html

01) 디퍼드 렌더링 (Deferred Rendering)

많은 수의 실시간 라이트를 비교적 좋은 성능으로 처리 가능. PC와 콘솔기기에서 널리 쓰임.

기기의 기본 성능이 받쳐주어야 함. 하나의 버퍼에 렌더링 하는 것이 아니라 여러 개의 버퍼에 한꺼번에 렌더링을 하는 멀티 렌더 타겟(Multi Render Target) 기능이 필요.

멀티렌더타겟을 이용해서 지오메트리 버퍼(G버퍼(G-buffer)) 여러 개에 불투명(Opaque) 오브젝트 렌더링.

- 디퓨즈 (Diffuse)

- 스크린 스페이스 노멀 (Screen Space Normal)

- 스페큘러 (Specular)

- 스무스니스 (Smoothness)

- 스크린 스페이스 뎁스 (Screen Space Depth)

등의 정보 기록

모든 오브젝트들을 G버퍼에 렌더링 -> 라이팅 처리. 최종적으로 프레임 버퍼에 출력.

씬 렌더링 완성.

-> 렌더링을 바로 수행하지 않고 최종 완성의 타이밍이 지연되기 때문에 Deferred(지연된) 라는 이름

G버퍼에 에 렌더링 = 지오메트리 패스

라이팅 처리 = 라이팅 패스

+ 투명 오브젝트 처리 포워드 패스

+ 화면 후처리를 위한 포스트 프로세싱 패스

등의 추가적 패스도 존재.

비싼 쉐이딩 연산으로 화면에 보이는 픽셀만 처리할 수 있다.

= 불필요한 쉐이딩 연산 절약.

= 많은 수의 실시간 라이트 드로우콜 부담 줄임.

유니티 테크 데모들도 대부분 디퍼드.

단, 메모리 대역폭이 뒷받침 되어야 함. 여러 G버퍼들을 처리하려면 높은 대역폭 필요.

모바일 디바이스는 대역폭이 낮음. 멀티 렌더 타겟 지원 사항도 기기마다 다름. 모바일에선 디퍼드 권장되지 않음.

PC에서도 모니터 해상도가 상당히 높아져서 성능 이슈 발생. 4K 이상 처리가 부하가 큼. FPTL(Fine pruned tiled lighting) 방식이 적용, 기존 디퍼드 렌더링 방식 보완. 유니티 기본 파이프라인은 아니지만, Scriptable Render Pipeline 을 통해 사용 가능.

02) 포워드 렌더링 (Forward Rendering)

전통적인 오브젝트 렌더링 기법. 이름이 없었는데, 디퍼드가 등장하면서 이름이 붙음.

아직은 모바일기기에서 주로 사용. 멀티렌더타겟 불필요. 오브젝트와 라이트를 적게 써서 성능 요구치 낮.

포워드 라이팅, 포워드 쉐이딩 등으로 불림.

유니티 라이트의 3가지 모드

Baked :

라이트를 미리 구워서 런타임 연산에 활용. 라이트맵, 라이트 프로브. 동적 물체는 적용 불가.

Realtime :

신시간 라이트 연산. 캐릭터 등 동적 오브젝트. 매 프레임마다 업데이트. 성능요구.

Mixed :

두 가지 혼합. Mixed 라이트는 실시간 라이팅과 Baked 라이팅 모두 영향. 라이트맵, 라이트 프로브, 동적 오브젝트 모두 대응 연산.

5-2 리얼타임 라이트와 드로우콜

리얼타임 라이트는 쉐이더 성능 뿐 아니라 드로우콜에도 영향.

풍부한 라이팅 효과 = 여러개 라이트 설치 = 라이트 개수 만큼 드로우콜 상승

구체 하나 폴리곤 : 770개

라이트 5개 = 렌더링 5번

렌더링 해야할 폴리곤 = 770 x 5 = 3850개

구체가 10개라면 = 라이트 5개 = 드로우콜 50번

쉐이더 처리할 폴리곤 갯수 = 770 x 50 = 38500 개

라이트 렌더모드 수정. 라이트 컴포넌트의 Render Mode 선택.

Important

해당 라이트가 중요하다 설정. 항상 필셀 당 연산. 스페큘러, 노멀맵 대응 가능하단 의미. 성능 필요.

Not Important

중요하지 않은 라이트. 픽셀 당 처리되지 않고 버텍스 당 처리되거나 스피리컬 하모닉스(SH; 구면조화함수)를 활용. 품질이 떨어지고 스페큘러 대응 안됨. 대신 성능 부담 적음.

Auto

라이트 생성하면 기본 Auto. 런타임 중 중요도를 자동 설정. 밝기에 따라 중요한/안중요한 라이트 분류.

퀄리티 셋팅에 의존적

Edit > Project Settings > Quality 셋팅창 오픈

Rendering 섹션의 Pixel Light Count 항목.

실시간 처리 포워드 렌더링의 라이트 중 픽셀 당 처리될 수 있는 라이트의 개수. Auto 일 경우 이 값을 참조하게 됨.

메인 디렉셔널 라이트 기본 1개 + Pixel Light Count 개수까지. Auto 라이트면 이 값을 따르고, Important 라이트는 모두 픽셀 당 처리되며 별도의 드로우콜 필요.

모바일 게임에선 Pixel Light Count 를 0 혹은 1로 셋팅, 씬에서는 라이트맵, 라이트 프로브를 활용 추천.

포인트 라이트 및 스팟 라이트는 범위와 거리에 따른 세기 감소가 존재. 디렉셔널 라이트는 없다.

즉, 포인트 라이트, 스팟 아리트는 오브젝트가 영향을 받지 않는 위치에 있으면 드로우콜 +0

주의, 라이트 영역 내에 있는지 여부는 바운딩 박스로 체크됨. 컬링의 기준으로도 씀.

에디터에 바운딩박스 그려주는 샘플

https://github.com/ozlael/ShowBoundsSample

5-3 내장 쉐이더

유니티 쉐이더는 버텍스 쉐이더와 프래그먼트 쉐이더 합쳐진 단위. 유니티 머티리얼 인스펙터에서 쉐이더 선택은 버텍스/프래그먼트 쉐이더 동시 선택의 의미.

* 쉐이더(Shader)와 머티리얼(Marterial)의 차이.

GUI 파이프라인 관점에서 쉐이더는 명시적인 요소. 머티리얼은 어플리케이션에서 관리하는 개념.

드로우콜에서 오브젝트 렌더링, 렌더상태 갱신됨.렌더링 엔진에서는 머티리얼에 설정된 파라미터 정보들을 기반으로 GPU 에게 정보를 넘겨줌. 이 정보들은 텍스쳐, 쉐이더, 쉐이더 파라미터 등.

01) 스탠다드 쉐이더 (Standard Shader)

유니티의 기본 쉐이더.Legacy Shadrs 는 유니티 4에 있던 것들.

모바일기기의 쉐이더는 신중하게 선택해야. 내장 쉐이더들, 특히 Standard Shader는 저사양 모바일 고려가 안돼있음. 머티리얼을 생성하면 기본적으로 스탠다드 쉐이더로 설정돼있음.

물리기반 렌더링은 말 그대로, 물리법칙 입각. 파라미터도 많고. 기존 쉐이더들도 물리 법칙을 어느정도 흉내내긴 했지만, 물리기반 렌더링에 들어간 쉐이더들은 좀 더 현실적 연산.

(유니티4에서는 디퓨즈 쉐이더가 기본 쉐이더였다)

물리 기반 렌더링 = 높은 성능 요구

저사양 디바이스에서 씬 전체를 스탠다드 쉐이더로 사용하는 것 권장하지 않음. 어느정도 보급화된 디바이스라면 고려해볼만 함.

그래픽스 셋팅에서 티어 별로 스탠다드 쉐이더의 퀄리티를 설정할 수도 있음.

예제 샘플 스샷. 프로파일러로 확인해보면 WaitForTargetFPS 가 11.2ms.

실제 성능은 16.6ms(60FPS) - 11.2ms = 5.4ms 만 사용.

스탠다드 쉐이더 퀄리티 설정

Edit > Project Settings > Graphics 의 Graphics Settings 에서 조절.

가령, Tier1(Low) 에서는Standard ShaderQuality 를 Low로, Tier2 에서는 Medium 으로 설정하는식.

모바일에서는 Tier가 자동 분류. OpenGL ES3.0 미 지원 기기는 티어1. Tier 에 따른 렌더링 변화 에디터에서도 확인 가능. Edit > Graphics Emulation 이용.

머터리얼에 스탠다드 쉐이더가 사용되면, 컴파일 중에 옵티마이즈 돼서 오버헤드 줄어듬.

만약,오브젝트가 반사 비중이 적다면 Foward Rendering Options / Specular Highlights 나 Reflections 플래그 꺼서 최적화 해버릴 수도. 시각 효과에 영향이 적다면 과감하게 생략하는 것도 좋다.

파라미터의 Rendering Mode. Opaque, Cutout, Fade, Transparent 중 하나 선택.

Opaque 는 일반적인 불투명 오브젝트를 의미. 권장. 카메라와가까운 오브젝트부터 렌더링.

Transparent 는 알파 블렌딩 적용. 투명 오브젝트로 철. 카메라와 먼 오브젝트부터 렌더링.

Albedo 의 A값을 조절해서 투명하게 보이게 만들고 프레임 디버거로 렌더링 순서를 살피면, 멀리있는 오브젝트를 먼저 렌더링. 주의, Rendering Mode 가 Transparent 면 투명도가 없어도 알파블랜딩 처리. 오버헤드 발생. 불투명한 오브젝트는 반드시 Opaque 로 처리.

컷아웃(Cutout)은 알파컷아웃(Alpha-cutout), 알파테스트(Alpha-Test) 투명처리 모드. 반투명이 없고 완전투명 or 불투명 처리. Opaque와 같이 카메라 가까운 오브젝트부터 렌더링. Transparent 보다는 Cutout 이 권장됨.

주의! 모바일 디바이스에서는 Cutout 보다 Transparent 가 권장됨. Cutout은 모바일 디바이스에서 성능 저하를 일으킬 수 있다. 알파테스트 쉐이더는 동적 분기(if문)을 사용하는데, 모바일 기기에서는 쉐이더 내부 동적 분기가 성능 저하를 일으킴.

또, 모바일 기기 렌더링 방식 특징 때문에라도 성능 저하가 발생할 수 있다.

모바일 그래픽 칩셋, 타일기반렌더링(Tile Based Rendering: TBR) 또는타일 기반 지연 렌더링(Tile Based Deferred Rendering : TBDR) 아키텍쳐 렌더링. Cutout의 알파테스트는 이러한 아키텍쳐의 이점 활용 못함.

(엄밀히, 성능이 저하된다기보다는, 좋은 성능을 끌어내기 어렵다는 것이 올바른 표현)

즉, 모바일 디바이스에서는 Opaque, Transparent 잘 활용해야.

TBR/TBDR에서 알파 테스트를 사용하면 안 되는 이유

모바일, 전력 소모와 물리적 크기 고려, 대역폭(bandwidth)이 작게 디자인. 프레임 버퍼를 일정 크기의 타일 영역으로 나눔. 버텍스 쉐이더에서 픽셀 쉐이더로 넘어가기 전에 타일 선택. 모든 타일들이 완성되면 프레임 버퍼에 그림.

(https://community.arm.com/developer/tools-software/graphics/b/blog/posts/how-low-can-you-go-building-low-power-low-bandwidth-arm-mali-gpus)

TBDR(Deferred) 는 버텍스 쉐이더 결과를 중간 데이터를 담는 파라미터 버퍼에 담는다.

(파라미터 버퍼(Parameter Buffer) 는 imgTec 에서 부르고, Arm 에선 폴리곤 리스트(Polygon List)로 부름.)

매 드로우콜마다 버텍스 쉐이더의 결과를 계속 담고 모든 드로우콜이 끝나면 타일을 렌더링하고 프레임 버퍼에 출력.

이 과정에서 타일의 각 픽셀에 은면 제거(Hidden Surface Removal)가 처리되고 픽셀쉐이더에 도달하기 때문에 픽셀 오버드로우 발생 없음.

여기서 Cutout 의 알파테스트는 TBDR 의 픽셀 차폐의 고석 처리를 망가뜨림. TBDR 에서 은면제거를 거치고 보이는 픽셀만 처리하는데, 알파테스트를 사용하면 버텍스 처리 단계에서는 해당 폴리곤이 차폐 되는지 여부를 판단할 수 없어서 Drferred 처리를 깨트림.

최근 출시되는 고성능 기기들은 크게 문제되진 않음.

-----

장면의 쉐이더를 통이해야하는 건 아님. 캐릭터만 스탠다드 쉐이더를 쓰고, 배경에 가벼운 쉐이더를 사용. 스탠다드 쉐이더를 사용해도, 라이트맵이 적용된 오브젝트는 라이팅 연산 비용이 대폭 감소.

Mixed Lighting 모드를 Subtractive로 두면 모바일 디바이스에서도 스탠다드 쉐이더 사용 무리 없음.

02) 모바일 쉐이더 (Mobile Shader)

Mobile 카테고리의 쉐이더 활용. 정밀도는 떨어지지만 작은 스크린 기반으로 함. 요즘의 보급폰 사양이더라도 알파 테스트(Alpha Test, Alpha Cutoff)는 조심해서 사용해야 함.

내장 쉐이더 Diffuse, Diffuse Bumped, Diffuse Bumped Specular, Vertex lit 등.

이 중 Diffuse, Vertex lit 은 버텍스 당 라이팅 처리되는 Per Vertex Lighting 쉐이더.

반면, Diffuse Bumped, Bumped Specular 는 픽셀마다 라이팅 처리, Per Pixel Lighting 쉐이더.

PPL 이 PVL 보다 성능이 떨어짐. 라이트 중요도에 따라 내부적으로 PVL로 처리되기도. (Light Component의 Render Mode 에 의해 결정됨)

이 책은 계속 포워드 렌더링 기준으로 설명하기 때문에 PVL과 PPL성능 차이가 큼. 쉐이더 사용을 구분짓는 정책을 세워야 함.

가령, 플레이어나 보스 캐릭터 등 시각적 중요도가 높아 노말맵을 사용하는 경우, Per Pixel Lighting 사용.

배경이나 잡몹은 Per Vertex Lighting 사용하는 정책 등.

에셋스토어의 mobile character 검색. 자체 개발한 쉐이더를 사용하는 경우도 많음. 잘 고려해야함. 프로젝트 시점 성격에 잘 맞는 쉐이더를 선택해야 함. 가령, 에셋스토어의 배경 어셋들 중, 알파테스트 쉐이더 사용하는 경우도 있는데, 알파블렌딩을 사용하는 쉐이더로 변경 필요.

유니티 내장 Mobile 쉐이더에는 알파테스트 쉐이더가 존재하지 않음.

5-4 이미지 기반 라이팅

내장 쉐이더는 일반적인 용도로만 만들어짐. 유니티는 쉐이더르 ㄹ직접 제작할 수 있는 시스템 지원, 커스텁 쉐이더 활용. 이미지에 라이팅을 미리 그려 넣는 이미지 기반 라이팅. 쉐이더 제작은 이 책 범위 밖, 간단히 생략. 이미 만들어진 커스텀 쉐이더 소개.

라이팅 처리는 두 벡터의 내적값으로 처리. Light Vector 와 Normal Vector 연산. 값이 1이면 빛을 바라보는 면, 0 아래이면 빛을 받지 못하는 면.

http://www.gamedevforever.com/220

사실적인 라이팅에는 조명이 여러개 필요. 소스는 태양빛. 하늘에 산란되고 바닥이나 물체에 반사되기도. 이를 흉내내기 위해 유니티의 스카이박스를 이용한 환경 라이팅 방식 제공. Lighting 창에서 Ambient Source 가 Skybox. 디렉셔널 라이트 하나만 두어도 환경광이 적용됨. (Legacy Shaders/Diffuse).

Ambient Intensity(Intensity Multiplier)를 0으로 두면 환경광 적용되지 않음.

스카이박스 환경광을 유니티는 미리 대략적으로 연산하여 추출해둠. 저렴함. 유니티5는 실시간 전역 조명(Real-time Global Illumination; GI)를 제공. 모바일 기기는 성능이 문제. 대신 Light Probe를 활용해서 라이팅 품질 높일수도. 그래서 라성비(라이트:성능)를 위해 이미지 기반 라이팅 활용. (Image Based Lighting) 텍스처에 라이팅 결과를 미리 그려놓고 쉐이더에서 라이팅 대신 사용. 실제 라이팅 처리 없이 라이팅 한다고 해서 Unlit Lighting 라고 부르기도.

한계가 많지만, 활용해보긴 좋음. 캐릭터같은 동적 오브젝트에 가성비 높다.

01) ToonRamp

라이트 벡터와 표면의 노멀 벡터의 각에 따른 라이트 반응 결과를 텍스처에 미리 그려넣는 방식. 빛을 바라보는 표면 컬러와 빛을 등지는 표면 컬러를 미리 텍스처에 칠해놓는 것. 카툰 렌더링에 주로사용된 방식.

https://github.com/ozlael/ToonRampSample

빛의 분포를 나타내는 텍스처. 직접 만들어도 되지만 구글에 toon ramp 검색하면 많이 나옴. 좌측은 빛을 등지는 역광 컬러. 우측이 빛을 바라보는 주광 컬러.

오브젝트 머티리얼 쉐이더를 Custom/ToonRamp 로 변경. Ramp 텍스처 설정. 디렉셔널 라이트 하나만 설치해도 다양한 라이트 효과를 줄 수 있다.

02) MatCap 쉐이더

Material Capture 의 약자. 현실세계의 라이팅을 수집/캡쳐하는 구체. 보통 CG 영상이나 이미지 실사 렌더링 라이팅 참고자료 용도. MapCap 쉐이더는 이런 Material Capture를 그대로 텍스처로 만들어라이팅 결과로 활용하는 것. RoonRamp 와 기본 컨셉은 동일. 다만 라이팅을 텍스처로 변환하는 과정이 차이.

에셋스토어 : MatCap Shaders 로 검색. Import.

JMO Assets/MatCap Shaders/Demo 에서 MC_Demo.unity 씬.

테두리만 보여주는 프레넬 효과(Fresnel Effect)를 응용한 특수 효과도 가능. 다양한 방식이 있는데

- 텍스처와 라이팅을 곱셈 또는 덧셈으로 처리하는지에 따른 차이

- 노멀맵 사용 여부

- 메인 텍스처 사용 여부

MatCap/Bumped/Textured Multiply 쉐이더.

노멀맵 사용, 라이팅과 메인 텍스처를 곱셈 처리.

메인 텍스처로 읽는 속성인 Albedo와 Diffuse 라이팅을 곱셈 처리, 일반적인 라이팅.

오브젝트 머티리얼 쉐이더 MatCap/Bumped/Textured Multiply 설정.

텍스처 설정. Assets > JMO Assets > MatCap Shaders > Textures > MatCrea

라이팅의 컬러뿐 아니라 스페큘러, 림 라이팅 등 재질의 특성도 그대로 반영 가능.

특수효과 : http://blenderartists.org

뷰공간 기준이라 카메라 방향에 따라가는 듯한 느낌.MatCap 텍스처 자체가 특정한 방향에서만 바라보는 결과물이라 당연한 현상. 텍스처의 좌상단이 붉고 우하단이 녹색이면, 카메라를 돌렸을 때 빛도 같이 따라 움직여 부자연스럽. 카메라의 방향이 변경될 일 없는 고정 카메라 게임이면 부자연스러운 상황이 발생할 경우가 없어서 문제되지 않음. 탑뷰, 쿼터뷰, 백뷰 등.

.

.

728x90
반응형