Sparse Textures (Texturas Dispersas)
Subida Asincrónica de Texturas

CullingGroup API

El CullingGroup ofrece una manera de integrar sus propios sistemas al pipeline LOD y al culling de Unity. Esto puede servir a varios propósitos; por ejemplo:

  • Simular una multitud de personas, mientras que solamente los personajes que están visibles en el momento tienen GameObjects completo.
  • Construir un sistema de partículas del GPU manejado por Graphics.DrawProcedural, al omitir el renderizado de sistemas de partículas que están detrás de una pared
  • Hacerle seguimiento a qué puntos de generación (spawn) están ocultos de la cámara con el fin de generar enemigos sin que el jugador los vea ‘aparecer’ en la vista
  • Cambiar los personajes de una animación de alta calidad y cálculos de AI cuando estén cerca, a un comportamiento más ‘barato’ de baja calidad en la distancia
  • Tener 10,000 puntos marcadores en su escena y eficientemente averiguar cuándo un jugador llega a 1m de cualquiera de ellos

El API funciona al usted proporcionar un arreglo de esferas que delimitan. La visibilidad de estas esferas relativas a una cámara en particular luego se calcula, junto con un valor ‘distance band’ (banda de distancia) que puede ser tratado como un número de un nivel (level) LOD.

Empezando con CullingGroup

No hay componentes o herramientas visuales para trabajar con CullingGroups; estas son puramente accesibles vía script.

Un CullingGroup se puede construir utilizando el operador ‘new’:

CullingGroup group = new CullingGroup();

Para que el CullingGroup realice cálculos de visibilidad, especifique la cámara que debe utilizar:

group.targetCamera = Camera.main;

Crea y puebla un arreglo de estructuras BoundingSphere (esferas de-limitanes) con las posiciones y radio de sus esferas, y lo pasa a SetBoundingSpheres junto con la cantidad de esferas que en realidad está en el arreglo. La cantidad de esferas no necesita ser del mismo tamaño del arreglo; de hecho nosotros recomendamos crear un arreglo que es lo suficiente grande para albergar la mayor cantidad de esferas que usted tendrá en un momento, incluso si el número inicial de esferas que usted tiene en el arreglo sea bajo. De esta manera usted evita re-dimensionar el arreglo a medida que se agreguen o quiten esferas, lo cual es una operación costosa.

BoundingSphere[] spheres = new BoundingSphere[1000];
spheres[0] = new BoundingSphere(Vector3.zero, 1f);
group.SetBoundingSpheres(spheres);
group.SetBoundingSphereCount(1);

En este punto, el CullingGroup va a empezar a calcular la visibilidad de una sola esfera cada frame.

Para limpiar el CullingGroup y librar toda la memoria que utiliza, elimine el CullingGroup vía el mecanismo estándar .NET IDisposable:

group.Dispose();
group = null;

Recibiendo resultados vía el callback onStateChanged

La manera más eficiente de responder al cambio de visibilidad de las esferas o el estado de distancia es utilizar el campo para el callback onStateChanged. Configure esto a una función que toma una estructura CullingGroupEvent como un argumento; luego será llamado después de que el culling haya sido completado, para cada esfera que ha cambiado de estado. Los miembros de la estructura CullingGroupEvent le dice a usted acerca de los estados previos y nuevos de la esfera.

group.onStateChanged = StateChangedMethod;

private void StateChangedMethod(CullingGroupEvent evt)
{
    if(evt.hasBecomeVisible)
        Debug.LogFormat("Sphere {0} has become visible!", evt.index);
    if(evt.hasBecomeInvisible)
        Debug.LogFormat("Sphere {0} has become invisible!", evt.index);
}

Recibiendo resultados vía el CullingGroup API de consultas

Adicionalmente al delegate onStateChanged, el CullingGroup proporciona un API para recuperar los últimos resultados de visibilidad y distancia de cualquiera esfera en el arreglo de las esferas que delimitan. Para revisar los estados de una sola esfera, utilice los métodos IsVisible y GetDistance:

bool sphereIsVisible = group.IsVisible(0);
int sphereDistanceBand = group.GetDistance(0);

Para revisar los estados de varias esferas, usted puede utilizar el método QueryIndices. Este método escanea un rango continuo de esferas para averiguar las que coinciden una visibilidad dada o estado de distancia.

// Asigne una matriz para contener los índices de esfera resultantes: el tamaño de la matriz determina las esferas máximas comprobadas por llamada
int[] resultIndices = new int[1000];
// También configure un int para almacenar el número real de resultados que se han colocado en la matriz
int numResults = 0;

// Encuentra todas las esferas que son visibles.
numResults = group.QueryIndices(true, resultIndices, 0);
// Encuentra todas las esferas que están en la banda de distancia 1
numResults = group.QueryIndices(1, resultIndices, 0);
// Encuentra todas las esferas que están ocultas en la banda de distancia 2, saltándose las primeras 100
numResults = group.QueryIndices(false, 2, resultIndices, 100);

Recuerde que la información recuperada por el API de consultas solamente se actualiza cuando la cámara utilizada por el CullingGroup en realidad realiza su culling.

Mejores prácticas del CullingGroup API

Cuando considere cómo aplicar el CullingGroup a su proyecto, considere el siguiente aspecto del diseño del CullingGroup.

Utilizando visibilidad

Todos los volúmenes para ver qué CullingGroup calcula la visibilidad están definidos por las esferas que delimitan - en práctica, una posición (el centro de la esfera) y un valor de un radio. Ningún otra forma que delimita está soportada, por razones de rendimiento. En práctica esto significa que usted definirá una esfera que completamente encierre el objeto que es de su interés para el culling. Si un encaje más ajustado se necesita, considere utilizar varias esferas para cubrir diferentes partes del objeto, y tomar decisiones basado en el estado de visibilidad de todas las esferas.

Con el fin de evaluar visibilidad, el CullingGroup necesita saber desde qué cámara la visibilidad será calculada. Actualmente un solo CullingGroup soporta una sola cámara. Si usted necesita evaluar la visibilidad de varias cámaras, debería utilizar un CullingGroup por cámara y combinar los resultados.

El CullingGroup calcula la visibilidad basado en el frustum culling y la occlusion culling estática solamente. No tomará los objetos dinámicos en cuenta como oclusores potenciales.

Utilizando la distancia

El CullingGroup es capaz de calcular la distancia enter algún punto de referencia (por ejemplo, la posición de la cámara o el jugador) y el punto más cercano en cada esfera. Este valor de distancia no se le proporciona directamente a usted, pero en vez es cuantificado utilizando un conjunto de valores de umbral que usted proporciona, con el fin de calcular un ‘distance band’(banda de distancia) discreto de tipo entero como resultado. La intención es que usted interprete estas distance bands como ‘close range’ (rango cercano), ‘medium range’ (rango mediano), ‘far range’ (rango lejano), y así.

El CullingGroup va a proporcionar callbacks cuando un objeto se mueve de estar en una banda a estar en otra, dándole a usted la oportunidad de hacer cosas como cambiar el comportamiento de ese objeto a algo menos intensivo al CPU.

Cualquier esfera que esté más allá de la última banda de distancia será considerada invisible, permitiéndole a usted construir fácilmente una implementación culling que completamente des-active los objetos que estén más lejos. Si usted no quiere este comportamiento, simplemente configure su valor umbral final a que esté en una distancia infinita.

Solo un punto de referencia es soportado por CullingGroup.

Rendimiento y diseño

El CullingGroup API no le da a usted la habilidad de realizar cambias a su escena y luego solicitar inmediatamente el nuevo estado de visibilidad de la esfera que delimita. Por razones de rendimiento, el CullingGroup solo calcula información nueva de visibilidad durante la ejecución del culling para la cámara completa; es en este punto que la información está disponible para usted, ya sea vía un callback, o vía el CullingGroup API de consultas. En práctica, esto significa que usted debería acercarse al CullingGroup de una manera asincrónica.

El arreglo de las esferas de-limitantes que usted proporciona al CullingGroup es referenciado por el CullingGroup, en vez de ser copiado. Esto significa que usted debe mantener una referencia al arreglo que usted pase a SetBoundingSpheres, y que pueda modificar los contenidos de este arreglo sin necesidad de llamar SetBoundingSpheres nuevamente. Si usted necesita que haya varios CullingGroups que calcule la visibilidad y las distancias para el mismo conjunto de esferas - por ejemplo, para varias cámaras - entonces es eficiente tener que todos los CullingGroups compartan la misma instancia de las esferas de-limitantes.

Sparse Textures (Texturas Dispersas)
Subida Asincrónica de Texturas