77 votes

Meilleures pratiques OpenGL VAO

Im confronté à un problème qui, je crois, VAO-personne à charge, mais Im pas sûr..

Je ne suis pas sûr au sujet de l'utilisation correcte d'un VAO, ce que j'ai l'habitude de faire pendant GL initialisation d'un simple

glGenVertexArrays(1,&vao)

suivi par un

glBindVertexArray(vao)

et plus tard, dans mon dessin pipeline, je viens d'appeler glBindBuffer(), glVertexAttribPointer(), glEnableVertexAttribArray() et ainsi de suite.. sans se soucier de la initally lié VAO

est-ce une bonne pratique?

89voto

Robert Rouhani Points 8317

VAOs agir de même à des Organisations sises à vienne et de textures à l'égard de la façon dont ils sont liés. Avoir un seul VAO lié pour toute la durée de votre programme de ne donneront aucun des avantages de performance, parce que vous pourriez tout aussi bien être rendu sans VAOs à tous. En fait c'est peut être inférieure en fonction de la façon dont la mise en œuvre intercepte vertex paramètres d'attributs qu'ils sont tirés.

Le point de VAO à l'exécution de toutes les méthodes nécessaires pour dessiner un objet une fois lors de l'initialisation et de couper tous les extra appel de méthode dans le ciel durant la boucle principale. Le point est d'avoir plusieurs VAOs et basculer entre eux lors de l'élaboration.

En termes de bonnes pratiques, voici comment vous devez organiser votre code:

initialization:
    for each batch
        generate, store, and bind a VAO
        bind all the buffers needed for a draw call
        unbind the VAO

main loop/whenever you render:
    for each batch
        bind VAO
        glDrawArrays(...); or glDrawElements(...); etc.
    unbind VAO

Cela permet d'éviter le gâchis de liaison/déliaison des tampons et le passage de tous les paramètres pour chaque sommet de l'attribut et le remplace par un seul appel de méthode, la liaison d'un VAO.

24voto

Non, ce n'est pas la façon dont vous utilisez VAO. Vous devez utiliser VAO de la même manière comment vous utilisez VBO ou des textures, ou les shaders. D'abord le configurer. Et lors du rendu que se Lient entre eux, sans le modifier.

Donc, avec VAO vous n'suivantes:

void Setup() {
    glGenVertexArrays(..);
    glBindVertexArray(..);
    // now setup all your VertexAttribPointers that will be bound to this VAO
   glBindBuffer(..);
   glVertexAttribPointer(..);
   glEnableVertexAttribArray(..);
}

void Render() {
    glBindVertexArray(vao);
    // that's it, now call one of glDraw... functions
    // no need to set up vertex attrib pointers and buffers!
    glDrawXYZ(..)
}

Voir aussi ces liens:

10voto

Nicol Bolas Points 133791

est-ce une bonne pratique?

Oui, c'est parfaitement légal et valide. Est-il bon? Bien...

Il y a eu quelques informelle des tests de performance sur ce genre de chose. Et il semble, au moins sur le matériel NVIDIA où cela a été testé, la "bonne" utilisation de VAOs (c'est à dire: ce que tout le monde préconisé) est en réalité le plus lent dans de nombreux cas. Cela est particulièrement vrai si l'évolution des VAOs ne pas changer les tampons sont liés.

Aucun des performances similaires, les tests ont eu lieu sur du matériel AMD, à ma connaissance. En général, à moins que quelque chose change avec eux, c'est une utilisation acceptable de VAOs.

3voto

Marek Points 11

Robert de la réponse ci-dessus a fonctionné pour moi quand je l'ai essayé. Pour ce que ça vaut ici, c'est le code, en Go, de l'utilisation de plusieurs Vertex Objets d'Attribut:

// VAO 1

vao1 := gl.GenVertexArray()
vao1.Bind()

vbo1 := gl.GenBuffer()
vbo1.Bind(gl.ARRAY_BUFFER)

verticies1 := []float32{0, 0, 0, 0, 1, 0, 1, 1, 0}
gl.BufferData(gl.ARRAY_BUFFER, len(verticies1)*4, verticies1, gl.STATIC_DRAW)

pa1 := program.GetAttribLocation("position")
pa1.AttribPointer(3, gl.FLOAT, false, 0, nil)
pa1.EnableArray()
defer pa1.DisableArray()

vao1.Unbind()

// VAO 2

vao2 := gl.GenVertexArray()
vao2.Bind()

vbo2 := gl.GenBuffer()
vbo2.Bind(gl.ARRAY_BUFFER)

verticies2 := []float32{-1, -1, 0, -1, 0, 0, 0, 0, 0}
gl.BufferData(gl.ARRAY_BUFFER, len(verticies2)*4, verticies2, gl.STATIC_DRAW)

pa2 := program.GetAttribLocation("position")
pa2.AttribPointer(3, gl.FLOAT, false, 0, nil)
pa2.EnableArray()
defer pa2.DisableArray()

vao2.Unbind()

Ensuite dans ta boucle principale, vous pouvez les utiliser en tant que tel:

for !window.ShouldClose() {
    gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

    vao1.Bind()
    gl.DrawArrays(gl.TRIANGLES, 0, 3)
    vao1.Unbind()

    vao2.Bind()
    gl.DrawArrays(gl.TRIANGLES, 0, 3)
    vao2.Unbind()

    window.SwapBuffers()
    glfw.PollEvents()

    if window.GetKey(glfw.KeyEscape) == glfw.Press {
        window.SetShouldClose(true)
    }
}

Si vous voulez voir la totalité du code source, il est disponible comme un Résumé de l'information et de la dérivée à partir des exemples en aller-gl:

https://gist.github.com/mdmarek/0f73890ae2547cdba3a7

Merci à tous pour les réponses initiales, j'ai eu la même question que ECrownofFire.

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