실감 기본편 언리얼 엔진 ICVFX 최적화
여러분 안녕하십니까
언리얼 엔진 ICVFX 강의를 진행하게 된 이도한입니다
오늘은 ICVFX 환경에서 웹 컨트롤을 활용해
언리얼 엔진의 성능을 최적화하고
작업 효율을 높이는 방법에 대해서 이야기를 해보겠습니다
ICVFX 환경에서는 단순한 환경 설정만으로는 충분하지 않습니다
실시간으로 다양한 요소를 제어하고
최적화하는 것이 정말 필수적인데요
이를 위해 웹 컨트롤이라는 매우 유용한 도구를 활용할 수 있습니다
이번 강의에서는 웹 컨트롤의 설정 방법과
이를 활용해 실시간 조명, 카메라 설정
그리고 다양한 엔진 요소를 최적화하는 방법을 설명드리겠습니다
ICVFX를 위한 언리얼 엔진 환경 최적화
ICVFX를 진행하면서 LED 월에서
애셋을 사실적으로 표현하기 위해서는
고해상도의 텍스처, 복잡한 라이팅
그리고 섬세한 디테일이 필요합니다
그러나 이러한 요소들은 실시간 구동에는 큰 부담을 주어
성능 저하와 렉을 유발할 수 있습니다
반대로 성능을 최우선으로 고려해 최적화를 진행하게 되면
퀄리티를 어느 정도 타협하거나
포기해야 하는 상황이 발생할 수 있습니다
최적화 과정에서 텍스처 해상도를 낮추거나
디테일을 줄이게 되면
의도한 리얼리티와 몰입감을
완벽히 구현하기가 어려워질 수 있습니다
이러한 현실적 한계를 극복하면서
성능과 퀄리티 사이에서 균형을 맞추기 위해
다양한 최적화 전략을 적용하는 것이 매우 중요합니다
우선 저희가 이번 강의에서 사용할 프로젝트 파일은
메가스캔에서 무료로 제공해주는
버려진 아파트 프로젝트 파일을 사용하도록 하겠습니다
저희가 작업하다 보면
보통 렉은 레벨 내 과도한 오브젝트의 수
이런 Mesh나 이런 Mesh들이 되겠죠
그리고 높은 폴리곤 수
이런 트라이앵글, 이런 폴리곤 수가 되겠죠
또는 복잡한 라이팅
라이팅이 여러 가지가 배치가 되어 있다면
많은 리소스를 잡아먹게 될 겁니다
이러한 문제를 해결하기 위해서
사용할 수 있는 콘솔 명령어와 최적화 방법들을
함께 알아보도록 하겠습니다
우선 저희는 프로파일링에 대해서 알아보도록 하겠습니다
프로파일링은 CPU, GPU, 메모리와 같은 자원이
어디에서 사용되는지 파악하기 위한 중요한 도구입니다
언리얼 엔진에서는 Stat Unit과 같은
다양한 콘솔 명령어가 제공되며
이를 통해 병목 현상이 어디서 발생하는지 찾아낼 수 있습니다
일단 가장 기본적으로
사용하는 명령어에 대해서 설명을 드리겠습니다
아까 말씀드린 Stat Unit 같은 경우를
사용하는 방법에 대해서 알려드리겠습니다
일단 저는 지금 켜놔서 다시 끄고
Command 라인에 Stat Unit을 검색하시면
저와 같이 오른쪽에 이런 표시를 볼 수 있습니다
일단 이 옵션에 대해서 설명을 드리자면
현재 프레임에 소모된 시간과 게임 스레드에 소요된 시간
렌더링 스레드에 소모된 시간
GPU에서 현재 프레임에 소모된 시간 등을 파악할 수가 있습니다
일단 첫 번째 옵션에 대해서 설명을 드리자면
첫 번째 옵션은 게임의 한 프레임을 생성하는데 소요된
총 시간을 볼 수 있습니다
그리고 그 아래에 있는 옵션을 보시면
게임 스레드에서 사용된 시간 값이
이 값이 프레임 시간과 유사하게 되면
게임 성능은 렌더링 스레드에
병목 현상이 발생한 것으로 볼 수 있습니다
그 아래의 옵션을 보게 되면
렌더링 스레드에서 사용된 시간 값이
이 값이 프레임과 비슷하면
게임 성능은 렌더링 스레드에 의해
병목 현상이 발생한 것으로 확인이 가능합니다
게임과는 반대로 이루어지는 것이죠
그 아래에 있는 것은
렌더링 하드웨어 인터페이스 스레드에서
소요된 시간이라고 할 수 있습니다
이 부분 같은 경우에는 3D OpenGL이라든지
D3D 다이렉트 12라든지 다이렉트 11
이런 쪽에 관련되어 있어서 이 부분은 패스하도록 하겠습니다
그 아래에 있는 GPU 타임은
실시간 저희가 보고 있는 이 Scene에서
렌더링에 사용된 GPU에서 소요된 시간
이것도 마찬가지로 프레임 시간에 동기화되므로
비슷한 시간을 가지게 됩니다
그 아래에 있는 DynRes 옵션은
Dynamic Resolution인 동적 해상도의 약자로
게임에서 실시간으로 해상도를 자동으로 조정하여
성능을 최적화할 수 있는 기능이라고 보시면 됩니다
쉽게 말해서 장면이 복잡해져서 GPU가 느려지면
해상도를 잠시 낮춰 성능을 개선할 수 있는 기능입니다
보통 이거는 비활성화가 되어 있지만
이를 사용하려면 프로젝트 설정에서 활성화가 가능합니다
이거는 추후에 프로젝트 설정하는 편에서 보여드리겠습니다
그 아래에 있는 이 옵션에 대해서 보여드리면
즉, 이 옵션은 드로우 콜의 수를 의미합니다
드로우 콜이라고 하면 CPU가 GPU에게
이 오브젝트를 그려라라고 명령을 하는 일종의 호출입니다
즉, 드로우 콜 수는 GPU가 그려야 하는
객체의 수와 관련이 있습니다
저는 한 2500개가 있다는 거겠죠
그 아래에 있는 옵션에 대해서 설명을 드리자면
현재 오브젝트가 갖고 있는
제가 지금 보고 있는 삼각형의 수라고 보시면 될 것 같아요
한 면에 삼각형이 이렇게 하나, 하나, 하나, 하나
이 삼각형을 뜻한다고 보시면 될 것 같습니다
이를 통해서 기본적으로 렉이 어떻게 걸리고
어느 부위에서 성능을 저하시키고 있는지 확인할 수가 있습니다
추가적으로 Stat 명령에 대해서 설명을 좀 드리도록 하겠습니다
일단 오른쪽에 있는 이 옵션들을 해제를 하려면
아까와 똑같은 Stat Unit를 검색하시면 사라지게 됩니다
일단 또 기본적으로 사용하는 옵션은 Stat FPS가 있습니다
말 그대로 이 옵션은 현재 프레임 속도 FPS를 보여주게 됩니다
FPS가 높을수록 성능이 좋다는 의미입니다
이 명령어는 전반적인 성능 상태를
쉽고 빠르게 확인하는데 유용합니다
근데 다양한 내용은 나오지 않겠죠
다시 없애고 그다음은 Stat UnitGraph입니다
이 옵션 같은 경우에는 Stat Unit에서 각 항목
프레임, 게임, 드로우, GPU 등
이 값을 그래프로 시각화해서 시각적으로 보여주게 됩니다
시간의 경과에 따라 각 스레드가 얼마나 많은 시간을 소모하는지
쉽게 확인할 수 있어
병목 현상을 파악하는 데 도움이 됩니다
이 그래프를 보시면 이렇게
실시간으로 변하는 걸 보실 수가 있습니다
또한 오른쪽에 컬러도 바뀌어서
이 컬러대로 나온다고 보시면 될 것 같아요
이 옵션도 없애려면 이렇게
그다음 옵션은 Stat Game이라고 합니다
이 옵션 같은 경우에는 게임 스레드에서
각종 작업에 소요되는 시간을 내역으로 보여줍니다
AI, 물리 연산, 블루프린트, 실행 등
게임 로직과 관련된 작업을 분석하여
최적화 포인트를 찾을 수가 있습니다
근데 저희는 크게 한 게 없기 때문에
블루프린트 로직이나 이런 걸 짠 게 없기 때문에
지금은 크게 반응하지 않습니다 다시 끄고
그다음은 Stat Slow 이 옵션 같은 경우에는
성능 저하가 발생하는 작업들을 확인할 수 있습니다
특정 작업이 예상보다 오래 걸리거나 반복되는 경우
이를 통해 문제를 식별하고 해결할 수 있습니다
말 그대로 가장 느려지는 부분들을
확인할 수 있다고 보시면 될 것 같아요 다시 끄겠습니다
그다음 옵션은 Stat SceneRendering이라고 합니다
이 옵션은 신 렌더링에 대한 자세한 정보를 제공하게 됩니다
여기에서는 드로우 콜의 수, 그림자의 계산
라이트의 내역 등이 포함되며
렌더링 단계에서 발생하는
성능 병목 현상을 파악하는 데 큰 도움이 됩니다
그리고 저희가 아까는 방금 보여드린 것처럼
이렇게 끌 수 있겠지만
여러 가지를 불러올 수 있어요
Stat Unit, Stat SceneRendering, Stat Slow
이렇게 다양하게 불러올 수 있는데
Stat GAME 이런 식으로 불러올 수 있는데
이걸 한 번에 끄기 위해서는 Stat None
이렇게 하시면 한 번에 종료할 수 있고 편리합니다
이번에는 최적화 뷰 모드에 대해서 설명드리도록 하겠습니다
언리얼 엔진에서는 최적화를 위한
다양한 뷰 모드를 제공하고 있습니다
그 뷰 모드를 보기 위해서는
이 부분에서 클릭하신 다음에
여기 Optimization Viewmodes 아래에 이렇게 있습니다
일단 첫 번째 옵션을 먼저 보게 되면
이렇게 보시면 빨간색도 있고 흰색도 있고
초록색도 있고 주황색도 있고 컬러가 좀 다양한데요
이 부분들도 엄청 겹치고 있죠
이 뷰 모드 같은 경우에는 신의 라이트 복잡도를
시각화하는 뷰 모드라고 보시면 될 것 같아요
이 모드는 신에 있는 각 라이트가
얼마나 많은 비용을 차지하고 있는지
색상으로 표현할 수가 있습니다
왼쪽으로 가까운 색상을 띄고 있는 것일수록
가벼운 비용을 나타내며
노란색과 빨간색처럼 오른쪽으로 나타내고 있는 것은
많은 성능을 필요로 하는 라이팅이라고 보시면 될 것 같습니다
특히 라이트가 이렇게 많이 겹치는 부분에서는
빨간색이나 보라색, 흰색으로 표시되며
이 부분에 대해서는 최적화가 필요한 부분이라고 생각이 듭니다
그다음에 대해서 설명드릴게요
그 아래에 있는 Lightmap Density
이 부분 같은 경우에는 라이트맵에 사용되는 밀도를
시각화한 뷰 모드라고 보시면 될 것 같아요
이것도 똑같이 초록색, 빨간색, 보라색 이렇게 있고
컬러는 다양하게 있습니다
색상으로 밀도를 표시하며 밀도가 너무 높거나 낮은 부분을
쉽게 파악할 수 있는 그런 뷰 모드입니다
이를 통해서 최적의 라이트맵 해상도를 설정하여
조명 품질과 성능의 균형을 맞추는 데 큰 도움을 주게 됩니다
선택하게 되면 라이트맵 밀도를 확인할 수가 있습니다
Stationary Light Overlap 이 뷰 모드가 될 경우에는
지금은 안 보이게 되지만 설명을 드리자면
이 뷰 모드는 Stationary Light가 겹치는 구간을 시각화합니다
Stationary Light는 한 지점에 고정된 조명을 제공하는데
여러 개의 Stationary Light가 동일한 영역에 겹쳐질 경우
성능의 비용이 매우 높아질 수가 있습니다
그 아래에 있는 옵션에 대해서 설명을 드리겠습니다
Shader Complexity
이 뷰 모드는 GPU가 계산하는 쉐이더의 복잡도를 시각화하여
각 픽셀이 얼마나 복잡한 계산을 수행하고 있는지 보여줍니다
파티클 같은 경우에는 빨간색으로 보이게 되죠
쉐이더가 복잡하면 복잡할수록 색상은
초록색에서 흰색으로 나타나게 됩니다
빨간색이나 흰색으로 표시된 영역은
쉐이더가 매우 복잡한 부분이므로
렉이 걸린다 하면 그 부분들에 대해서 최적화를 해야 합니다
파티클에서도 많이 그럴 거고 지금도 깨진 창문 이쪽 라인
그리고 바닥에 이런 부분들은 사실
텍스처로 그냥 대체하기 때문에
크게 복잡하지 않고 바로 이런 퀄리티를 낼 수 있습니다
그 아래에 있는 옵션에 대해서 설명을 드리자면
이 모드는 쉐이더의 복잡도와 쿼드 오버드로우를
동시에 같이 시각화할 수 있습니다
쉐이더 복잡도와 픽셀당 쿼드 오버드로우의 정보를
합쳐서 보여줌으로써 쉐이더의 복잡성뿐만 아니라
각 픽셀의 렌더링 효율을 한눈에 파악할 수 있습니다
쉐이더가 복잡하거나 오버드로우가 높은 부분은
성능 최적화가 필요로 하게 됩니다
이제 Quad Overdraw에 대해서 설명을 드리자면
이 뷰 모드 같은 경우에는
오버드로우가 발생하는 부분을 시각화할 수 있습니다
오버드로우는 동일한 픽셀이 여러 번 그려지는 현상을 의미하며
이는 성능 저하의 주요 원인 중 하나입니다
Quad Overdraw 뷰 모드는 이를 시각화하여
불필요한 렌더링 작업을 줄일 수 있도록 도와주게 됩니다
특히 인스턴싱을 사용하거나 Mesh를 병합하여
오버드로우를 줄여주시는 것도
최적화의 방법이 될 수 있습니다
이런 식으로 뷰 모드를 활용하여 어디서 렉이 걸리고
어떤 부분에서 렉이 걸리고 성능 저하가 이루어지는지
시각적으로 확인을 할 수 있고
아까 제가 말씀드린 Stat 명령어를 통해서
성능 저하가 어디서 일어나는지를 확인할 수가 있습니다
우선 이전에 저희가 어디서 병목 현상이 발생하고
어디서 렉이 발생하는지에 대해서
확인을 하는 방법에 대해서 알아봤습니다
이번에는 최적화를 하는 방법에 대해서 설명드리겠습니다
일단 첫 번째로는 LOD를 활용한 최적화 방법이 있겠죠
LOD란 무엇인가? LOD는 Level of Detail의 약자입니다
LOD 시스템을 적용하여 전체 Scene과 개별 Mesh의
불필요한 면을 제거함으로써
최적화 작업을 진행할 수 있습니다
LOD는 오브젝트의 거리나 중요도에 따라
디테일 수준을 조절하여
멀면 LOD4, 가까우면 LOD0까지 이렇게 조절하여
GPU와 메모리 사용량을 줄여줄 수 있습니다
보시는 사진과 같이 LOD0부터 LOD4까지
총 5가지 단계가 있습니다
단계가 높아지면 높아질수록 삼각형 수가 줄어듦으로써
오브젝트가 간단해집니다
예를 들어 오브젝트를 보시게 되면
LOD0에서는 16,128개의 면이 있지만
LOD4까지 가면 48개로 간소화하게 됩니다
이로써 LOD를 사용하여 가까운 곳에서는 높은 디테일 0번
멀리 있을수록 낮은 디테일 4번
중간에는 LOD2가 될 수도 있고
어느 특정 거리에 가면 LOD3이 될 수도 있고
이를 통해서 불필요한 리소스 사용을 줄여
성능을 높일 수 있습니다
아래도 같은 LOD0, LOD1, LOD2 등을 표현할 수 있습니다
사진을 보시게 되면 LOD0부터 LOD4까지 설정되어 있고
가까이에서는 고해상도의 LOD0이 사용되고
멀리 있을수록 단순한 LOD4가 사용됩니다
LOD를 만들기 위해서는 MAYA나 블렌더, 3D MAX
이런 툴에서 LOD 그룹을 만들어서
LOD0 Mesh랑 LOD1 Mesh
LOD2 Mesh, LOD3 Mesh, LOD4 Mesh
이런 식으로 만들어서 LOD 그룹으로 만들어주게 되면
이 파일을 FBX로 뽑아서
언리얼 자체에서는 FBX를 Import 할 때
Import 옵션에 보시면 Import Mesh LODs라고 있습니다
이 부분을 체크하게 되시면
아까 저희가 이전에 설정했던 LOD0, 1, 2, 3, 4 등이
자동으로 불러와지게 됩니다
이 과정을 통해 성능을 최적화하면서도
필요한 디테일을 유지할 수가 있습니다
또한 다각형 수 감소라는 최적화 방법이 있습니다
각 Mesh의 불필요한 다각형 수를 줄여 최적화를 합니다
너무 높은 폴리곤 모델 대신에
적절한 다각형 수를 유지하여
효율적인 렌더링을 할 수 있도록 합니다
사실 이 부분의 최적화 같은 경우에는
모델링에 필요 없는 면이나 필요 없는 선
필요 없는 것들에 대해서 정리를 필요로 합니다
그다음으로는 불필요한 오브젝트 제거입니다
언리얼 화면에서 보시게 되면
플레이어가 볼 수 없는 곳에
오브젝트나 사용하지 않는 요소들이
Scene에서 제거를 하게 되어
렌더링 오버드로우를 줄이게 됩니다
ICVFX나 이런 카메라를 통해 렌더링을 진행하는데
불필요한 곳에 라이팅이 있다든지 Mesh가 있다든지
그런 부분들에 대해서도 정리를 해주게 되면
성능 저하나 렉을 줄이는 방법이 될 수 있습니다
그다음으로는 일단 Stat Unit로 가보겠습니다
드로우 콜 수라고 있죠?
저희가 지금 3000개의 삼각형을 보고 있는 건데
일단 오브젝트 병합이라는 방법이 있습니다
지금은 이런 식으로 다 뜯어져 있긴 합니다
이런 작은 Mesh들을 병합하여 드로우 콜 수를 줄이고
성능을 향상시킬 수 있습니다
이게 하나의 드로우 콜, 하나의 드로우 콜
이런 것들을 합쳐가지고
조금 더 작은 드로우 콜 수로 계산해서
확인할 수가 있습니다
그리고 그다음 방법에 대해서 설명을 드리자면
서브 레벨의 개념입니다 서브 레벨을 하나 만들어 볼게요
콘텐츠에 폴더를 만들고 sub_level
그리고 이 아래에 레벨을 만드신 다음에
라이팅 레벨을 만드신 다음에 저장해 주시고
여기다가 라이팅을 넣게 되시면
사실 이렇게 껐다 켜도 아무 변화가 없어요
이 레벨에 아무것도 존재하지 않기 때문이죠
일단 Persistent Level로 돌아가신 다음에
여기서 라이팅을 검색해 보겠습니다
라이트가 지금 다섯 개 이걸 껐을 때 이렇게 보이게 될 건데
여기로 가서 보겠습니다
지금은 라이트맵이 구워져 있어서 이렇게 보이지만
이 라이트들을 이제 이 레벨에 넣게 될 건데
넣는 방법에 대해서는
이 라이트들을 선택하신 다음에
라이팅 레벨의 서브 레벨을 우클릭 하셔가지고
Move Selected Actors to Level을 클릭하게 되시면
라이팅 오브젝트들은 이 라이팅 레벨에 들어가 있어서
라이팅 레벨을 끄시게 되면
이런 식으로 조절을 할 수가 있어서
이 서브 레벨을 통해서 라이팅 레벨을 따로 주시고
그리고 레벨을 제작할 때 구역을 나눠주게 될 텐데
이쪽에 한 구역, 이쪽에 이 구역 이런 식으로 나눠가지고
서브 레벨로 배치를 할 수도 있습니다
그리고 그다음 방식에 대해서 설명을 드리도록 하겠습니다
일단 이 Static Mesh를 안쪽으로 들어가서 보시게 되면
이제 LOD 그룹에 대해서 설명을 드리도록 하겠습니다
아래에 보시면 LOD 그룹이라는 게 있습니다
이 LOD 그룹은 Mesh가 특정 그룹에 속하는 경우
자동으로 언리얼에서 계산한
적절한 LOD 설정을 적용하도록 도와주는
기능이라고 생각하시면 될 것 같습니다
언리얼이 자체적으로 오브젝트의 크기나 특성에 맞는
LOD 거리와 품질을 미리 정의해 놓아서
개발자가 직접 LOD를 하나하나 세팅하지 않아도
쉽게 최적화가 가능합니다
이 부분 같은 경우는 Foliage를 사용했기 때문에
Foliage를 선택하게 되시면
Foliage에 맞는 LOD 계산값들이 들어가게 될 겁니다
그리고 이 부분에 대해서
이런 식으로 그룹으로 나눠놨지만
그래도 렉이 걸리고 좀 불필요한 경우가 있다
이럴 때 LOD를 수동으로 조절할 수가 있습니다
LOD를 수동으로 조절하는 곳에는
이 위에 /토글 버튼을 누르시게 되면
이런 옵션들이 보이게 될 텐데
Percent Triangles 값을 조절해서 몇 퍼센트 수준으로 사용할지
그런 것을 조절할 수 있는 옵션이라고 보시면 될 것 같아요
이를 통해서 LOD1 또는 LOD2에서
폴리곤 수를 적절히 줄여 최적화가 가능하게 됩니다
그래서 이 부분이 지금은 100%라고 볼 수 있는데
이 부분을 보여드리자면 이런 식으로 100%인데
이 부분을 50%로 줄여가지고 보겠다
바꾸고 나서 Apply Changes를 꼭 눌러주셔야 변경이 됩니다
그래서 이 부분은 트라이앵글 50%로 읽는
그런 뜻이라고 보시면 될 것 같아요
그다음 방법으로는 나나이트를 이용한 최적화입니다
나나이트는 언리얼 엔진에서 복잡한 모델의 디테일을
효율적으로 처리하기 위해 개발된 기술로
인식할 수 있는 디테일만 처리하여
성능을 최적화할 수 있습니다
기능으로는 기존에는 거리별로 LOD를 설정하였지만
나나이트를 활용하여 자동으로 처리해주기 때문에
사전 LOD 작업이 필요가 없습니다
이를 통해 멀리 있는 객체는
자동으로 로우폴리로 변환하여 렌더링 부하를 줄이고
가까이 있는 객체는 자동으로 하이폴리 수준의 Mesh로 변경되어
섬세한 표현이 가능하며 최적화가 가능합니다
나나이트를 활성화하기 위해서는 두 가지 방식이 있는데요
이 애셋을 콘텐츠 브라우저에서 우클릭하신 다음에
나나이트에서 Enable Nanite를 하시거나
더블 클릭하셔서 디테일 모드로 들어가신 다음에
이 디테일에 나나이트 세팅이 있습니다
Enable Nanite Support 체크를 해주신 다음에
Apply Changes를 눌러주시면
나나이트로 변경되어 활용할 수가 있습니다
그리고 나나이트 뷰 모드를 보기 위함이 있는데요
Lit 버튼을 누르시게 되면 나나이트
이 부분에서 Triangles를 누르시게 되면
지금 나나이트로 설정된 Mesh들을 볼 수가 있습니다
지금은 면 개수가 이렇게 보이지만
멀어지면 멀어질수록 이 트라이앵글들이 점점 커져서
GPU가 계산하는 값이 줄어들게 될 겁니다
이번에는 텍스처 맵을 이용한
폴리곤 최적화 방식에 대해서 알려드리도록 하겠습니다
우선은 Normal Map을 활용한 폴리곤 최적화 방식입니다
위쪽에 보이는 이미지를 보시게 되면
각기 다른 폴리곤 수를 가진 구체들이 있습니다
고해상도의 디테일을 표현하려면 폴리곤 수가 늘어나지만
이는 성능에 부담을 줄 수가 있습니다
아래쪽 그림은 Mesh의 Normal 원리를 보여주게 됩니다
이 Normal을 Bake하여
각 표현의 법선 방향을 기록하여
이 맵을 이용하여 로우폴리 모델에서도
디테일이 있는 것처럼 보이게 할 수 있습니다
이를 활용하여 적은 폴리곤으로 마치 고해상도의 Mesh처럼
입체적인 느낌을 줄 수 있습니다
왼쪽 이미지를 보시게 되면
비교적 적은 면을 가진 모델에서는 법선 벡터가
각 면의 중심으로 뻗어 나오는 것을 볼 수 있습니다
이와 달리 오른쪽 이미지 같은 구조에는
더 많은 면을 추가하여
각 면에 더 많은 법선 벡터가 생성된 상태입니다
이렇게 면의 개수가 많아지면
법선 방향이 더욱 세밀하게 표현이 되지만
폴리곤 수가 늘어나면서 성능에 부담이 될 수도 있습니다
이를 해결하기 위해
추가적인 폴리곤 없이도 디테일을 표현하기 위해
Normal Map을 사용하는 것이 효과적입니다
Normal Map을 사용하면 법선 정보를 텍스처에 담아
실제로 면을 늘리지 않고도 디테일을 추가할 수 있습니다
사진을 보시게 되면
동일한 288개의 폴리곤 수를 가진 두 구체가 있습니다
왼쪽 구체는 각 면이 명확하게 드러나는 로우폴리 모델이고
오른쪽은 Normal Map을 적용하여
고해상도처럼 보이게 만든 로우폴리 모델입니다
오른쪽 구체는 실제로는 폴리곤 수가 적지만
Normal Map을 통해
하이폴리와 같은 Mesh 형태를 가지게 되었습니다
그 오른쪽에 있는 다이어그램을 통해
이 과정을 좀 더 이해해보자면
맨 위에 로우폴리 모델은 디테일이 부족하고
법선 방향이 단순합니다
가운데 하이폴리 모델은 복잡한 곡선을 가지고 있어
법선 방향이 더 세밀하게 정의가 되어 있습니다
Normal Map Baking 과정에서는
이 하이폴리 법선 정보를 로우폴리 모델에 Baking하여
로우폴리 모델이 실제로는 적은 폴리곤을 가졌지만
마치 하이폴리처럼 복잡한 디테일을 가진 것처럼 보이게 합니다
이를 통해서 로우폴리에 Normal Map을 적용시키면
추가적인 면 추가 없이
디테일이 있는 것처럼 Mesh를 만들 수 있습니다
하이폴리 Baking을 통해
두 번째에 있는 Mesh에 세 번째의 Normal을 입히게 되면
최종적으로 1번과 같은 시각적 디테일을 얻을 수 있습니다
다음은 Mask Map을 이용한 최적화 방법에 대해서
설명드리도록 하겠습니다
왼쪽 이미지를 보시게 되면
철망 같은 펜스 디테일이 들어가 있는
투명한 형태로 보이게 됩니다
만약 이 철망 같은 Mesh를 하나하나 모델링 하게 되면
면의 개수도 많아지고 작업시간이 크게 증가할 것으로 보입니다
철망 구조를 폴리곤으로 모두 표현하려면
복잡한 모델링 작업을 필요로 하며
이는 성능에 큰 부담이 될 수도 있습니다
오른쪽 이미지처럼 언리얼 엔진에서는
머티리얼 에디터에서 Mask Map을 사용하면
철망 부분만 표시하고 나머지 부분은 투명하게 처리할 수 있습니다
이를 통해 추가적인 폴리곤을 사용하지 않고도
철망의 빈 공간을 사실적으로 표현할 수 있습니다
이와 같이 Mask Map을 사용하면
작업시간이 단축될 뿐만 아니라
폴리곤 수를 줄여 성능을 최적화하는 데도 매우 효과적입니다
그 외에도 사진과 같이 Mask Map을 이용하여
찢어진 천이라든지 특히 나뭇잎을 표현할 때
가장 많이 사용하기도 합니다
나뭇잎을 Mesh로 표현하게 되면
정말 많은 디테일들을 표현하려면
많은 면들도 필요하게 될 거고
하지만 이 나뭇잎들도 되게 많은 개수의 나뭇잎이 필요할 텐데
이런 부분들에 대해서는 Mask Map을 쓰는 게
정말 중요하다고 생각합니다
다음은 머티리얼 최적화에 대해서 설명드리도록 하겠습니다
머티리얼을 최적화해 불필요한 텍스처를 제거하고
텍스처 해상도를 낮춰 메모리 사용을 줄입니다
또한 사용하지 않는 머티리얼을 제거하여
퍼포먼스를 높일 수가 있습니다
머티리얼 복잡도는 GPU 부하에 큰 영향을 주므로
주의가 필요합니다
이 사진을 보시게 되면 이 Mesh에는
7개의 머티리얼 슬롯이 있습니다
우드도 있고, 콘크리트도 있고, 페이퍼도 있고
각 슬롯마다 서로 다른 머티리얼을 적용할 수가 있는데
이렇게 슬롯이 많을 경우
각각 머티리얼에 대해 드로우 콜이 발생합니다
즉, 이 하나의 Mesh에 7개의 머티리얼 슬롯이 있다면
이 한 개의 Mesh에 7개의 드로우 콜이 발생하는 것입니다
이처럼 많은 머티리얼 슬롯을 사용하면
드로우 콜 수가 늘어나 성능에 부담을 줄 수 있어
최적화를 위해 슬롯을 줄이는 것도 방법이 있습니다
이번에는 머티리얼 인스턴스 사용인데요
기본 머티리얼을 바탕으로
사진과 같은 2개의 인스턴스를 만들었습니다
인스턴스를 사용하게 되면
같은 기본 머티리얼을 공유하면서도
색상이나 질감을 다르게 적용할 수 있습니다
오른쪽 이미지를 보듯이 나뭇잎 2개에는
모두 같은 기본 머티리얼을 사용하면서도
각기 다른 색상으로 표현이 되었습니다
이 방식도 최적화 방식 중 하나입니다
기본 마스터 머티리얼 하나로 여러 개의 인스턴스를 생성하면
각기 다른 머티리얼을 사용할 때보다
메모리 사용량과 드로우 콜 수를 줄일 수 있습니다
그다음 머티리얼 최적화 방식은
데칼을 이용한 최적화 방식이 있습니다
데칼 표현에 그림이나 텍스처를 입히는 방식으로
개별 Mesh에 직접적인 텍스처를 추가하지 않고도
장면에 다양한 디테일을 쉽게 추가할 수 있습니다
이미지를 보시게 되면 바닥에 맨홀 표현이 되어 있습니다
만약 이 디테일을 각각 Mesh로 만든 뒤
텍스처를 만들어 넣었다면
메모리와 드로우 콜이 증가하여
성능에 큰 부담이 되었을 것입니다
하지만 데칼을 이용하여
추가적인 Mesh나 텍스처 없이
필요한 부분에만 그래픽을 입힐 수 있고
성능을 향상시킬 수 있습니다
따라서 데칼을 활용하게 되면
디테일을 효율적으로 추가하면서도
성능을 최적화할 수 있고
특히 복잡한 장면에서도 정말 유용한 방법이라고 생각됩니다
이번에는 서브 레벨을 이용한
레벨 스트리밍 최적화에 대해서 설명드리도록 하겠습니다
이전에도 라이팅을 서브 레벨로 최적화하는 방식을 설명드렸지만
더 자세히 설명을 드리자면
서브 레벨 스트리밍을 사용하여 환경 제작에 있어
필요한 레벨만 온오프 시키며 필요 없는 구역은 언로드해서
메모리 사용량과 로딩 시간을 줄이고
성능을 높일 수가 있습니다
저희가 이렇게 작업을 하고 있다가
지금은 이런 풀들을 따로 작업을 할 건 아닌데
이런 큰 프랍들을 수정할 건데
이런 작은 풀들이 있다고 했을 때
리소스를 많이 잡아먹게 될 거잖아요
이 부분들에 대해서 눈을
제가 leaf를 따로 나눠 놨어요
이 부분에 대해서 눈을 끄시게 되면 이 부분들이 사라져서
더 높은 프레임과 더 적은 드로우 콜 수로
작업을 진행할 수 있습니다
또한 라이팅도 끄고 작업을 진행하실 수도 있죠 Unlit 모드로
그래서 엄청 대규모인 Scene을 활용해서 작업하실 때는
섹션별로 나눠서 레벨을 나누시기도 하고
Lighting, Foliage, Mesh
그런 것들을 나눌 수가 있습니다
이번에는 쉐이더 최적화에 대해서 설명을 드리겠습니다
일단 마스터 머티리얼을 켜보겠습니다
이렇게 복잡한 쉐이더는 GPU 자원을 많이 소모하므로
최적화가 필요합니다
가능한 복잡한 수식을 단순화하거나
불필요한 연산을 제거해 쉐이더를 최적화합니다
아까 말씀드린 뷰 모드에서
여기서 Shader Complexity 뷰 모드를 사용하여
복잡도를 시각화해서 어느 부분이 복잡하고
어느 부분이 정리가 필요한지 찾아내서
머티리얼에 들어오시게 되면
지금은 꽤 많이 정리가 되어 있는 상태입니다
복잡한 거라면 이런 식으로 연결되어 있고 되게 개수가 많아요
이 부분들에 대해서 불필요한 수학 연산이나
복잡한 논리를 최대한 단순화해서
쉐이더를 최적화하는 방법도 있습니다
이번에는 코드 최적화에 대해서 설명드리도록 하겠습니다
이 부분은 집중적으로 다룰 것도 아니고
조금 어려운 부분이기도 하지만
코드 최적화는 CPU 자원 사용을 줄이는 데 매우 중요합니다
블루프린트에서 불필요한 함수 호출을 제거하고
잠시만요 한번 보여드릴게요
예를 들어 블루프린트로
여기서 저희가 필요한 기능을 만들어서
Get All Actors of Class 이렇게 해서
Static Mesh Actor
지금 갖고 있는 Static Mesh를 다 갖고 와서
뒤에 기능들을 추가할 수 있지만
불필요한 함수 호출을 제거하고
비효율적인 루프 구조를 개선하는 것이 좋습니다
루프라고 하면 이런 루프가 있는데
이런 Get All Actors Of Class니까
Static Mesh Actor를 다 가져오게 되면
개수가 되게 많아질 거잖아요
그 배열 속에 있는 Static Mesh들을 다 읽어내는
한 바퀴 돌고 하나 읽고 한 바퀴 돌고 두 번 읽고
그런 식으로 하는 걸 루프라고 하는데
이런 구조를 조금 더 개선하는 것이 좋습니다
특히 블루프린트 스크립트를 사용할 때도
프로파일링을 통해서 병목 구간을 파악해야 합니다
그리고 이벤트 그래프 같은 경우에서도 틱 그래프
이 틱 그래프 같은 경우는
매 프레임마다 계속해서 반응을 하는 건데
불필요한 틱 이벤트 사용을 최대한 피하고
필요한 경우에만 활성화해서 사용해 주시면 될 것 같습니다
이제 프로젝트 세팅에 대해서 설명을 드리겠습니다
일단 세팅에서 프로젝트 세팅을 눌러서 들어오시면 됩니다
일단 프로젝트 세팅에서 저희가 설정할 거는
Frame Rate를 고정적으로 사용하기 위해서 할 건데
그걸 왜 사용하느냐
프로젝트 또는 ICVFX에서 사용될
고정된 프레임 속도를 설정하는 건데
Frame Rate를 사용하는 것이 좋습니다
여기서 일단 Frame Rate
여기서 애니메이션은 어떻게 들어올지랑
그리고 타임 코드 이런 것들을 설정해서
외부에서 쓰고 있는 타임 코드랑
맞춰서 사용하시면 될 것 같습니다
두 번째로는 Motion Blur Unable입니다
ICVFX 환경에서는 실제 카메라와 가상 배경이
완벽하게 동기화가 되어야 합니다
Motion Blur가 활성화되면 카메라의 빠른 움직임이
가상 배경에 적용되는 블러와
실제 카메라와 일치하지 않기 때문에
시각적으로도 어색해 보일 수 있습니다
이런 불일치를 줄이기 위해서는
Motion Blur를 프로젝트 세팅에서 비활성화하게 되면
가상 배경과 실제 촬영 장면이
보다 자연스럽고 일관된 방식으로 표현됩니다
해제하는 방법은 Motion Blur를 검색해서
체크 버튼을 해제해 주시면 될 것 같습니다
그다음은 Auto Exposure Unable입니다
Auto Exposure는 자동 노출인데
ICVFX 작업에서는 자동 노출을
비활성화하는 것이 정말 중요합니다
자동 노출이 활성화되면
LED 벽에 표시된 가상 배경의 밝기가
카메라 움직임에 따라 변화하기 때문입니다
이는 실제 조명과 가상 배경의 밝기가 서로 달라져
촬영 장면의 시각적 일관성을 방해하기 때문에
자동 노출을 비활성화하는 것이 좋습니다
체크를 해제해주시면 됩니다
그다음으로는 Auto Save입니다
Auto Save는 프로젝트 세팅이 아니라
Edit 누르시면 Editor Preferences 이 부분에서 Auto Save
이 부분을 왜 해제하느냐
ICVFX 작업은 여러 시스템과 실시간 연동이 필요합니다
카메라 데이터가 넘어오기도 하고 조명 데이터
네트워크적으로 들어오는 것이 많습니다
그래서 실시간으로 연동이 필요하기 때문에
안정성이 매우 중요합니다
그리고 촬영 중간에 자동 저장 기능이 활성화되면
멀티 유저와의 연결이나 라이브 링크 등
실시간 데이터 연결이 끊길 수 있습니다
이러한 불안정성은 촬영 흐름에 방해가 되거나
실시간 작업에서 오류를 유발할 수 있습니다
따라서 Auto Save 기능은 비활성화하여
작업의 안정성을 유지하는 것이 좋습니다
저희가 작업할 때는 Auto Save를 꼭 끄고
ICVFX 촬영을 진행하고 있습니다
ICVFX에서 주의해야 하는 언리얼 엔진 세팅
ICVFX를 하면서 하면 안 되는 행동들이 있습니다
실시간으로 촬영 중일 때는 프로젝트 세팅이나 디스플레이 등
중요한 설정들을 변경하지 않도록 주의를 해야 합니다
이는 LED벽에 표시되는 가상 배경의 품질에 영향을 미치거나
프레임 드롭 및 시스템 불안정성을 초래할 수 있습니다
그렇기 때문에 그런 중요한 프로젝트 설정들은
변경하지 않는 것이 좋습니다
그다음은 정확한 카메라 설정의 유지
언리얼상의 가상의 카메라와
현실의 실제 카메라의 FOV Field of View
카메라 렌즈 세팅, 필름백, 포커스 세팅 등이 있겠는데요
이 부분들이 일치하지 않으면
가상 배경이 왜곡돼서 보이게 될 수도 있습니다
카메라 움직임과 가상 배경의 자연스러운 일치를 위해
촬영 전에 두 카메라의 설정들을 확인해야 합니다
마지막 주의사항으로는 멀티유저 세션에서의 주의사항인데
여기에 멀티유저 브라우저라고 있습니다
ICVFX를 활용하게 되면 언리얼을 틀고 있는 메인 컴퓨터
그리고 이 화면을 띄우게 될 LED 컴퓨터가
멀티유저에 한 번에 들어와서
카메라를 움직이거나 오브젝트를 움직여도
LED 월에도 한 번에 반영될 수 있게
멀티유저로 들어오게 되는데
멀티유저 세션에서는 한 사용자가
실시간으로 작업 내용을 업데이트하거나 변경할 때
연결된 다른 사용자들이 일시적으로 세션에서 튕기거나
연결이 끊길 수가 있습니다
특히 데이터 양이 많거나 큰 변경이 이루어질 경우
네트워크 지연이나 버퍼링 문제로
튕김 현상이 발생할 가능성이 크기 때문에
이런 조그만 것들은 움직이셔도 되지만
너무 크거나 엄청난 것을 변경해야 된다
그런 경우에는 지양하는 것이 좋습니다
ICVFX의 Web Control 기능
이제 최적화 방식도 알아보고
ICVFX를 하면서 하면 안 되는
그런 방법들에 대해서도 설명을 드렸는데
막간의 팁으로 웹 컨트롤에 대해서 설명을 드리도록 하겠습니다
웹 컨트롤을 사용하는 이유에서는
언리얼 엔진에서 사용자가 프로젝트의 다양한 요소를
원격으로 제어하고 실시간으로도 확인할 수 있도록 도와줍니다
특히 ICVFX In-Camera Visual Effects를 구현하기 위해서
매우 중요한 도구입니다
ICVFX 환경에서 실시간으로
라이팅, 카메라 설정 등을 조정하고
시퀀스를 관리하기도 하며
가상의 프로덕션의 다양한 요소들을
원격으로 효율적으로 관리할 수 있습니다
이를 통해서 실시간으로 원하는 장면을 테스트하거나
라이브 환경에서 즉각적인 피드백을 반영할 수 있습니다
설정하는 방식은 플러그인에서 웹을 먼저 검색해 주시면
Remote Control Web Interface와 Remote Control API
이 두 개를 활성화해 주신 다음에 재시작해 주시면 됩니다
그리고 컨트롤을 껐다 켜시면 아웃풋로그에 보시면
서치 로그에 Remote Control Web Interface
이게 뜨게 되시면 이제 활성화가 된 겁니다
그리고 또 세팅해 줘야 될 게 프로젝트 설정에서
Remote Control 검색하게 되시면 이렇게 있을 텐데
Remote Control Web Interface가 사용하는
포트 번호로 변경을 할 수가 있습니다
이 기능을 통해서 네트워크 충돌을 방지하거나
특정 네트워크 환경에 맞게 설정을 조절할 수가 있습니다
지금은 변경하지 않을게요
그리고 이제 콘텐츠에서 저희가
Remote Control Preset을 만들어야 되는데
일단 오른쪽 클릭해서
아래에 보시면 Remote Control이 있습니다
여기서 Remote Control Preset을 누르시게 되면
이름은 가만히 놔두고
프리셋이 만들어지게 되는데 일단 저장을 눌러주겠습니다
그리고 이제 인터넷을 통해서 저희가 컨트롤하게 될 텐데요
여기서 일단 지금 저희는 로컬로 하기 때문에
바로 진행하도록 하겠습니다
로컬 아이디는 127.0.0.1 그리고 30000
아까 저희가 적은 포트 번호를 입력하시면 이렇게 뜨게 됩니다
여기서 컨트롤과 이 버튼을 누르면 디자인 버튼이 있는데
모드를 전환해서 사용자가 원하는 방식으로
프로젝트를 실시간으로 제어할 수 있습니다
일단 변수를 저희가 달아야 되는데
일단 여기서 설정하기 위해서는 저는
라이트로 하겠습니다 Directional Light의 컬러
컬러를 조절할 수 있는 그런 기능을 넣겠습니다
프리셋을 여시게 되면 이런 아이콘들이 뜨게 됩니다
이런 아이콘들을 웹 컨트롤에 집어넣겠다는 표시고요
이 버튼을 누르시게 되면 여기에 들어갈 거고
여기 아이디에 컬러 적어주시고 나서
다시 웹으로 들어오시게 되면
라이트 컬러가 생기게 됩니다
여기서 이제 디자인에서 컬러 픽하고
Build Your Own UI 이걸 선택하신 다음에 끌어오시면
이런 식으로 UI가 들어오게 된 걸 확인할 수 있습니다
그래서 이걸 사용하는 걸 확인하고 싶으시면
창을 좀 줄일게요
여기서 이제 컬러를 바꾸시게 되면
실시간으로 여기가 변하는 걸 볼 수 있습니다
실시간으로 컬러가 바뀌어서 들어가는 걸 볼 수가 있어요
이런 식으로 원하시는 파라미터 값들을 넣고 조절해서
변화하는 걸 보실 수도 있고 사용할 수가 있습니다
지금까지 ICVFX를 위한
언리얼 엔진 환경 세팅하는 방법에 대해서 알아봤습니다
앞서 설명드린 것처럼
실무를 하다 보면 프로그램이 무거워지며
그만큼 작업에 물리적인 시간이 더 소요될 수 밖에 없습니다
그래서 항상 최적화를 염두에 두면서 환경 세팅을 해두면
그만큼 작업 시간을 줄일 수 있다는 점 기억하시길 바라면서
그럼 이번 시간에 학습한 내용을 정리하면서 마무리하겠습니다
감사합니다
ICVFX를 위한 언리얼 엔진 환경 최적화
Stat Unit 요소 Frame: 게임의 한 프레임 생성에 소요된 총 시간
Game: 게임 스레드에서 사용된 시간 값 Draw: 렌더링 스레드에서 사용된 시간 값
RHIT: 렌더링 하드웨어 인터페이스 스레드에서 소요된 시간
GPU: 실시간 신(Scene) 렌더링에서 사용된 GPU에서 소요된 시간
DynRes(동적 해상도): 게임에서 실시간으로 해상도를 자동 조정하여 성능 최적화
Draws: 드로우 콜의 수 Primes: 현재 오브젝트상 삼각형의 개수
Stat 명령어 Stat FPS: 현재 프레임 속도(FPS) 표시
Stat UnitGraph: Stat Unit의 각 항목 값을 그래프로 시각화
Stat GAME: 게임 스레드에서 각종 작업에 소요되는 시간 내역 표시
Stat Slow: 성능 저하가 발생하는 작업 확인
Stat SceneRendering: 신 렌더링에 대한 자세한 정보 제공
Stat None: 현재까지 활성화된 모든 Stat 명령어 출력 종료
최적화 뷰 모드 Light Complexity: 신의 라이트 복잡도 시각화
Lightmap Density: 라이트맵에 사용되는 밀도 시각화
Stationary Light Overlap : 스테이셔너리 라이트가 겹치는 구간 시각화
Shader Complexity : GPU가 계산하는 쉐이더의 복잡도를 시각화하여
각 픽셀이 수행하는 계산의 복잡도 표시
Shader Complexity & Quads : 쉐이더 복잡도와 쿼드 오버드로우 동시에 시각화
Quad Overdraw: 오버드로우가 발생하는 부분 시각화
다양한 최적화 방법
LOD를 활용한 최적화 나나이트를 활용한 최적화
텍스처 맵을 활용한 폴리곤 최적화 머티리얼 최적화
레벨 스트리밍을 활용한 최적화 쉐이더 최적화
코드 최적화 프로젝트 세팅
ICVFX에서 주의해야 하는 언리얼 엔진 세팅
ICVFX 작업 시 주의사항 실시간 렌더링 중 프로젝트 설정 변경 금지
멀티유저 세션에서는 너무 큰 변경 지양
ICVFX의 Web Control 기능
웹 컨트롤(Web Control) 사용자가 프로젝트 다양한 요소를 원격으로 제어하고
실시간 확인할 수 있도록 하는 도구
원하는 장면을 실시간 테스트하거나 라이브 환경에서 피드백에 즉각 반응할 수 있음