C++ glBufferData和glBufferSubData偏移量
我试图在OpenGL3.3中渲染Suzanne(来自Blender),但缓冲区数据似乎不正确。我明白了: 我还尝试使用简单纹理渲染球体: “我的导入器”将顶点数据作为单个浮点插入std::vector: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[
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我建议专门为此创建一个新问题。很好!很高兴你能让它工作