This subject, as with any optimisation problem, gets hit on a lot, but I just couldn't find what I (think) I want.

A lot of tutorials, and even SO questions have similar tips; generally covering:

  • Use GL face culling (the OpenGL function, not the scene logic)
  • Precalculate anything you can
  • Use interleaved Vertices
  • Minimize as many GL calls as possible, batch where appropriate

And possibly a few/many others. I am (for curiosity reasons) rendering 28 million triangles in my application using several vertex buffers. I have tried all the above techniques (to the best of my knowledge), and received almost no performance change.

Whilst I am receiving around 40FPS in my implementation, which is by no means problematic, I am still curious as to where these optimisation 'tips' actually come into use?

My CPU is idling around 20-50% during rendering, therefore I assume I am GPU bound for increasing performance.

Note: I am looking into gDEBugger at the moment

Cross posted at StackOverflow

  • 4
    \$\begingroup\$ If you are rendering 28 million triangles to a display with only 4 million pixels then some of the computation must be wasted. \$\endgroup\$
    – finnw
    Jul 1, 2011 at 15:08
  • \$\begingroup\$ And your advice is? \$\endgroup\$ Jul 1, 2011 at 23:50
  • \$\begingroup\$ I guess what @finnw is saying and so do I: you try to optimize for a case that will not happen in a real game, because if it was a real game, you had worse problems than a 40 fps GPU with 28 million triangles, because a real game has any sort of interaction/processing with those triangles (hit tests/space partitioning/skinning) and not only sending them to the GPU like you do now, no CPU can handle that, so again you are optimizing for a impossible case, so its useless in the first place \$\endgroup\$ Jul 2, 2011 at 8:29
  • \$\begingroup\$ Given that you need around 32 bytes per point (point, normal, texture coordiantes etc) multiplied with 28*10^6*3 points, that is 2.5 GB only for the points. This is way over the budget for any game, since memory must be moved, processed and manipulated. Games are not static, things change over time. Not to speak of memory available on current gen consoles. But even if it wasn't over the budget, it's still a huge waste, since as @finnw pointed out, you will only see a very few of those triangles. There is not much you can learn from this setup, except to avoid premature optimizations. \$\endgroup\$ Jul 2, 2011 at 9:20
  • \$\begingroup\$ I think your missing the point, I was just interested in seeing if there was anything else that was obvious in improving performance, as was pointed out in an answer below, I could use extensions to really push for performance. It was so I could avoid spending too much time on optimisation; I wanted to make sure I'd done all the basic micro-level optimisations first. For what its worth, I only have ~5MB of vertex data. And since when can I not ask questions out of curiosity? It may not be a situation you can think of; and I'm not after your opinion. \$\endgroup\$ Jul 2, 2011 at 10:27

5 Answers 5


as far as I know those are good optimization techniques but since new GPUs are beasts in matrix vector operations, maybe in your case you need to use more effective optimization techniques for example you may use frustum culling , dynamic level of detail ,occlusion culling, try to minimize state changes by sorting (you can also sort based on shaders ), minimize copying from/to GPU memory.

  • \$\begingroup\$ So to clarify from what has been said by both yourself and Sam, there are not many options left in the low level. I am probably best to begin moving up to another level (ie past the 'rendering' and 'vbo' abstraction, to mesh level optimisations (frustum culling, edge collapses, LODs etc). \$\endgroup\$ Mar 9, 2011 at 10:21
  • \$\begingroup\$ yes that what I meant \$\endgroup\$
    – concept3d
    Mar 9, 2011 at 10:53
  • \$\begingroup\$ I'd say there are not many obvious options left in the low level. Only profiling will tell. You could be shader instruction bound, texture lookup bound, fill rate bound... \$\endgroup\$ Mar 9, 2011 at 10:55
  • \$\begingroup\$ Granted, I meant obvious. \$\endgroup\$ Mar 9, 2011 at 11:19
  • \$\begingroup\$ Please realize that low level optimizations will only apply to your video card, driver revision and CPU combination, on different setups the balances will shift. \$\endgroup\$ Dec 9, 2011 at 17:47

28 Million triangles at 40fps is 1120Million triangles/sec. This is pretty close to peak rates for top end graphics cards (what are you using?), so it wouldn't surprise me if you are simply limited by the clipping or setup hardware max throughput. The only way to get faster is to draw less triangles.

For your specific questions: •Use GL face culling (the OpenGL function, not the scene logic)

The hardware can avoid rasterization of invisible on-screen clipping. Helps most when your geometry is on screen and you are raster limited (or limited by memory bandwidth, or z-test performance). Turn it on (assuming you have closes/2-manifold objects).

•Precalculate anything you can

As someone said in another answer, you have more triangles than pixels. You may have all sub-pixel sized triangles, but more likely the triangles are either overdrawing each other on the screen, or they are off screen and clipped. For the former, you can look into occlusion culling techniques (occlusion queries, visibility pre-processing, z-pass rendering, front to back rendering, etc.). For the latter, you should group spatial coherent triangles (i.e., compact objects) into some sort of spatial hierarchy (be it an octree or a simple bounding box per object), and manually reject chunks of triangles on the CPU, in order to avoid even making the draw calls for those objects.

•Use interleaved Vertices

What is this? Are you referring to tessellation?

•Minimize as many GL calls as possible, batch where appropriate

This is a benefit if you are CPU limited. BTW, are you sure that no core is running at 100%? All it takes is one to become likely CPU limited. The taskmanager reports the idleness of ALL cores.


Look into macro-optimizations.

  • Don't render details you don't notice anyway. Sounds obvious? Well, if your game is a spacesim, an optimization could be scaling the level of detail, where you have different models for different distances. If your game is a closed-quarters first person shooter, you can use a BSP tree to only render the rooms that are in range.

  • Removing duplicate calculations. Animations can be shared and textures can be pre-blended.

  • Is the bottleneck in lighting? You could try reducing the number of lights or even do lighting deferred. Is the bottleneck in shader code? Try simplifying them and hardcode values.


You will probably not get any further without serious GPU profiling. gDEBugger is indeed an excellent start. However, chances are that your design is simple enough that you are indeed maximising the GPU's capabilities.

I also strongly suggest you start thinking about simplifying the geometry, for instance with LODs. At the moment you have 10 to 15 times more triangles than real pixels on the screen. That doesn't make much sense to me. You should start thinking about which triangles could be merged or even completely removed.


You can also explore some data types and traffic optimizations - you can for example use half float instead of float (if you don't need really accurate positions). If it's not enough and you want to decrease traffic, you can use ARB_vertex_type_2_10_10_10_rev, which is even smaller (4 coordinates - xyzw - in 32 bits).

If you have more models with few vertices (few indices), you can also use ARB_draw_elements_base_vertex (you can find some material here), you can send unsigned short or byte indices instead of unsigned int (you will save 3/4 or 1/2 of its size).

If you have more VBOs and you frequently use glBindBuffer, you can use NV_vertex_buffer_unified_memory (there is also example on that site).

These OpenGL extensions don't increase performance too much if you have just few vertices, but you have a lot of triangles, so it could be worth a try.

There is also more such extensions, like Vertex array range. You have to search.


You must log in to answer this question.

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