web-dev-qa-db-fra.com

Liaison d'emplacement d'attribut explicite vs automatique pour les shaders OpenGL

Lorsque vous configurez des emplacements d'attribut pour un programme de shader OpenGL, vous êtes confronté à deux options:

glBindAttribLocation () avant la liaison pour définir explicitement un emplacement d'attribut.

ou

glGetAttribLocation () après la liaison pour obtenir un emplacement d'attribut attribué automatiquement.

Quel est l'utilité pour utiliser l'un sur l'autre?

Et lequel, le cas échéant, est préféré dans la pratique?

74
Jing

Je connais une bonne raison de préférer la définition d'emplacement explicite .

Considérez que vous conservez vos données de géométrie dans Vertex Array Objects. Pour un objet donné, vous créez un VAO de telle manière que les indices correspondent, par exemple:

  • index 0 : positions,
  • index 1 : normales,
  • index 2 : texcoords

Considérez maintenant que vous voulez dessiner un objet avec deux shaders différents . Un shader nécessite la position et des données normales en entrée, l'autre - les positions et les cordons de texture .

Si vous compilez ces shaders, vous remarquerez que le premier shader attendra les positions à l'indice d'attribut 0 et les normales à 1. L'autre s'attendrait à des positions à 0 mais des coordonnées de texture à 1.

Citation https://www.opengl.org/wiki/Vertex_Shader :

Affectation automatique

Si aucune des deux méthodes précédentes n'affecte une entrée à un index d'attribut, alors l'index est automatiquement attribué par OpenGL lorsque le programme est lié. L'index attribué est complètement arbitraire et peut être différent pour les différents programmes liés, même s'ils utilisent exactement le même code de vertex shader.

Cela signifie que vous ne pourriez pas utiliser votre VAO avec les deux shaders. Au lieu d'avoir un VAO par, disons, objet, vous auriez besoin - dans le pire des cas - un VAO distinct par objet et par shader .

Forcer les shaders à utiliser votre propre convention de numérotation d'attributs via glBindAttribLocation peut résoudre ce problème facilement - tout ce que vous devez faire est de maintenir une relation cohérente entre les attributs et leurs ID établis, et forcer les shaders à utiliser cette convention lorsque mise en relation.

(Ce n'est pas vraiment un gros problème si vous n'utilisez pas de VAO séparés, mais cela pourrait quand même rendre votre code plus clair.)


BTW:

Lors de la configuration des emplacements d'attribut pour un programme de shader OpenGL, vous êtes confronté à deux options

Il existe une troisième option dans OpenGL/GLSL 3.3: Spécifiez l'emplacement directement dans le code shader . Cela ressemble à ceci:

layout(location=0) in vec4 position;

Mais cela n'est pas présent dans le langage de shader GLSL ES.

87
Kos

Une autre réponse ici est que glGetAttribLocation renvoie des données à l'appelant, ce qui signifie qu'il nécessite implicitement un vidage du pipeline. Si vous l'appelez juste après avoir compilé votre programme, vous forcez essentiellement la compilation asynchrone à se produire de manière synchrone.

18
Litherum

La troisième option, c'est-à-dire layout(location=0) in vec4 position; dans le code du shader, est désormais disponible dans OpenGL ES 3.0/GLSL 300 es. Seulement pour les variables d'entrée de vertex shader.

8
lane