Bonsoir,
Alors que j'étais entrain de contempler une petite scène de test pour mon viewer 3D:
http://yno.goldzoneweb.info/m3d-view...ta/bscene2.jpg
Il me vint à l'esprit une idée rigolote: si j'essayai de faire marcher mon programme en display list ?
La fonctionnalité était déjà prévue, il m'a juste suffit d'appeler mon programme avec le flag prévue à cet effet pour obtenir un rendu par display list.
Et là, Ô étonnement, les FPS ont quadruplé![]()
La scène comporte:
4851 sphères;
482 vertices par sphère;
320 faces par sphère.
Soit un total de 2338182 vertices et 1552320 faces.
En mode VBO j'obtiens:
19/20fps en 1280*1024 AA4x
En display list:
50fps si je prend un point de vue éloigné, et les fps augmente considérablement moins il y a de sphères à l'écran, je tourne aux environ de 90/100, voir même 150 dans certains cas.
Je trouve ça assé hallucinant![]()
Voici le code que j'utilise pour "construire" mon objet 3D:
La partie la plus interessante se trouve en haut, c'est là que je construit mon VBO, en bas, c'est une simple empilation de glVertex* dans une display list.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 int M3D_MakeObj(M3D_Obj* obj, const int vbo_supported) { unsigned int j=0; if(obj) { if(obj->material->texfile != NULL) { obj->material->tex = loadPNG(obj->material->texfile); if(obj->material->tex == 0) { printf("__\nerror: cannot load texture %s!\n", obj->material->texfile); return (-1); } } if(vbo_supported) { obj->list = 0; glGenBuffers(1, &obj->vbo); glBindBuffer(GL_ARRAY_BUFFER, obj->vbo); glBufferData(GL_ARRAY_BUFFER, (obj->vsize*sizeof(float))+(obj->nsize*sizeof(float))+(obj->tsize*sizeof(float)), 0, GL_STREAM_DRAW); glBufferSubData(GL_ARRAY_BUFFER, 0, obj->vsize*sizeof(float), obj->vertices); glBufferSubData(GL_ARRAY_BUFFER, obj->vsize*sizeof(float), obj->nsize*sizeof(float), obj->normals); if(obj->tsize > 0) glBufferSubData(GL_ARRAY_BUFFER, obj->vsize*sizeof(float)+obj->nsize*sizeof(float), obj->tsize*sizeof(float), obj->texcoords); glBindBuffer(GL_ARRAY_BUFFER,0); } else /* simple display list... */ { obj->vbo = 0; obj->list = glGenLists(1); glNewList(obj->list, GL_COMPILE); glMaterialfv(GL_FRONT, GL_AMBIENT, obj->material->ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, obj->material->diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, obj->material->specular); glMaterialf(GL_FRONT, GL_SHININESS, obj->material->shininess); if(obj->material->tex != 0) glBindTexture(GL_TEXTURE_2D, obj->material->tex); if(obj->lines_count > 0) { glBegin(GL_LINES); for(j=0; j<obj->lines_count; j++) { if(obj->tsize > 0) glTexCoord2fv(&obj->texcoords[obj->lines_index[j]*2]); glNormal3fv(&obj->normals[obj->lines_index[j]*3]); glVertex3fv(&obj->vertices[obj->lines_index[j]*3]); } glEnd(); } if(obj->triangles_count > 0) { glBegin(GL_TRIANGLES); for(j=0; j<obj->triangles_count; j++) { if(obj->tsize > 0) glTexCoord2fv(&obj->texcoords[obj->triangles_index[j]*2]); glNormal3fv(&obj->normals[obj->triangles_index[j]*3]); glVertex3fv(&obj->vertices[obj->triangles_index[j]*3]); } glEnd(); } if(obj->quads_count > 0) { glBegin(GL_QUADS); for(j=0; j<obj->quads_count; j++) { if(obj->tsize > 0) glTexCoord2fv(&obj->texcoords[obj->quads_index[j]*2]); glNormal3fv(&obj->normals[obj->quads_index[j]*3]); glVertex3fv(&obj->vertices[obj->quads_index[j]*3]); } glEnd(); } glEndList(); } } else { printf("__\nerror: M3D_MakeObj: obj argument is null!\n"); return (-1); } return (0); }
Voici le code utilisé pour le rendu :
La structure M3D_Obj contient les sommets et les indices, chargés à partir d'un fichier .obj... enfin c'est plus compliqué que ça, mais cette structure contient les données de l'objet quoi.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 void Render(M3D_Obj *obj) { if(obj->vbo != 0) { glBindBuffer(GL_ARRAY_BUFFER, obj->vbo); glVertexPointer(3, GL_FLOAT, 0, 0); glNormalPointer(GL_FLOAT, 0, BUFFER_OFFSET(obj->vsize*sizeof(float))); if(obj->tsize > 0) glTexCoordPointer(2, GL_FLOAT, 0, BUFFER_OFFSET((obj->vsize*sizeof(float)) + (obj->nsize*sizeof(float)))); glMaterialfv(GL_FRONT, GL_AMBIENT, obj->material->ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, obj->material->diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, obj->material->specular); glMaterialf(GL_FRONT, GL_SHININESS, obj->material->shininess); if(obj->material->tex != 0) { glEnableClientState(GL_TEXTURE_COORD_ARRAY); glBindTexture(GL_TEXTURE_2D, obj->material->tex); } glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); if(obj->lines_count > 0) glDrawElements(GL_LINES, obj->lines_count, GL_UNSIGNED_INT, obj->lines_index); if(obj->triangles_count > 0) glDrawElements(GL_TRIANGLES, obj->triangles_count, GL_UNSIGNED_INT, obj->triangles_index); if(obj->quads_count > 0) glDrawElements(GL_QUADS, obj->quads_count, GL_UNSIGNED_INT, obj->quads_index); glBindBuffer(GL_ARRAY_BUFFER, 0); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); } else if(obj->list != 0) glCallList(obj->list); else /* on va pas s'emmerder avec le gestionnaire d'erreur */ printf("__\nerror: no vbo or display list are detected!\n"); }
Je précise aussi que le pointeur sur cette structure n'est autre qu'un tableau de taille... 4851(nombre de sphères)
glBindBuffer() ralentirait-il le schmilblick ? (un peu comme glBindTexture)
Ma config (dès fois que ça puisse s'avérer utile, pour juger les performances que j'obtiens par exemple):
AMD Sempron 2200+ OC @ 1.8GHz
CM: Asus A7N8X-E Deluxe
CG: POV 6600GT 128mo OC @ 580MHz
OS: Linux Ubuntu EdgyEft
Mes questions:
- Les résultats que j'obtiens sont-ils "normaux" ?
- Est-ce que je fais une bonne utilisation des VBOs ? Ou mauvaise, d'où de faibles performances ?
- Si j'en fais une mauvaise, pourriez-vous m'orienter et/ou me donner un tutoriel ?
J'ai un peu regardé les sources de NeHe sur les VBOs, c'est quasiment comme moi, en tout cas je n'arrive pas à déceler de différence majeur
J'ai lu une petite partie de ce tutoriel pour apprendre à me servir des VBOs:
http://www.g-truc.net/article/vbo-fr.pdf
J'ai vu que par la suite il utilisait des fonctions comme glMapBuffer, je ne me suis pas encore penché dessus, peut-être est-ce la solution ?
Merci de m'éclaircir à ce sujet
Bonne fin de soirée, et passez de joyeuses fêtes.
Partager