使用着色器在OpenGL中绘制spritesheets的技巧

时间:2013-01-20 16:11:36

标签: c++ opengl sprite-sheet

我现在正在学习OpenGL,我想从精灵表中将一些精灵画到屏幕上。我注意到,如果我这样做是正确的。

我想做的是用Terraria瓷砖建造一个世界。这意味着构建我的世界的所有图块都是1x1,但我可能想要的东西更像是2x1,1x2,2x2等实体。

我现在所做的是我有一个名为“Tile”的类,它包含tile的变换矩阵和指向其缓冲区的指针。很简单:

Tile::Tile(glm::vec2 position, GLuint* vbo)
{
    transformMatrix = glm::translate(transformMatrix, glm::vec3(position, 0.0f));
    buffer = vbo;
}

然后当我绘制瓷砖时,我只是绑定缓冲区并更新着色器的UV-coords和顶点位置。之后,我将tile的变换矩阵传递给着色器并使用glDrawElements绘制它:

glEnableVertexAttribArray(positionAttrib);
glEnableVertexAttribArray(textureAttrib);

for(int i = 0; i < 5; i++) 
{
    glBindBuffer(GL_ARRAY_BUFFER, *tiles[i].buffer);

    glVertexAttribPointer(positionAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
    glVertexAttribPointer(textureAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));

    glUniformMatrix4fv(transformMatrixLoc, 1, GL_FALSE, value_ptr(tiles[i].transformMatrix));
    glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
}

glDisableVertexAttribArray(positionAttrib);
glDisableVertexAttribArray(textureAttrib);

我可以更有效地做到这一点吗?我以为我可以为1x1磁贴设置一个缓冲区,为2x1磁贴设置一个缓冲区等等。然后让Tile类包含UVpos和UVsize然后将它们发送到着色器,但我不知道我是怎么做的这样做。

我认为我用1x1缓冲区和2x1缓冲区描述的内容听起来要快得多。

1 个答案:

答案 0 :(得分:1)

  

我可以更有效地做到这一点吗?

我认为你不能有效地。您正在为每个四边形绑定一个完整的缓冲区对象。然后,您正在上传矩阵。对于每个四元组。

tilemap绘图(只有 map ,而不是实体)的正常工作方式是构建一个缓冲区对象,其中包含可见屏幕的某些部分。空白空间呈现为透明瓷砖。然后,您可以在一个绘图调用中为屏幕的该区域渲染所有的切片。您为该区域中的所有图块提供一个矩阵。

通常情况下,您将拥有一些此类可见区域,以便在更改时更新该区域的图块。屏幕外的区域会重新用于屏幕上显示的区域,因此您可以使用新的图块数据填充它们。