opengl : performance des programmes de vertex

opengl : performance des programmes de vertex - C++ - Programmation

Marsh Posté le 26-04-2004 à 13:19:24    

Bonjour !
J'utilise des tableaux de vertex pour rendre une scène assez légère en terme de nombre de polygones mais assez lourde pour ce qui est du traitement qui leur est appliqué (bumpmapping diffus et spéculaire)
Je cherche régulièrement à optimiser les performances de ce moteur en vue d'une conséquente augmentation du nombre de polygones.
Pour cela je suis en train d'étudier l'extension incontournable ARB_vertex_program.
 
J'ai donc écrit quelques petits programmes de vertex très simples qui pour l'instant ne s'occupent que des transformations géométriques des vertex (plus tard ils effectueront aussi tous les calculs préalables au bumpmapping)
 
ils sont du genre:
 
const unsigned char ARBVertexProgTexture3[] =  
"!!ARBvp1.0\
ATTRIB iPos         = vertex.position;\
ATTRIB iColor  = vertex.color;\
ATTRIB iTexCoord0 = vertex.texcoord[0];\
ATTRIB iTexCoord1 = vertex.texcoord[1];\
ATTRIB iTexCoord2 = vertex.texcoord[2];\
PARAM  mvp[4]       = { state.matrix.mvp };\
OUTPUT oPos         = result.position;\
OUTPUT oColor       = result.color;\
OUTPUT oTexCoord0 = result.texcoord[0];\
OUTPUT oTexCoord1 = result.texcoord[1];\
OUTPUT oTexCoord2 = result.texcoord[2];\
# matrice modelview\n\
DP4 oPos.x, mvp[0], iPos;\
DP4 oPos.y, mvp[1], iPos;\
DP4 oPos.z, mvp[2], iPos;\
DP4 oPos.w, mvp[3], iPos;\
MOV oColor, iColor;\
MOV oTexCoord0, iTexCoord0;\
MOV oTexCoord1, iTexCoord1;\
MOV oTexCoord2, iTexCoord2;\
END";
 
Très simples donc, mais sensés quand même décharger le cpu du calcul géométrique du vertex.
 
Ma scène étant assez légère en polygones, je ne m'attendais pas à une grande augmentation des performances CPU, mais là, j'avoue avoir été surpris en constatant que c'était même l'effet inverse qui se produisait.
 
Ce que j'appelle "performances CPU", ce sont les performances maximales atteintes par le moteur lorsqu'il n'est pas bridé par la carte graphique, donc en gros lorsqu'il s'exécute dans une fenêtre de 40x30.
 
Pour information, sans ces petits programmes de vertex mon moteur tourne à 550 fps, et avec à seulement 480 fps.
 
J'étudie constamment les spécifications de l'extension ARB mais elles sont tellement vastes que je peine à trouver une explication pour cette baisse de performances.
 
Je me demande si l'explication tient dans les initialisations des unités de texture que j'effectue avant d'appeler un glDrawArray().
Je me demande si ces initialisations ne seraient pas redondantes avec les programmes de vertex qui les contiendraient de manière implicite (ex: activation des trois unités de texture redondante avec le fait de demander des pointeurs vers les coordonnées de texture de ces trois unités dans les vertexprogram)
 
Merci pour toute réponse !
 
john_john

Reply

Marsh Posté le 26-04-2004 à 13:19:24   

Reply

Marsh Posté le 26-04-2004 à 21:10:56    

Je m'auto-réponds parceque je viens de faire cette après-midi une découverte assez révolutionnaire pour moi, et que j'aimerais partager avec un maximum de gens pour éviter de futures malentendus à propos de opengl et du T&L.
 
Elle est en deux partie, attention ça fait mal:
  1)L'extension ARB_vertex_program N'EST PAS ce que l'on appelle le T&L.
  2)OPENGL SUPPORTE NATIVEMENT LE T&L, c'est à dire que lorsqu'un programme opengl détecte une carte supportant le T&L, il active en temps réelle cette fonctionnalité. Sans que le programmeur ait besoin de faire quelque manipulation que ce soit.
 
Voilà, peut-être était-ce une évidence pour certains de vous, moi je sais que cette découverte clos de longues semaines d'interrogation au sujet des liens entre le T&L et de l'extension ARB_vertex_program que je voulais utiliser(et que je croyais nécessaire). (je pense aussi, après avoir lu de nombreux forums, que je n'étais pas le seul à faire fausse route sur ce sujet)
 
En réalité, cette extension est une sorte de T&L deuxième génération qui introduit la programmabilité du GPU, sans toutefois atteindre le niveau de celle des vertex shaders.
 
Du coup, mon problème trouve une réponse évidente:
Les tous petits programmes de vertex que j'ai écris ne servent littéralement à rien étant donné qu'il ne font que calculer la transformation du vertex, et qu'ainsi ils entrent en conflit avec le T&L dont c'est la principal occupation. D'où la perte de performances (Le T&L est spécialisé donc imbattable).
Lorsque mes programmes de vertex seront plus complexes et effectueront les calculs préalables au bumpmapping par exemple, alors je devrai avoir un gain conséquent de perfomances (ce ne sera plus "vertex program contre T&L" mais "vertex program contre CPU+T&L" )
 
Maintenant que je suis en train de complexifier mes programmes de vertex, je demande si l'un d'entre vous saurait me guider dans leur conception (j'ai quelques idées et des questions) ou si il est préférable que je m'oriente vers par exemple le forum d'opengl.org.
 
Merci pour votre attention !
 
john_john

Reply

Marsh Posté le 26-04-2004 à 21:26:34    

Euh si justement, l'extention ARB_vertex_program c'est ce que DirectX appelle les vertex shader et c'est aussi puissant que ceux-ci ( ou tout du moins de ceux qu'on trouve dans DirectX 8 )

Reply

Marsh Posté le 26-04-2004 à 21:33:06    

ouaip, exact, je voulais parler des vertex shader de dx9

Reply

Marsh Posté le 26-04-2004 à 21:48:22    

C'est justement à ça que sert OpenGL 1.5 :)

Reply

Marsh Posté le 27-04-2004 à 01:47:04    

Bon, je me lance.
J'aurais une question concernant un programme de vertex effectuant le calcul du bumpmapping diffus.
La technique classique que j'utilisais jusqu'alors (en c++ donc) reposait sur les coordonnees S et T  qui permettent de définir un repère local à chaque vertex. Le vecteur L projeté sur ce repère était normalisé par un cube map puis dot3-multiplié sur une normal map. Bon, que du classique donc.
Ca marchait sans problème sur l'implémentation classique ... beaucoup moins bien avec mon programme de vertex.
 
voilà en pseudo code la sequence c++ utilisée en combinaison avec le programme de vertex pour afficher un objet A (en mouvement constant) (1ere passe: calcul diffus):
 
- Calculer la position de la lumiere dans le repere de l'objet A
- Etablir cette position relative comme nouvelle position pour opengl
- Indiquer le tableau des normales
- Indiquer le tableau des coordonnees de texture pour le cube map
- Indiquer le tableau des coordonnees de texture pour la normal map
- Indiquer les tableaux des coordonnees S et T comme parametres generiques 11 et 12 du vertex program
- Tout afficher
 
Et maintenant le code commenté de mon programme de vertex pour le calcul diffus:
 
"!!ARBvp1.0
ATTRIB iPos         = vertex.position;
ATTRIB iColor     = vertex.color;
ATTRIB iNormal      = vertex.normal;
ATTRIB iTexCoord0   = vertex.texcoord[0]; #pour le cube map
ATTRIB iTexCoord1   = vertex.texcoord[1]; #pour la normal map
ATTRIB coordS       = vertex.attrib[11];  #element du tableau des S
ATTRIB coordT       = vertex.attrib[12];  #element du tableau des T
PARAM  lightPos     = state.light[0].position; #position selon l'objet A
PARAM  mvp[4]       = { state.matrix.mvp };
TEMP   vertexToLight; #vecteur L
OUTPUT oPos         = result.position;
OUTPUT oColor       = result.color;
OUTPUT oTexCoord0   = result.texcoord[0]; #c'est l'element a calculer
OUTPUT oTexCoord1   = result.texcoord[1]; #lui ne change pas
 
# transformation geometrique du vertex\n
DP4     oPos.x, mvp[0], iPos;
DP4     oPos.y, mvp[1], iPos;
DP4     oPos.z, mvp[2], iPos;
DP4     oPos.w, mvp[3], iPos;
 
# calcul du vecteur L puis normalisation\n
SUB vertexToLight, lightPos, iPos;
DP3  vertexToLight.w, vertexToLight, vertexToLight;
RSQ  vertexToLight.w, vertexToLight.w;
MUL  vertexToLight.xyz, vertexToLight.w, vertexToLight;
 
# calcul des coordonnees de textures du cubeMap\n
# projection de L selon S, T et la normale
DP3 oTexCoord0.x, coordS, vertexToLight;
DP3 oTexCoord0.y, coordT, vertexToLight;
DP3 oTexCoord0.z, iNormal, vertexToLight;
 
# le reste est transmis tel quel
MOV  oColor, iColor;
MOV oTexCoord1, iTexCoord1;
END"
 
Alors voilà, ça marche ... mais pas comme il faudrait, l'objet s'affiche, on voit bien son bumpmap, mais celui réagit à la position de l'observateur et c'est là où je ne comprends plus ! qu'est ce qui, dans mon programme, dépend de la position de l'observateur ?
Selon moi juste le calcul géométrique du vertex, en aucun cas le calcul de L ou sa projection. Pourtant il suffit que je tourne la tête, pour que la surface se modifie, preuve qu'un changement opère dans les paramètres du programme.
 
Y-aurait-il une subtilité qui m'aurait échappé dans l'accés aux paramètres associés aux vertex ? Y-aurait-il une transformation implicite de certains d'entre eux ? Basiquement, ce calcul équivaut à celui que je faisais sur le CPU lorsque je n'utilisais pas de programmes de vertex. Il n'était pas nécessaire de transformer les normales car tout se passait dans le repere de l'objet, seule la source lumineuse était transformée.
 
Note: dans mes tests actuels, je n'ai pas encore implémenté le calcul spéculaire, donc se n'est pas lui qui aurait pu venir polluer mon rendu.
 
Note2: Je n'encombrerai pas le forum à chaque programme que j'écrirai, j'essaie seulement de comprendre les bases. Si j'arrive à écrire un programme qui marche, les autres devraient être beaucoup plus rapides à réaliser.
 
 
Je prends toutes les idées sinon !
 
Mille merci pour votre attention.
 
john_john

Reply

Marsh Posté le 28-04-2004 à 16:29:48    

Argl, je viens de trouver la réponse, alors je m'auto-réponds encore une fois. En fait gros béta que je suis, j'avais oublié que le placement d'une source de lumière par glLight était transformé par la matrice en cours, donc c'était la position transformée qui était transmise à mon programme, d'où les réactions aux mouvements de la caméra.
Bon, voilà, je me suis répondu alors je me remercie.
Merci, merci vraiment.
Oh ce ne n'est rien.
Si si j'insiste, merci.
Bon.
 
john_john

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed