OpenGL ES 1.1 Tutorial
Contents[hide] |
Introduction
Unfortunately, the OpenGL ES takes away many of the functions that beginner programmers use. They do this, because a lot of those functions are plain rubbish for any high-end application. We're only covering ES 1.1 here, but the Pandora also supports ES 2.0, which, leaves you with a handful of functions, you have to do all of the matrix math on your own. Which can be really hard if you're not good at maths, I'll cover how to do that in a later tutorial. What you're learning here isn't just for the Pandora, you should use these new methods in your Windows/Linux code. These changes are being made to the core OpenGL too, so you're loosing all of this stuff soon enough. Which is silly, OpenGL is good because beginners can pick it up easily. But whatever, I'm not in charge.
The Basics
glBegin() and glEnd()
glBegin(GL_TRIANGLES);
glVertex3f(1,0,0); glVertex3f(0,1,0); glVertex3f(-1,0,0);
glEnd();
You know what I just did? Yeah, I drew a triangle! Nope, you can't draw stuff like this in OpenGL ES 1.1, so how would one draw a triangle in ES? Bare with me while you read this if you don't understand it, I'll explain it in depth.
GLfloat vertices[] = {1,0,0, 0,1,0, -1,0,0};
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableClientState(GL_VERTEX_ARRAY);
This is called drawing with a vertex array. Eww? Yeah, you would never draw like that in a real program, your vertex array would be stored already, you wouldn't have to define it every time you drew somthing. While it's messy for drawing primitives, it's really cool for drawing models, because your models vertices are generally stored in arrays like that already. I'll show you an example from TINCS after I explain this code.
GLfloat vertices[] = {1,0,0, 0,1,0, -1,0,0};
This should be obvious, we're simply creating an array that stores the vertices of our triangle. It can be of any size, you can store as many vertices as you want. Note, how I space out every three numbers, this is because a vertex is made of X,Y,Z components. So we have our X, our Y, our Z then a space for the next three. You don't have to space it like this, it's mainly so you can see what's going on.
glEnableClientState(GL_VERTEX_ARRAY);
We need to do this before we start drawing, this tells OGL that we're going to feed it a vertex array from the client side (rather than the server, which is the graphics card).
glVertexPointer(3, GL_FLOAT, 0, vertices);
Ok, here is where we're telling OGL where to get it's vertices from. The first argument, tells OGL how many components (or floats) there are per vertex. Remember we talked about how we were spacing them out every 3 numbers? Here we're telling OGL that we did that! The next argument tells OpenGL that we're giving it floating point numbers. Now we have a "0". This is called the stride, I could explain it in detail, but you don't need to understand it yet. Just leave it at 0. In the last argument we give OGL our vertex array!
glDrawArrays(GL_TRIANGLES, 0, 3);
Here is where the work is done. The first argument is telling OGL that we're drawing in triangles. (This can be GL_QUADS, GL_LINES, whatever!). The second is specifying where we want to start in the array we passed OGL earier. The last one is telling OpenGL how many vertices we want to draw. In this case, it's just the three.
glDisableClientState(GL_VERTEX_ARRAY);
Finally, we're disabling the vertex array state. We're done!
So this is one of the ways to draw stuff in OpenGL. It's the next step up from glBegin and glEnd and it works fine in ES 1.1, so it works fine on the Pandora!
Drawing Textured Quads
OpenGL can be great for speeding up your 2D application. One of the ways you do this, is by drawing with OpenGL rather than SDL. 2D games are made up of lots of sprites, which are just images that move about in a 2D world. You can use hardware acceleration to speed this up. If you're only planning on using 3D stuff on the Pandora, read this anyway, it introduces you to texturing with texture arrays and you're probably going to need to use sprites somewhere anyway.
So, we can pick apart my method of sprite drawing in TINCS for this tutorial, I mainly use this function to draw text, once it's been rendered by SDL_ttf and converted into a OpenGL texture, but never mind any of that.
static void DrawSprite(GLuint sprite, float X, float Y, float Z, float W, float H) { glBindTexture(GL_TEXTURE_2D,sprite);
GLfloat box[] = {X,Y + H,Z, X + W,Y + H,Z, X + W, Y, Z, X,Y,Z}; GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3, GL_FLOAT, 0,box); glTexCoordPointer(2, GL_FLOAT, 0, tex);
glDrawArrays(GL_QUADS,0,4);
glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); }
Give it a good read, make sure you understand all of the stuff we've been over before and how it's applied in this example! Also, I'm not sure how this will fare in the 3D realm, I only use it when I'm in Ortho mode (2D, drawing ma GUI).
Right!
glBindTexture(GL_TEXTURE_2D,sprite);
As you can see here, binding the texture that's passed to the function to GL_TEXTURE_2D. You should understand this already. (If not, hit up NeHes tutorials!)
GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};
This is new too, what we've done, is got the texture co-ordinates that we would usually pass to OGL per-vertex. (glTexCoord2f() style) Then put them into a little array.
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
Just like last time, we're enabling a state on the client (not the server), this one tells the GPU we want to pass a texture coordinate array too.
glTexCoordPointer(2, GL_FLOAT, 0, tex);
Here we're passing the texture coordinates to OGL. Exactly like the vertex coordinates, except that the first argument (the size) is only two. This is because we only need two values per texture coordinate (a U and a V).
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
We disable the texture coordinate array just like we did with the vertex array.
There we go! That's not much harder than SDL blit is it? I guarantee it will make your app run a whole bunch faster too :D
Conclusion
This is all you need to know to use OpenGL on the Pandora. Note, you can't open your window like you would in SDL/Linux/Windows, it's a little bit different in OpenGL ES and I'll go over that in my Combining OpenGL ES 1.1 and SDL to create a window on the Pandora tutorial! Remember, you can and should use this knowledge for regular OpenGL!
I want to add one last section about drawing models once I've released the source to my model format loader/drawer