tags:

views:

456

answers:

3

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?

+1  A: 

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.

bkritzer
Well I'm not sure your first paragraph really addresses the issue, though I'm sure it's largely because I didn't explain myself well enough. I need to come back to this question when I have a clearer idea of exactly what I'm trying to ask. Thanks for the insight on push/pop though, I like that explanation.
Ricket
+1  A: 

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

Eric
Yes, I'm quite familiar with them. I'm using Java, so there's Xith3D and jMonkeyEngine. The problem was that I obsessed over these engines and didn't actually make anything worthwhile. Now that I've been just writing pure OpenGL, I'm actually getting stuff done. Thanks though.
Ricket
It seems like you're re-inventing the wheel a bit. How much of what you have accomplished was already managed by a scene graph library?
Eric
.ms3d file loader with bounding box computation. That's probably about it. What I can't do with a scene graph library, at least easily, is my special heightmap (with planned dynamic loading) and my custom GUI features. So yeah it's a tradeoff, but it's easier for me to write the things a scene graph library can do and then do other things that it can't, rather than use one and try to figure out workarounds and hacks just to be able to draw 2d shapes on the screen or something.
Ricket
+1  A: 

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.

karx11erx