Keeping track of OpenGL state can be a pain in the bum, especially with pluggable rendering. The obvious approaches - of blindly setting all desired state or always returning to some known baseline - make unnecessary GL calls and can be error-prone.
So, here’s some code to handle it all for you. JavaDoc is here, and you can browse the svn over there.
Setting up OpenGL with blending, depth testing and a texture enabled looks like
State s = new State();
s.blend.enabled = true;
s.blend.srcFactor = SourceFactor.SRC_ALPHA;
s.blend.destFactor = DestinationFactor.ONE_MINUS_SRC_ALPHA;
s.depthTest.enabled = true;
s.depthTest.func = ComparisonFunction.LEQUAL;
s.texture.id = myTexID;
s.texture.filter.min = MinFilter.LINEAR_MIPMAP_LINEAR;
s.texture.filter.mag = MagFilter.LINEAR;
s.texture.wrap.s = TextureWrap.CLAMP;
s.texture.wrap.t = TextureWrap.CLAMP;
s.apply();
Nice features:
- Applying a state will result in the minimum number of calls to OpenGL needed to transition from the current state to the new one
- Type-safe: no more GL_INVALID_ENUM, only valid values are presented for code-completion
- Sortable: States are Comparable, and sorting a list of them on that basis will cluster similar states together, with priority given to the most expensive state changes (shader and texture changes). Use this to batch up your rendering to minimise state changes and maximise the amount of data you can squirt to OpenGL in one go
- Comparison can be made fast: You’ll probably end up only using a fixed number of State objects that won’t change often, so it seems a bit wasteful to have to compare the whole tree of state settings every time. Worry not, comparisons between states that have been passed into the same call to compile only involve one integer subtraction, or you can use getCompiledIndex() to directly address an array. Subsequent changes to compiled States will raise assertion errors, as you’ve probably messed up the ordering
The only thing to look out for is fairly obvious - The system won’t know about changes made to OpenGL state outside of state.apply(), so if you call glDisable( GL11.GL_DEPTH_TEST ) manually, depth testing will stay disabled despite applying a state with it enabled. Of course, this can also be useful, e.g.: switching to wireframe mode without changing all your State objects.
Also remember to call State.resetState() when OpenGL is initialised e.g.: on display re-creation.
The set of opengl state currently managed is:
- Shader. Only one example at the moment
- Alpha test
- Alpha blending
- Depth test
- Lighting parameters
- Polygon rasterisation mode
- Polygon offset
- Texture
You can specify that you want to control only a subset of these facets at State construction and reduce the work needed to compare and transition between states.
Does anyone have any suggestions for more that should be handled?
This is currently written for LWJGL, but it wouldn’t take much to covert to JOGL (just add the passing around of the gl instance, change GL** to GL, etc)
Also note that the clever shadery bits were nicked from the SPGL and the distance-field rendering from Slick.
edit: added jar download, javadoc links