OpenGL VAO 모범 사례


79

VAO 의존적이라고 생각되는 문제에 직면했지만 확실하지 않습니다 ..

VAO의 올바른 사용법에 대해 잘 모르겠습니다. GL 초기화 중에 사용했던 작업은 간단했습니다.

glGenVertexArrays(1,&vao)

다음에

glBindVertexArray(vao)

나중에 드로잉 파이프 라인에서 glBindBuffer (), glVertexAttribPointer (), glEnableVertexAttribArray () 등을 호출했습니다. 초기 바인딩 된 VAO는 신경 쓰지 않고

이것이 올바른 관행입니까?


31
왜이 질문이 -1을 받았는지 모르겠습니다. 어떤 노력도 보여주지 않거나 명확하지 않습니까? 나는 위키 및 포럼이 게시하기 전에, 사양과 사투를 벌인 삼일 보냈다 .. MEH .. 내가 VAO을 사용해야 어떤 진짜 이유를 얻을 didnt는
user815129

18
멋진 형제의 경우 잘라내어 붙여 넣기를 편리하게 사용하는 즉시 모든 것이 분명해지기 때문에 왜 물건을 이해하는 데 귀찮게합니까 ??
mlvljr 2013

답변:


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의 속성 설정을 대체합니다. .
Robert Rouhani

2
바인딩 해제가 한 번만 루프 외부에서 발생하는 이유는 무엇입니까? 바인딩 해제는 배치별로 발생하지 않아야합니까?
batbrat 2013

12
새 VAO를 바인딩하면 이전 VAO가 대체됩니다. 루프 내부의 바인딩 해제는 추가 작업 일뿐입니다.
Robert Rouhani 2013

1
@RobertRouhani 그렇다면 마지막 바인딩 해제 VAO에 대한 이점이 있습니까? (바인딩 해제는 아무 영향을주지 않습니까?)
Mateen Ulhaq

27

아니요, VAO를 사용하는 방법이 아닙니다. VBO, 텍스처 또는 셰이더를 사용하는 것과 동일한 방식으로 VAO를 사용해야합니다. 먼저 설정하십시오. 그리고 렌더링 중에는 수정하지 않고 바인딩 만합니다.

따라서 VAO를 사용하면 다음을 수행합니다.

다음 링크를 참조하십시오.


1
이 대답은 더 높아야합니다. 특히 내 버그를 추적하기 어려운 문제를 해결했습니다.
abarax

3
glEnableVertexAttribArray(...)전에 호출해야 glVertexAttribPointer(...)합니다. 일부 드라이버 (내를 포함하여) 는 그 반대 방향을 정말로 좋아하지 않습니다.
RecursiveExceptionException

2
대부분의 예제는 VAO 바인딩 중에 glEnableVertexAttribArray를 호출해야한다는 것이 명확하지 않기 때문에 찬성되었습니다.
Rupert Rawnsley

10

이것이 올바른 관행입니까?

예, 이것은 완벽하게 합법적이고 유효합니다. 좋은가요? 잘...

이런 종류의 비공식 성능 테스트 가있었습니다 . 그리고 적어도 이것이 테스트 된 NVIDIA 하드웨어에서 VAO의 "적절한"사용 (즉, 다른 사람들이 옹호 한 것)은 실제로 많은 경우에 더 느린 것 같습니다 . VAO를 변경해도 바인딩되는 버퍼가 변경되지 않는 경우 특히 그렇습니다.

내가 아는 한 AMD 하드웨어에서 유사한 성능 테스트가 수행되지 않았습니다. 일반적으로 변경 사항이 없으면 VAO를 사용할 수 있습니다.


2
확실히 각 VAO가 추적 할 수있는 충분한 다양한 상태를 갖게되면 렌더링 루프 동안 수동으로 버퍼 및 속성 ptr을 전환하려면 많은 호출이 필요하며 VAO 사용으로 인해 향상된 성능을보기 시작할 수 있습니까?
Steven Lu

불행히도 링크가 끊어졌습니다.
Nick Caplinger 2017

3

위의 Robert의 대답은 내가 시도했을 때 나를 위해 일했습니다. 여기서 가치가있는 것은 Go에서 여러 Vertex Attribute Object를 사용하는 코드입니다.

// 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
vao2를 바인딩하기 전에 vao1을 바인딩 해제 할 필요가 없습니다. 단순히 vao2를 바인딩하는 것으로 충분합니다.
havokentity
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.