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!
答案 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);
,position
,texcoord
。
纹理坐标通常只是一对浮点数(例如normal
)所以我将第二个参数更改为vec2 texcoord
以进行texcoord调用。
最后,当使用交错数组时,最后一个参数只需要指定每个顶点的偏移量。因此,我们分别得到2
,0
和3
作为位置偏移,texcoord偏移和普通偏移。
希望这能让你到达目的地。