티스토리 뷰
지난 포스팅 때 Unity에서 그래픽스를 최적화하는 방법이 총 4가지 정도 있다는 것을 알아봤습니다.
https://mathmakeworld.tistory.com/61
각각은 GPU Instancing, Static Batching, Dynamic Batching, SRP Batching 이었습니다.
이번 포스팅에서는 각각의 옵션을 통해 최적화를 확인해보는 실험을 해보겠습니다.
위 4개의 방법은 Unity에서 직접 옵션을 통해 사용할지 안할지 컨트롤할 수 있습니다.
일단 가장 먼저 어떻게 각각의 옵션들을 설정하는지 알아보겠습니다.
SRP Batcher는 SRP(Scriptable Render Pipeline)이 나온 이후로 생긴 것이므로 SRP의 일종인 Universal Render Pipeline을 이용해서 테스트하겠습니다. 1, 2강에서 해왔던 프로젝트와는 다른 프로젝트입니다.
유니티에서 옵션을 컨트롤 하는 방법
GPU Instancing
GPU Instancing은 URP의 Shader(Universal Render Pipeline/Lit)를 쓰는 Material에서 옵션을 켤 수 있습니다.
해당 옵션은 Shader를 만들 때 직접 만들어 준 것이고 내부적으로는 2강에서 배웠던 DrawSettings의 변수를 바꿔주는 역할을 합니다. DrawingSettings에 대한 Unity 문서는 여기에 있습니다.
DrawSettings는 실제 씬에 배치되는 오브젝트들을 그리는 함수인 DrawRenderers라는 함수의 인자로 보내는 값입니다.
자세한 내용은 다음에 이어지는 강의를 통해 알아보겠습니다.
SRP Batcher & Dynamic Batching
SRP Batcher와 Dynamic Batching은 Render Pipeline Asset에서 셋팅을 변경하는 방법으로 수정할 수 있습니다.
내부적으로 Dynamic Batching은 GPU Instancing처럼 DrawSettings의 값을 바꿔주는 방식이고 SRP Batcher는 GraphicsSettings 클래스의 useScriptableRenderPipelineBatching이라는 static property를 변경하는 방법입니다.
따라서 따로 옵션을 선택하지 않고 직접 코드를 통해 바꿀 수도 있습니다.
Static Batching
Static Batching은 Static 오브젝트에 적용된다는 특성 답게 Inspector에서 설정할 수 있습니다.
아래의 이미지처럼 하나의 오브젝트를 잡고 Inspector의 옵션을 누르는 방식으로 설정할 수 있습니다.
옵션 확인하기
유니티에서는 옵션이 잘 적용되는지 확인하는 방법이 존재합니다.
가장 쉽게 확인할 수 있는 방법은 2가지 정도입니다.
첫 번째는 Game 탭의 Stats를 확인하는 방법입니다.
주로 봐야할 부분은 Batches, Saved by Batching과 SetPassCall입니다.
두 번째는 Frame Debugger를 이용한 방법입니다.
아래 이미지처럼 Window -> Analysis -> Frame Debugger를 통해 Frame Debugger를 켤 수 있습니다.
Frame Debugger은 하나의 Frame이 어떤 식으로 진행되는지 세분화해서 보여줍니다.
Frame Debugger는 플레이 버튼을 누른 상태에서도 볼 수 있고 꺼져 있는 상태에서도 볼 수 있습니다.
주의할 점은 플레이 상태냐 아니냐에 따라 조금 다르게 batching 되는 경우가 있다는 것입니다.
테스트
드디어 모든 무기가 갖춰졌습니다.
1. 첫 번째로 Unity에서 사용되는 최적화 방식들의 종류와 원리를 이론적으로 공부했고
2. 두 번째로 옵션을 통해 각 최적화 방식을 끄고 켜는 방식을 알아봤고
3. 마지막으로 최적화가 잘 진행되는지 확인하는 방법을 알아봤습니다.
이제 이 이론적으로 알게된 부분들이 실제로 어떻게 동작하는지 테스트를 통해 알아볼 시간입니다.
본격적으로 테스트에 들어가기에 앞서 실험 환경에 대해서 간략하게 살펴보겠습니다.
실험환경
유니티 버전: 2019.3.13f
CPU: AMD Ryzen 5 3600X 6-Core Processor
Memory: 16GB
OS: Windows 10
Graphics Device Name: NVIDIA GeForce GTX 1660 Ti
Graphics Device Type: Direct3D11
테스트1 - 완전히 똑같은 여러 개의 큐브
가장 먼저 해볼 테스트는 "완전히 똑같은 여러 개의 큐브" 씬 입니다.
유니티로 프로젝트를 시작하면 처음에 여러가지 기본적인 mesh, material, component 등을 제공합니다.
기본으로 제공된 mesh 등을 사용하는 방법은 매우 간단합니다.
Hierarchy에서 "마우스 오른쪽 클릭" -> "3D Object" -> "Cube"를 누르면 씬에 Cube가 생성됩니다.
생성된 Cube는 아래와 같은 셋팅으로 생성됩니다.
기본적으로 Mesh와 Material이 설정되는데 이 중에서 Material만 바꿔주면 됩니다.
*Material을 바꿔주는 이유는 해당 Material이 기본적으로 제공되는 메터리얼이기 때문에 옵션을 설정할 수 없도록 되어 있기 때문입니다.
실제로 Mesh Renderer의 기본 Material인 Lit를 눌러보면 아래 이미지처럼 옵션 선택이 비활성화된 것을 볼 수 있습니다.
따라서 새로 Material을 만들되 Shader는 기본 Material처럼 Universal Render Pipeline/Lit으로 바꿔주어야 합니다.
Material을 만들고 Shader를 선택했다면 아까 생성한 Cube가 해당 Material을 사용하도록 설정합니다.
새로운 Material을 쓴 Cube까지 만들었다면 이번에는 이 Cube를 씬에 많이 배치해봅시다.
물론 ctrl + c와 ctrl + v를 통해서 여러 개의 Cube를 씬에 배치할 수 있습니다.
하지만 그것보다는 Prefab을 통해 만들고 스크립트를 통해 runtime에서 여러 개 생성하는게 좋겠죠
목표 영상
목표는 아래 영상과 같습니다.
키보드 입력을 받으면 껍질을 하나 생성하고 또 다른 입력을 받으면 껍질이 하나 제거됩니다.
선형적으로 큐브의 숫자가 늘어나지는 않지만 적은 입력만으로 큐브의 숫자를 급격하게 늘릴 수 있습니다.
그리고 무엇보다도 이런 식으로 구현하는게 재밌어보입니다.
소스 코드
어찌됐든 아래와 같은 코드를 통해 구현했습니다.
일단 환경을 이렇게 만들고 위에서 알아봤던 옵션들을 켜고 끄면서 어떻게 바뀌는지 확인해보겠습니다.
아래는 실험 결과를 테이블로 정리한 것입니다.
총 4개의 옵션이고 각각을 끄고 켤 수 있기 때문에 총 $2^4=16$의 경우의 수가 존재합니다.
단, 현재 상태에서 cube는 런타임에 생성되므로 static batch는 끈 상태로 테스트했습니다.
런타임에 생성된 객체에 static batching을 적용하려면 추가적인 작업(combine)이 필요합니다.
이 작업에 대해서는 다음 포스팅에서 설명하겠습니다.
Static Batching을 제외했으므로 경우의 수는 $2^3=8$입니다.
각각의 옵션을 켠 상황을 초록색으로 표시했고 끈 상황을 빨간색으로 표시했습니다.
srp(SRP Batcher), gpu(GPU Instancing), dynamic(Dynamic Batching) 입니다.
다음 row는 frame debugger에서 어떤 식으로 객체를 그렸는지를 나타냅니다.
Shadow를 그리는 Render Main Shadow와 실제 Object를 그리는 Render Opaque를 나눠서 표시했습니다.
srp gpu dynamic |
srp gpu dynamic |
srp gpu dynamic |
srp gpu dynamic |
srp gpu dynamic |
srp gpu dynamic |
srp gpu dynamic |
srp gpu dynamic |
Shadow Map Draw Mesh Opaque Draw Mesh |
Shadow Map Draw Mesh Opaque Draw Dynamic |
Shadow Map Draw Mesh Instanced Opaque Draw Mesh Instanced |
Shadow Map Draw Mesh Instanced Opaque Draw Mesh Instanced |
Shadow Map SRP Batch Opaque SRP Batch |
Shadow Map SRP Batch Opaque SRP Batch |
Shadow Map SRP Batch Opaque SRP Batch |
Shadow Map SRP Batch Opaque SRP Batch |
주의해야 할 부분은 3가지 정도입니다.
1) dynamic batching만 켤 경우 shadow map과 opaque를 그리는 방식이 다르다.
2) srp, gpu, dynamic의 우선순위는 srp > gpu > dynamic 순인 듯하다
3) material, shader가 똑같고 vertex수가 적은 기본 cube는 모든 batching이 가능하다.
일단 3번의 경우 다른 최적화 글에서 대체로 봤던 내용이므로 별로 특별할 것이 없습니다.
2번의 경우 모든 상황에서 확신할 수는 없을 것 같습니다.
어떤 상황에서는 srp와 gpu instancing이 켜져있을 때 srp batch가 불가능하면 gpu instancing을 사용할 것으로 예상됩니다.
1번의 경우는 Shadow Map에 대한 이해가 필요해보입니다.
Shadow Map이란 그림자를 그릴 때 필요한 정보를 담아두는 Map입니다.
Light를 기준으로 Depth Map 같은 것을 그려서 Shadow Map을 미리 만들어두고 나중에 실제로 Rendering할 때 사용합니다.
위 표가 뜻하는 것은 shadow map을 그리는 과정은 dynamic batching이 되지 않는다는 것입니다.
정확한 이유는 확인하기 어렵지만 이곳에서 설명하는 "Almost all Unity Shaders support several Lights in forward rendering, effectively doing additional passes for them. The draw calls for “additional per-pixel lights” are not batched." 이 이유가 아닐까 예상해봅니다.
기본 환경을 만드는데만 해도 꽤나 많은 작업이 필요했습니다.
일단 씬을 하나 만들어서 테스트해봤지만 아직 여러 환경에 대해서 테스트하지는 못했습니다.
cube 개수를 바꾼 상황이나 큐브가 움직임을 갖는 경우 혹은 각각 다른 크기이거나 다른 Material, Shader를 사용하는 경우, cube가 아니라 복잡한 mesh를 사용하는 경우, 여러 개의 Light를 사용하는 경우도 어떻게 batching이 될지 모르니 확인해봐야 합니다.
내용이 너무 길어졌으므로 위 내용에 대해서는 이어지는 포스팅에서 계속하겠습니다.
참고자료
https://forum.unity.com/threads/srp-batcher-and-gpu-instancing.833362/
'Unity' 카테고리의 다른 글
큐브 맞추는 기계 살 돈이 없어서 직접 만드는 글 #11 (0) | 2020.08.30 |
---|---|
큐브 맞추는 기계 살 돈이 없어서 직접 만드는 글 #10 (0) | 2020.08.17 |
큐브 맞추는 기계 살 돈이 없어서 직접 만드는 글 #9 (0) | 2020.08.09 |
큐브 맞추는 기계 살 돈이 없어서 직접 만드는 글 #8 (0) | 2020.07.31 |
큐브 맞추는 기계 살 돈이 없어서 직접 만드는 글 #7 (0) | 2020.07.23 |
- Total
- Today
- Yesterday
- 유니티
- VTK
- collision detection
- CollisionDetection
- reference type
- batching
- Unreal
- value type
- static batching
- perspective projection
- normalized device coordinate
- 강화학습
- opengl
- MeshProcessing
- 값 형식
- Scriptable Render Pipeline
- 루빅스큐브
- C#
- NDC
- transform
- Transformation
- dynamic batching
- RL
- 참조 형식
- AABB
- RubiksCube
- Mesh Processing
- Unity
- Mesh
- SRP
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |