Red de conocimiento informático - Problemas con los teléfonos móviles - Unidos para abrir el mundo, ¿cómo optimizar la tierra?

Unidos para abrir el mundo, ¿cómo optimizar la tierra?

Solución de carga de datos de terreno grande

Teniendo en cuenta el mecanismo de memoria existente, la carga de terreno grande no se puede agregar a la memoria al mismo tiempo. El problema es obvio. De hecho, a menudo nos encontramos con esto en el desarrollo de juegos, como nuestra barra de progreso común. El propósito de la barra de progreso de carga es esperar a que el programa cargue la escena. La barra de progreso es solo una máscara. No hay otra forma de cargar terreno grande excepto bloquearlo. Esta es la dirección general, entonces, como programa, ¿cómo bloquearlo? ¿Qué tan grande es este vecindario? Necesitamos segmentar estos temas específicos según los requisitos. Por ejemplo, el tamaño del bloque del simulador de vuelo puede ser mayor porque la vista de pájaro es más grande, el bloque de recorrido por la escena puede ser más pequeño, etc. Primero tomemos el clásico juego "World of Warcraft Terrain Loading Scheme" como ejemplo para presentar su principio de implementación a los lectores. El juego World of Warcraft realiza un empalme de mapas perfecto, por lo que es de gran valor de referencia, como se muestra en la siguiente figura:

¿Cómo logra World of Warcraft mapas infinitos? De hecho, también es la unión de muchos bloques de escenas. Analizamos la división por tamaños de los bloques de terreno en World of Warcraft a través del editor. La escena de World of Warcraft, que llamamos mundo de mapas, consta de una serie de mosaicos de mapas con un tamaño de 1600/3 ≈ 533,33 m. Cada mosaico de mapa consta de MapChunk de 16x16, a partir del cual podemos calcular cada mapa. Luego está la textura de la superficie que consta de una altura de vértice del terreno de 9x9+8x8, normales y varias capas de textura (generalmente 4 capas). No discutiremos aquí el tamaño del terreno de World of Warcraft, pero podemos aprender de su idea de bloqueo.

Continúa analizando el método de bloqueo de World of Warcraft: divide según la matriz y procede en el plano XZ. Cada mosaico contendrá algunos datos informativos, como el mosaico del mapa en la ubicación XZ (3,3), y cada mosaico del mapa contiene ejemplos del mapa y el modelo utilizados en el mosaico del mapa. Las llamadas instancias de modelo, que son nuestros accesorios, pueden entenderse como información sobre diferentes posiciones de ubicación, tamaños y ángulos del mismo modelo en los mosaicos, todos los cuales se almacenan en archivos binarios. Para ahorrar tamaño de archivo, las instancias de modelo se guardan mediante modelos indexados, similar a la indexación de vértices. Cada imagen de textura también contiene información de textura, como el nombre de la textura y la información UV. El modelo de pensamiento en bloques de este curso es similar al de World of Warcraft, que se presentará en detalle en capítulos posteriores. Después de dividir en bloques, el siguiente es el principio de implementación.

Principio de implementación: en cualquier momento, el programa siempre mantiene mosaicos de mapas de 3x3 dentro y alrededor del jugador. Estos mosaicos de mapas se actualizarán dinámicamente a medida que el jugador se mueva y se cargarán nuevos mosaicos de mapas para reemplazar los mosaicos de mapas antiguos que no se instalaron. Para mejorar la eficiencia de la programación, Warcraft introdujo un mecanismo de almacenamiento en caché, y el caché puede almacenar hasta 16 datos de MapTile. Cuando necesite cargar un mapa nuevo, primero lo buscará en el caché; los mosaicos de mapas antiguos que no están instalados no se eliminan inmediatamente, sino que se guardan en el caché para recuperarlos. Debido a que el rango de actividad de un jugador normalmente no cambia mucho durante un período de tiempo, esta estrategia de almacenamiento en caché funciona muy bien en las aplicaciones, que es el principio básico detrás de los mapas integrados. La carga y descarga dinámica de terreno se implementará mediante subprocesos múltiples e integraremos dos subprocesos: un subproceso está dedicado a cargar terreno y el otro subproceso está dedicado a descargar u ocultar MapTiles del terreno. Recordemos el juego clásico. El efecto de la escena del juego es el siguiente:

El método implementado en este curso puede manejar el problema de cargar y mostrar bloques de dos maneras. Una forma es utilizar el grupo de objetos para precargar el terreno dividido, determinar qué bloques mostrar y ocultarlos según la detección de la línea de visión, y no eliminarlos aquí. Entonces solo se necesita un hilo. Otra forma es utilizar subprocesos múltiples, con un subproceso dedicado a eliminar y descargar trazados que no están a la vista, lo que puede mejorar la eficiencia. A continuación se muestra una solución de carga que utiliza subprocesos múltiples.

Implementación de subprocesos múltiples para esquemas de carga de terrenos grandes

El subproceso múltiple se usa ampliamente en juegos de PC. Por ejemplo, puedes configurar un hilo para cargar recursos, que también se utiliza en los servidores de juegos. Aquí presentamos a los lectores el esquema de implementación de subprocesos múltiples. El problema con el procesamiento de subprocesos múltiples es poner toda la lógica de carga en un nuevo proceso, realizar alguna comunicación entre procesos con el subproceso principal, aceptar las sugerencias de carga del subproceso principal, realizar cargas bajo demanda y también realizar algunas precargas por adelantado. y ponerlo en la memoria asignada, tal como lo hace World of Warcraft. El proceso principal del juego siempre necesita mantener una pequeña cantidad de memoria y una gran cantidad de datos de la memoria se procesa en otro proceso. De esta manera, se puede optimizar la carga de bloques de terreno grandes. El método de implementación es el siguiente:

Primero, el hilo principal cargará nueve bloques de terreno y el hilo principal solo es responsable de mantener estos nueve. bloques de terreno.

No importa cómo se mueva el personaje, toda el área donde se encuentra el personaje siempre son nueve terrenos. Como se muestra en la figura anterior, el hilo principal puede cargar estos nueve bloques directamente en la memoria, y los 16 bloques restantes se colocarán en el caché a través de otro hilo. La posición del personaje es en medio de los nueve terrenos cargados, que es donde está A. A medida que el personaje se mueve, se agregan nuevos mosaicos de terreno y se reemplazan los mosaicos de terreno existentes, de modo que siempre se muestran 9 mosaicos de terreno. El terreno reemplazado no se descarga inmediatamente, sino que se predice en función de los movimientos del personaje. Esperará a que el hilo principal le notifique que descargue y cargue bloques de tierra de acuerdo con ciertas reglas. De hecho, este método de implementación es lo que normalmente llamamos tecnología de doble almacenamiento en búfer y subprocesos múltiples. El efecto logrado es el siguiente:

Después de cargar el terreno en trozos, se debe considerar el mapeo de texturas en el terreno, y los recursos de mapeo del terreno también ocuparán mucha memoria. A continuación se describe cómo cargar datos topográficos y cartográficos masivos.

Solución de carga masiva de imágenes para terrenos grandes

Hay muchas imágenes de escenas en el terreno grande y hay al menos cuatro capas de mapas en el terreno. Estos factores deben tenerse en cuenta al cargar tantos mapas y también al bloquear. Además, el horneado del mapa de luz utilizado en la escena también es un tema que debe tenerse en cuenta. Para aliviar la presión de la memoria, empaquetaremos los materiales del terreno y de construcción en bloques con anticipación. ¿Cómo cargar primero las texturas de la escena en trozos? Se implementa así:

La idea es convertir los mapas de la escena en diferentes atlas en función de los bloques que dividimos. Por supuesto, los mapas de los dos bloques también se pueden convertir en un atlas. Para PC, el tamaño máximo de galería es 4096 y para dispositivos móviles, el tamaño máximo de galería es 2048. Esto también es para evitar la carga y descarga frecuente de memoria, lo que provocará una gran fragmentación de la memoria, lo que no favorece la asignación futura de una gran cantidad de memoria. Antes de dibujar el atlas, lo que debemos hacer es establecer una correspondencia uno a uno entre el mapa de textura en el bloque de terreno y el atlas que empaquetamos, para que pueda coincidir fácilmente. Debido a que el atlas que empaquetamos no tiene nada que ver con el terreno real, para establecer la correspondencia entre ellos, necesitamos tener una tabla de archivos de índice completa, que es el puente entre el atlas y la textura del terreno real. A través del archivo de índice que creamos, podemos encontrar la correspondencia entre la textura del terreno real y la textura del atlas. La tabla de índice que creamos se cargará en la memoria. Sin embargo, nuestro atlas se agrega a la memoria después de la tarea de carga, lo que requiere que nuestros archivos de índice sean lo más pequeños posible porque residen en la memoria. Además de cargar imágenes masivas, también debemos manejar la carga de edificios densos.

-Plan de carga de edificios densos

Carga de edificios densos, imagínese, si todos los edificios en la escena se cargan en la memoria a la vez, la memoria se llenará instantáneamente, el El número de fotogramas cae instantáneamente, por lo que te quedas atascado cuando te encuentras con edificios densos mientras te mueves en la escena del juego. En el pasado, se utilizaba el procesamiento LOD y se utilizaban modelos simples para objetos ocluidos, lo que también aumentaría el efecto de carga de memoria. Si el personaje sigue yendo y viniendo entre edificios, es necesario cambiar diferentes modelos de LOD, lo que también es una carga para la memoria y el efecto no es ideal. ¿Cómo solucionar estos problemas que tienen que resolver los programadores? Mucha gente piensa en fusionar grandes redes, lo cual no es factible. Las rejillas grandes no son adecuadas para operaciones de cultivo. Imagínese si la cámara solo mira una pequeña parte de la malla fusionada, deben cargarse juntas en la memoria porque son un todo, pero en realidad no necesitamos tantos datos del modelo. Al fusionar mallas, también me gustaría dar una sugerencia a los lectores: intente fusionar modelos que estén muy juntos para evitar los problemas anteriores. De hecho, la solución más efectiva es bloquear, lo que se puede hacer usando la idea de bloque de terreno que está estrechamente relacionado con el bloque de terreno. Los edificios en cada bloque de terreno se cargan junto con el bloque de terreno. Si los edificios en el bloque son muy densos, este método no se puede resolver por completo y se requiere un procesamiento adicional, es decir, agregar el algoritmo de oclusión OC combinado con el algoritmo LOD, para que nuestro problema actual se pueda resolver por completo, que también es un curso.

Para ilustrar el método, un método de optimización adicional es colocar el algoritmo de oclusión OC y el algoritmo LOD en la GPU para su cálculo, de modo que se mejore la eficiencia. En Siggraph2015, se publicó un artículo sobre el proceso de renderizado impulsado por GPU. Su idea es utilizar la GPU para oclusión y recorte, que se divide principalmente en dos etapas, utilizando la API de gráficos DX12, como se muestra en la siguiente figura:

La idea es hacer una oclusión y recorte aproximados lista en el primer paso. La operación de recorte luego se refina aún más según la distancia de la línea de visión o la detección de luz.

Esta idea es similar a nuestro algoritmo de detección de colisiones, y el algoritmo de detección de colisiones en el motor también se implementa de acuerdo con este principio. Permítanme presentarles a los lectores: el algoritmo de detección de colisiones real generalmente se divide en dos etapas:

La primera etapa, la fase amplia, encuentra rápidamente una lista de posibles pares de objetos de colisión. Es absolutamente imposible no estarlo. en esta lista. Se produjo una colisión. La fase Amplia ha identificado algunos pares de objetivos que requieren una mayor inspección.

En la segunda etapa, la etapa estrecha encuentra con precisión la lista de pares de objetos en colisión. Debido a que algunos pares de objetos de la etapa anterior en realidad no chocaron, es necesario eliminar esta etapa.

Un algoritmo simple en la etapa amplia se llama escaneo y poda (SAP), que esencialmente utiliza un algoritmo de clasificación. El primer paso es inicializar la lista ordenada. Los elementos de la lista son cuadros delimitadores, que se pueden completar utilizando cualquier algoritmo de clasificación, como la clasificación posterior, que no se basa en la clasificación rápida, sino en la burbujeación. ¿Por qué es mejor la clasificación por burbujas? Esto se debe a una premisa predeterminada: el movimiento del objeto tiene coherencia temporal, es decir, las posiciones del cuadro actual y el siguiente cuadro están cerca, por lo que durante el proceso de clasificación de burbujas, se espera que el intercambio de posiciones sea muy cercano.

De hecho, existen muchas similitudes en los algoritmos. Aquí necesitamos aprender de las ideas de resolución de problemas de los demás para resolver nuestros problemas. Una vez creé un juego de cliente y muchas de las ideas de optimización del juego de cliente también son aplicables a la versión móvil. En comparación con el lado de la PC, el lado móvil es solo una computadora con una configuración inferior. Luego continuamos presentando nuestro recorte de oclusión a los lectores, y el autor del artículo también realizó una prueba de eficiencia. Tomando como ejemplo 250.000 objetos y una cuadrícula de 1G, los resultados de la prueba son los siguientes:

¿No es genial? Se puede utilizar para resolver problemas en el desarrollo de proyectos. Primero hablemos sobre el uso de la GPU para optimizar nuestra escena del terreno.

Solución de optimización de renderizado de terrenos grandes mediante GPU

En primer lugar, nuestro terreno tendrá su propio mapa de superficie. Los mapas de superficie de uso común son una fusión de cuatro texturas y puede haber hasta ocho. La representación de la textura del terreno implicará el algoritmo LOD. La cuadrícula del terreno en la distancia se puede simplificar y el mapa correspondiente también es el más bajo. Este es el uso de MipMap. Además, debe haber hierba, flores y muchos otros objetos similares para renderizar. Primero hablemos de cómo dibujar hierba y flores. Habrá muchos de ellos en el juego. Un método común es pasar por el parche proporcionado por el motor o por tres imágenes y luego mapear el mapa con el canal Alfa, como se muestra en la siguiente imagen:

La CPU dibuja estos pastos o flores en la PC Es posible, porque las computadoras ahora tienen múltiples núcleos, lo que afectará la eficiencia de los teléfonos móviles. Cuando se usa la CPU para dibujar, habrá muchas DrawCalls y será necesario mover el césped o las flores, lo que requiere muchos cálculos y afecta gravemente la eficiencia operativa. Si la CPU tiene dificultades, la GPU puede ayudar. Podemos poner hierba o flores en la GPU para ejecutar. El efecto es el siguiente: