understanding glVertexAttribPointer?

喜欢而已 提交于 2019-11-27 12:33:34

问题


i am a newbie at Open GL and came here to clear out a confusion i had. I appreciate any help!

private int vbo;
private int ibo;

vbo = glGenBuffers();
ibo = glGenBuffers();

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, Util.createFlippedBuffer(vertices), GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, Util.createFlippedBuffer(indices), GL_STATIC_DRAW);




glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
//glEnableVertexAttribArray(2);

//glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, Vertex.SIZE * 4, 12);
//glVertexAttribPointer(2, 3, GL_FLOAT, false, Vertex.SIZE * 4, 20);

//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
//glDisableVertexAttribArray(2);

The vertex shader code looks like

#version 330

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;

out vec2 texCoord0;

uniform mat4 transform;

void main()
{
    gl_Position = transform * vec4(position, 1.0);
    texCoord0 = texCoord;
}

So, here is my understanding. The purpose of glVertexAttribPointer is to define the format of data in the vertex buffer object. So, in vbo it stores data as follows

buffer.put(vertices[i].getPos().getX());
buffer.put(vertices[i].getPos().getY());
buffer.put(vertices[i].getPos().getZ());
buffer.put(vertices[i].getTexCoord().getX());
buffer.put(vertices[i].getTexCoord().getY());
buffer.put(vertices[i].getNormal().getX());
buffer.put(vertices[i].getNormal().getY());
buffer.put(vertices[i].getNormal().getZ());

So, we have two glVertexAttribPointer lines because we have two variables defined in the vertex shader. So basically we are defining what these two variables point to. So, the first glVertexAttribPointer defines that the first variable "position" is a vertex with three coordinates each being float. The second glVertexAttribPointer defines the second variable "texCoord" being a pair of texture coordinates each being float. So, if my understanding is correct so far then i was assuming we first need to bind the vertex buffer object first but even after commenting out this line

glBindBuffer(GL_ARRAY_BUFFER, vbo);

it still works. I am confused. How does it know which buffer object we are talking about since there are two vbos?

I appreciate any help. Thanks a lot!


回答1:


@datenwolf already covered the key aspect in a comment above. To elaborate some more:

You do not have to bind GL_ARRAY_BUFFER again before the glDrawElements() call. What matters is that the buffer you want to source a given attribute from is bound when you make the glVertexAttribPointer() call for that attribute.

The best way to picture this is that when you make this call:

glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);

you're specifying all the state needed to tell OpenGL where to get the data for attribute 0 (first argument) from, and how to read it. Most of that state is given directly by the arguments:

  • it has 3 components
  • the components are float values
  • vertices are read with a stride of 20 bytes...
  • ... and starting at byte 0 of the buffer

But there's an additional implied piece of state that is also stored away for attribute 0 when you make the call:

  • the data is read from the buffer currently bound to GL_ARRAY_BUFFER

In other words, the state associated with each attribute includes the id of the buffer the attribute data is sourced from. This can be the same buffer for multiple/all attributes, or it can be a different buffer for each attribute.

Note that the same is not true for GL_ELEMENT_ARRAY_BUFFER. That one needs to be bound at the time of the glDrawElements() call. While it seems somewhat inconsistent, this is necessary because there's no equivalent to glVertexAttribPointer() for the index array. The API could have been defined to have this kind of call, but... it was not. The reason is most likely that it was simply not necessary, since only one index array can be used for a draw call, while multiple vertex buffers can be used.



来源:https://stackoverflow.com/questions/24876647/understanding-glvertexattribpointer

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!