具有纹理图集的实例绘图

时间:2016-12-07 22:31:28

标签: c++ opengl

我目前正在尝试使用实例绘图创建一个tilemap。我已经能够通过在单独的VBO中使用属性除数发送与几何图形相对应的顶点以及每个图块的偏移量并使用属性除数来绘制图块的多个实例。

然而,这允许我只使用一个纹理。所以我从顶点分割纹理坐标并为偏移创建一个单独的VBO,但它不会产生预期的结果。假设我发送的坐标是与第一个图块的图集中的第一个纹理匹配的坐标,以及与其他图块的第二个纹理匹配的坐标,如果我使用glAttributeDivisor(1, 0),则所有图块仅使用第一个图块质地。如果我使用任何其他值,我会得到某种格子图案,每个纹理只有一个像素用于整个图块。

以下是属性divisior为0时的作用:Divisor is 0 这是属性除数为1的时候:Divisor is 1 通常情况下,左下角的第一个瓷砖应该是草砖,就像除数为0时,其他所有瓷砖应该是一个污垢瓷砖。

这就是我创建缓冲区的方法:

TileMap::TileMap(std::vector<glm::vec2> positions, std::vector<glm::vec2> texCoords, glm::vec2 tileSize,
                 std::shared_ptr<graphics::Shader> shader,
                 std::shared_ptr<graphics::Texture> texture) :
m_positions(positions), m_texCoords(texCoords), m_tileSize(tileSize), m_shader(shader), m_texture(texture) {
    m_model = glm::mat4();
    m_model = glm::scale(m_model, glm::vec3(tileSize, 1.0f));

    GLfloat vertices[] =
    {
        // Positions
        1.0f, 1.0f,     // Top Right
        1.0f, 0.0f,     // Bottom Right
        0.0f, 0.0f,     // Bottom Left
        0.0f, 1.0f      // Top Left
    };

    GLuint indices[] =
    {
        0, 1, 3,
        1, 2, 3
    };

    glGenVertexArrays(1, &m_vao);
    glGenBuffers(1, &m_vbo);
    glGenBuffers(1, &m_ebo);

    glGenBuffers(1, &m_textureVbo);
    glBindBuffer(GL_ARRAY_BUFFER, m_textureVbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * m_texCoords.size(), &m_texCoords[0], GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glGenBuffers(1, &m_instanceVbo);
    glBindBuffer(GL_ARRAY_BUFFER, m_instanceVbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * m_positions.size(), &m_positions[0], GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glBindVertexArray(m_vao);
        glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);

        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ARRAY_BUFFER, m_textureVbo);
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glEnableVertexAttribArray(2);
        glBindBuffer(GL_ARRAY_BUFFER, m_instanceVbo);
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glVertexAttribDivisor(1, 0);
        glVertexAttribDivisor(2, 1);
    glBindVertexArray(0);
}

这就是我生成tilemap的方式:

std::vector<glm::vec2> positions;
std::vector<glm::vec2> texCoords;
bool test = false;
for(float i = 0.0f; i < 7.0f; i++) {
    for(float j = 0.0f; j < 7.0f; j++) {
        positions.push_back(glm::vec2(j, i));

        if(test){
            texCoords.push_back(glm::vec2(1.0f, 1.0f)); // Top Right
            texCoords.push_back(glm::vec2(1.0f, 0.0f)); // Bottom Right
            texCoords.push_back(glm::vec2(0.5f, 0.0f)); // Bottom Left
            texCoords.push_back(glm::vec2(0.5f, 1.0f)); // Top Left
        } else {
            texCoords.push_back(glm::vec2(0.5f, 1.0f)); // Top Right
            texCoords.push_back(glm::vec2(0.5f, 0.0f)); // Bottom Right
            texCoords.push_back(glm::vec2(0.0f, 0.0f)); // Bottom Left
            texCoords.push_back(glm::vec2(0.0f, 1.0f)); // Top Left
        }

        test = true; //This is just to test the texture switching after the first tile
    }
}

graphics::TileMap tileMap(positions, texCoords, glm::vec2(64.0f), shader, texture);

我对OpenGl并不熟悉,所以我完全不知道是什么导致了这个问题,也不知道该使用什么,以便每个四边形读取应该绑定它们的4个纹理坐标。

0 个答案:

没有答案