我面临的问题是我认为取决于VAO,但我不确定。
我不确定VAO的正确用法,我在GL初始化过程中曾经做过的事情很简单
glGenVertexArrays(1,&vao)
跟一个
glBindVertexArray(vao)
之后,在我的绘制管道中,我只调用了glBindBuffer(),glVertexAttribPointer(),glEnableVertexAttribArray()等。
这是正确的做法吗?
我面临的问题是我认为取决于VAO,但我不确定。
我不确定VAO的正确用法,我在GL初始化过程中曾经做过的事情很简单
glGenVertexArrays(1,&vao)
跟一个
glBindVertexArray(vao)
之后,在我的绘制管道中,我只调用了glBindBuffer(),glVertexAttribPointer(),glEnableVertexAttribArray()等。
这是正确的做法吗?
Answers:
VAO的行为与VBO和纹理相似。在程序的整个长度上绑定一个VAO不会产生任何性能上的好处,因为您可能完全不使用VAO进行渲染。实际上,它可能会慢一些,具体取决于实现在绘制顶点属性设置时如何拦截它们。
VAO的目的是在初始化期间运行绘制一次对象所需的所有方法,并在主循环期间消除所有额外的方法调用开销。关键是要有多个VAO,并在绘制时在它们之间切换。
根据最佳实践,这是组织代码的方式:
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
这避免了绑定/取消绑定缓冲区和传递每个顶点属性的所有设置的麻烦,并仅用一个方法调用(绑定VAO)将其替换。
不,那不是您使用VAO的方式。您应该以与使用VBO或纹理或着色器相同的方式使用VAO。首先进行设置。并且仅在渲染期间绑定它们,而无需对其进行修改。
因此,使用VAO,您可以执行以下操作:
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(..)
}
另请参阅以下链接:
glEnableVertexAttribArray(...)
应该在之前被调用glVertexAttribPointer(...)
。相反,有些司机(包括我的)真的不喜欢它。
当我尝试时,以上罗伯特的回答对我有用。在这里值得使用Go中使用多个Vertex Attribute Objects的代码:
// 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()
然后,可以在主循环中按如下方式使用它们:
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)
}
}
如果要查看完整的源代码,可以将其作为要点,并从go-gl中的示例获取:
https://gist.github.com/mdmarek/0f73890ae2547cdba3a7
谢谢大家的原始回答,我和ECrownofFire有相同的问题。