gpt4 book ai didi

c++ - glBufferData 和 glBufferSubData 偏移量

转载 作者:行者123 更新时间:2023-11-28 02:07:55 28 4
gpt4 key购买 nike

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

https://gyazo.com/ab82f9acb6854a49fccc527ed96cc4e8

我还尝试渲染一个具有简单纹理的球体:

https://gyazo.com/85c1e87fcc4eab128ca37b1a0cb1deaa

我的导入器将顶点数据作为单个 float 插入到 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_ELEMENT_ARRAY_BUFFER)。

然后我指向信息:

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;

我是不是搞砸了偏移量?

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

由于以下回复,还修复了一些其他错误!

最佳答案

如果没有看到您的着色器,我无法 100% 确定您对 glVertexAttribPointer 的调用是否合法。我也不知道你是否想要在单个 VBO 中交错顶点数据。你目前拥有的首先是所有的顶点位置,然后是所有的纹理坐标,最后是所有的法线。

要交错数据,您首先要将所有数据放入一个数组(或 vector )中,以便每个顶点重复 PPPTTNNN 模式。其中 PPP 是三个位置 float ,TT 是两个 texcoord float ,NNN 是三个普通 float 。

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

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 的 vector 中,然后您可以使用一个命令上传它:

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

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

好的,现在是着色器位。

假设您有一个如下所示的顶点着色器:

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);

请注意每次调用的第一个参数是不同的数字。这分别对应顶点着色器中的positiontexcoordnormal

此外,纹理坐标通常只是一对 float (例如 vec2 texcoord),因此我将第二个参数更改为 2 以用于 texcoord 调用。

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

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

查看 docs.gl page on glVertexAttribPointer了解更多信息。

关于c++ - glBufferData 和 glBufferSubData 偏移量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36781322/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com