프로그래밍/Unity

카메라와 컬링 이해

gameObject 2023. 11. 14. 19:49
728x90

컬링의 기본 컨셉

보이지 않는 것은 그리지 말자

 

MVP Transformation

Frustum Culling

Spatial Partition

Occlusion Culling

Culling Layer

Multi Camera

Cinemachine vs Camera

 

게임을 개발하며 어떤식으로 카메라가 랜더되는지 설명한다고 한다.

 

MVP Transformation (Vertex Transformation)

쉐이더 쪽 이야기

카메라에 오브젝트가 보여주기 위해서 오브젝트는 매 프레임 그릴때마다 변환을 거치게 된다.

수학적인 얘기가 끼어들수밖에 없으나 개념적인 얘기만 들어보자

쉐이더를 거칠때 꼭 알아야 할 내용인데 예습하는 느낌으로 들어보자.

 

카메라도 가만히 있고 오브젝트도 가만히 있지만 내부적으로는 계속 변환이 일어난다고 한다.

이는 다 Vertex에서 일어난다고 한다.

 

Mesh가 움직이는것이 아니라 Vertex가 움직이는것이다.

 

 

어떤과정으로 우측 하단의 화면을 나타나게 되는것일까?

 

 

Vertex 점들의 좌표를 기준으로 선, 면이 생성된다.

어떤 유니티 씬에 올라가있지 않는 모델만 있는, 오브젝트만 있는 공간을

모델 스페이서, 로컬 스페이스, 오브젝트 스페이스 등으로 불린다고 한다.

 

오브젝트 자체의 공간이 있다고 이해하면 된다.

중점을 기준으로 점마다 얼마나 떨어져있는지 확인이 되는것도 그런것이다.

 

 

그 오브젝트를 월드에 올리게 되면

월드 스페이스로써 어떤 신 공간에

오브젝트가 위치를 한다.(World Transform)

 

 

중요한것은 

우리는 카메라를 통해서 바라보기 때문에

카메라를 통해서 모든 오브젝트가 카메라를 기준으로 정렬이 되어야 한다.

 

이를 View(Camera) Space으로 변환해주고

그 기준을 카메라로 변환하는것이 View Transform이다.

 

아까 말한 오브젝트가 계속 변환된다고 한 이야기가.  이것이다.

Local Space -> World Space -> Camera Space 로 Transform이 계속해서 변환되는것이다.

이런과정들이 매번 Vertex Shader에서 일어난다고 보면 된다고 한다.

 

카메라라고 이야기 했지만 이것은 결국 모니터에서 보는것.

모니터에서 볼때는 결국 Projection을 거친다.

2D공간으로 볼 수 있게 Clip Space라는 공간으로 변환하게 되는데

보통 Projection을 거친다.

 

 

다시 말하면

Local Space -> World Space -> Camera Space -> Clip Space 과정을 거친다.

 

내부적으로는 4번이나 변환되는것을 볼 수 있다.

 

Projection이라는 개념

보통 원근법을 보면

실제 눈으로 봤을때와 같도록

Projection을 거치고 나면 원근법이 표현이 된다.

 

3D에서는 Perspective를 적용

 

모두 행렬을 통해서 이루어진다고 한다.

행렬은 아래 영상을 참조

 

 

코드에서 변환되는 모습이다.

 

마지막 return UNITY_MATRIX_VP 에서 VP가 View Projection이다.

 

Frustum Culling

 

카메라 입장에서는 보이는것만 그리려다 보니 컬링이라는 개념이 들어가게 된다.

 

파란 오브젝트가 뷰 공간, 빨강이 카메라영역 밖이다.

Frustum 공간에 들어와있는지 아닌지를 판단해서 그릴지 안그릴지를 판단한다.

 

 

Far보다 멀리있는 오브젝트는 그리지 않고

Near보다 앞에 있는 오브젝트는 그리지 않는다.

 

Far값을 너무 크게 잡으면 너무 멀리있는것도 다 그리게 된다.

보통 모바일게임에서는 Far값을 많이 줄인다고 한다.

위 사진은 DrawCall이 2000개, 아래 사진은 1300개로 보이는것을 알 수 있다.

Fog값과 Clipping값을 비슷하게 하면 팝핀형상이 적절하다고 한다.

 

컬링만으로도 내용이 매우 많다고 한다. 특히 SRP에 넘어가면 컬링도 커스터마이징이 가능하다고,,,

 

Spatial Partition (Octree / Quadtree)

공간 분할 기법 (3D 에서는 Octree / 2D에서는 Quadtree)

world를 4등분했다가 다시 4등분하며 공간을 잘게 잘게 쪼갠다.

3D면 8개로 분할되기때문에 Octree/ 2D면 4개로 분할되니까 QuadTree라고 한다.

 

여기서 Frustum에 걸리는지 체크를 해서 그림을 그릴지 안그릴지 판단한다.

 

 

컬링이라는 개념은 엔진에서 하는것이고, 기본적으로는 CPU로 (오브젝트가 그려질 대상인지 아닌지 판단)

자르게되는것은 GPU의 랜더링 파트, 랜더링 파이프라인에서 자를지 말지를 판단한다.

 

위의 내용은 CPU???


Occlusion Culling

오클루젼 컬링은 플러스텀 컬링 내에 있더라도, 어떤 오브젝트에 가려 보이지 않을때 그리지 않는것을 얘기한다.

 

유니티에서는 언브라?라는 시스템을 사용한다고 한다. (자체적인 구현이 아닌 서비스를 이용)

 

보통 인도어에서 많이 사용하는 기능 (FPS 등)

오히려 아웃도어에서는 연산비용이 더 많이 나가는 경우도 있기 때문임.

 

400과 900의 차이가난다. 절반이상 줄인것을 볼 수 있다.

 

오브젝트가 가려져있기 때문에 Fragment Shader 만 생략되는것이고,

드로우 콜이나 버택스 쉐이더는 다 연산을 거치고 있다고 보면 된다고 한다.

 

요즘 GPU를 많이 사용해서 컬링을 시도를 하고있다고하는데

게임마다 CPU, GPU 어디에서 컬링을 하는게 나을지는 다르다고 한다.

일반적으로는 GPU에서 하는것이 더 빠를것이라고 생각은 하지만, 상황마다 다 다르고, 정답은 없다고 한다.

CPU가 힘든상황, GPU가 힘든상황을 확인이 필요함

 

여기까지 Rendering만 설명이고

매 프레임 업데이트거나 물리라던지는 완전 다른 이야기라고 한다. 

 

 

가리는자 : Occluder -> 유니티에서는 정적인 애만 된다고 보면 된다.

가려지는자 : Occludee  -> 정적인애도 되고 동적인 애도 된다.

 

 

왼쪽 상단을 보면 카메라 절두체에 해당안되는부분이 다 잘려서 안보이는것을 알 수 있다.

(기본적인 Frustum Culling) _ 바닥은 안잘리는것을 볼 수 있음.

 

 

오클루전 컬링으로 앞의 벽때문에 뒤도 다 날아간것을 볼 수 있음.

 

오클루전 컬링을 위해서는 Masic Number를 찾아야 한다.

 

얼마나 공간을 잘게 자르느냐가 중요하다.

너무 촘촘하게 자르면 데이터가 너무 많아짐에 따라 연산할께 많아지다보니 연산 오버헤드가 발생할 수 있고

너무 큼직하면 컬링 효율이 떨어질 수가 있다.

 

그래서 Masic Number를 찾아야 한다는것이다. 정확한 공식이 아니라 이것도 해보고 저것도 해보는 숫자를 이야기한다.ㅋㅋ

 

Occlusion Portal

 

Occlusion Portal이라는 컴포넌트를 추가하여 

문을 열게되면, 포탈이 Open됬다 설정해주고, 닫히면 False를 해주면

문을 통해 컬링을 할지 말지 적용해줄 수 있다고 한다.

 

Culling Mask

보통 카메라가 여러개일때 사용한다.

Layer -> Culling할꺼라고 생각하지만

사실 반대이다.

유니티에서는 Culling을 먼저 하고나서 Layer를 랜더링한다.

 

컬링도 연산이 들어가는 부분이다보니, 왠만하면 멀티 카메라를 사용하는것을 권장하지는 않는다고 한다.

보통 카메라가 여러개가 존재해야한다고 하면

시네머신을 이용하는것을 추천한다고 한다.

 

실제 카메라가 아니라, 실제 카메라를 컨트롤해주는 가상의 카메라이기 때문에 단순히 카메라를 컨트롤해주는것이기때문에 시네머신은 많이 사용한다고 해서 실제 카메라를 여러개 사용하는것처럼 많이 연산을 소모하지는 않는다고 한다.

 

다만 Camera Stacking을 해야하는 경우 카메라를 많이 써야하는데

이때는 Frustum이 겹치지 않도록 하는것을 권장한다고 한다.

중복연산이 이루어지기 때문이다.

 

** UI 카메라가 따로 달려있을때의 경우에도, Frustum이 겹치지 않도록 영역이 겹치지 않도록 하는것이 좋다.

Culling이 먼저 이루어지고 Layer가 이루어지기때문에, 결국 UI카메라의 Frustum에서 Culling을 한번 연산을 하게 되서 중복연산을 하게된다.

 

LOD

 

멀리 있는 애들을 아예 잘라버리는 기법도 있다고 한다.

LOD는 메쉬를 조절하는 방법.

 

결론 : 카메라 최적화 고려사항들

1. Multi Camera 지양

 - 카메라별 culling 후 Layer filtering을 하기 때문

 - 만약 사용을 해야만 한다면 Frustum영역이 겹치지 않도록 사용

2. Multi Camera 대신 시네머신 권장

3. Culling

 - Frustum Culling은 기본적으로 유니티가 함

 - Occlusion Culling (인도어시에 사용 _ 실내)

 - LOD (멀리있는거 일치감찌 자르기)

4. Clipping Far와 Fog distance

5. Top-down View 게임에서는 Skybox 불필요 (랜더링 비용 절약)


https://www.youtube.com/watch?v=O0qliGO7Oes&t=34s

 

 

728x90