Attributs de sommet OpenGL - Normalisation

8

Hélas, j'ai cherché et je n'ai trouvé aucune réponse définitive.

Quand souhaitez-vous normaliser les données de sommet dans OpenGL en utilisant la commande suivante:

glVertexAttribPointer(index, size, type, normalize, stride, pointer);

C'est-à-dire quand le ferait normalize == GL_TRUE; quelles situations, et pourquoi choisiriez-vous de laisser le GPU faire les calculs au lieu de le prétraiter? Tous les exemples que j'ai jamais vus, ont cet ensemble à GL_FALSE; et je ne peux pas personnellement voir une utilisation pour cela. Mais Khronos n'est pas stupide, donc il doit être là pour quelque chose d'utile (et probablement commun).

caviar décéléré
la source

Réponses:

9

Le paramètre "normalisé" affecte l'utilisation de valeurs à virgule fixe.

Ce document indique que le paramètre "spécifie si les valeurs de données à virgule fixe doivent être normalisées (GL_TRUE) ou converties directement en valeurs à virgule fixe (GL_FALSE) lors de leur accès."

De plus, celui-ci indique "Pour glVertexAttribPointer, si normalisé est défini sur GL_TRUE, il indique que les valeurs stockées dans un format entier doivent être mappées sur la plage [-1,1] (pour les valeurs signées) ou [0,1] ( pour les valeurs non signées) lorsqu'elles sont accédées et converties en virgule flottante. Sinon, les valeurs seront converties en flottants directement sans normalisation. "

En résumé, si vous n'utilisez pas de valeurs à virgule fixe, vous n'avez pas besoin de vous en soucier. Si vous le faites, cet indicateur contrôle si (par exemple) la valeur d'octet 128 doit être 0,5 ou 128,0.

Jari Komppa
la source
3
Cela ne répond pas vraiment à la question, j'ai déjà compris ce que ça fait, mais je voulais savoir quand cela serait effectivement applicable à une implémentation «commune».
deceleratedcaviar
2
Je suis presque sûr que c'était pertinent lorsque de nombreuses applications mobiles utilisaient principalement des mathématiques à virgule fixe et ne voulaient pas toucher aux mathématiques à virgule flottante. Une autre possibilité est que vous souhaitiez parfois stocker des données de manière plus compacte, par exemple, en octets, si la précision est suffisante, et laisser OpenGL convertir les octets dans une plage de 0..1.
Jari Komppa
C'est toujours d'actualité. Pensez aux cordons UV par exemple. Vous ne voudrez peut-être pas gaspiller de l'espace et le stocker en tant que float2, vous le stockez donc en tant que 2 uint8 à la place comme optimisation et définissez l'indicateur de normalisation afin d'obtenir la plage [0, 1] au lieu de [0, 256] dans le programme.
nul
128 va-t-il devenir 0,5 ou 128/255 = légèrement supérieur?
riv
11

C'est une vieille question, mais la réponse actuelle n'explique pas vraiment à quoi vous les utiliseriez.

Il s'agit de gagner de l'espace. Et avec les attributs de sommet, moins d'espace peut signifier des performances plus élevées (si vous êtes lié au transfert de sommet).

Les couleurs n'ont généralement pas besoin de plus de 8 bits par composant. Parfois, vous avez besoin de 16 bits, si c'est une valeur lumineuse HDR ou quelque chose. Mais pour les caractéristiques de surface (ce qui est le cas de la plupart des attributs de sommet), 8 bits conviennent. Les octets normalisés non signés sont donc un bon format de sommet.

Les coordonnées de texture n'ont pas besoin de 32 bits de précision en virgule flottante. Une valeur de 16 bits de [0, 1] est suffisante. Les shorts non signés normalisés sont donc un format de sommet raisonnable.

Les normales n'ont jamais besoin d'une précision de 32 bits. Ce sont des directions. Les octets normalisés signés 8 bits ont tendance à être un peu petits, mais les valeurs normalisées 10 bits sont suffisantes la plupart du temps. OpenGL (3.3+) vous permet même d'utiliser des normales 10 bits via un format compressé 10/10/10/2 bits, stocké dans un seul entier non signé 32 bits.

Vous pouvez même jouer à des jeux avec des positions de vertex, si vous vous trouvez dans le besoin urgent de plus de mémoire.

Sans normalisation, vous devrez gaspiller de précieux cycles dans votre shader en divisant les attributs en octets par 255,0. Pourquoi faire cela, alors que le matériel peut le faire gratuitement?

Nicol Bolas
la source
Une belle réponse. Mais le surcoût de la division mathématique en virgule flottante est-il comparable à une diminution de la taille normale de 50%? (C'est-à-dire 32 bits pour dire 16 bits); sur du matériel MODERNE. D'autant plus que nous n'avons pas vraiment à nous soucier de trop de mémoire (du moins dans mon cas de toute façon).
deceleratedcaviar
1
@Daniel: Eh bien, réfléchissons-y. Sur le "matériel MODERNE", le surcoût lié au passage de valeurs normalisées est ... zéro. La surcharge de la division dans le shader est ... non nulle. Peu importe à quel point il est petit, il est toujours plus grand que zéro. Sans parler des économies de bande passante de l'envoi d'un bloc de 32 octets de données de vertex plutôt que d'un bloc de 64 octets. Oh, et le shader n'a pas besoin d'être spécialement programmé; vous pouvez utiliser le même shader pour prendre des valeurs normalisées ou flottantes. Si vous mettez la division dans le shader, vous avez maintenant besoin de nouveaux shaders pour différentes tailles de données de vertex.
Nicol Bolas
Merci pour la gentille réponse. Je vais certainement le garder à l'esprit, ce n'est pas nécessaire pour le moment car j'envoie des données de vertex alignées, mais au fur et à mesure que j'ajoute des informations, ce n'est peut-être pas la même chose, et cela pourrait être un grand avantage, à la fois dans la mise en cache et le débit.
deceleratedcaviar
Des stratégies sur la façon de convertir le normal (stocké actuellement dans une séquence de (3x) flottants 32 bits) en un entier 32 bits (10/10/10/2)?
deceleratedcaviar
@Daniel: Si vous demandez comment utiliser l' extension ARB_vertex_type_2_10_10_10_rev , je vous suggère de lire la spécification d'extension que je viens de lier. Si vous demandez comment faire personnellement la manipulation de bits, je suggère une structure de style C qui contient des champs de bits .
Nicol Bolas
0

Imaginez que vous ayez un maillage avec des normales de haute précision et un autre maillage avec des basses. Avec la normalisation d'attribut, vous pouvez utiliser le même shader mais empaqueter les normales du deuxième maillage en octets.

Stepan Zastupov
la source