Where to initialize OpenGL objects after the init method has passed?

Lets say your init() call is over and you are now in the infinite display() call loop.

You now need to set up a new VBO or shader that was not needed at init() time.

The method I have used in the past is to essentially have an if statement every time you need to use your new VBO to ensure it has been set up before using it.

Would it be a good or bad idea to set up the VBO using the Threading class to remove the if statement?

Here is some pseudocode to explain myself:


constructor() {
	if (Threading.isOpenGLThread()) {
		setUpVBO(GLContext.getCurrent().getGL());
	} else {
		Threading.invokeOnOpenGLThread(new Runnable() {
			public void run() {
				setUpVBO(GLContext.getCurrent().getGL());
			}
		});
	}
}

render() {
	//Just use VBO
}

rather than


constructor() {
	//Nothing
}

render() {
	if(notSetUp) {
		setUpVBO(gl);
	}
	//Use VBO
}

The more I think about it it seems like a bad idea since you don’t know when and where the GL stuff will be executed even if it is definately on the GL thread.

Personally I use the second approach as well. This approach is also very useful because the underlying gl context can be destroyed by certain java windowing activity (adding/removing, going to fullscreen(?), and similar things).

Ditto for the second method: personally I keep my GL stuff out of the constructor and have GL stuff happening in init/render/delete(GL) methods.

I pass the GL reference to my constructor and initialise everything there, it works out very nicely. I’m big on RAII.

It is a very bad idea, I did the same thing in TUER until September and using a fresh GL reference instead of doing this has solved some problems, especially for people using my source code in windowed mode whereas my game is in full screen mode. Rather use GLU.getCurrentGL() and ensure you are allowed to call this.

No gouessej, you kept the reference around even after the frame was rendered. That’s very bad indeed.

KILER simply passes the ref to the constructor, and initializes everything in the constructor. That’s safe.

You’re right but if he kept this reference passed to the constructor to render the VBO, it would be unsafe.

That was never an issue. I made sure to read documentation thoroughly before doing something.
https://jogl.dev.java.net/nonav/source/browse/checkout/jogl/doc/userguide/index.html?rev=HEAD&content-type=text/html

Under the section “Writing a GLEventListener”:

[quote]It is strongly recommended that applications always refetch the GL object out of the GLAutoDrawable upon each call to the init(), display() and reshape() methods and pass the GL object down on the stack to any drawing routines, as opposed to storing the GL in a field and referencing it from there.
[/quote]
Sample init code:


public void init(GLAutoDrawable drawable) {
        GL gl = drawable.getGL();
        ...
        this.prog = new ShaderProgram(gl, vert, geo, frag);
        ...

Render code:


public void display(GLAutoDrawable drawable) {
        GL gl = drawable.getGL();
        prog.enable(gl);
               ...
        prog.disable(gl);
        ...

OP:
If I need to initialise a new object within the game, I use an existing renderable item (I load up everything in the first shot) and change it’s properties. For instance, properties of shaders can be changed like:


public void enable(GL gl) {
        gl.glUseProgram(this.id);
        
        while(!this.glVariables.isEmpty()) {
            GLSLVariable variable = this.glVariables.remove(0);
            int location = variable.getLocation(gl, this.id);
            variable.setValue(gl, location);
        }
    }

On the other hand if you wish to pass new geometry it would be worth looking into various data structures and patterns (The state pattern looks suited to this) depending on your existing design.

Thanks for your replies.

After some more experimenting I am using the following:


RenderableObject {
	constructor {
		GL gl = GLU.getCurrentGL();
		inititalize(gl);
	}
	
	private initialize(GL gl) {
		//Initialize FBOs, VBOs, Programs...
	}

	public render(GL gl) {
		//Render without testing if FBOs, VBOs, Programs are initialized...
	}

}

This means the RenderableObject must be created on the GL thread and most likely from the init() or display() methods of the GLEventListener.

This should reduce the number of ugly if statements and seems to be the way the official utility classes like Texture work.


Now here is question 1. Instead of


	public render(GL gl) {
		//Render without testing if FBOs, VBOs, Programs are initialized...
	}

I could have


	public render() {
		GL gl = GLU.getCurrentGL();
		//Render without testing if FBOs, VBOs, Programs are initialized...
	}

Would you expect the latter be slower?
If GLU.getCurrentGL() is called in my render method it will be invoked many times per frame whereas using GLU.getCurrentGL() in the constructors would result in negligible invocations… so…


Now question 2, a state question, which would be more efficient?

	
public render(GL gl) {
	gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
	gl.glEnableVertexAttribArray(attribIndex);
	gl.glEnableClientState(GL.GL_COLOR_ARRAY);
	gl.glEnableClientState(GL.GL_NORMAL_ARRAY);
		
	//Use VBOs...
}

or

	
public render(GL gl) {
	GLState.ensureGLEnableClientState(GL.GL_VERTEX_ARRAY);
	GLState.ensureGLEnableVertexAttribArray(attribIndex);
	GLState.ensureGLEnableClientState(GL.GL_COLOR_ARRAY);
	GLState.ensureGLEnableClientState(GL.GL_NORMAL_ARRAY);
		
	//Use VBOs...
}

where GLState.ensureGLABC(D) would remember the last call of glABC and only call glABC if D is different from the previous call’s arguments.

EDIT: well not exactly that as it doesn’t depend on the last invokation of glDisableClientState(…), but I just mean in general recording the state of the machine to reduce gl calls…


I would appreciate any thoughts on these questions.