Найкращі практики OpenGL VAO


79

Я стикаюся з проблемою, яка, на мою думку, залежить від VAO, але я не впевнений ..

Я не впевнений у правильному використанні VAO, те, що я робив під час ініціалізації GL, було простим

glGenVertexArrays(1,&vao)

слідом за а

glBindVertexArray(vao)

і пізніше, у своєму конвеєрі для малювання, я просто зателефонував glBindBuffer (), glVertexAttribPointer (), glEnableVertexAttribArray () і так далі .. не дбаючи про початково пов'язаний VAO

це правильна практика?


31
Я не впевнений, чому це питання отримало -1 .. воно не показує жодних зусиль і. Чи незрозуміло? Я витратив 3 дні на боротьбу зі специфікаціями, вікі та форумами, перш ніж розміщувати це повідомлення, і не отримав жодної реальної причини, через яку я мав би використовувати VAO .. meh ..
user815129

18
Оскільки для крутих братів це все очевидно, як тільки у них є під рукою вирізки та пасти, навіщо морочитися з розумінням речі ??
mlvljr

Відповіді:


94

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.


1
чи справді необхідно розв’язати VAO? Я знайшов різні практики навколо
user815129

3
Це не потрібно, але я зазвичай роблю це на випадок, якщо якийсь інший об'єкт вирішить візуалізувати без VAO (налагоджувальний малюнок / бібліотека візуалізації шрифтів / тощо), оскільки це (наскільки мені відомо) замінить налаштування атрибутів для поточно пов'язаного VAO .
Роберт Рухані,

2
Чому розв’язування відбувається лише один раз і поза циклом? Чи не повинно звільнення відбуватися за партією?
batbrat

12
Прив'язка нового VAO замінює старий VAO. Розв’язування всередині циклу було б просто додатковою роботою.
Роберт Рухані,

1
@RobertRouhani Чи є тоді якась вигода від останнього відв’язування VAO? (Чи розв’язування ні на що не впливає?)
Mateen Ulhaq

27

Ні, ви не використовуєте VAO. Вам слід використовувати VAO так само, як і VBO, текстури або шейдери. Спочатку налаштуйте його. І під час рендерингу лише прив'язуйте їх, не змінюючи цього.

Отже, з VAO ви робите наступне:

Дивіться також ці посилання:


1
Ця відповідь повинна бути вищою. Це спеціально виправило важку вишукувану помилку.
абаракс

3
glEnableVertexAttribArray(...)слід дзвонити раніше glVertexAttribPointer(...). Деяким водіям (включаючи мій) насправді не подобається навпаки.
RecursiveExceptionException

2
Проголосовано, оскільки більшість прикладів не зрозумілі, що ПОВИНЕН викликати glEnableVertexAttribArray під час прив’язки VAO.
Руперт Раунслі

10

це правильна практика?

Так, це цілком законно і дійсне. Це добре? Ну...

Було проведено кілька неформальних тестів ефективності подібного роду речей. І, здається, принаймні на апаратному забезпеченні NVIDIA, де це тестувалось, "правильне" використання VAO (тобто те, за що виступали всі інші) насправді у багатьох випадках відбувається повільніше . Це особливо вірно, якщо зміна VAO не змінює, які буфери пов'язані.

Наскільки мені відомо, подібного тестування продуктивності на апаратному забезпеченні AMD не проводилось. Загалом, якщо з ними щось не зміниться, це прийнятне використання VAO.


2
Безумовно, як тільки кожен VAO має достатньо різноманітного стану, який він відстежує, що перемикання буферів та attrib ptrs вручну під час циклу візуалізації потребуватиме багатьох дзвінків, і ми почнемо бачити покращену продуктивність від використання VAO?
Steven Lu

На жаль, посилання мертве.
Nick Caplinger

3

Відповідь Роберта вище працювала для мене, коли я спробував. Для того, що тут варто, це код у Go, що використовує кілька об'єктів атрибутів вершин:

// 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.


3
Вам не потрібно розв’язувати vao1 перед прив’язуванням vao2, досить буде просто прив’язати vao2.
хаос
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.