glBufferData and glBufferSubData Offset

时间:2016-04-21 22:08:36

标签: c++ opengl buffer opengl-3

I'm attempting to render Suzanne (from Blender) in OpenGL 3.3, but the buffer data doesn't seem to be correct. I get this:

https://gyazo.com/ab82f9acb6854a49fccc527ed96cc4e8

I also tried to render a sphere with a simple texture:

https://gyazo.com/85c1e87fcc4eab128ca37b1a0cb1deaa

My importer inserts the vertex data into a std::vector as single floats:

if(line.substr(0,2) == "v ")
{
/** Vertex position */
    std::istringstream s(line.substr(2));
    float v[3];
    s >> v[0]; s >> v[1]; s >> v[2];

    this->vertices.push_back(v[0]);
    this->vertices.push_back(v[1]);
    this->vertices.push_back(v[2]);
}

I setup the array buffer as follows:

glGenBuffers(1, &this->vbo);
glBindBuffer(GL_ARRAY_BUFFER, this->vbo);

glBufferData(GL_ARRAY_BUFFER,
    sizeof(float)*(this->vertices.size()+this->textures.size()+this->normals.size()),
    NULL,
    GL_STATIC_DRAW);

And then I insert the actual data using glBufferSubData

glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*this->vertices.size(), this->vertices.data());
glBufferSubData(GL_ARRAY_BUFFER, sizeof(float)*this->vertices.size(), sizeof(float)*this->textures.size(), this->textures.data());
glBufferSubData(GL_ARRAY_BUFFER, sizeof(float)*(this->vertices.size()+this->textures.size()), sizeof(float)*this->normals.size(), this->normals.data());

I also insert the indices in the same way (GL_ELEMENT_ARRAY_BUFFER of course).

I then point to the information:

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (GLvoid*)0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (GLvoid*)(sizeof(float)*this->v.size()));
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (GLvoid*)(sizeof(float)*this->v.size()+this->vt.size()));

My vertex shader takes in the data like this:

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

Am I screwing up the offsets?

EDIT: I figured out the biggest issue! I wrote an external Lua program to convert the obj files to a format that was easier to import, but it ended up messing with the data and duplicating the indices on the "f #/#/# #/#/# #/#/#" so the file looked like this (x->y->x) instead of (x->y->z)

Also fixed a few other errors thanks to the responses below!

1 个答案:

答案 0 :(得分:2)

如果您对[{1}}的来电合法,我无法看到您的着色器,我无法100%确定。我也不知道你是否想要在单个VBO中交错的顶点数据。你现在拥有的包括所有顶点位置,然后是所有纹理坐标,最后是所有法线。

要交错数据,首先要将所有数据放入单个数组(或向量)中,以便每个顶点重复glVertexAttribPointer模式。其中PPPTTNNN是三个位置浮点数,PPP是两个texcoord浮点数,TT是三个正常浮点数。

它看起来像这样(使用虚假类型,值和间距来帮助说明模式):

NNN

我们假设您将其全部放入名为float[] vertices = { /* pX, pY, pZ, tX, tY, nX, nY, nZ */ 1, 1, 1, 0, 0, 1, 1, 1, // vertex 1 0, 0, 0, 1, 1, 0, 0, 0, // vertex 2 1, 1, 1, 0, 0, 1, 1, 1, // vertex 3 ... }; 的单个向量中,然后您可以使用一个命令上传它:

vertices

您还可以将每个属性放入自己的VBO中。您决定如何将数据存储在GPU上最终取决于您。如果您有意以您的方式存储数据,请在评论中告诉我,我会更新答案。

好的,现在是着色器位。

让我们说你有一个如下所示的顶点着色器:

glBufferData(GL_ARRAY_BUFFER, sizeof(float) * this->vertices.size(), this->vertices.data(), GL_STATIC_DRAW);

片段着色器看起来像这样:

in vec3 position;
in vec2 texcoord;
in vec3 normal;
out vec2 uv;

void main() {
    gl_Position = vec4(position, 1);
    uv = texcoord;
}

然后您需要以下in vec2 uv; uniform sampler2D image; out vec4 color; void main() { color = texture(image, uv); } 次来电:

glVertexAttribPointer

注意每个调用的第一个参数是不同的数字。这相当于顶点着色器中的int stride = (3 + 2 + 3) * sizeof(float); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*)3); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)5); positiontexcoord

纹理坐标通常只是一对浮点数(例如normal)所以我将第二个参数更改为vec2 texcoord以进行texcoord调用。

最后,当使用交错数组时,最后一个参数只需要指定每个顶点的偏移量。因此,我们分别得到203作为位置偏移,texcoord偏移和普通偏移。

希望这能让你到达目的地。

查看docs.gl page on glVertexAttribPointer了解详情。