¿Cuál es la mejor manera de dibujar muchos árboles?

8

Estoy escribiendo una aplicación que representa una isla aleatoria plantada con árboles. Los árboles son actualmente dos quads, entrecruzados y dibujados con texturas. Planeo tener mallas más complejas que formen diferentes tipos de plantas, por ejemplo, una palmera, roble, hierbas, etc.

Isla de muestra

El problema que enfrento es que debido a que las texturas son transparentes, debo dibujarlas de atrás hacia adelante. Plan-b es llamar al uso de descarte en el frag shader, pero el orden z da mejores resultados:

uniform float uTreeAlpha;
uniform sampler2D uTexture;

varying vec2 vTexCoordOut;

void main (void)
{
  vec4 colour = texture2D(uTexture, vTexCoordOut);
  if (colour.a < 0.1) {
    discard;
  }
  gl_FragColor = vec4(colour.rgb, colour.a * uTreeAlpha);   
}

El segundo problema es porque el orden cambia según la cámara y el aspecto. No conozco una forma eficiente de dibujarlos en OpenGL en una sola llamada.

En la actualidad, mi código de representación se parece a este pseudocódigo:

if cameraChangedFromLastTime() then
  sortTreesBackToFront();
end
for i = 0 to trees.size() -1
  drawTree()
end

Donde cada drawTree () establece algunos uniformes, establece la textura y luego llama a glDrawArrays (). Tengo algunas optimizaciones para omitir la configuración de una textura o actualizar los códigos de textura si el último árbol y la corriente son los mismos, y establecer algunos uniformes comunes fuera del bucle y omitir árboles que están demasiado lejos, pero básicamente si tengo 3000 árboles I ir 3000 veces alrededor del bucle.

Dibujar cada árbol individualmente es el asesino de rendimiento. Si pudiera dibujarlos en una sola llamada, o en lotes (manteniendo el orden Z) probablemente lo haría en 1/10 del tiempo.

Entonces, ¿cómo haría eso? Tenga en cuenta que mis árboles son marcadores de posición y eventualmente tendría:

  • Mallas diferentes para diferentes árboles.
  • Diferentes escalas y ángulos para que los árboles den más variedad
  • Diferentes texturas para diferentes árboles, potencialmente múltiples texturas aplicadas a una malla (por ejemplo, deja una textura, tronco otra)
  • Los árboles están todos mezclados, así que no hay una manera simple de dibujar un tipo y luego otro
  • Alguna forma de animación cíclica simple (ramas flotando en el viento)
  • Todas las texturas residirían en un solo atlas

Entonces, ¿cuál es el mejor enfoque aquí? ¿Es factible renderizar en una sola pasada? Si usara glDrawElements, reconstruyendo los índices pero no los vértices, ¿podría lograr esto?

locka
fuente
vterrain.org , vea la columna derecha debajo de la sección de plantas para la representación de la planta, la columna izquierda respectiva, la sección de representación para el nivel de detalle / aceleraciones generales de representación. Sin embargo, tenga cuidado: la fuente es más listas de trabajos de investigación que tutoriales.
Exilyth
No sé mucho sobre estas cosas. Pero echa un vistazo al software VUE. Se utiliza para crear paisajes con árboles, montañas, atmósfera y mucho más, en 3d. Pero no estoy seguro de si ayudará en su situación
user1981248

Respuestas:

3

Lo que quieres es instancias de hardware . Nota: He hecho esto en XNA (es decir, DirectX), pero no sé mucho sobre OpenGL. Sin embargo, estoy seguro de que hay una característica comparable. Básicamente, lo que equivale es unir los vértices de su modelo de árbol con otra secuencia de vértices que transporta coordenadas mundiales para cada instancia.

DrHeinous
fuente
1
El equivalente de OpenGL sería la extensión opengl.org/registry/specs/EXT/draw_instanced.txt . Pero, para empezar, puede mostrar Listas en OpenGL y Vertex Array Objects / Vertex Buffer Objects en OpenGL moderno. En ambos casos, un objeto / malla se almacena en la Lista / VAO / VBO, luego cada instancia se dibuja con una transformación diferente. Usando mallas estáticas, los datos pueden cargarse una vez y luego reutilizarse. sol.gfxile.net/instancing.html ofrece una breve descripción de los diferentes métodos.
Exilyth
Gracias, la instancia es una idea interesante. Sin embargo, no pude usar una extensión draw_instanced ya que estoy usando OpenGL ES 2.0 y estoy trabajando en algo que funciona en todo. Tal vez estoy pensando que puedo cargar las diversas mallas de árbol en un VBO (potencialmente con modelos más simples más lejos), ordenar en z y luego dibujarlas en lotes desde un búfer de índice que construiría para cada lote. Podría dibujar 30 o 40 a la vez de esa manera.
locka
2

La transparencia solo necesita ser ordenada si usa una mezcla no aditiva. Para una tonelada de vallas publicitarias distantes, la combinación es innecesaria (realmente no se puede ver). Procese al menos los otros con transparencia de recorte (alfa de solo 1 o 0) y no necesita ordenarlos.

Puede usar una especie de hoja de sprites para representar diferentes tipos de árboles, con animaciones horneadas. Dibuja mallas para árboles más cercanos que puedas animar con más fidelidad en función de los vientos o lo que quieras.

Sean Middleditch
fuente
He experimentado con el uso de descarte y sin clasificación, pero los resultados parecen un poco duff: los árboles tienden a superponerse mucho, por lo que si no hay un orden consistente, obtengo un montón de pop donde un árbol va delante del otro y " gana "el píxel. He dejado el descarte porque todavía hay colisiones ocasionales (por ejemplo, 2 árboles con la misma distancia de la cámara), pero es una alternativa. También he experimentado con vallas publicitarias y el efecto es demasiado falso, especialmente para los pasos elevados.
locka
Utiliza mejores vallas publicitarias. Lo ideal es tener un modelo de árbol. Genere el sprite de la cartelera para un ángulo de visión, y use ese sprite donde el ángulo coincida aproximadamente. Para los recortes, funcionan mejor a distancia, donde no se puede ver la diferencia. A medida que se acerca, necesita usar modelos más complicados (tal vez algunos quads por árbol), o puede cambiar a la transparencia de la puerta de la pantalla.
Sean Middleditch
En algún momento, debe averiguar el equilibrio aceptable entre calidad y velocidad. No obtendrá "increíblemente rápido" y "perfecto" para las escenas más complejas en hardware básico.
Sean Middleditch