Methods for drawing sprites in OpenGL with shaders

I am learning OpenGL right now and I would like to draw some sprites to the screen from a sprite sheet. I'm sure if I do it right, though.

What I want to do is build a world of tiles Γ  la Terraria. This means that all the tiles that build my world are 1x1, but I may want later than objects that are 2x1, 1x2, 2x2, etc.

What I am doing right now is that I have a class named "Tile" that contains the tile transformation matrix and a pointer to its buffer. Very simple:

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

      

Then, when I draw the slice, I simply bind the buffer and update the shader UV coordinates and vertex positions. After that, I pass the tile transform matrix to the shader and draw it using 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);

      

Can I do it more efficiently? I thought I might have one buffer for 1x1 tiles, one buffer for 2x1 tiles, etc. Etc., and then just the Tile class contains UVpos and UVsize and then just send them to the shader, but I'm not sure how I would go about doing that.

I think that what I described with one buffer for 1x1 and one for 2x1 seems to be much faster.

+3


source to share


1 answer


Can I do it more efficiently?

I don't think you could have done it less efficiently. You are binding the entire buffer object for each square. Then you load the matrix. For each quad.



Typically, a tilemap (and only a map, not an entity) works in such a way that you create a buffer object that contains a portion of the visible portions of the screen. White space appears as a transparent tile. Then you render all the tiles for that area of ​​the screen, all in one draw call. You provide one matrix for all fragments in that region.

Typically you will have a number of such visible areas to make it easier to update the tiles for that region when they change. The offscreen regions are reused for the regions that appear on the screen, so you populate them with new tile data.

+1


source







All Articles