Quelle est la meilleure façon de dessiner beaucoup d'arbres

8

J'écris une application qui rend une île aléatoire plantée d'arbres. Les arbres sont actuellement deux quads, entrecroisés et dessinés avec des textures. Je prévois d'avoir des mailles plus complexes qui forment différents types de plantes, par exemple un palmier, un chêne, des herbes, etc.

Exemple d'île

Le problème auquel je suis confronté est que parce que les textures sont transparentes, je dois les dessiner de l'arrière vers l'avant. Le plan-b consiste à appeler l'utilisation de la suppression dans le shader de frag, mais l'ordre z donne de meilleurs résultats:

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);   
}

Le deuxième problème est dû au fait que l'ordre change en fonction de la caméra et du look. Je ne connais pas de moyen efficace de les dessiner en OpenGL en un seul appel.

À l'heure actuelle, mon code de rendu ressemble à ce pseudocode:

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

Où chaque drawTree () définit des uniformes, définit la texture, puis appelle glDrawArrays (). J'ai quelques optimisations pour ignorer la définition d'une texture ou la mise à jour des coords de texture si le dernier arbre et le courant sont les mêmes, et la mise en place d'uniformes communs en dehors de la boucle, et de sauter des arbres qui sont trop éloignés mais, fondamentalement, si j'ai 3000 arbres, je faire 3000 fois le tour de la boucle.

Dessiner chaque arbre individuellement est le tueur de performance. Si je pouvais les dessiner en un seul appel, ou en lots (tout en préservant l'ordre Z), je le ferais probablement au 1 / 10e du temps.

Alors, comment pourrais-je faire cela. Gardez à l'esprit que mes arbres sont des espaces réservés et, éventuellement, j'aurais:

  • Différentes mailles pour différents arbres
  • Différentes échelles et angles pour les arbres pour donner plus de variété
  • Différentes textures pour différents arbres, potentiellement plusieurs textures appliquées à un maillage (par exemple, laisse une texture, tronc une autre)
  • Les arbres sont tous mélangés, donc pas de moyen simple de dessiner une sorte puis une autre
  • Une certaine forme d'animation cyclique simple (branches flottant dans le vent)
  • Toutes les textures résideraient dans un seul atlas

Alors, quelle est la meilleure approche ici? Est-il possible de rendre en un seul passage? Si j'utilisais glDrawElements, reconstruisant les indices mais pas les sommets, pourrais-je y parvenir?

locka
la source
vterrain.org , voir la colonne de droite sous la section plantes pour le rendu des plantes, la colonne de gauche respective, la section pour le niveau de détail / les accélérations de rendu générales. Attention cependant: la source est plus une liste d'articles de recherche qu'un tutoriel.
Exilyth
Je ne connais pas grand-chose à ce sujet. Mais consultez le logiciel VUE. Il est utilisé pour créer des paysages avec des arbres, des montagnes, de l'atmosphère et bien plus encore, en 3D. Mais je ne sais pas si cela vous aidera dans votre situation
user1981248

Réponses:

3

Ce que vous voulez, c'est une instanciation matérielle . Remarque: je l'ai fait dans XNA (c'est-à-dire DirectX), mais je ne connais pas grand-chose à OpenGL. Je suis toutefois certain qu'il existe une caractéristique comparable. Fondamentalement, cela revient à lier les sommets de votre modèle d'arbre à un autre flux de sommets qui porte les coordonnées du monde pour chaque instance.

DrHeinous
la source
1
L'équivalent OpenGL serait l'extension opengl.org/registry/specs/EXT/draw_instanced.txt . Mais, pour commencer, afficher les listes dans OpenGL hérités et les objets Vertex Array / Vertex Buffer Objects dans OpenGL moderne pourrait faire l'affaire. Dans les deux cas, un objet / maillage est stocké dans la liste / VAO / VBO, puis chaque instance est dessinée avec une transformation différente. À l'aide de maillages statiques, les données peuvent être téléchargées une fois, puis réutilisées. sol.gfxile.net/instancing.html donne un bref aperçu des différentes méthodes.
Exilyth
Merci, l'instanciation est une idée intéressante. Je ne pouvais pas utiliser une extension draw_instanced cependant car j'utilise OpenGL ES 2.0 et je travaille sur quelque chose qui fonctionne sur tout. Je pense peut-être que je peux charger les différents maillages d'arbre dans un VBO (potentiellement avec des modèles plus simples plus loin), z-sort, puis les dessiner par lots à partir d'un tampon d'index que je construirais pour chaque lot. Je pourrais peut-être en dessiner 30 ou 40 à la fois de cette façon.
locka
2

La transparence ne doit être commandée que si elle utilise un mélange non additif. Pour une tonne de panneaux d'affichage éloignés, le mélange est inutile (vous ne pouvez pas vraiment le voir). Rendez au moins les autres avec une transparence de découpe (alpha de seulement 1 ou 0) et vous n'avez pas besoin de les trier.

Vous pouvez utiliser une sorte de feuille de sprite pour rendre différents types d'arbres, avec des animations cuites. Dessinez des maillages pour des arbres plus proches que vous pouvez animer avec plus de fidélité en fonction des vents ou de tout ce que vous voulez.

Sean Middleditch
la source
J'ai essayé d'utiliser la suppression et aucun tri, mais les résultats semblent un peu mous - les arbres ont tendance à se chevaucher beaucoup, donc s'il n'y a pas d'ordre cohérent, j'obtiens beaucoup de pop où un arbre passe devant l'autre et " gagne "le pixel. J'ai laissé le rebut dedans car il y a encore des collisions occasionnelles (par exemple 2 arbres avec la même distance exacte de la caméra) mais c'est un repli. J'ai également expérimenté des panneaux d'affichage et l'effet est trop faux, surtout pour les survols.
locka
Utilisez de meilleurs panneaux d'affichage. Idéalement, ayez un modèle d'arbre. Générez l'image-objet de panneau d'affichage pour un angle de vue et utilisez cette image-objet là où l'angle correspond approximativement. Pour les découpes, elles fonctionnent mieux à distance, où vous ne pouvez pas voir la différence. Au fur et à mesure que vous vous rapprochez, vous devez utiliser plus de modèles cocmpliqués (peut-être quelques quads par arbre), ou vous pouvez passer à la transparence de la porte moustiquaire.
Sean Middleditch
À un moment donné, vous devez trouver l'équilibre acceptable entre qualité et vitesse. Vous n'obtiendrez pas une "rapidité fulgurante" et "parfaite" pour la plupart des scènes complexes sur du matériel de base.
Sean Middleditch