OpenGL VAO mejores prácticas
opengl-3 (4)
¿Es esta una práctica correcta?
Sí, esto es perfectamente legal y válido. ¿Esta bien? Bien...
Ha habido algunas pruebas de rendimiento informales en este tipo de cosas. Y parece que, al menos en el hardware de NVIDIA donde esto se probó, el uso "adecuado" de VAO (es decir, lo que todos los demás defendieron) en realidad es más lento en muchos casos. Esto es especialmente cierto si el cambio de VAO no cambia qué búferes están vinculados.
A mi entender, no se han realizado pruebas de rendimiento similares en el hardware de AMD. En general, a menos que algo cambie con ellos, este es un uso aceptable de los VAO.
Estoy enfrentando un problema que creo que depende de VAO, pero no estoy seguro ...
No estoy seguro del uso correcto de un VAO, lo que solía hacer durante la inicialización de GL era simple
glGenVertexArrays(1,&vao)
seguido por un
glBindVertexArray(vao)
y más tarde, en mi proyecto de dibujo, acabo de llamar a glBindBuffer (), glVertexAttribPointer (), glEnableVertexAttribArray () y así sucesivamente ... sin preocuparme por el VAO vinculado inicialmente
¿Es esta una práctica correcta?
La respuesta de Robert anterior funcionó para mí cuando lo probé. Lo que vale aquí es el código, en Go, de usar múltiples Objetos de atributo de Vertex:
// 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()
Luego, en su ciclo principal puede usarlos como tales:
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 desea ver la fuente completa, está disponible como una idea general y se deriva de los ejemplos en go-gl:
https://gist.github.com/mdmarek/0f73890ae2547cdba3a7
Gracias a todos por las respuestas originales, tuve la misma pregunta que ECrownofFire.
Los VAO actúan de forma similar a los VBO y las texturas con respecto a cómo están vinculados. Tener un único VAO vinculado a la duración total de su programa no arrojará beneficios de rendimiento, ya que también podría estar renderizando sin VAO en absoluto. De hecho, puede ser más lento dependiendo de cómo la implementación intercepta la configuración del atributo de vértice a medida que se dibujan.
El objetivo de un VAO es ejecutar todos los métodos necesarios para dibujar un objeto una vez durante la inicialización y cortar toda la sobrecarga del método extra durante el ciclo principal. El punto es tener varios VAO y cambiar entre ellos cuando se dibuja.
En términos de mejores prácticas, así es cómo debe organizar su código:
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
Esto evita el desorden de los búferes de enlace / desvinculación y pasa todos los ajustes para cada atributo de vértice y lo reemplaza con una sola llamada a método, vinculando un VAO.
No, así no es como usas VAO. Debe usar VAO de la misma manera que está usando VBO o texturas, o sombreadores. Primero configúralo. Y durante la renderización, únelos, sin modificarlos.
Entonces con VAO haces lo siguiente:
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(..)
}
Ver también estos enlaces: