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:

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);
}
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.

Voici le code utilisé pour le rendu :

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");
}
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.
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.