38 votes

Mappage d'attributs de vertex shader dans le GLSL

Je code un petit moteur de rendu avec les shaders GLSL:

Chaque Maille (bien, submesh) a un certain nombre de vertex flux (par exemple. position normale,la texture,la tangente,etc) dans une grande VBO et un MaterialID.

Chaque Matériau a un jeu de textures et propriétés (par exemple. spéculaire-couleur, diffus, de la couleur, la texture, normal map,etc)

Ensuite, j'ai un shader GLSL, avec des uniformes et des attributs. Disons:

uniform vec3 DiffuseColor;
uniform sampler2D NormalMapTexture;
attribute vec3 Position;
attribute vec2 TexCoord;

Je suis un peu coincé en essayant de concevoir une façon pour le shader GLSL pour définir le flux de mappages (sémantique) pour les attributs et les uniformes, et ensuite lier le sommet des flux pour les attributs appropriés.

Quelque chose dans les lignes de dire à la maille :"mettez votre position flux dans l'attribut "Position" et votre tex coordonnées "TexCoord". Aussi mettre votre couleur diffuse du matériau dans "DiffuseColor" et votre matériel de seconde texture en "NormalMapTexture"

Pour le moment je suis en utilisant codée en dur noms pour les attributs (ie. vertex pos est toujours "Position" ,etc) et de vérifier chaque uniforme et le nom de l'attribut à comprendre ce que le shader est de l'utiliser pour.

Je suppose que je suis à la recherche d'un moyen de créer un "vertex déclaration", mais y compris les uniformes et les textures aussi.

Je me demandais comment les gens le faire à grande échelle des moteurs de rendu.

Edit:

Récapitulatif des méthodes proposées:

1. Attribut/Uniforme de la sémantique est donnée par le nom de la variable (ce que je fais maintenant) À l'aide de noms prédéfinis pour chaque attribut.Le GLSL classeur de requête le nom de chaque attribut et lien le vertex array basé sur le nom de la variable:

//global static variable

semantics (name,normalize,offset) = {"Position",false,0} {"Normal",true,1},{"TextureUV,false,2}

 ...when linking
for (int index=0;index<allAttribs;index++)
{
   glGetActiveAttrib(program,index,bufSize,length,size[index],type[index],name);      
   semantics[index]= GetSemanticsFromGlobalHardCodedList(name);
} 
... when binding vertex arrays for render
 for (int index=0;index<allAttribs;index++)
{
    glVertexAttribPointer(index,size[index],type[index],semantics[index]->normalized,bufferStride,semantics[index]->offset);

}  

2. Des emplacements prédéfinis pour chaque sémantique

GLSL classeur de toujours lier les vertex arrays aux mêmes endroits.C'est le shader à utiliser les les noms appropriés pour correspondre. (Cela semble terriblement similaire à la méthode 1, mais à moins que j'ai mal compris, ce qui implique la liaison de TOUS les vertices disponibles données, même si le shader ne le consomme pas)

.. when linking the program...
glBindAttribLocation(prog, 0, "mg_Position");
glBindAttribLocation(prog, 1, "mg_Color");
glBindAttribLocation(prog, 2, "mg_Normal");

3. Dictionnaire des attributs disponibles à partir de Matériau, Moteur globals, moteur de Rendu et de Maille

Mettez à jour la liste des attributs disponibles publiés par la matière active, le Moteur globals, l'actuel moteur de Rendu et de la Scène actuelle Nœud.

par exemple:

 Material has (uniformName,value) =  {"ambientColor", (1.0,1.0,1.0)}, {"diffuseColor",(0.2,0.2,0.2)}
 Mesh has (attributeName,offset) = {"Position",0,},{"Normals",1},{"BumpBlendUV",2}

puis dans le shader:

 uniform vec3 ambientColor,diffuseColo;
 attribute vec3 Position;

Lors de la liaison du sommet de données pour le shader, le GLSL classeur en boucle sur les attribs et de la lier à celle que l'on trouve (ou pas? ) dans le dictionnaire:

 for (int index=0;index<allAttribs;index++)
    {
       glGetActiveAttrib(program,index,bufSize,length,size[index],type[index],name);      
      semantics[index] = Mesh->GetAttributeSemantics(name);
}

et la même chose avec les uniformes, la seule requête de matière active et globals aswell.

16voto

kvark Points 3427

Attributs:

Votre mesh a un certain nombre de flux de données. Pour chaque flux, vous pouvez conserver les informations suivantes: (nom, type, données).

Lors de la liaison, vous pouvez interroger le GLSL programme actif d'attributs et de la forme d'un attribut dictionnaire pour ce programme. Chaque élément est juste (nom, type).

Lorsque vous dessinez un maillage avec GLSL programme, vous allez par le biais de programmes d'attribut et le dictionnaire de lier le correspondant de maillage cours d'eau (ou de signaler une erreur dans le cas d'incohérence).

Uniformes:

Laissez le paramètre du shader dictionnaire de l'ensemble de (nom, type, liaison de données). Généralement, vous pouvez avoir les dictionnaires suivants:

  • Matériau (diffuse,spéculaire,brillance,etc) - prise à partir de la matière
  • Moteur (appareil photo, le modèle, les lumières, les timers, etc) - prise de moteur singleton (global)
  • Render (paramètres personnalisés liés à l'shader créateur: SSAO rayon, la quantité de flou, etc) - fournis exclusivement par le shader créateur de la classe (render)

Après la liaison, le GLSL programme est donné à un ensemble de paramètre dictionnaires afin de remplir son propre dictionnaire avec l'élément suivant le format: (emplacement, le type de liaison de données). Cette population se fait par interrogation de la liste des actifs d'uniformes et de l'appariement (nom, type) paire avec l'une dans les dictionnaires.

Conclusion: Cette méthode permet la mesure de vertex attributs et shader uniformes pour être adoptée, sans codée en dur le nom de la sémantique dans le moteur. Fondamentalement, seulement le chargeur et rendre savoir à propos de sémantique particulière:

  • Chargeur remplit le maillage des flux de données des déclarations et des matériaux de dictionnaires.
  • De rendu utilise un shader qui est au courant des noms, fournit des paramètres supplémentaires et sélectionne la bonne mailles à dessinés avec.

8voto

rotoglup Points 3662

De mon expérience, OpenGL ne définit pas la notion d'attributs ou des uniformes de la sémantique.

Tout ce que vous pouvez faire est de définir votre propre chemin de la cartographie de votre sémantique à OpenGL variables, en utilisant le seul paramètre, vous pouvez le contrôle de ces variables: leur emplacement.

Si vous n'êtes pas contraint par la plate-forme de questions, vous pouvez essayer d'utiliser le "nouveau" GL_ARB_explicit_attrib_location (core en OpenGL 3.3 si je ne me trompe pas) qui permet de shaders à exprimer explicitement dont l'emplacement est prévu pour les attributs. De cette façon, vous pouvez coder en dur (ou de modifier) les données que vous souhaitez lier à l'attribut de localisation, et d'interroger les shaders " lieux après il est compilé. Il semble que cette fonctionnalité n'est pas encore mature, et peut-être sujet à des bugs dans les différents pilotes.

L'inverse est de lier les emplacements de vos attributs à l'aide de glBindAttribLocation. Pour cela, vous devez connaître les noms des attributs que vous souhaitez lier, et les endroits que vous souhaitez leur attribuer.

Pour trouver les noms utilisés dans un shader, vous pouvez:

  • interroger le shader pour les attributs active
  • analyser le code source du shader trouver vous-même

Je vous déconseille d'utiliser le GLSL analyse de façon (même si elle peut répondre à vos besoins si vous êtes assez simple contextes): l'analyseur peut être facilement vaincu par le préprocesseur. En supposant que votre code du shader devient un peu complexe, vous pouvez commencer à utiliser des #comprend, #définit, #ifdef, etc. Robuste d'analyse suppose que vous avez une solide préprocesseur, qui peut devenir assez lourd à mettre en place.

De toute façon, avec votre active les noms d'attributs, vous devez les affecter à des endroits (et/ou sémantique), pour cela, vous êtes seul avec votre cas d'utilisation.

Dans notre moteur, nous sommes heureux de coder en dur les emplacements de noms prédéfinis à des valeurs spécifiques, tels que:

glBindAttribLocation(prog, 0, "mg_Position");
glBindAttribLocation(prog, 1, "mg_Color");
glBindAttribLocation(prog, 2, "mg_Normal");
...

Après, c'est le shader de l'écrivain pour se conformer à la prédéfinis de la sémantique des attributs.

Autant que je sache, c'est la façon la plus commune de faire les choses, OGRE utilise par exemple. Ce n'est pas la science de fusée, mais fonctionne bien dans la pratique.

Si vous voulez ajouter un peu de contrôle, vous pouvez fournir une API pour définir la sémantique sur un shader de base, peut-être même d'avoir cette description dans un fichier supplémentaire, facilement parsable, vivant près le code source du shader.

Je ne suis pas en uniforme, où la situation est presque la même, sauf que les "nouveaux" extensions vous permettent de force GLSL des blocs homogènes à une disposition de la mémoire qui est compatible avec votre application.

Je ne suis pas convaincu par tout cela, moi-même, donc je vais être heureux d'avoir quelques informations contradictoires :)

3voto

shoosh Points 34322

Vous souhaitez mai à envisager réellement de l'analyse du GLSL lui-même.

L'uniforme/déclaration d'attribut syntaxe est assez simple. Vous pouvez venir avec un petit manuel de l'analyseur qui recherche les lignes qui commencent par uniform ou attribute, le type et le nom et les exposer certaines API C++ à l'aide de cordes. Cela vous fera économiser la peine de codage en dur des noms. Si vous ne voulez pas d'obtenir vos mains sales avec manuel d'utilisation de l'analyse d'un couple de "j'aime" d' Esprit ferait l'affaire.
Vous ne voudrez probablement pas entièrement analyser GLSL de sorte que vous aurez besoin pour vous assurer de ne pas faire quelque chose de drôle dans les décélérations de nature à en altérer la signification réelle. Une complication qui vient à l'esprit est la compilation conditionnelle à l'aide de macros dans le GLSL.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X