C++ glBufferData和glBufferSubData偏移量

C++ glBufferData和glBufferSubData偏移量,c++,opengl,buffer,opengl-3,C++,Opengl,Buffer,Opengl 3,我试图在OpenGL3.3中渲染Suzanne(来自Blender),但缓冲区数据似乎不正确。我明白了: 我还尝试使用简单纹理渲染球体: “我的导入器”将顶点数据作为单个浮点插入std::vector: if(line.substr(0,2) == "v ") { /** Vertex position */ std::istringstream s(line.substr(2)); float v[3]; s >> v[0]; s >> v[

我试图在OpenGL3.3中渲染Suzanne(来自Blender),但缓冲区数据似乎不正确。我明白了:

我还尝试使用简单纹理渲染球体:

“我的导入器”将顶点数据作为单个浮点插入std::vector:

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]);
}
我按如下方式设置阵列缓冲区:

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);
然后我使用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());
我也以同样的方式插入索引(当然是GL_元素_数组_缓冲区)

然后我指出以下信息:

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()));
我的顶点着色器接收如下数据:

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;
layout(location = 2) in vec3 normals;
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);
}
我把偏移量搞砸了吗

编辑: 我发现了最大的问题!我编写了一个外部Lua程序,将obj文件转换为更易于导入的格式,但它最终弄乱了数据并复制了“f#/#/#/#/#/#/#/#/#”上的索引,因此该文件看起来像这样(x->y->x),而不是(x->y->z)


由于下面的回复,还修复了一些其他错误

在没有看到着色器的情况下,我无法100%确定对
glvertexattributepointer
的调用是否合法。我也无法判断是否需要在单个VBO中使用交错顶点数据。您当前拥有的将首先打包所有顶点位置,然后打包所有纹理坐标,最后打包所有法线

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

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

假设您将其全部放入一个名为
顶点
的向量中,然后您可以使用单个命令上载它:

glBufferData(GL_ARRAY_BUFFER, sizeof(float) * this->vertices.size(), this->vertices.data(), GL_STATIC_DRAW);
您还可以将每个属性放入其自己的VBO中。如何在GPU上存储数据最终取决于您。如果您有意以现有方式存储数据,请在评论中告诉我,我将更新答案

好的,现在是着色器位

假设你有一个顶点着色器,看起来像这样:

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;
layout(location = 2) in vec3 normals;
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);
}
还有一个片段着色器,看起来像这样:

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;
layout(location = 2) in vec3 normals;
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);
}
然后需要以下
glvertexattributepointer
调用:

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);
请注意,每个调用的第一个参数是一个不同的数字。这分别对应于顶点着色器中的
position
texcoord
normal

此外,纹理坐标通常仅为一对浮点(例如,
vec2 texcoord
),因此我将texcoord调用的第二个参数更改为
2

最后一个参数,当使用交错数组时,只需要指定每个顶点的偏移量。因此,我们分别得到了位置偏移、texcoord偏移和法线偏移的
0
3
5

希望这能让你达到你想去的地方


查看以了解更多信息。

如果没有看到着色器,我无法100%确定对
glvertexattributepointer
的调用是否合法。我也无法判断是否需要在单个VBO中使用交错顶点数据。您当前拥有的将首先打包所有顶点位置,然后打包所有纹理坐标,最后打包所有法线

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

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

假设您将其全部放入一个名为
顶点
的向量中,然后您可以使用单个命令上载它:

glBufferData(GL_ARRAY_BUFFER, sizeof(float) * this->vertices.size(), this->vertices.data(), GL_STATIC_DRAW);
您还可以将每个属性放入其自己的VBO中。如何在GPU上存储数据最终取决于您。如果您有意以现有方式存储数据,请在评论中告诉我,我将更新答案

好的,现在是着色器位

假设你有一个顶点着色器,看起来像这样:

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;
layout(location = 2) in vec3 normals;
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);
}
还有一个片段着色器,看起来像这样:

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;
layout(location = 2) in vec3 normals;
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);
}
然后需要以下
glvertexattributepointer
调用:

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);
请注意,每个调用的第一个参数是一个不同的数字。这分别对应于顶点着色器中的
position
texcoord
normal

此外,纹理坐标通常仅为一对浮点(例如,
vec2 texcoord
),因此我将texcoord调用的第二个参数更改为
2

最后一个参数,当使用交错数组时,只需要指定每个顶点的偏移量。因此,我们分别得到了位置偏移、texcoord偏移和法线偏移的
0
3
5

希望这能让你达到你想去的地方


有关更多信息,请查看。

感谢您的回复!我会用着色器更新我的问题!我从obj文件中获取数据的方式使附加数据而不是交错数据变得更容易。@exide如何设置iBO,首先是所有顶点位置,然后是所有纹理坐标,最后是所有法线情况?@feisal我建议专门为此创建一个新问题。感谢您的回答!我会用着色器更新我的问题!我从obj文件中获取数据的方式使附加数据而不是交错数据变得更容易。@exide如何设置iBO,首先是所有顶点位置,然后是所有纹理坐标,最后是所有法线情况?@feisal我建议专门为此创建一个新问题。很好!很高兴你能让它工作