I recently was given this link to a tutorial site from someone who I gave the original OGL Redbook to. The third header down says distinctly to forget glBegin() & glEnd() as the typical render method. I learned via the Redbook's method, but I see some benefit in VBOs. Is this really the way to go, and if so, is there a way to easily convert the render code, and subsequent shaders, into VBOs and subsequent datatypes?


2 Answers 2


With modern OpenGL's VBO's are the way to go, fixed function stuff (including glBegin/glEnd and the stuff in between) has been deprecated since 3.0 and removed since 3.1.

With the OpenGL Core Profile, OpenGL ES 2.0+ and WebGL you don't even have access to the old stuff.

Some people think learning the old stuff first is better because it's a bit easier, but that stuff you learn is mostly useless and then stuff you have to unlearn.

It's not just VBO's though, you need to use shaders for everything and do matrix transforms yourself (or use GLM).

The only reason to use the old stuff would be if you wanted to target OpenGL before 2.0. which was back released in 2003. There are a few really crappy embedded netbook chipsets that are 1.5 but even 1.5 should support VBOs just not shaders. Or OpenGL ES 1.x which is based on the fixed function pipeline (for example it's used on older iPhones). Or OpenGL SC (for safety critical systems).

The following commonly used functions are all deprecated:

  • glBegin
  • glEnd
  • glVertex*
  • glNormal*
  • glTextCoord*
  • glTranslate*
  • glRotate*
  • glScale*
  • glLoadIdenity
  • glModelViewMatrix

The opengl-tutorial.org tutorials have what I think is the best way to go about learning OpenGL. They rely on some of the legacy compatilibty stuff but they don't actually teach it to you. For example your not supposed to render anything without a shader but it does work. And you need to handle matrices operations (rotate, translate, etc.) yourself but by default you will get a basic flat 2D viewport.

In addition to avoiding the deprecated stuff there are a bunch of functions that make coding OpenGL much nicer but with many of them you have to decide if you are ok with requiring newer 3.x+ versions of OpenGL and compatible hardware.

There's more info in a post I made here.

If you do need to support older OpenGL for some reason, you can use VBOs when possible and when it's not, provide a fallback that uses glBegin/glEnd and loops across your vertex data.

On the other hand, there's no real 'easy' way to upconvert old render code. You could perhaps implement your own version of the functions that add the vertices to a array/vector that then dumps it into a VBO and draws it when you fake glEnd is called. but that would be very inefficient since it would be doing it every frame (unless you put in a check to only do it once but that doesn't work for animated objects) and would probably be more work that just switching to VBOs. I suppose if you had a lot of code that approach might work.


With VBOs you generally have two major advantages.

Advantage 1 relates to fully static data and comes from being able to keep your vertex data in memory that is more optimal for the GPU.

Advantage 2 relates to dynamic data and comes from being able to specify your vertex data at any point in time prior to using it for rendering, which can pipeline better.

A third advantage comes from draw call batching, but is also shared with old-school vertex arrays so I'm not calling it out specifically for VBOs. Sending data to a GPU (or using data already on the GPU) is similar in many ways to disk I/O and network traffic - if you have a few large batches it's more efficient than many small batches.

A good (not 100% accurate but enough to help you get the idea) analogy for this is if you're a bus driver who has to bring 50 people from one city to another. You can load them up one at a time and make 50 separate trips - that's glBegin/glEnd. Alternatively you can put all 50 of them on the bus and just make a single trip - that's batching with vertex arrays or VBOs (in the VBO case the 50 people would already be on the bus ;)).

This comes at a price though, and here the price is that you lose the ability to just specify vertex data as and when you require it. Well, OK, you can do that (with some additional work), but you won't be getting the full performance out of your code. Instead you need to think more about your vertex data, how it's used, how (and if) it needs to be updated, whether any animations can be done in a shader (thus enabling the data to remain static - VBOs really need shaders for a lot of animation cases to work well) or whether you need to respecify the vertex data each frame, efficient update strategies if the latter, etc. If you don't do this and just implement a naive conversion you have a very high risk of putting in a lot of work only for the end result to actually run slower! (I frequently get annoyed when I see recommendations to just "use a VBO" when it's obvious that the person making that recommendation hasn't put much, if any, thought into the actual problem.)

This can seem like an awful lot of work when you first encounter it, but it's not, really. Once you get into the mode of thinking like this, you'll actually find that it's incredibly easy and almost comes naturally. But you may screw up your first few attempts and you shouldn't be discouraged if so - screwing up is an opportunity to learn from what you did wrong.

A few final thoughts.

Having your model data in a format that can be easily loaded into a VBO can help make this whole process a lot easier for you. That means that you should avoid more complex or exotic formats, at least at first (and until you're more comfortable with the process); keep things as simple and basic as possible when learning and there will be less things to go wrong, and less places to have to look for error if (or when!) things do go wrong.

People are sometimes put off if they see a VBO implementation using more memory than an optimized/compressed glBegin/glEnd implementation (they may even refer to it as "waste"). Don't be like that. Except in extreme cases, memory usage is really not that important. It's a clear tradeoff here - you're accepting potentially higher memory usage in exchange for substantially higher performance. Also helps to develop the mindset that memory is a cheap and plentiful resource that is there to be used; performance is not.

And finally the old chestnut - if it's already fast enough then your job is done. If you're hitting your target framerate, if you have headroom for transient conditions, then it's good enough and you can move on to the next step. You can waste a lot of time and energy squeezing an extra 10% out of something that doesn't actually need it (been there, done that, still fall into the trap) so always consider what the most optimal use of your own time is - because programmer time is even less cheap and less plentiful than performance!


You must log in to answer this question.

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