1
\$\begingroup\$

I'm new to OpenGL, I'm currently building a 2D game engine. Right now I'm only using one shader as I only draw textured quads (basically sprites).

The thing is... I don't know if should I be using uniforms or VBOs with glBufferSubData.
Edit: My concern is efficiency, more specifically CPU overhead.
Edit2: I want to make the best out of OpenGL and the GPU, and to have as little CPU overhead as possible.

The way I have it setup right now is that I create a single VBO, VAO and EBO.
This is my VBO (vec2 for position [center of the screen] and another vec2 for texture coordinates, times 4)

{
    -0.5f,  0.5f, 0.0f, 0.0f,
     0.5f,  0.5f, 1.0f, 0.0f,
     0.5f, -0.5f, 1.0f, 1.0f,
    -0.5f, -0.5f, 0.0f, 1.0f
}

And this is the EBO which I use to draw the quad with glDrawElements with the above VBO:

{
   0, 1, 2,
   2, 3, 0
}

This is all static and I currently use uniforms for transformation (position, camera, rotation, etc.) and color.

So every frame, for every sprite, I update the uniforms with glUniformMatrix4fv and glUniform2fv and I draw the quad (I batch sprites with identical transformation and color attributes, to minimize the amount of these calls).

And I have no idea if this is bad or not. I have no prior experience in OpenGL.

I know the VAO will always be the same (as I only render textured quads with a single shader), but should I not use uniforms and instead create a VBO for each sprite object and update the needed data in the VBO with glBufferSubData?

P.S.
If both ways are not good and there's a better way to do this please let me know.

Update (kind of an answer):
Using the method above made it impossible to use spritesheets as the UV was static.
I didn't think of that when I began working on it.
So what I did instead was implementing a completely different approach that I came across last week by reading some books.
I'm still using a single shader, a single VBO, a single VAO and a single EBO.
The VBO consists of positions, UVs and colors.
Except that the VBO and EBO are large (predefined MaxVertices variable determines how large).
I initially allocate memory with glBufferData (only once). To the VBO with GL_DYNAMIC_DRAW and to the EBO with GL_STATIC_DRAW.
I upload the data to the EBO once, which is just static indices to the VBO (using 4 vertices to draw a quad by drawing them with that EBO and glDrawElements, same method as before).
I have a Begin(), Draw(...) and End() calls, which are similar to a typical sprite batch class.
Whenever the amount of vetices exceeds the predefined MaxVertices variable, or when End() is called, the vertices that were batched are actually uploaded (with glBufferSubData to avoid memory reallocation) and drawn.
For now, I found this to be the most efficient way to do what I want. If batched correctly, each batch will have the least amount of CPU and GPU overhead by "sacrificing" (more like utilizing) GPU memory.
I am still not sure if this is the most optimal way to reduce overhead, but so far it's a big improvement over what I've previously done. And it makes it so I can use spritesheets which I completely forgot about :P
I would appreciate any input on this implementation. :)

\$\endgroup\$
  • \$\begingroup\$ What is your definition of "best"? If you're concerned about efficiency, I wouldn't worry about it until you know it's actually a problem. \$\endgroup\$ – user1118321 Apr 17 at 2:44
  • \$\begingroup\$ Yes, my concern is efficiency. More specifically CPU overhead. I will edit my question now (sorry). I will take your advice and continue the way it is and when I have a more solid project I will do profiling on the two methods. Knowing that this is not a completely bad way to do this helps :). Thank you very much for your comment \$\endgroup\$ – CountessAnise Apr 17 at 5:08
  • \$\begingroup\$ You can usually get away with anything when doing 2d, since it probably won't need a lot of performance. You should try an engine or framework though if you want to create a game and non an engine \$\endgroup\$ – Bálint Apr 17 at 6:23
  • \$\begingroup\$ @Bálint The main purpose is an engine. But not for the sake of actually creating games in the future (I'm a pure hobbyist). I want to have a basic understanding of modern OpenGL and how to approach 2D efficiently (to make the best out of OpenGL and the GPU, and to have as little CPU overhead as possible). Thank you for your comment! :) \$\endgroup\$ – CountessAnise Apr 17 at 11:33
  • \$\begingroup\$ @user1118321 I know it has been 2 weeks, but I've updated the question with a sort of an answer. A few things I've learned and implemented. I would really appreciate if any of you are still around and are willing to give your input on my new implementation :) \$\endgroup\$ – CountessAnise May 1 at 0:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.