1. 공부 목적
갑자기 웬 오클루전 컬링이냐...
오타쿠는 게임을 하다 보면 이게 어떻게 되지...? 라는 생각을 하게 됩니다...
요즘 가장 관심을 가지고 보고 있는 것이 맵이다.
특히 오픈월드를 하다 보면 저 많은 prop들을 어찌... 물론 매 프레임마다 다 품고 가는 것은 아니겠지만
구체적으로 어떤 방법들을 사용하는지 알아봐야겠다는 생각만 일주일이나 했다. (졸업시켜줘)
가장 먼저 알아보게 된 것이 바로 오클루전 컬링!
이전 프로젝트들에서는 배칭만 사용해보았는데 (이것도 주도적으로 적용해본 것이 아니기 때문에 추가적인 공부를 할 예정!) 공부를 하다 보니 오클루전 컬링을 사용하기에 적합했겠다 싶은 프로젝트들 몇 개가 떠오른다.
* 나중에 다 까먹더라도 꼭 생각할 것 두 가지:
GPU를 절약할 필요가 있을 때 사용하기 적합
정적인 오브젝트들로 이루어져 있고, 서로에 의해 가려지는 부분이 많을 경우 사용하기 적합
2. Occlusion Culling 알아보기
🦄 How it works?
Preventing wasted rendering operations can save on both CPU and GPU time. Unity’s built-in occlusion culling performs runtime calculations on the CPU, which can offset the CPU time that it saves. Occlusion culling is therefore most likely to result in performance improvements when a Project is GPU-bound due to overdraw.
- 오클루전 컬링을 통해 불필요한 렌더링을 방지하면 GPU와 CPU의 효율을 높일 수 있는 동시에, 유니티의 오클루전 컬링은 런타임 시 CPU 계산이 소요되므로 결과적으로는 절약된 CPU가 다시 사용되어 상쇄된다. → 따라서 주로 GPU의 효율을 높인다는 판단 하에 사용된다.
Occlusion culling generates data about your Scene in the Unity Editor (and load the data when the scene is loaded), and then uses that data at runtime to determine what a Camera can see. The process of generating data is known as baking. (* "베이킹"이라는 용어는 미리 계산된 데이터를 생성하고 저장하는 과정을 의미하며, 이는 런타임 성능을 향상시키고 게임의 품질을 향상시키는 데 도움.
"씬에 대한 데이터를 생성한다"는 말은 오클루전 컬링이 Unity 에디터에서 씬에 대한 오클루전 컬링 데이터를 생성하는 과정을 의미한다. 이는 주로 오클루전 컬링 데이터를 베이킹하여 씬의 구조와 가시성에 대한 정보를 포함하는 데이터를 만드는 과정을 말한다.
🦄 Use of it
- Occlusion culling works best in Scenes where small, well-defined areas are clearly separated from one another by solid GameObjects. A common example is rooms connected by corridors.
- You can use occlusion culling to occlude Dynamic GameObjects, but Dynamic GameObjects cannot occlude other GameObjects. If your Project generates Scene geometry at runtime, then Unity’s built-in occlusion culling is not suitable for your Project. A dynamic GameObject can be an occludee at runtime, but it cannot be an occluder.
- 게임 씬이 로드될 때 정적인 오브젝트의 정보를 기반으로 오클루전 컬링이 이루어짐 (위의 베이킹 과정 참고) 따라서 동적 오브젝트가 정적 오브젝트를 가려 보이지 않는 상황에서는 오클루전 컬링이 이루어지지 않을 수 있음.
- 참고로 동적인 오브젝트는 컬링되는 대상이 될 수는 있으나, 가리는 주체는 되지 못함. 동적 오브젝트의 컬링은 설정 가능
- You might want to disable Dynamic Occlusion to achieve specific effects, such as drawing an outline around a character who is behind a wall.
→ 정적이고 길이 복잡하거나 벽이 많은 맵 (오브젝트가 서로에 의해 가려지는 경우가 많을 때) 사용하기에 적합
🦄 Occlusion Culling & Camera
- 오클루전 컬링에서 baking은 정적 오브젝트 간의 거리와 상대적 위치를 계산하고, 해당 오브젝트가 가려질 수 있는 카메라 영역을 결정하는 것이다. (현재 카메라 위치와 상관 x)
- 하지만 런타임 중에 카메라의 위치가 계속해서 변화한다면 카메라가 오클루전 컬링이 가능한 영역에 위치해 있는지(실제 위치 + POV + Aspect Ratio)의 정보를 계속해서 계산해야 한다. 이 과정에서 더 많은 CPU 자원이 소모된다.
🦄 Occlusion Area
- Occlusion Area 컴포넌트는 Unity의 오클루전 컬링 시스템에서 View Volumes를 정의하는 데 사용된다.
- View Volumes는 런타임 시 카메라가 위치할 가능성이 있는 씬 내의 영역이다.
- 런타임에서는 카메라의 위치가 View Volume 내에 있을 때 Unity가 더 높은 정밀도의 계산을 수행한다. 이는 오클루전 컬링이 View Volume 내에서 더 효율적으로 동작하고, 보다 정확한 렌더링 결정을 내릴 수 있게 한다.
- 만약 씬에서 View Volumes를 정의하지 않은 경우, Unity는 베이크 시간에 모든 씬 지오메트리를 포함하는 View Volume을 생성한다. 이때 씬 지오메트리 중 Occluder Static 또는 Occludee Static으로 표시된 오브젝트들이 해당된다.
🦄 Practical Information
- 베이킹은 직접 진행해서 에셋을 미리 만들어줘야 함.
- Unity에서 오클루전 컬링 데이터를 베이크하는 과정은 다음과 같이 수행된다:
- Unity Editor에서 베이크할 씬을 연다.
- 메뉴에서 Window > Rendering > Occlusion Culling을 선택하여 Occlusion Culling 설정 창을 연다.
- Occlusion Culling 설정 창에서 필요한 설정을 수행한다. 이 설정에는 Bake Parameters(베이크 파라미터), Visualization(시각화), Data Management(데이터 관리) 등이 포함된다.
- 설정이 완료되면 Bake 버튼을 클릭하여 베이크 과정을 시작한다.
- Unity는 베이크를 수행하고, 씬에 대한 오클루전 컬링 데이터를 생성하여 설정된 경로에 저장한다.
- 일반적으로 오클루전 컬링 데이터는 Assets 폴더 내에 씬 이름과 같은 하위 폴더에 자동으로 저장된다. 이렇게 저장된 데이터는 씬이 로드될 때 함께 로드되어 사용된다.
- 따라서 베이크된 오클루전 컬링 데이터의 경로는 다음과 같음: Assets/Scenes/[SceneName]/OcclusionCullingData.asset
- 베이크된 데이터는 .asset 확장자를 가지며 해당 씬에 대한 오클루전 컬링 정보가 포함되어 있다.
- 런타임 중에 Unity는 동시에 하나의 오클루전 컬링 데이터 에셋만을 로드한다. 즉, 얼마나 많은 씬이 열려있든 상관없이 Unity는 한 번에 하나의 오클루전 컬링 데이터만을 처리한다. 이것은 씬을 로드하는 방식에 따라 오클루전 컬링 데이터를 준비하는 방법이 달라져야 한다는 것을 의미한다.
- 여러 씬을 한 번에 로드하는 경우 (LoadSceneMode.Additive):
- LoadSceneMode.Additive를 사용하여 여러 씬을 한 번에 로드할 때는 해당 씬들에 대한 데이터를 함께 bake해야 한다.
- Unity 에디터에서 Unity가 런타임에 로드할 씬 그룹의 첫 번째 씬을 열고, 그것을 활성화된 씬으로 설정한다.
- 나머지 씬들을 추가적으로 열어 모두 Unity 에디터에서 동시에 열려 있도록 한다.
- 모든 씬에 대해 데이터를 bake하면 Unity는 열려있는 모든 씬에 대한 오클루전 컬링 데이터를 생성하고 [활성화된 씬 이름]/OcclusionCullingData.asset로 저장한다.
- 런타임에서는 첫 번째 씬을 LoadSceneMode.Single을 사용하여 로드하고, 해당 씬의 공유된 오클루전 데이터를 함께 로드합니다. 추가적인 씬들은 LoadSceneMode.Additive를 사용하여 필요할 때 로드된다.
- 한 번에 하나의 씬을 로드하는 경우 (LoadSceneMode.Single):
- LoadSceneMode.Single로 한 번에 하나의 씬을 로드할 때는 각 씬에 대해 별도로 오클루전 컬링 데이터를 준비해야 한다.
- Unity 에디터에서 각 씬을 열고 해당 씬에 대한 오클루전 컬링 데이터를 bake해야 한다.
- 런타임에서는 LoadSceneMode.Single을 사용하여 씬을 로드할 때 Unity는 현재 활성화된 씬과 그 씬의 오클루전 데이터를 언로드하고, 새로운 씬을 로드할 때 해당 씬의 오클루전 데이터도 함께 로드한다.
- 참고사항:
- 공유된 오클루전 데이터 에셋은 파일 크기가 더 크게 될 수 있다. 그러나 런타임에서 더 큰 오클루전 데이터를 사용하는 것에 따른 추가적인 CPU 부하는 없다.
- 일단 알아본 바로는 오클루전 컬링 데이터의 이름을 기준으로 데이터를 가져오는 것이 아니기 때문에 특정 씬이 Single로 열리든 Additive의 활성씬으로 되어 있든 상관 없이 알아서 내부적으로 처리한다고는 함. (사용할 때 확인하기)
- 여러 씬을 한 번에 로드하는 경우 (LoadSceneMode.Additive):
🦄 Occluder vs. Occludee
- Occluder가 적합하지 않은 경우 : 구멍이 많은 오브젝트, 투명도가 있는 오브젝트
- Occluder - Considered to be a single big bowl of polygon soup anyway.
- Occludee - Chunking objects too aggressively typically doesn’t help. One should group only objects that are similar in terms of visibility. On the other hand, too fine-grained subdivision may introduce some unnecessary per-object overhead. In reality, this becomes a problem only once there are tens of thousands of occludees in the scene.
🦄 Occlusion Portal
- 사용 : 문과 같이 상황에 따라 뒤의 오브젝트가 보여야 하거나 보이지 않아야 할 때
void OpenDoor() {
// Toggle the Occlusion Portal's open state, so that Unity renders the GameObjects behind it
myOcclusionPortal.open = true;
// Call a function that plays a door opening animation, or otherwise hides the GameObject
…
}
- Ensure that the GameObject is not marked as Occluder Static or Occludee Static.
3. 참고 자료들
For Basic Understanding
Unity - Manual: Occlusion culling
Unity - Manual: Occlusion culling
Getting started with occlusion culling Occlusion culling Occlusion culling is a process which prevents Unity from performing renderingThe process of drawing graphics to the screen (or to a render texture). By default, the main camera in Unity renders its v
docs.unity3d.com
Use Occlusion Culling like a PRO | unity advanced tutorial
More Information
개인적으로 아래의 3부작 블로그가 이해하는 데 도움이 정말 많이 됨
Occlusion culling in Unity 4.3: The basics | Unity Blog
Occlusion culling in Unity 4.3: The basics | Unity Blog
Umbra’s occlusion culling process can be roughly divided into two distinct stages. In the editor, Umbra processes the game scene so that visibility queries can be performed in the game runtime, in the player. So first, Umbra needs to take the game scene
blog.unity.com
- 깊이 버퍼(depth buffer): 3차원 공간에서 픽셀의 깊이를 저장하는 버퍼이다. 이 버퍼는 카메라에서 렌더링되는 각 픽셀의 깊이를 기록하여, 화면에 표시되는 오브젝트의 깊이를 비교하여 렌더링 순서를 결정한다. 일반적으로는 카메라에서 먼 거리의 픽셀일수록 깊이 값이 작아지며, 가까운 거리의 픽셀일수록 깊이 값이 커진다. 이를 통해 화면에 오브젝트를 올바르게 렌더링할 수 있다.
- 레스터라이제이션: 3D 모델을 2D 이미지로 변환하는 과정입니다. 레스터라이제이션은 카메라에서 보이는 모든 객체를 픽셀로 변환하여 렌더링하는 것을 의미한다. 이 과정에서 모든 객체는 삼각형 형태로 분해되고, 각 삼각형은 화면에 픽셀로 렌더링된다. 또한 깊이 버퍼를 사용하여 렌더링할 때 픽셀의 깊이를 비교하여 픽셀의 가시성을 결정한다. 이후 렌더링된 픽셀은 화면에 표시된다.
- Smallest Hole : In practice, we’ve found that values between 5 cm to 50 cm work fairly well for most games where the scale is “human-like”.
- Smallest Occluder : In most games, keeping smallest occluder slightly larger than the player, so around a few meters, is a good default. So anywhere between 2 and 6 meters may make sense if your game’s scale isn’t microscopic or galactic. The default value in Unity is 5 meters.
- Backface Threshold : It’s important to note that the parameter exists only for a single purpose: occlusion data size optimization. This means that if your occlusion data size is OK, you should probably just disregard backface threshold altogether. …These invalid locations(underneath the terrain or inside a solid object) are also ones from which you tend to “see” mostly back-facing triangles (although they may of course get backface-culled). So in many cases it’s safe to assume that any location in the scene, from which the camera sees a lot of back-facing triangles, is an “invalid” one, meaning that the in-game camera will never end up in those locations.
Occlusion culling in Unity 4.3: Best practices | Unity Blog
Occlusion culling in Unity 4.3: Best practices | Unity Blog
It may seem obvious, but of course the first thing to make sure is that your scene actually contains meaningful occlusion. Moreover, the occlusion should preferably consist of good, large occluders if possible, as opposed to fine details that only accumula
blog.unity.com
- Make sure that if your renderer is non-opaque, it shouldn’t be an occluder either. (Unity will actually issue a warning if this is the case.) This naturally includes transparent objects and such.
- If your object contains very small holes (consider e.g. a cheese grater or a bushy plant) that you wish to see through, but reducing the value of smallest hole globally doesn’t make sense, simply removing the occluder flag from the renderer is the correct thing to do.
- Because occluders are considered solid, correct culling can typically be guaranteed if the camera doesn’t intersect an occluder. This means that if e.g. the collision system cannot prevent the camera from flying inside an occluder, you should probably remove the occluder flag in order to get meaningful results.
- Splitting up the terrain into multiple patches is typically a good idea, unless you want the entire terrain to always be visible (Umbra does object-level occlusion culling).
- Umbra is always conservative, meaning that in various cases Umbra considers the occluders slightly smaller than what they are in reality, or conversely, the empty areas slightly larger.
- While voxelization does patch a lot of unintentional cracks and gaps in the occluding geometry, it’s still highly important to try to model the geometry as water-tightly as possible.
Occlusion culling in Unity 4.3: Troubleshooting | Unity Blog
Occlusion culling in Unity 4.3: Troubleshooting | Unity Blog
The reason for slow culling is typically very simple. Umbra traverses too many portals, and thus the visibility query takes a long time. The parameter that controls the portal resolution in the occlusion data is smallest occluder. A larger value will produ
blog.unity.com