Подтвердить что ты не робот

Рекомендации OpenGL VAO

Мне кажется, что проблема связана с VAO, но я не уверен...

Я не уверен относительно правильного использования VAO, то, что я использовал во время инициализации GL, было простым

glGenVertexArrays(1,&vao)

а затем

glBindVertexArray(vao)

а затем, в моем конвейере чертежа, я просто вызвал glBindBuffer(), glVertexAttribPointer(), glEnableVertexAttribArray() и т.д., не заботясь о связанный с VAO

Это правильная практика?

4b9b3361

Ответ 1

VAO действуют аналогично VBOs и текстурам в отношении того, как они связаны. Наличие единого 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.

Ответ 2

Нет, это не то, как вы используете VAO. Вы должны использовать VAO так же, как вы используете VBO или текстуры, или шейдеры. Сначала настройте его. А во время рендеринга только привязать их, не изменяя его.

Итак, с 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 it, now call one of glDraw... functions
    // no need to set up vertex attrib pointers and buffers!
    glDrawXYZ(..)
}

Смотрите также эти ссылки:

Ответ 3

Это правильная практика?

Да, это совершенно законно и справедливо. Это хорошо? Ну...

Неофициальное тестирование производительности. Похоже, что по крайней мере на оборудовании NVIDIA, где это было протестировано, "правильное" использование VAO (то есть: то, что все остальные защищают) на самом деле во многих случаях медленнее. Это особенно верно, если изменение VAO не изменяет, какие буферы привязаны.

Насколько мне известно, аналогичных проверок производительности на оборудовании AMD не было. В общем, если что-то не меняется с ними, это приемлемое использование VAO.

Ответ 4

Роберт ответ выше работал у меня, когда я пробовал. Для того, что здесь стоит, это код в Go, используя несколько объектов атрибута 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()

Затем в вашем основном цикле вы можете использовать их как таковые:

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

Если вы хотите увидеть полный источник, он доступен как Gist и получен из примеров в go-gl:

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

Спасибо всем за оригинальные ответы, у меня был тот же вопрос, что и ECrownofFire.