본문 바로가기

카테고리 없음

최적화 Optimization

* VR 프로젝트를 최적화하기 위해 공부한 내용을 간단 메모한 것입니다. 그냥 메모장 내용!

r.RHI.Name : 현재 directx11, 12인지 뭔지 알려준다
r.HairStrands.Strands 0
r.HairStrands.UseCardsInsteadOfStrands 1
mh.Identity.ExportMeshes 1
stat fps (Ctrl + Shift + H)
stat streaming
stat unit >> drawcall 볼 수 있다
stat unit graph
stat anim
stat SceneRendring >> drawcall 볼 수 있다
r.MeshDrawCommands.DynamicInstancing >> 0으로 끄고 1로 켤 수 있다

-CPU는 Unreal Insights로, GPU는 GPU Visualizer로 하면 되는 듯? GPU 프로파일링은 RenderDoc을 쓰기도 함. gpu 프로파일링은 언리얼 기본꺼 쓸려면 Ctrl + Shift + , 을 눌러서 켜던가. 더 자세히 프로파일링 정보 보고 싶으면 r.RHISetGPUCaptureOptions 1
-그래서 GPU bound이냐 CPU bound이냐는 stat unit으로 알 수 있다. 그냥 숫자 높은게 bottleneck임
-렌더 과정에서 픽셀이 가장 느리다. 높은 해상도는 더 많은 픽셀을 필요로 하다. 또, 무거운 라이팅과 셰이더, pp도 영향을 미친다. 그래서 r.ScreenPercentage를 낮추거나 r.SetRes를 뭐 480x270 등으로 낮추면 된다. 낮췄을때 frame rate가 크게 향상됐다면 픽셀이 문제였던 것
-VR은 매 프레임마다 화면을 2번씩 렌더링해야 함. 그래서 120프레임이라면 양쪽 눈에 각각 60프레임 정도가 적용된다고 하는 듯
-VR는 일반 비디오게임에서보다 fps는 절반 낮아질 것이고 resolution은 2배 올려야 선명하게 보일 것! 일반 4k 비디오는 선명하지만 고프로 촬영했을 때 보면 VR영상의 4k는 후진 것처럼
-그래서 VR은 메모리 관리가 중요. UV 채널은 1개만 쓰기. 2개쓰면 메모리 차지량이 2배가 되는 건 아니지만 어쨋든 메모리 차지량이 증가될 것이다. 왜냐면 모든 버텍스마다 2차원의 정보가 2개씩 담기게 될테니깐
-Baked Lighting을 쓰면 싸지만 메모리 차지량이 늘어날 것! 왜냐면 매 프레임마다 메모리에 저장하고 불어오고 하기 때문에. 그리고 dynamic한 것도 불가능
-Virtual Shadow Map은 VR에선 정말 안쓰는게 좋은 듯? 왜냐면 need to fetch probably different pages 라고 한다.
-Nanaite는 어떤지 아직 unexplored된 영역이다. VR은 한 번에 두 개의 프레임을 렌더해야되는건데 어떻게 될 지 모른다
-VR에선 Baked Lighting이 더 맞는 방법이다. 그러나 프로젝트가 복잡하지 않다면 Lumen도 가능. 구울지 루멘으로 할 지는 프로젝트마다 다를 것. 그러나 루멘 자체가 굽는 것보다 무겁다는 것을 알아두기
-pixel bound의 문제는 traslucent 머티리얼이 있다.
-만약 r.ScreenPercentage 20으로 낮췄을 때 fps가 크게 향상됐다면 GPU bound
-Quad overdraw 또한 GPU 시간을 잡아먹는다. 생각보다 트라이앵글의 수는 거의 영향을 미치지 않는다. 작고 얇은 삼각형을 피하는 것이 더 중요하다. lod로 수정하거나 폴리곤을 크고 고르게 하는 것ㅇ 중요하다. Foliage의 empty pixel은 엄청난 낭비다. Clip이 미쳤기 때문. Quad draw는 상단에 Lit > Optimization Viewmodes > Quad Overdraw.
-vertex bound problem에는 dynamic shadow가 있다. 라이트를 static으로 놓고 point light보단 spot light를, 그리고 attenuation 범위를 최대한 줄이자. 그리고 dynamic shadow를 끌 수 있는 곳은 모두 끄자
-memory related problem의 원인에는 대역폭, 너무 많은 텍스처 샘플러를 쓰는 것 등이 있다. 텍스처 compression은 많은 도움이 되고 texture packing(channel packing)도 많은 도움이 된다. 얘는 texture sampler 수도 줄여주고 메모리 사용량도 줄어든다
-streaming pool은 GPU 캐시는 아니고 언리얼에 의한 일반적인 캐시다. 한번에 로드할 수 있는 텍스처의 저장소라고 할 수 있다. 이 텍스처에는 머티리얼의 텍스처뿐만 아니라 라이트맵도 포함된다. 스트리밍 풀을 보려면 stat Streaming을 치면 된다. 원래 멀리있는 물체의 텍스처는 최대한 가장 낮은 해상도를 로드하려고 하는데 캐시가 다 차면 가까이 있는 물체의 텍스처 해상도도 최대한 낮춰버릴 것이다
-상단에 Lit > Optimization Viewmodes > Light Complexity (Alt 7). 각 라이트의 radius를 보여준다. 많이 겹칠수록 퍼포먼스가 낮아진다
-셰이더 복잡도 : 렌더링하는 픽셀들의 복잡도를 나타낸다
-Lit > Optimization Viewmodes > Lightmap Density도 있음. 라이트맵의 실제 픽셀의 사이즈를 보여준다. 파란색이면 괜찮은거. 라이트맵은 오브젝트마다 각각 저장되어있다. 이거 라이트맵 density 픽셀 바꿀 수 있다. 에디터에서 오브젝트 하나 클릭하고 디테일 창에서 Lighting > Overriden Light Map 어쩌고를 낮추면 된다
-DrawCall은 CPU가 GPU를 컨트롤하기 위해 내리는 명령이다. 예를 들어 메시를 렌더링해라, 머티리얼을 바꿔라 이런게 있음. a set of draw calls를 pass라고 함!
-r.PixelDensity 0.8정도로 낮추면 fps가 올라간다. 0~1의 값으로 조정하면 된다
-VR에서 25fps 이상이면 꽤 smooth하다
-command에서 Scalability 1이면 medium quality, 0이면 low, 2면 high, 3이면 epic. 보통은 2로 둔다. 그래야 reflection, gi 등이 적용돼서
-프로젝트 세팅 > 렌더링 > VR에서 Instanced Streo는 왼쪽 눈의 픽셀을 오른쪽 눈에 reuse, reproject 해주는거라 frame rate가 많이 올라간다. 원래 default stereo는 왼쪽 눈의 정보를 렌더하고 오른쪽 눈을 렌더한 다음 라이트를 최종적으로 렌더한다. 그치만 움직이는 물체가 있다면 적합하지 않다. 움직이는 물체의 경우 오른쪽 눈이 jittering거릴 것. 그래서 이건 우리가 못쓸 듯.
그다음 Stereo Foveation Level은 gpu가 많이 안쓰이고 있으면 모든 픽셀을 draw하고 gpu가 많이 쓰이고 있으면 낮은 수의 픽셀을 draw한다. medium으로 두는 것이 적당
내가 보고 있는 곳의 픽셀 density만 높이고 나머지 주위 부분은 낮춰주는건데 오큘러스가 아이트래킹이 안되면 소용없는 기능일 듯. 그리고 이거 할려면 OpenXR, OpenXR Eyetracking 플러그인 켜야 함. xr.VRS.FoveationLevel 1-3 to enable foveation
xr.VRS.GazeTrackedFoveation 1 to enable Gaze-Tracked Foveation
xr.VRS.FoveationPreview 1 to enable preview of the foveation mask

-vr.SpectatorScreenMode 2로 하면 vr플레이를 좌우 눈 2분할로 볼 수 있음
-r.AntiAliasingMethod가 0이면 None, 1이면 FXAA, 2면 TAA, 3이면 MSAA, 4면 TSR. 4가 제일 비싸고 나머지는 비슷. 2가 제일 나은 듯? MSAA는 포워드 셰이딩에서 작동되는 듯 하다. PP단계가 아니라 Base Pass에서 전부 작동하기 때문 deferred pass가 없음. 디퍼드는 TAA 쓴다.

<Distance Field Shadow Map>
-Distance Field Shadow Map은 일반 cascaded shadow map보다 30~50% 싸다. 단점은 static하다는 것. 애니메이션되는 것, 흔들리는 나무같은 것에는 어울리지 않는다. 실시간으로 계산하는게 아니고 메모리에 올라가있는 데이터를 쓰는거라 cpu 부담은 적지만 메모리가 쌓인다.
-그래서 카메라 거리를 정해놓고 일정 거리 밖에 있으면 Distance Field Shadow, 가까이 있으면 일반 cascaded Shadow Map을 쓰도록 blending한다. 그러면 gpu가 많이 향상된다
-캐릭터 등의 그림자를 만들 때 실제 오브젝트가 아니라 Physics Asset의 캡슐의 그림자를 보여주는 방식으로 최적화를 하기도 한다!
-이것들은 UE4에서 Lighting Build할 때 사용했던 방법이다! UE5에선 Mesh Distance Field가 훨씬 향상되었고 이제 이건 디스턴스 필드 셰도우, 디스턴스 필드 AO에 이용되기 보단 Lumen에 이용된다. (Optimizing UE4 for Fortnite: Battle Royal - Part1 참고)
 
<Instanced Static Mesh(ISM)과 Hierarchical Instanced Static Mesh(HISM)>
: 둘 다 BP에서의 컴포넌트이다. ISM과 HISM을 쓰려면 BP를 만들어서 컴포넌트로 추가하면 된다. ISM은 같은 스태틱 메시를 다수의 인스턴스로 렌더해준다. 똑같은 스태틱 메시를 각각 여러 개 쌓지 않고 하나로 묶을 때 쓴다. 같은 스태틱 메시를 몇 천개 복사하던지 아주 적은 양의 drawcall로 취급한다. 퍼포먼스가 좋아지지만 단점이 있다. ISM을 아주 넓은 맵에 서로 멀리 흩뿌려놓는다면 단점이 될 것이다. 왜냐면 ISM은 개별 인스턴스 별로 LOD가 세팅되는 것이 아니라 흩뿌려진 ISM들이 전부 동일한 LOD를 가지게 된다. 이런 경우에는 HISM을 이용하면 된다. 각 인스턴스 별로 서로 다른 LOD를 가질 수 있다. 그치만 5.4부터는 ISM도 개별적으로 LOD를 세팅할 수 있게 되었다. 액터들을 Level Instance로 만들면 자동으로 액터가 HISM로 그룹화된다고 한다. 그러나 왜 HISM을 항상 이용하진 않냐면 이걸 쓰면 어느 LOD를 써야할 지 계산해야되기 때문에 extra load가 발생된다. HISM을 작은 맵에서 쓰게 될 경우 오히려 ISM보다 load를 더 발생기키거나 퍼포먼스가 낮아질 수 있다. 집을 만드는 것 처럼 작은 구역의 경우 ISM, 도시처럼 넓은 맵에 흩뿌려놓을거면 HISM을 추천한다. 둘은 사실 같은 기능인데 개별 LOD 지원의 차이일 뿐이다.
ISM이라고 똑같은 메시만 조합할 경우에만 이용하는 것은 아니다. BP에서 ISM 컴포넌트 추가 후 벽돌 넣어주고, 또 다른 ISM 컴포넌트 추가 후 문 에셋 넣어주고 이런 식으로 만들면 된다. 그러나 ISM 컴포넌트 추가 후 디테일 창에서 Static Mesh를 지정해도 메시가 보이지 않는다. 왜냐면 아직 인스턴스를 추가하지 않아서 그런다. 디테일 창 아래쪽에 Instances에 +버튼을 눌러 추가해주고, 각 메시들의 transform을 조절해주면 된다.
이미 만들어놓은 세트를 ISM으로 바꾸려면 에디터에서 세트로 만들 모든 메시 선택 후 좌측 상단의 액터 > 액터 병합 > 배치(Batch) 눌러주면 된다.