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.
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?
la source
Réponses:
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.
la source
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.
la source