developer tip

glBindVertexArrays 대 glBindBuffer의 역할은 무엇이며 그 관계는 무엇입니까?

copycodes 2020. 11. 7. 10:15
반응형

glBindVertexArrays 대 glBindBuffer의 역할은 무엇이며 그 관계는 무엇입니까?


저는 OpenGL 및 그래픽 프로그래밍을 처음 사용합니다. 지금까지 정말 꼼꼼하고 잘 쓰여진 교과서를 읽고 있었는데, 코드에서 이해가 잘 안되는 부분을 봤는데이 줄을 먼저 이해하고 싶습니다. 이동합니다.

GLuint abuffer;

glGenVertexArrays(1, &abuffer);
glBindVertexArray(abuffer);

GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);

이 책은 처음 세 줄이 정점 배열과 관련된 데이터를 묶는 데 사용되는 정점 배열 객체를 생성한다고 설명합니다 . 두 번째 줄은 사용되지 않은 이름 (에 저장된 부호없는 정수 식별자를 추측하고 있음)을 찾고 abuffer세 번째 줄은 개체를 생성 / 활성화합니다.

이 책은 데이터를 저장하기 위한 버퍼 객체생성하는 4 ~ 7 번째 줄에 대해 설명합니다. 5 번째 줄은 사용되지 않은 식별자 (정점 배열 개체의 경우 2 번째 줄과 비슷합니까?), 버퍼를 생성하는 6 번째 줄, 7 번째 줄은 라인 CPU에 충분한 메모리를 할당하고에 대한 데이터 (포인트)에 대한 포인터를 생성합니다 GL_STATIC_DRAW.

개체가 활성화된다는 것은 무엇을 의미합니까? 나중에 언제 사용 abuffer하시겠습니까? 정점 배열이 관련 데이터를 묶는다는 것은 무엇을 의미하며이 정점 배열 객체와 연결된 데이터는 언제였습니까?

나는 사이의 관계에 대해 혼란스러워하고있어 abufferbuffer. 정점 배열과 버퍼 객체의 관계가 무엇인지, 그리고 그 관계가 형성되는 지점에 대해 혼란 스럽습니다. 실제로 관련이 있는지는 확실하지 않지만 교과서에 바로 나와 있습니다.

어떤 도움을 주시면 감사하겠습니다. 감사.


낮은 수준의 관점에서 배열은 두 부분으로 구성되어 있다고 생각할 수 있습니다.

  • 배열의 크기, 모양 및 유형에 대한 정보 (예 : 각각 4 개의 요소가있는 벡터 행을 포함하는 32 비트 부동 소수점 숫자).

  • 큰 바이트 blob에 불과한 배열 데이터입니다.

저수준 개념은 거의 동일하게 유지되었지만 배열을 지정하는 방식은 수년에 걸쳐 여러 번 변경되었습니다.

OpenGL 3.0 / ARB_vertex_array_object

이것은 아마도 오늘 일을해야하는 방식 입니다. OpenGL 3.x를 실행할 수 없지만 소프트웨어에 투자 할 돈이있는 사람을 찾는 것은 매우 드뭅니다.

OpenGL의 버퍼 객체는 큰 비트 덩어리입니다. "활성"버퍼를 전역 변수로 생각하면 매개 변수를 사용하는 대신 활성 버퍼를 사용하는 함수가 많이 있습니다. 이러한 전역 상태 변수는 OpenGL의 추악한 측면입니다 (아래에서 설명하는 직접 상태 액세스 이전).

GLuint buffer;

// Generate a name for a new buffer.
// e.g. buffer = 2
glGenBuffers(1, &buffer);

// Make the new buffer active, creating it if necessary.
// Kind of like:
// if (opengl->buffers[buffer] == null)
//     opengl->buffers[buffer] = new Buffer()
// opengl->current_array_buffer = opengl->buffers[buffer]
glBindBuffer(GL_ARRAY_BUFFER, buffer);

// Upload a bunch of data into the active array buffer
// Kind of like:
// opengl->current_array_buffer->data = new byte[sizeof(points)]
// memcpy(opengl->current_array_buffer->data, points, sizeof(points))
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);

지금, 당신의 전형적인 버텍스 쉐이더 걸립니다 꼭지점 입력 비트가 아닌 큰 덩어리로합니다. 따라서 비트 blob (버퍼)이 정점으로 디코딩되는 방법을 지정해야합니다. 이것이 어레이의 역할입니다. 마찬가지로 전역 변수로 생각할 수있는 "활성"배열이 있습니다.

GLuint array;
// Generate a name for a new array.
glGenVertexArrays(1, &array);
// Make the new array active, creating it if necessary.
glBindVertexArray(array);

// Make the buffer the active array buffer.
glBindBuffer(GL_ARRAY_BUFFER, buffer);
// Attach the active buffer to the active array,
// as an array of vectors with 4 floats each.
// Kind of like:
// opengl->current_vertex_array->attributes[attr] = {
//     type = GL_FLOAT,
//     size = 4,
//     data = opengl->current_array_buffer
// }
glVertexAttribPointer(attr, 4, GL_FLOAT, GL_FALSE, 0, 0);
// Enable the vertex attribute
glEnableVertexAttribArray(attr);

OpenGL 2.0 (이전 방식)

OpenGL 2.x에는 정점 배열이 없었고 데이터는 전역이었습니다. 당신은 여전히 전화를했다 glVertexAttribPointer()하고 glEnableVertexAttribArray(), 그러나 당신은 그들에게 전화했다 때마다 당신은 버퍼를 사용하는 것이다. OpenGL 3.x에서는 어레이를 한 번만 설정하면됩니다.

OpenGL 1.5로 돌아 가면 실제로 버퍼를 사용할 수 있지만 각 종류의 데이터를 바인딩하기 위해 별도의 함수를 사용했습니다. 예를 들어, glVertexPointer()정점 데이터 용이고 glNormalPointer()일반 데이터 용이었습니다. OpenGL 1.5 이전에는 버퍼가 없었지만 응용 프로그램 메모리에 대한 포인터를 사용할 수있었습니다.

OpenGL 4.3 / ARB_vertex_attrib_binding

4.3에서 또는 ARB_vertex_attrib_binding 확장이있는 경우 속성 형식과 속성 데이터를 개별적으로 지정할 수 있습니다. 다른 버퍼간에 하나의 정점 배열을 쉽게 전환 할 수 있기 때문에 좋습니다.

GLuint array;
// Generate a name for a new array array.
glGenVertexArrays(1, &array);
// Make the new array active, creating it if necessary.
glBindVertexArray(array);

// Enable my attributes
glEnableVertexAttribArray(loc_attrib);
glEnableVertexAttribArray(normal_attrib);
glEnableVertexAttribArray(texcoord_attrib);
// Set up the formats for my attributes
glVertexAttribFormat(loc_attrib,      3, GL_FLOAT, GL_FALSE, 0);
glVertexAttribFormat(normal_attrib,   3, GL_FLOAT, GL_FALSE, 12);
glVertexAttribFormat(texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 24);
// Make my attributes all use binding 0
glVertexAttribBinding(loc_attrib,      0);
glVertexAttribBinding(normal_attrib,   0);
glVertexAttribBinding(texcoord_attrib, 0);

// Quickly bind all attributes to use "buffer"
// This replaces several calls to glVertexAttribPointer()
// Note: you don't need to bind the buffer first!  Nice!
glBindVertexBuffer(0, buffer, 0, 32);

// Quickly bind all attributes to use "buffer2"
glBindVertexBuffer(0, buffer2, 0, 32);

OpenGL 4.5 / ARB_direct_state_access

OpenGL 4.5에서 또는 ARB_direct_state_access 확장이있는 경우 더 이상 호출 glBindBuffer()하거나 glBindVertexArray()설정하기 위해 필요하지 않습니다 . 배열과 버퍼를 직접 지정합니다. 배열을 그리기 위해서는 끝에 배열 만 바인딩하면됩니다.

GLuint array;
// Generate a name for the array and create it.
// Note that glGenVertexArrays() won't work here.
glCreateVertexArrays(1, &array);
// Instead of binding it, we pass it to the functions below.

// Enable my attributes
glEnableVertexArrayAttrib(array, loc_attrib);
glEnableVertexArrayAttrib(array, normal_attrib);
glEnableVertexArrayAttrib(array, texcoord_attrib);
// Set up the formats for my attributes
glVertexArrayAttribFormat(array, loc_attrib,      3, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribFormat(array, normal_attrib,   3, GL_FLOAT, GL_FALSE, 12);
glVertexArrayAttribFormat(array, texcoord_attrib, 2, GL_FLOAT, GL_FALSE, 24);
// Make my attributes all use binding 0
glVertexArrayAttribBinding(array, loc_attrib,      0);
glVertexArrayAttribBinding(array, normal_attrib,   0);
glVertexArrayAttribBinding(array, texcoord_attrib, 0);

// Quickly bind all attributes to use "buffer"
glVertexArrayVertexBuffer(array, 0, buffer, 0, 32);

// Quickly bind all attributes to use "buffer2"
glVertexArrayVertexBuffer(array, 0, buffer2, 0, 32);

// You still have to bind the array to draw.
glBindVertexArray(array);
glDrawArrays(...);

ARB_direct_state_access는 여러 가지 이유로 좋습니다. 그릴 때를 제외하고 배열과 버퍼를 바인딩하는 것을 잊을 수 있으므로 OpenGL이 추적하는 숨겨진 전역 변수에 대해 생각할 필요가 없습니다. 당신은 때문에 "객체를 생성", "객체의 이름을 생성"과의 차이에 대해 잊을 수 glCreateBuffer()glCreateArray()두 가지를 동시에 할.

불칸

Vulkan은 더 나아가 위에서 작성한 의사 코드와 같은 코드를 작성하도록합니다. 따라서 다음과 같은 내용이 표시됩니다.

// This defines part of a "vertex array", sort of
VkVertexInputAttributeDescription attrib[3];
attrib[0].location = 0; // Feed data into shader input #0
attrib[0].binding = 0;  // Get data from buffer bound to slot #0
attrib[0].format = VK_FORMAT_R32G32B32_SFLOAT;
attrib[0].offset = 0;
// repeat for attrib[1], attrib[2]

책에 대한 귀하의 해석이 완전히 정확하지 않습니다. Vertex Array Objects는 데이터를 저장하지 않습니다. 그것들은 Framebuffer Objects와 같이 컨테이너로 알려진 객체의 클래스입니다. 다른 개체를 연결 / 연결할 수 있지만 데이터 자체는 저장하지 않습니다. 따라서 컨텍스트 공유 가능한 리소스가 아닙니다.

기본적으로 정점 배열 객체는 OpenGL 3.0에서 정점 배열 상태를 캡슐화합니다. OpenGL을 3.1부터 (대신 GL_ARB_compatibility및 OpenGL 3.2 이상 코어 프로파일)하면 0이 아닌 VAO 같은 명령에 대해 항상 바인딩이 있어야합니다 glVertexAttribPointer (...)또는 glDrawArrays (...)함수. 바인딩 된 VAO는 이러한 명령에 필요한 컨텍스트를 형성하고 상태를 지속적으로 저장합니다.

이전 버전의 GL (및 호환성)에서 VAO에 의해 저장된 상태는 전역 상태 시스템의 일부였습니다.

It is also worth mentioning that the "current" binding for GL_ARRAY_BUFFER is not one of the states that VAOs track. While this binding is used by commands such as glVertexAttribPointer (...), VAOs do not store the binding they only store pointers (the GL_ARB_vertex_attrib_binding extension introduced alongside GL 4.3 complicates this a bit, so let us ignore it for simplicity).

VAOs do remember what is bound to GL_ELEMENT_ARRAY_BUFFER, however, so that indexed drawing commands such as glDrawElements (...) function as you would expect (e.g. VAOs re-use the last element array buffer bound).


The relationship is created when calling glVertexAttribPointer.

VertexArrays 개요

GL_VERTEX_ARRAY_BINDING and GL_ARRAY_BUFFER_BINDING are constants but they can point to the global state of the binding. I'm referring to the state not the constant(orange) in the image. Use glGet to find about different global states.

VertexArray is grouping information(including array buffer) about a vertex or many parallel vertices.

Use GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING with glGetVertexAttrib to find which attribute array buffer is set.

glBindBuffer(GL_ARRAY_BUFFER sets the global state GL_ARRAY_BUFFER_BINDING

glBindVertexArray sets the global state GL_VERTEX_ARRAY_BINDING


OpenGL is a stateful interface. It's bad, antiquated and ugly but that is legacy for ya.

A vertex array object is a collection of buffer bindings that the driver can use to get the data for the draw calls, most tutorials only use the one and never explain how to use multiple VAOs.

A buffer binding tells opengl to use that buffer for related methods in particular for the glVertexAttribPointer methods.


There is no relationship between VertexArray and VBO.

A vertex array allocates the memory in RAM and sends pointer to the API. VBO allocates the memory in the graphics card - system memory has no address for it. If you need to access the vbo data from system you need to copy it from vbo to the system first.

Also, in newer versions of OpenGL, vertex arrays are completely removed (depcrecated in 3.0, removed in 3.1)

참고 URL : https://stackoverflow.com/questions/21652546/what-is-the-role-of-glbindvertexarrays-vs-glbindbuffer-and-what-is-their-relatio

반응형