OpenGL Vertex Buffer对象纹理坐标

时间:2015-01-21 15:15:38

标签: opengl textures vbo coordinate vertex-buffer-objects

我想在C ++中用VBO创建网格类。 该课程如下:

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

mesh::~mesh()
{
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &IND);
}

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

但结果是错误的,你可以在左下图中看到(右边的图片是所需的图片):

The image on the left side is from VBO, on the right side is immediate mode

顶点处于正交模式,因此顶点的坐标原点位于左上角,而对于纹理坐标,原点位于左下角,就像在OpenGL中一样。

1 个答案:

答案 0 :(得分:5)

当使用索引来寻址顶点位置时,纹理坐标也会被索引。在您的情况下,这意味着您只使用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 =&gt; 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));