Czy zdarzyło Ci się kiedyś, że obiekty znajdowały się po za obszarem kamery (ang. camera frustum), a mimo to zostały wyrenderowane? Najprawdopodobniej powodem były granice obiektów, które mogą zajmować znacznie więcej miejsca niż sam obiekt 🙂 .
Wyobraźmy sobie, że mamy prostą scenę z kilkoma obiektami 3d i kamerą:
Jeśli użyjemy frame debuggera, żeby sprawdzić ile obiektów zostało przetworzonych, to zobaczymy, że wszystkie zostały wyrenderowane.
Jest to spowodowane przez granice obiektów, które nachodzą na obszar kamery. Jak możemy je sprawdzić? Możemy użyć prostego skryptu, który wyświetli nam gizmo reprezentujące granice renderera.
using UnityEngine;
[ExecuteInEditMode]
public sealed class BoundingBoxView : MonoBehaviour
{
[SerializeField]
private Renderer rendererComponent;
[SerializeField]
private Color boxColor = Color.red;
[SerializeField]
private Color selectedBoxColor = Color.green;
private void Awake()
{
if (rendererComponent == null)
{
rendererComponent = GetComponent<Renderer>();
}
}
private void OnDrawGizmos()
{
if (rendererComponent != null)
{
var bounds = rendererComponent.bounds;
var gizmosColor = Gizmos.color;
Gizmos.color = boxColor;
Gizmos.DrawWireCube(bounds.center, bounds.size);
Gizmos.color = gizmosColor;
}
}
private void OnDrawGizmosSelected()
{
if (rendererComponent != null)
{
var bounds = rendererComponent.bounds;
var gizmosColor = Gizmos.color;
Gizmos.color = selectedBoxColor;
Gizmos.DrawWireCube(bounds.center, bounds.size);
Gizmos.color = gizmosColor;
}
}
}
Kiedy dodamy skrypt BoundingBoxView do wszystkich obiektów 3d na scenie i ustawimy im różne kolory gizmo to powinniśmy zobaczyć coś podobnego jak na rys. 3.
Jak możemy zobaczyć, wszystkie gizmo nachodzą na obszar kamery. Z tego powodu wszystkie obiekty na scenie zostały wyrenderowane. Czy da się to jakoś zoptymalizować? Obiekty można podzielić na mniejsze kawałki co spowoduje, że każda składowa będzie miała własne, mniejsze granice.
Granice są wyznaczane jako prostopadłościan okalający wszystkie wierzchołki obiektu. Prostopadłościan jest liczony względem globalnych współrzędnych. To znaczy, że ściany prostopadłościanu są równoległe do globalnych osi X, Y, Z. Z tego powodu obiekt może mieć różne granice w zależności od aktualnego obrotu. Jest to istotne jeśli obiekty na scenie nie są wyrównane do globalnych osi współrzędnych tj. są względem nich obrócone. Powinieneś zwrócić na to uwagę podczas dzielenia obiektów 3d na mniejsze kawałki w czasie optymalizacji sceny.
Na koniec wyobraźmy sobie, że nasza scena zbudowana jest ze statycznych obiektów i mamy wypalone mapy światła. Wszystkie obiekty zostały złączone w jeden combined mesh przez statyczny batching i są wyświetlane w jednym odwołaniu do karty graficznej. Czy nadal warto dzielić obiekty na mniejsze kawałki? Nie oszczędzimy przecież odwołań do karty graficznej, bo wszystko jest renderowane za jednym razem.
Dobre wieści 🙂 ! Nadal warto podzielić obiekty na mniejsze. Ograniczymy liczbę wierzchołków przetwarzanych przez kartę graficzną, ponieważ połączony mesh jest najprawdopodobniej zbudowany z części, które mogą być włączane/wyłączane niezależnie. Unity pominie części, które nie muszą zostać wyrenderowane, co uprości geometrię.