버퍼 바인딩을 해제해야합니까?


12

OpenGL ES 2로 몇 가지 테스트를하고 몇 가지 질문이 있습니다. 현재 프로그램은 다음과 같습니다.

Init
-------
-> create index buffer
-> fill index buffer glBufferData 
-> create vertex buffer
-> fill vertex buffer glBufferData 

Draw
-------
 1. Apply vertex buffer

    -> Bind VAO
       -> bind vertex buffer
          - enable attributs (glVertexPointer, …)
       -> unbind vertex buffer
    -> Unbind VAO
    -> Bind VAO

 3. Apply index buffer
 4. Draw

문제

주어진 코드 충돌, 몇 가지 연구 후, 나는 이유를 이해했습니다 : 인덱스 버퍼를 초기화 부분 ( "fill index buffer glBufferData"이후)에 바인딩 해제하거나 첫 번째 "Bind VAO"전에 바인딩 해제해야합니다

내 질문은 :

  • 인덱스 버퍼를 VAO (VAO 주식 인덱스 버퍼)에 넣을 수 있습니까?
  • 각 업데이트 (glBufferData) 후에 버퍼 바인딩을 해제해야합니까?

내 응용 프로그램에는 각 프레임 (예 : 입자)에서 업데이트되는 버퍼가 있으므로 다음과 같은 OpenGL 스택이 있습니다.

-> bind buffer 1
-> update buffer 1
-> close buffer 1
-> bind buffer 1
-> draw

처음 3 줄은 마지막 그리기 객체 인 정점 버퍼를 업데이트합니다.

-> bind buffer 1
-> update buffer 1
-> draw

감사

답변:


12

불필요한 바인딩 / 바인딩을 많이하지 않는 것 같습니다. VAO를 사용하는 경우 VAO를 설정하고 형상을 그릴 때 VAO 만 바인딩해야합니다. 업데이트해야 할 때만 VBO / IBO를 바인딩합니다.

버퍼를 그리거나 업데이트 한 후에는 반드시 바인딩을 해제 할 필요는 없지만 바인딩 된 버퍼에 실수로 쓰지 않도록하는 것이 좋습니다.

이제 일련의 작업 순서를 취하면 다음과 같은 전반적인 순서가 표시됩니다.

초기화시 :

  1. VAO를 생성하고 바인딩합니다. 시퀀스에서 바인딩하는 모든 VBO 및 IBO는 현재 VAO (이 중 하나)와 연결됩니다.

  2. 인덱스 버퍼 생성 및 바인딩

    • 로 색인 버퍼를 채 웁니다 glBufferData/glMapBuffer.
  3. 정점 버퍼를 생성하고 바인딩합니다.

    • 정점 버퍼를 채 웁니다 glBufferData/glMapBuffer.
  4. glEnableVertexAttribArray/glVertexAttribPointer등으로 정점 속성 설정

  5. 버퍼와 VAO를 실수로 수정하지 않도록 모든 것을 선택적으로 바인드 해제하십시오. VAO를 먼저 바인딩 해제 해야합니다 . 예 :glBindVertexArray(0);

추첨시 :

  1. 버퍼 만 그리는 경우 :

    • VAO를 묶습니다.
    • 드로우 콜을 수행합니다.
  2. 업데이트 및 드로잉하는 경우 :

    • VAO, VBO, IBO를 바인딩합니다.
    • 버퍼를 업데이트합니다 (정점 속성 업데이트는 정점 형식이 변경된 경우에만 필요합니다).
    • 드로우 콜을 수행합니다.
  3. 버퍼와 VAO를 실수로 수정하지 않도록 선택적으로 바인딩을 해제합니다.

그렇게 간단합니다. 이 작업 순서는 문제없이 작동해야합니다.


2
실제 사례 (GPU에서 병목 현상이 발생하지 않는 간단한 셰이더)를 사용한 실험 (2014)에서 VAO를 사용하여 성능을 향상시킨 것은 적절한 주문 후 중요하지 않은 것으로 나타났습니다 (<2 % CPU 절약) 연속 렌더링 호출에서 동일한 VBO를 사용할 때 (10 ~ 33 % CPU 절약) VBO 설정을 완전히 건너 뛰도록 렌더링 호출 수를 구현했으며 VAO로 일부 드라이버 버그를 발견하여 기본적으로 해제했습니다. 복잡한 셰이더, MSAA 등을 사용할 때 GPU에서 병목 현상이 발생하여 모바일에서도 CPU가 유휴 상태로 남아있게됩니다.
Stephane Hockenhull

2
하드웨어에서 지원하지 않는 방식으로 정점 데이터를 잘못 정렬하면 GPU 드라이버가 각 설정에서 VBO 데이터의 순서를 다시 조정해야하지만 YMMV와 같이 아무것도 변경되지 않는 한 드라이버는 VAO로 한 번 재정렬 할 수 있습니다. 어쨌든 정점 데이터를 정렬하고 채우는 것이 가장 좋습니다.
Stephane Hockenhull

1
VAO를 다른 모든 것보다 먼저 묶어야하는 이유는 무엇입니까?
Daniel Safari

@DanielSafari, 당신은 설정 후 의미? 버퍼를 먼저 바인딩 해제하면 (바인딩 버퍼 0 / 널) 현재 VAO에서 해당 바인딩 포인트를 지 웁니다. 따라서 null VAO를 먼저 설정해야합니다.
glampert

@glampert-아니요, 바인딩이 작동하는 방식이 아닙니다. 버퍼 바인딩은 glVertexAttribPointer가 호출 될 때 사용되며 그렇지 않은 경우에는 사용되지 않습니다 (예외 : GL_ELEMENT_ARRAY_BUFFER). glVertexAttribPointer 호출 후 버퍼 바인딩을 변경해도 아무런 영향이 없습니다.
Maximus Minimus
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.