Le moyen le plus efficace pour dessiner un grand nombre des mêmes objets, mais avec des transformations différentes

8

J'aimerais dessiner un grand nombre (plusieurs milliers) de maillages simples (chacun peut-être ... un maximum de 50 triangles, mais même cela est une très haute limite supérieure), qui sont tous exactement les mêmes.

En tant que moyen de force brute simple, en ce moment, je ne fais que des milliers d'appels de dessin, où je change simplement les matrices de transformation dont les shaders ont besoin, puis dessine à nouveau les mêmes objets.

Bien sûr, cela est horriblement lent, car (je suppose) il y a trop d'appels de tirage pour que le pilote et mon PC soient traités efficacement.

Que puis-je faire pour l'accélérer?

TravisG
la source
4
Je ne peux pas vous donner une réponse complète, mais la réponse de haut niveau consiste à utiliser l' instanciation de la géométrie .
Seth Battin
Recherche google pour "Instanciation de la géométrie", peut-être que vous pouvez trouver quelque chose qui vous aide de cette façon
Luis W

Réponses:

11

La solution à cela est l'instanciation. Ce tutoriel explique quelques méthodes d'instanciation. Si vous en avez ARB_draw_instancedet ARB_instanced_arraysutilisez-les.

L'idée générale est de stocker toutes les transformations de vos maillages dans un objet tampon séparé et de le lier à un tableau d'attributs qui utilise un "sommet" par instance via glVertexAttribDivisor.

Si, après cela, vous ne courez toujours pas aussi vite que vous le souhaitez, vous êtes probablement lié au processeur de vertex. Faites un tri sélectif sur les mailles, et construisez de préférence un BVH pour traverser au lieu de faire le tri sur toutes les mailles indépendamment.

Robert Rouhani
la source
1
+1; avec plusieurs milliers d'objets, vous pouvez également devenir lié au processeur lors des transformations (envoyer simplement la position et la rotation dans votre tampon par instance et calculer la matrice par objet sur le GPU peut aider ici), et n'oubliez pas de regarder comment vous mettez à jour ce tampon de vertex dynamique!
Maximus Minimus
@Robert Rouhani: Merci, je l'ai recherché et rapidement mis en œuvre. Maintenant, je peux dessiner 5000 mailles avec 20 tris chacune à 250 FPS. Soit dit en passant, votre méthode suggérée semble un peu dépassée. Étant donné que l'instanciation de la géométrie d'OpenGL 3. fait partie officielle de la spécification de base d'OpenGL, plus besoin d'ARB_xxx. J'utilise un tampon uniforme pour stocker les matrices et j'utilise glDrawElementsInstanced. A l'intérieur du vertex shader, il y a une disposition (std140) de matrices uniformes {mat4 array [5000]; } où je peux accéder à l'élément pertinent via le tableau [gl_InstanceID]
TravisG
1
@TravisG J'ai tendance à essayer de prendre en charge les anciennes versions. Je comprends que ces deux extensions ont été promues au noyau pendant un certain temps, la chaîne d'extension sera toujours présente, cependant :). En outre, l'utilisation glVertexAttribDivisor(qui n'est en aucun cas obsolète ou obsolète) a l'avantage de ne pas avoir de limite supérieure sur le nombre d'instances. Les performances ont été historiquement meilleures que les tampons uniformes, mais elles sont probablement identiques ou très similaires maintenant, et les deux manières font le travail.
Robert Rouhani
@Robert Rouhani: Mhm ... Je suppose que c'est vrai. Quelqu'un avec des pilotes obsolètes pourrait prendre en charge ARB_xxx mais pas les fonctionnalités principales officielles d'OpenGl 3.x. Je vais jeter un œil à glVertexAttribDivisor, merci.
TravisG
@Robert Rouhani: J'ai implémenté les deux versions (en utilisant des tampons uniformes et alternativement votre version suggérée où j'utilise un attribut vertex qui ne change qu'une fois par instance), et la version du tampon uniforme est en fait environ deux fois plus rapide (4000 fps en mode release, vs ~ 2000 avec glVertexAttribDivisor, le nombre de 250 fps était uniquement pour le côté CPU).
TravisG