How to properly use open gl calls with libGDX

Tags: , ,



I am trying to render a terrain using my own shader and by using low level open gl methods. But other parts of the game use SpriteBatch and other GDXlib render classes.

My openGL code for terrain renders correctly until I make a call to:

spriteBatch.draw(...);

or something similar like:

stage.draw();

After that call, my openGL code just not draw anymore. No error, just nothing on screen. But SpriteBatch works just OK.

After a loooong time, I figured out that I need to call

glEnableVertexAttribArray(...);    

and

Gdx.gl.glBindBuffer(GL20.GL_ARRAY_BUFFER, posVertexBufferLoc);
Gdx.gl.glVertexAttribPointer(positionAttribLoc, 4, GL20.GL_FLOAT, false, 0, 0);

I NEED TO CALL IT BEFORE I CALL -> glDrawArrays(…);

EVERY TIME BEFORE I USE glDraw… , -> EVERY FRAME

If I don’t call first one, nothing is rendered.

If I don’t call second one, it renders at the wrong positions.

It looks like everytime I use GDXlib classes to render, it somehow messes my attributes up.

Init code:

shaderProgram = new ShaderProgram(baseVertexShader, baseFragmentShader);
if (!shaderProgram.isCompiled()) {
    Gdx.app.error("TerrainRenderer - Cannot compile shader", shaderProgram.getLog());
}

shaderProgram.begin();

//vertexBuffers
vertexBuffer = BufferUtils.newFloatBuffer(quadPosVertices.length);
vertexBuffer.put(quadPosVertices);
vertexBuffer.rewind();
//VBOs
//generate buffers
posVertexBufferLoc = Gdx.gl.glGenBuffer();
//pass data into buffers
Gdx.gl.glBindBuffer(GL20.GL_ARRAY_BUFFER, posVertexBufferLoc);
Gdx.gl.glBufferData(GL20.GL_ARRAY_BUFFER, vertexBuffer.capacity()*4, vertexBuffer, GL20.GL_STATIC_DRAW);
//attributes
//locations
positionAttribLoc = shaderProgram.getAttributeLocation("position");
//attributes specifications
Gdx.gl.glBindBuffer(GL20.GL_ARRAY_BUFFER, posVertexBufferLoc);
Gdx.gl.glVertexAttribPointer(positionAttribLoc, 4, GL20.GL_FLOAT, false, 0, 0);
//enabling attributes
shaderProgram.enableVertexAttribute(positionAttribLoc);
//end shader
shaderProgram.end();
Gdx.gl.glBindBuffer(GL20.GL_ARRAY_BUFFER, 0); //unbind

Draw code:

Gdx.gl.glBindBuffer(GL20.GL_ARRAY_BUFFER, posVertexBufferLoc);
Gdx.gl.glVertexAttribPointer(positionAttribLoc, 4, GL20.GL_FLOAT, false, 0, 0);

shaderProgram.enableVertexAttribute(positionAttribLoc);

shaderProgram.begin();
Gdx.gl.glDrawArrays(GL20.GL_TRIANGLES, 0, 6);
shaderProgram.end();
Gdx.gl.glBindBuffer(GL20.GL_ARRAY_BUFFER, 0);

So What is the correct way to use openGL methods with GDXlib classes? Do I really need to call those attribute functions every frame?

Answer

OpenGL is a state machine. When libGDX is doing something with OpenGL it will inevitably change the state of the OpenGL context to something different.

The canonical way to draw stuff in OpenGL is:

  1. Set every state you depend on to the values you need for drawing.

  2. Then draw it.

For the longest time OpenGL didn’t have VAOs (vertex array objects) and you had in fact to do a glBindBuffer, glVertexAttribPointer combo every time you switched vertex buffers. Most OpenGL drivers are well optimized in that code path, and for a matter of fact, back when when VAOs got introduced, using them impaired performance. That’s no longer the case, but it used to be.

Also you can’t improve performance by “saving” on OpenGL calls. OpenGL isn’t that low level and in many ways operates a lot like a modern out-of-order-execution CPU: As long as the outcome is identical to what would render if every command was done in order it can delay and rearrange operations.



Source: stackoverflow