OpenGL 顶点缓冲区对象纹理坐标
OpenGL Vertexbuffer object texture coordinates
我想在 C++ 中使用 VBO 创建网格 class。
class 如下所示:
mesh::mesh(std::vector<Vector3d>* Vertices, std::vector<unsigned int>* Indices, std::vector<Vector2d>* TextureCoords) {
if(Vertices) this->vertices = *Vertices;
if(Indices) this->indices = *Indices;
if(TextureCoords) this->textureCoords = *TextureCoords;
chatbox.AddMessageToQueue("vertices.size() : %d", vertices.size());
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(Vector3d) + textureCoords.size()*sizeof(Vector2d), 0, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size()*sizeof(Vector3d), vertices.data());
glBufferSubData(GL_ARRAY_BUFFER, vertices.size()*sizeof(Vector3d), textureCoords.size()*sizeof(Vector2d), textureCoords.data());
glGenBuffers(1, &IND);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IND);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
}
void mesh::draw() {
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexPointer(3, GL_FLOAT, 0, (void*)0);
glTexCoordPointer(2, GL_FLOAT, 0, (void*)(sizeof(float)*3*6));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IND);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (unsigned int*)0 + 0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
问题仅出在纹理坐标中。我正在尝试像这样创建网格:
std::vector<unsigned int> indices;
std::vector<mesh::Vector3d> vertices;
std::vector<mesh::Vector2d> texCoords;
vertices.push_back({PosX, PosY, 1.0});
vertices.push_back({PosX + SizeX, PosY, 1.0});
vertices.push_back({PosX + SizeX, PosY + SizeY, 1.0});
vertices.push_back({PosX, PosY + SizeY, 1.0});
indices.push_back(0);
indices.push_back(1);
indices.push_back(2);
indices.push_back(0);
indices.push_back(2);
indices.push_back(3);
texCoords.push_back({0, 1});
texCoords.push_back({1, 0});
texCoords.push_back({0, 0});
texCoords.push_back({0, 1});
texCoords.push_back({1, 1});
texCoords.push_back({1, 0});
gui_checkbox = new mesh(&vertices, &indices, &texCoords);
但是结果是错误的,如下左图(右图是想要的):
顶点处于正交模式,所以顶点的坐标原点在左上角,纹理坐标的原点在左下角,就像在 OpenGL 中一样。
当使用索引来寻址顶点位置时,纹理坐标也会被索引。在您的情况下,这意味着您仅使用 texCoords 中的前四个条目。奇怪的外观来自 texCoords[0] == texCoords[3].
正确的 texCoords 很可能是
texCoords.push_back({0, 1});
texCoords.push_back({1, 1});
texCoords.push_back({1, 0});
texCoords.push_back({0, 0});
这些可以从顶点坐标导出:只要对应的顶点具有相同的组件值,texCoords 就应该在组件处具有相同的值。例如如果顶点[0].y == 顶点[1].y => texCoords[0].y == texCoords[1].y 等等。此外,必须翻转 texCoords y 坐标,因为顶点原点在左上角,而 texcoords 从左下角开始。
编辑:
glTexCoordPointer(2, GL_FLOAT, 0, (void*)(sizeof(float)*3*6));
我觉得不对。这个语句表明第一个纹理坐标在第六个 vector3 之后开始,但它们不应该在第四个之后开始吗? (您在顶点中只有 4 个条目):
glTexCoordPointer(2, GL_FLOAT, 0, (void*)(sizeof(float)*3*4));
我想在 C++ 中使用 VBO 创建网格 class。 class 如下所示:
mesh::mesh(std::vector<Vector3d>* Vertices, std::vector<unsigned int>* Indices, std::vector<Vector2d>* TextureCoords) {
if(Vertices) this->vertices = *Vertices;
if(Indices) this->indices = *Indices;
if(TextureCoords) this->textureCoords = *TextureCoords;
chatbox.AddMessageToQueue("vertices.size() : %d", vertices.size());
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(Vector3d) + textureCoords.size()*sizeof(Vector2d), 0, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size()*sizeof(Vector3d), vertices.data());
glBufferSubData(GL_ARRAY_BUFFER, vertices.size()*sizeof(Vector3d), textureCoords.size()*sizeof(Vector2d), textureCoords.data());
glGenBuffers(1, &IND);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IND);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
}
void mesh::draw() {
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexPointer(3, GL_FLOAT, 0, (void*)0);
glTexCoordPointer(2, GL_FLOAT, 0, (void*)(sizeof(float)*3*6));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IND);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (unsigned int*)0 + 0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
问题仅出在纹理坐标中。我正在尝试像这样创建网格:
std::vector<unsigned int> indices;
std::vector<mesh::Vector3d> vertices;
std::vector<mesh::Vector2d> texCoords;
vertices.push_back({PosX, PosY, 1.0});
vertices.push_back({PosX + SizeX, PosY, 1.0});
vertices.push_back({PosX + SizeX, PosY + SizeY, 1.0});
vertices.push_back({PosX, PosY + SizeY, 1.0});
indices.push_back(0);
indices.push_back(1);
indices.push_back(2);
indices.push_back(0);
indices.push_back(2);
indices.push_back(3);
texCoords.push_back({0, 1});
texCoords.push_back({1, 0});
texCoords.push_back({0, 0});
texCoords.push_back({0, 1});
texCoords.push_back({1, 1});
texCoords.push_back({1, 0});
gui_checkbox = new mesh(&vertices, &indices, &texCoords);
但是结果是错误的,如下左图(右图是想要的):
顶点处于正交模式,所以顶点的坐标原点在左上角,纹理坐标的原点在左下角,就像在 OpenGL 中一样。
当使用索引来寻址顶点位置时,纹理坐标也会被索引。在您的情况下,这意味着您仅使用 texCoords 中的前四个条目。奇怪的外观来自 texCoords[0] == texCoords[3].
正确的 texCoords 很可能是
texCoords.push_back({0, 1});
texCoords.push_back({1, 1});
texCoords.push_back({1, 0});
texCoords.push_back({0, 0});
这些可以从顶点坐标导出:只要对应的顶点具有相同的组件值,texCoords 就应该在组件处具有相同的值。例如如果顶点[0].y == 顶点[1].y => texCoords[0].y == texCoords[1].y 等等。此外,必须翻转 texCoords y 坐标,因为顶点原点在左上角,而 texcoords 从左下角开始。
编辑:
glTexCoordPointer(2, GL_FLOAT, 0, (void*)(sizeof(float)*3*6));
我觉得不对。这个语句表明第一个纹理坐标在第六个 vector3 之后开始,但它们不应该在第四个之后开始吗? (您在顶点中只有 4 个条目):
glTexCoordPointer(2, GL_FLOAT, 0, (void*)(sizeof(float)*3*4));