Optimización de gráficos. Interesante casco cóncavo

En un momento, durante el desarrollo del juego, me enfrenté al problema del rendimiento en las PC modernas. Nuestro modelador tiene una computadora moderna de ensamblaje rojo bastante poderosa. Pero tenía nuestro proyecto terriblemente lento, cargando un núcleo de procesador.

La razón es simple: los nuevos procesadores tienen muchos núcleos, pero de hecho son menos eficientes en aplicaciones de un solo subproceso. En ese momento, tenía un render en una secuencia. Pero, de hecho, las razones no fueron tanto en esto. Y en el proceso de encontrar el problema, decidí calcular cuántos polígonos hay en la escena:



En el mapa de juego promedio, con la distancia máxima y con un gran grupo de palmeras, ¡ 15 824 756 triángulos! ¡Casi 16 millones! Un gran número

Después de jugar un poco con el generador de mapas, logré encontrar un lugar con 16,75 millones:



Aunque, aquí, un lugar similar con árboles de Navidad dio solo 8,5 millones de triángulos:



La escena promedio consistió en ~ 4 millones:



En general, me alegré de que mi render estuviera haciendo frente a una cantidad tan enorme de triángulos, pero su número era excesivo. La solución estaba en la superficie:

  1. Optimizar el número de polígonos en modelos.
  2. Optimiza la malla poligonal del paisaje.
  3. La implementación de renderizado multiproceso.

Para aquellos que pueden no estar interesados ​​en el primer párrafo de nuestro programa de optimización, por ejemplo, especialistas sin experiencia, les recomiendo ir con seguridad a la segunda parte.

1. Optimización del número de polígonos en modelos.


En nuestro motor, la vegetación se dibuja en "paquetes", todo el paisaje se divide en mosaicos y sub-mosaicos, el paquete mínimo es un sub-mosaico.



Un paquete es una malla, ya que la reducción de la cantidad de mallas reduce significativamente la cantidad de llamadas de CPU-> GPU.



Inicialmente, nuestros árboles consistían en conos truncados, moviéndose a conos completos, logramos eliminar un par de triángulos adicionales:



La guinda del pastel fue la decisión de quitar los troncos de los árboles, porque con nuestro ángulo de cámara simplemente no eran visibles.

Como resultado, logramos reducir el número de polígonos, en un paquete de árboles de Navidad, en un promedio del 40%. Las diferencias son casi invisibles:



Con las palmeras fue más difícil, pero los paquetes de 5000 a 6000 polígonos necesitaban ser reparados. ¿Cómo lograr la masividad y densidad de la selva? La alta densidad de la selva se logró debido a la gran cantidad de palmeras:



Decidimos simplificar las palmeras e introducir un segundo nivel de vegetación, lo que nos permitió mantener la densidad visible y lograr los deseados 600 a 700 polígonos por paquete.



Reducir el número de polígonos en 10 veces es un excelente resultado.



2. Optimización del paisaje de malla poligonal.



Inicialmente, la cuadrícula del paisaje era:



La captura de pantalla muestra secciones planas del paisaje, estos son azulejos de prados, llanuras, aunque otras superficies lisas. Decidí eliminar pequeñas irregularidades en el paisaje. Por lo tanto, aumentó el área de los mismos azulejos de altura. No al comprobar astutamente todos los vértices de los mosaicos y sub-mosaicos para la igualdad en altura, pude lograr este resultado:



Todavía había lugares planos que podían optimizarse, y comencé a construir polígonos a partir de esos triángulos que tenían la misma altura. Se tomó un mosaico y todos sus triángulos se clasificaron en una matriz de triángulos de altura desigual y una lista de matrices que consta de triángulos adyacentes y de igual altura.



En el ejemplo dado, resultó: 1 conjunto de triángulos que no se pueden cambiar, ya que todos tenían diferentes alturas (triángulos rojos) y una lista que consta de dos conjuntos de triángulos con la misma altura (los conjuntos están llenos de color).

Ahora la tarea consistía en encontrar a partir de la matriz de triángulos su contorno convexo-cóncavo (Casco cóncavo), y muchos triángulos podrían tener agujeros. Anteriormente, me encontré con Convex Hull en mi trabajo, no hubo problemas con ellos, ya usé el algoritmo de Graham. Pero hubo problemas con la construcción del casco cóncavo ... Resultó ser bastante difícil encontrar información sobre este tema en Internet. Tuve que escribir una implementación de algoritmos desde cero. No mentiré si digo que he leído sobre diez disertaciones diferentes sobre este tema. Pero todos los algoritmos propuestos dieron un resultado aproximado con algún error. Después de una semana de tormento y dolor, se me ocurrió la idea de mi algoritmo.

Traté de construir un contorno a partir del conjunto de vértices de los triángulos, es decir. Traduje la matriz de triángulos en una matriz de vértices y ya construí un caparazón sobre ellos. Pero para mi tarea esto no era necesario. Según mis conclusiones, fue más fácil construir un caparazón directamente a partir de triángulos, y la precisión del casco cóncavo fue del 100%.

Inicialmente, quería poner un mosaico del código fuente del algoritmo aquí, pero parece más fácil describirlo en pocas palabras: la regla es la base: si el vértice de un triángulo se incluye en cuatro o menos triángulos, entonces uno de los bordes que forma el vértice se encuentra en el borde. A continuación, se forma una lista de dichos bordes teniendo en cuenta la eliminación de bordes idénticos. Encontramos el borde con las X e Y más pequeñas y desde allí comenzamos el pasaje / clasificación de los bordes con la adición de vértices únicos a la lista. Esta lista será la cáscara de muchos triángulos. Lo único en la final es eliminar los puntos colineales de la lista.

Como resultado de esto, podría construir Casco cóncavo de casi cualquier complejidad. Este algoritmo no encajaba en un conjunto de agujeros, pero lo resolví simplemente dividiendo este conjunto en dos mitades en un agujero. Luego tomé el circuito y lo triangulé:







Todo salió bien:



Pero al final, el resultado me molestó. El algoritmo que desarrollé dio un aumento tangible en el rendimiento al renderizar una escena, ya que el número de polígonos en promedio se redujo en un 60 - 70%. Pero al mismo tiempo, la generación de tarjetas comenzó a ocurrir 10 veces más lento. El algoritmo resultó ser muy lento.

Tomó tres días considerar una versión liviana del algoritmo para optimizar la malla poligonal del paisaje, lo que dio estos resultados:



Ahora los cálculos de datos para la optimización no se han notado en el contexto de la generación de mapas, y el número de polígonos ha disminuido en promedio en un 40-50%.

Este artículo es de prueba y superficial. Si alguien está interesado en el tema del desarrollo de juegos, estoy listo para continuar y expandir el artículo con el fantasma de pasos específicos, soluciones y planes futuros. Además, creo que le interesará el tema de la construcción de una aplicación Open GL multiproceso desarrollada en Java, de la que trataré de hablar en el próximo artículo.

Source: https://habr.com/ru/post/es436040/


All Articles