[opengl] glVertexAttribPointer 설명

내가 이것을 올바르게 이해하고 있는지 확인하고 싶습니다 (SO Chat에서 묻 겠지만 거기에는 죽었습니다!) :

우리는 정점 배열을 가지고 있으며,이를 바인딩하여 “현재”로 만들고
버퍼를 얻었습니다.이 버퍼를 Target에 바인딩
한 다음 해당 대상 glBufferData
에 바인딩 된 모든 것을 기본적으로 채우는 대상을 채 웁니다. 즉, 버퍼
그런 다음 glVertexAttribPointer데이터가 배치되는 방식을 설명하는 호출 을 호출 합니다. 데이터는 바인딩 된 데이터이며이 GL_ARRAY_BUFFER
설명자는 원래 Vertex Array에 저장됩니다.

(1) 내 이해가 정확합니까? 문서는 어떻게 모든의 상관 관계에 대해 조금 스파 스입니다.

(2) 어떤 종류의 기본 정점 배열이 있습니까? 잊고 / 생략 glGenVertexArrays했고 glBindVertexArray내 프로그램이 그것 없이는 잘 작동했기 때문입니다.


편집 : 나는 단계를 놓쳤다 … glEnableVertexAttribArray.

(3) Vertex Attrib glVertexAttribPointerglEnableVertexAttribArray해당 시점에 Vertex Array에 연결되어 있습니까? 그러면 현재 어떤 Vertex Array가 바인딩되어 있는지에 관계없이 언제든지 해당 attrib을 활성화 / 비활성화 할 수 있습니까?

또는 (3b) 당시 Vertex Array에 묶인 Vertex Attrib glEnableVertexAttribArray이 호출 되었는가 glEnableVertexAttribArray? 따라서 다른 Vertex Array가 바인딩되어있을 때 다른 시간 에 호출하여 동일한 Vertex Attrib을 여러 Vertex Array에 추가 할 수 있습니까?



답변

일부 용어는 약간 벗어났습니다.

  • A Vertex Arrayfloat[]꼭짓점 데이터를 포함 하는 배열 (일반적으로 a )입니다. 어떤 것에 묶일 필요가 없습니다. Vertex Array Object또는 VAO 와 혼동하지 마십시오. 나중에 살펴 보겠습니다.
  • A는 Buffer Object, 일반적으로 언급 Vertex Buffer Object정점을 저장, 또는 줄여서 VBO 때, 당신은 단지를 호출하는 것입니다 Buffer.
  • 어떤 것도 정점 배열에 다시 저장되지 않고 glVertexAttribPointer정확히 동일하게 작동 glVertexPointer하거나 glTexCoordPointer작동합니다. 이름이 지정된 속성 대신 고유 한 속성을 지정하는 숫자를 제공하게됩니다. 이 값을 index. 모든 glVertexAttribPointer통화는 다음에 glDrawArrays또는을 ( 를) 호출 할 때 대기열에 추가됩니다 glDrawElements. VAO 바인딩이있는 경우 VAO는 모든 속성에 대한 설정을 저장합니다.

여기서 가장 중요한 문제는 정점 속성을 VAO와 혼동하고 있다는 것입니다. 정점 속성은 그리기를 위해 정점, texcoord, 법선 등을 정의하는 새로운 방법입니다. VAO는 상태를 저장합니다. 먼저 버텍스 속성을 사용하여 드로잉이 작동하는 방식을 설명하고 VAO를 사용하여 메서드 호출 수를 줄이는 방법을 설명합니다.

  1. 셰이더에서 속성을 사용하려면 먼저 속성을 활성화해야합니다. 예를 들어 정점을 셰이더로 보내려는 경우 첫 번째 속성 인 0으로 보낼 가능성이 높습니다. 따라서 렌더링하기 전에을 사용하여 활성화해야합니다 glEnableVertexAttribArray(0);.
  2. 이제 속성이 활성화되었으므로 사용할 데이터를 정의해야합니다. 그렇게하려면 VBO-를 바인딩해야합니다 glBindBuffer(GL_ARRAY_BUFFER, myBuffer);.
  3. 이제 속성을 정의 할 수 있습니다 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);. 매개 변수 순서 : 0은 정의하려는 속성, 3은 각 정점의 크기 GL_FLOAT, 유형, GL_FALSE각 정점을 정규화하지 않음을 의미하며 마지막 2 개의 0은 정점에 보폭이나 오프셋이 없음을 의미합니다.
  4. 그것으로 무언가를 그려라- glDrawArrays(GL_TRIANGLES, 0, 6);
  5. 다음으로 그리는 것은 속성 0을 사용하지 않을 수 있으므로 (실제로는 사용되지만 이것은 예제입니다) 비활성화 할 수 있습니다. glDisableVertexAttribArray(0);

그것을 glUseProgram()호출로 감싸면 셰이더와 제대로 작동하는 렌더링 시스템이 있습니다. 하지만 5 개의 다른 속성, 정점, texcoord, 법선, 색상 및 라이트 맵 좌표가 있다고 가정 해 보겠습니다. 우선, glVertexAttribPointer이러한 각 속성에 대해 단일 호출을 만들고 모든 속성을 미리 활성화해야합니다. 내가 나열한대로 0-4 속성을 정의한다고 가정 해 보겠습니다. 다음과 같이 모두 활성화합니다.

for (int i = 0; i < 5; i++)
    glEnableVertexAttribArray(i);

그런 다음 각 속성에 대해 서로 다른 VBO를 바인딩해야합니다 (모두 하나의 VBO에 저장하고 오프셋 / 스트라이드를 사용하지 않는 한), 정점에 대해 각각 라이트 맵 좌표 에 대해 5 개의 서로 다른 glVertexAttribPointer호출 을 수행해야합니다 .glVertexAttribPointer(0,...);glVertexAttribPointer(4,...);

이 시스템만으로도 이해가 되길 바랍니다. 이제 이러한 유형의 렌더링을 수행 할 때 VAO를 사용하여 메서드 호출 수를 줄이는 방법을 설명하기 위해 VAO로 이동합니다. VAO를 사용할 필요는 없습니다.

A Vertex Array Object또는 VAO는 모든 glVertexAttribPointer호출 의 상태 와 각 glVertexAttribPointer호출이 수행 될 때 대상이 된 VBO 를 저장하는 데 사용됩니다 .

에 대한 호출로 하나를 생성합니다 glGenVertexArrays. 필요한 모든 것을 VAO에 저장하려면로 바인딩 glBindVertexArray한 다음 전체 그리기 호출을 수행하십시오 . 모든 드로우 바인드 호출은 VAO에 의해 가로 채서 저장됩니다. VAO의 바인딩을 해제 할 수 있습니다.glBindVertexArray(0);

이제 개체를 그리려는 경우 모든 VBO 바인딩 또는 호출을 다시 호출 할 필요가 없습니다 glVertexAttribPointer. VAO를 glBindVertexArraythen call glDrawArrays또는 호출 로 바인딩 glDrawElements하면됩니다. 모든 메소드 호출을하고있었습니다. 나중에 VAO의 바인딩을 해제하고 싶을 수도 있습니다.

VAO의 바인딩을 해제하면 모든 상태가 VAO를 바인딩하기 전의 상태로 돌아갑니다. VAO가 바인딩되어있는 동안 변경 한 내용이 유지되는지 확실하지 않지만 테스트 프로그램으로 쉽게 알아낼 수 있습니다. glBindVertexArray(0);“기본”VAO에 바인딩하는 것으로 생각할 수 있습니다 .


업데이트 : 누군가가 실제 드로우 콜이 필요하다는 점을 알려주었습니다. 결과적으로 VAO를 설정할 때 실제로 FULL 드로우 콜을 수행 할 필요가 없습니다. 왜 더 일찍 필요하다고 생각했는지 모르겠지만 지금은 해결되었습니다.


답변

호출 할 API의 용어와 순서는 실제로 매우 혼란 스럽습니다. 더욱 혼란스러운 것은 버퍼, 일반 정점 속성 및 셰이더 속성 변수와 같은 다양한 측면이 연결되는 방식입니다. 꽤 좋은 설명 은 OpenGL 용어 를 참조하십시오 .

또한 OpenGL-VBO, shader, VAO 링크 는 필요한 API 호출이 포함 된 간단한 예를 보여줍니다. 즉각적인 모드에서 프로그래밍 가능한 파이프 라인으로 전환하는 사람들에게 특히 좋습니다.

도움이되기를 바랍니다.

편집 : 아래 설명에서 볼 수 있듯이 사람들은 가정을하고 결론을 내릴 수 있습니다. 현실은 초보자에게 상당히 혼란 스럽습니다.


답변