I am in the process of migrating away from legacy OpenGL calls in my 2D LWJGL game. Previously I would render each sprite using immediate mode, which was dead easy - bind the texture, add the vertices, and it's done.

Now I want to use vertex arrays. Ideally I would put the vertices for ALL my entities in one big array and render it in a single draw call. The problem? Each entity type uses a different texture, and glDrawArrays uses just one texure at a time.

Here are some possible solutions I came up with:

1) Create a separate vertex array for each entity

This is by far the easiest solution, but it somehow seems wrong to me, because it's so similar to using immediate mode. Doesn't this defeat the benefit of using vertex arrays?

2) Create a separate vertex array for each entity type

In other words, all entities that have the same texture will be rendered together. This isn't ideal as it would involve a good chunk of extra work and some extra effort on the CPU to separate the entities by type, and more importantly, would affect the z-ordering of the entities.

For example, it would be impossible to have a Tree that appears in front of one Squirrel but behind another Squirrel.

That is, unless I introduced a depth buffer, but I was trying to avoid this as it adds another level of complexity and, as I understand it, more work on the GPU (although that probably doesn't matter too much).

3) Combine all textures using a texture atlas

If I was able to use a single texture for all entities, I could use a single vertex array. However, there are 2 problems with this:

  1. I have not been able to find a good library for creating a texture atlas at runtime, and writing this code myself would be non-trivial.

  2. I am worried that some GPUs may have a prohibitively small texture size limit.


  • Would the first solution be viable / advisable?
  • Am I being foolish for trying to avoid using the depth buffer?
  • Am I missing something here? Is there a better solution?
  • \$\begingroup\$ Quake used a depth buffer in 1996; I don't think you have anything to worry about in that regard. \$\endgroup\$ Aug 31, 2018 at 14:59
  • 2
    \$\begingroup\$ If you decide to use a texture atlas, you don't want to create it on runtime, but have it as an atlas at compile-time. Also, why exactly would you want to avoid the depth buffer? Have you tried it and there was something that you didn't like? Most of your questions are answerable just by trying them out and see what works or not. \$\endgroup\$ Aug 31, 2018 at 16:07
  • \$\begingroup\$ Any one of these solutions will involve time and effort, so I'd rather make sure I'm not barking up the wrong tree before I start implementing one of them. This is also the main reason I'm trying to avoid using the depth buffer, as it will involve changes to my shader and all the code that's using the shader. I'm not convinced that the second solution offers enough benefits to warrant such work. \$\endgroup\$
    – Dan
    Aug 31, 2018 at 18:28
  • \$\begingroup\$ @Dan You are already enormously far behind the curve by just getting into non immediate mode OpenGL, you are going to need all the help you can get to the point where you can overwrite the numerous bad assumptions and habits immediate mode gave developers about GPUs. It's probably going to benefit you more if you try to implement these things yourself and come back to us with specific questions about those implementations, rather than worrying about the best way to do something you don't yet have enough experience to reason your self about. \$\endgroup\$
    – Krupip
    Aug 31, 2018 at 19:29
  • \$\begingroup\$ @Dan Also GPUs are all different, what works best for one may not work at all well for another. Asking for the "best" way to do something is overly broad. \$\endgroup\$
    – Krupip
    Aug 31, 2018 at 19:31

1 Answer 1


Having spent a not-insignificant amount of time rewriting my rendering code, here is what I would like to tell my past self...

Immediate Mode vs. "Modern" OpenGL

  • Immediate mode is terrible practice; migrating away from that cannot be a bad thing.

  • If you are migrating in order to support MacOS, don't bother; they have stopped supporting OpenGL altogether.

  • OpenGL is still a valid choice.

VAO Strategy

  • There is no "right" solution; some may be more efficient than others, but for a simple 2D game, they are probably all viable; graphics processing is not going to be a huge strain on the GPU, even with a sub-optimal approach.

  • Switching textures is expensive! Consider rendering by texture.

  • Fewer VAOs is always better.

  • Start simple, and optimise later if required.

Depth Buffer


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .