8
votes

Since OpenGL is a state machine, I am constantly glEnable() and glDisable()-ing things in my program. There are a select few calls that I make only at the beginning (such as glClearColor) but most others I flip on and off (like lighting, depending on if I'm rendering a model or 3d text or the gui).

How do you keep track of what state things in? Do you constantly set/reset these things at the top of each function? Isn't that a lot of unnecessary overhead?

For example, when I write a new function, sometimes I know what state things will be in when the function is called, and I leave out glEnable or glDisable or other related state-switching calls at the top of the function. Other times, I'm just writing the function in advance and I add in these sorts of things. So my functions end up being very messy, some of them modifying OpenGL state and others just making assumptions (that are later broken, and then I have to go back and figure out why something turned yellow or why another thing is upside down, etc.).

How do you keep track of OpenGL across functions in an object oriented environment?


Also related to this question, is how to know when to use push and pop, and when to just set the value.

For example, let's say you have a program that draws some 3D stuff, then draws some 2D stuff. Obviously the projection matrix is different in each case. So do you:

  1. set up a 3d projection matrix, draw 3D, set up a 2d projection matrix, draw 2d, loop
  2. set up a 3d projection matrix at the program; then draw 3d, push matrix, draw 2d, pop matrix, loop

And why?

3

3 Answers

2
votes

Great question. Think about how textures work. There are an insane amount of textures for OpenGL to switch between, and you need to enable/disable texturing after every object is drawn. You generally try to optimize this by drawing all objects with the same texture at once, but there's still a remarkable amount of state-switching that goes on. Because of this fact, I do my best to draw everything with the same state at once, but I'm not sure if it's terribly important to optimize it the way you're thinking.

As for pushing and popping between 3D and 2D projection modes, pushing and popping is intended to be used for hierarchical modeling. If you need your 2D projection to be at a location relative to a 3D object, by all means, push the matrix and switch to 2D projection mode, then pop when you're done. However, if you're writing a 2D GUI overlay that has a constant location on the screen, I see no reason why pushing and popping is important.

2
votes

You might be interested to read more about scene graph libraries. They are meant to manage your graphics from a higher level. They don't handle everything well, but they excel at organizing your geometry for optimized rendering. They can additionally be used for sorting your scenes based on OpenGL state, although many do not do this. By sorting on state, you can render your geometry in an order that results in the fewer state transitions. Here's a nice overview about scene graph libraries:

http://www.realityprime.com/articles/scenegraphs-past-present-and-future

2
votes

I think the simplest approach would be to write your own render class, wrapping all OpenGL state manipulation functions you are using and do book keeping of the states you set. You need to take into account that changing screen resolution or toggling fullscreen mode will invalidate your current OpenGL render context's states and data, which means that after such an event you will have to set all states, re-upload all textures and shader programs, etc.