| 1. Fri May 15, 2015 - Understanding LibGDX's OpenGL ES abstractions

Badlogic Games • View topic - Understanding LibGDX's OpenGL ES abstractions

Understanding LibGDX's OpenGL ES abstractions

Anything libgdx related goes here!

Understanding LibGDX's OpenGL ES abstractions

Postby libbyjix » Fri May 15, 2015 5:53 pm
*EDIT #2* - I created a blog documenting my adventures into libGDX's source code and where/how libGDX internally calls OpenGL ES commands. This hopefully helps someone else who wants to effectively leverage libGDX's abstraction. The best entrance point is if you've already read into how OpenGL ES works and then want to see how libGDX internally calls it. The blog is here: http://clarityncode.blogspot.com/

*EDIT* - I'm updating this thread with new questions as I work through libGDX's code. Questions are at bottom of this post.

Hey all, I'm simultaneously working through how opengl es 2.0 commands work (official wiki, pdfs, etc.) and how libGDX abstracts those commands away (working through the code on github) so I can fully use what libGDX offers. First up is the process of specifying vertex attributes and uploading those to a VBO (vertex buffer object). In raw opengl es commands it looks something like this:

Code: Select all
//create some points
vertices = new float[]{
                0.0f,  0.0f, 0.0f, // Vertex 1 (x, y, z)
                0.5f, 0.5f, -1.0f, // Vertex 2 (x, y, z)
                0.5f, 0.1f, 0.5f  // Vertex 3 (x, y, z)
        };
//create VBO
vbb = ByteBuffer.allocateDirect( vertices.length * 4 ); //float is 4 bytes, so multiply num vertices by 4.
vbb.order( ByteOrder.nativeOrder() );
vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put( vertisees.toArray() );
vertexBuffer.position( 0 );

//set vbo as array buffer
vbo = Gdx.gl.glGenBuffer();
Gdx.gl.glBindBuffer(Gdx.gl.GL_ARRAY_BUFFER, vbo);
Gdx.gl.glBufferData( Gdx.gl.GL_ARRAY_BUFFER, vertices.length * 4, vertexBuffer, Gdx.gl.GL_DYNAMIC_DRAW );


LibGDX has a set of classes to help with this: VertexAttribute.java, VertexAttributes.java, VertexBufferObject.java, VertexBufferSubData.java, etc. To keep things simple I started with just a single VertexAttribute instance. The code comment of VertexAttribute.java says:

Code: Select all
A single vertex attribute defined by its {@link Usage}, its number of components and its shader alias. The Usage is needed for
the fixed function pipeline of OpenGL ES 1.x. Generic attributes are not supported in the fixed function pipeline. The number
of components defines how many components the attribute has. The alias defines to which shader attribute this attribute should
bind. The alias is used by a {@link Mesh} when drawing with a {@link ShaderProgram}. The alias can be changed at any time.


Questions:
1. (Solved: see 1st post by Mats and xoppa) OpenGL ES 1.x. is no longer supported by libGDX according to http://www.badlogicgames.com/wordpress/?p=3311. Yet when I look at the test examples on github I see the Usage being initialized as (Usage.Position | Usage.Normal). These two values are defined in VertexAttributes.java as equaling 1 and 8, respectively. What does OR'ing them accomplish? Is this used as a sort of dummy value in opengl es 2.0?

2. (Solved) From the official opengl wiki here https://www.opengl.org/wiki/Vertex_Shader#Inputs, vertex attributes are said to be "User-defined input values to vertex shaders...", so wouldn't a single vertex attribute correspond to a single shader variable? I'm assuming this isn't correct since "number of components" means a single VertexAttribute can have multiple of something.
*EDIT* - nvm this 2nd question, I found the answer here: https://www.opengl.org/wiki/Vertex_Specification#Vertex_format. For anyone reading, a single vertex attribute is defined as a vector of 1 - 4 values (e.g. a 3D position would be a 3-value <x,y,z> vector)

3. In the above code, vertices are specified in a float array and then uploaded to a VBO. Does libGDX provide a class that handles dynamically resizing a VBO to match an array (e.g. adding vertices on the fly in a, say, 3D modeling program/editor)? I notice the setBuffer() function in VertexBufferObject.java but it says "use with care!" in comments. Is this function meant for this use case? I'm familiar with libGDX's Array.java class and how an underlying static array is made dynamic with functions like resize() and shrink(). I'm looking for functionality for VBO's like that.

All help is greatly appreciated. Thanks :)
Last edited by libbyjix on Fri Jun 05, 2015 3:56 pm, edited 9 times in total.
libbyjix
 
Posts: 18
Joined: Fri May 15, 2015 5:07 pm

Re: Understanding LibGDX's OpenGL ES abstractions

Postby Mats » Sat May 16, 2015 3:07 am
I don't know what the attributes in question 1 does, exactly, but I can tell you about ORing them:

In binary
8 => 1000
1 => 0001

so when having flags in your code, it's normal to do that by having values where each flag has a different bit set to 1. Because this enables you to combine multiple flags. Notice that | is not the same as ||. | is a bitwise or. So (8 | 1) will be (1000 | 0001) in which each bit is ORed, so the result is 1001. So when you pass this value, the function can see that both the flag corresponding to values 8 and 1 is enabled.
Image Image Image
Mats
 
Posts: 224
Joined: Fri Sep 23, 2011 8:17 am

Re: Understanding LibGDX's OpenGL ES abstractions

Postby libbyjix » Sat May 16, 2015 10:40 am
Hey, thanks for the response.

Notice that | is not the same as ||. | is a bitwise or. So (8 | 1) will be (1000 | 0001) in which each bit is ORed, so the result is 1001. So when you pass this value, the function can see that both the flag corresponding to values 8 and 1 is enabled.


Yep, I double-checked before I posted to make sure I wasn't mixing up Java's logical OR and bitwise OR. Your explanation confirms that libGDX is setting the Usage flags to indicate both Position and Normal. Which leads to my question: are Usage values being set for "legacy code" reasons (the part of code that was written with OpenGL 1.x in mind before support for it was dropped) or are the Usage values now being used in ES 2.0 in some way?

I'm still working my way up through the levels of abstraction so maybe I'll stumble upon the "aha!" point later ;)
libbyjix
 
Posts: 18
Joined: Fri May 15, 2015 5:07 pm

Re: Understanding LibGDX's OpenGL ES abstractions

Postby xoppa » Sat May 16, 2015 11:07 am
That's just a convenience method of the 3d api, see: https://github.com/libgdx/libgdx/blob/m ... .java#L118. While the usage isn't strictly required for rendering, the API uses it to identify various types of attributes. For example MeshBuilder knows that it needs to calculate vertex normals if you include a VertexAttribute of type Usage.Normal. Likewise the shader might cache the attribute location based on usage rather than a (costly) string lookup (based on the alias). Also comparing or sorting attributes is typically done based on the usage instead of the alias.

tl;dr: Usage is not specific to a gles version. It was required for gles1, but it is still useful in gles2.
xoppa
 
Posts: 689
Joined: Thu Aug 23, 2012 6:27 pm

Re: Understanding LibGDX's OpenGL ES abstractions

Postby libbyjix » Sat May 16, 2015 9:34 pm
Thank you for the response. So Usage is used as metadata hints for the API, gotcha.
libbyjix
 
Posts: 18
Joined: Fri May 15, 2015 5:07 pm

Re: Understanding LibGDX's OpenGL ES abstractions

Postby libbyjix » Fri May 22, 2015 1:58 pm
I've updated this thread with a new question relating to my original post.
libbyjix
 
Posts: 18
Joined: Fri May 15, 2015 5:07 pm

Re: Understanding LibGDX's OpenGL ES abstractions

Postby libbyjix » Fri Jun 05, 2015 3:17 pm
I've updated the original post with (hopefully) helpful information.
libbyjix
 
Posts: 18
Joined: Fri May 15, 2015 5:07 pm



Return to Libgdx

Who is online

Users browsing this forum: Bing [Bot], Google [Bot], libbyjix and 1 guest