Je pense à une scène de type minecraft, où par voxel vous voulez dire un monde de blocs qui sont réellement rendus à l'aide de polygones:
Si vous utilisez un shader de géométrie, il sera difficile d'éviter d'avoir exactement trois faces (ou autre) par voxel.
Si vous avez beaucoup de blocs adjacents qui ont la même texture, vous pouvez utiliser le pavage des textures pour avoir beaucoup moins de triangles dans votre bande (dégénérée) dans une approche VBO. Je veux dire, s'il y a une belle grande zone plate 6x6 de voxels d'herbe, vous pouvez dessiner tout le haut en seulement 2 triangles plutôt que 64.
Avec l'approche GS, vous ne pouvez pas non plus effectuer l'abattage trivial de visages occlus par des voxels adjacents, ce qui est très simple avec une approche VBO.
Je n'ai pas essayé l'approche GS, mais je peux dire que l'approche VBO avec la combinaison de répétition de tuiles adjacentes fonctionne très bien. J'ai trouvé que jouer avec les indices des éléments était beaucoup plus lent que de simplement répéter les sommets. Si vous divisez votre monde en beaux petits cubes, vous pouvez généralement utiliser un seul octet par composant par sommet et même emballer les informations de texture et les normales (une face sur un cube aligné sur l'axe n'a que 3 normales possibles), etc. dans un quatrième octet à faire 4 octets par sommet, ce qui est agréable et rapide.
J'ai utilisé des VBO séparés pour chacun des 6 visages - vous n'avez besoin que de dessiner au plus 3 d'entre eux évidemment. Cela correspond bien aux différentes textures habituellement utilisées sur les parties supérieures des voxels de style minecraft. Parce que pour chaque ensemble, la normale et telle est alors uniforme.
Avec l'utilisation de pixmaps en mosaïque verticale dans un atlas avec GL_REPEAT
sur l'axe horizontal et ayant des versions tournées à 90 degrés des pixmaps dans le même atlas, j'ai trouvé que je peux dessiner des quantités massives de blocs apparemment différents en utilisant le même VBO dans le même appel. Dans l'exemple de l'herbe 6x6, j'aurais divisé cela en 12 triangles car je n'ai répété qu'une seule dimension dans mon atlas.
J'ai surtout fait fonctionner cela sur le très bas de gamme des puces graphiques intégrées et du mobile, où GS est juste quelque chose avec lequel je peux rêver un jour de jouer.
Qu'en est-il de la troisième option, en utilisant des tableaux instanciés? Fondamentalement, vous dessinez de nombreuses boîtes (faites d'un simple cube à 8 sommets) avec un seul appel de tirage, en recherchant les positions (et d'autres données) en tant qu'attributs par instance à partir du VBO voxel-data (en utilisant
glVertexAttribDivisor
OpenGL, je suis sûr DX a ça aussi). Cela pourrait être plus rapide que l'approche des shaders de géométrie bien que le code d'application (non-shader) devrait être assez similaire, car je me souviens des shaders de géométrie ayant la réputation d'être lent, bien que je n'ai aucune expérience avec eux (ou instanciation) car je suis toujours assis sur le matériel 2.1.Mais de toute façon, les shaders de géométrie ou les tableaux instanciés devraient être plus adaptés que la géométrie de voxel construite par CPU, en particulier lorsque les données de voxel sont sujettes à changement. En conjonction avec la rétroaction de transformation (sortie de flux en DX?), Vous pourrez peut-être configurer une bonne technique de suppression basée sur GPU.
la source
La version Geometry Shader me semble beaucoup mieux. Vous ne pouvez avoir qu'un point vbo et une boîte de construction à la volée (point d'entrée, flux triangulaire de sortie). Ce sera rapide (encore plus rapide si vous utilisez l'unité de pavage dans le shader modèle 5 éq. DX11) et réduira considérablement la bande passante, ce sera une solution agréable et propre.
À propos de GS. Il est placé entre le vertex shader et le pixel shader et modifie le flux de vertex (primitives) en sortie. Alors que le vertex shader fonctionne uniquement sur les sommets, le geometry shader fonctionne sur des primitives entières. La sortie de ce flux va uniquement au pixel shader (et est tramée avant cela bien sûr :)) et il n'y a aucun moyen de l'enregistrer. (Peut-être par un rendu fou à la texture, puis une analyse syntaxique ... mais pas de possibilité vraiment simple)
Note sur les performances: vous devriez pouvoir tout faire dans le shader de géométrie et sauter (juste passer des données) vertex shader. Mais ce n'est pas le meilleur moyen. Mieux (plus rapidement) consiste à effectuer la plupart des transformations possibles sur le vertex shader et à essayer de minimiser le programme de géométrie shader. N'ayez pas peur d'utiliser pour le cycle si vous en aurez besoin (pour la création de box par exemple). Le compilateur le déroulera pour vous.
la source