Programing

OpenGL VAO 모범 사례

lottogame 2020. 10. 17. 09:00
반응형

OpenGL VAO 모범 사례


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

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

glGenVertexArrays(1,&vao)

다음에

glBindVertexArray(vao)

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

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


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

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


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

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

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

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


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

If you want to see the full source, it is available as a Gist and derived from the examples in go-gl:

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

Thanks everyone for the original answers, I had the same question as ECrownofFire.

참고URL : https://stackoverflow.com/questions/8923174/opengl-vao-best-practices

반응형