How to reset from an arbitrary (unknown) OpenGL state?


#1

Hi there, I have some “black box” OpenGL code, which is very complicated and “has its way” with the OpenGL state. Is there some recipe to get Cinder (v0.9.0 on macOS) back into a known state after calling into my black box code, so it can render its own primitive types (for example using gl::drawStrokedCube() or gl::drawLine())?

I think the problem comes from the VAO and shader program. If I reset it to null (using gl::ScopedVao vao(nullptr)), I get OpenGL errors (GL_INVALID_OPERATION). If I set the shader program to null (using gl::ScopedGlslProg prog(nullptr)), then the call to draw a stroked cube or line returns an error and does nothing (they expect a shader program to be bound, whereas it seems to replace the context’s default VAO using getDefaultVao()).

I’ve also tried explicitly setting the shader program this way, prior to drawing Cinder line primitives:

    gl::ScopedGlslProg prog(gl::context()->getStockShader(gl::ShaderDef().color()));

In either case, I get OpenGL errors. If I add my own checks for glGetError() after each line in the Cinder draw function, I see the error occurs in the call to gl::enableVertexAttribArray(posLoc) in drawStrokedCube() (it’s enabling the posLoc for geom::Attrib::POSITION, which is set to 0, which sounds like a reasonable value). With different combinations of state setting – I may get the OpenGL error in other places.

Can someone give me a “formula” for getting Cinder back in a valid state, so it can draw its own primitive types?

(By the way, everything works fine – it draws with no OpenGL errors – if I first draw an arbitrary Cinder gl::Batch with its own shader program, and then afterward call gl::drawLine() in the same scope).

Thanks,
Glen.


#2

Hi - the integration with AntTweakBar has the same challenge. You might start by looking at the implementation of pushGlState() and popGlState():

In particular the restoreInvalidated*() family of calls in popGlState() might be useful.


#3

Yes, that’s exactly what I was looking for. Simply pushing/popping the GlslProg, plus doing a restoreInvalidatedVao() after calling my external code were enough to do the trick (in my case). If I have problems with other state, I know I can push/pop those as well.

Thanks, Andrew, for the quick reply!

(Maybe these “heavy” push/pop methods (in Params.cpp, above) should be exposed as part of the Cinder API…?)