GLES

From Pandora Wiki
Revision as of 00:23, 6 October 2013 by Kingu (talk | contribs) (Kingu moved page OpenGL ES 1.1 Tutorial to GLES: Too long and shouldnt be specific to GLES1.1)
Jump to: navigation, search

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? Bear 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


Reference and learning material

Books

  • OpenGL ES 2.0 Programming Guide (OpenGL) (NB - Amazon.co.uk link) - This is a great book, very much like the defacto stadard text for OpenGL - the Red Book - I highly recommend this if you are serious about it. (£34+)

Online

Tools

(See also Development_Tools)

First, you will need to be able to test and run your programs on your development machine. For this you will need an OpenGL ES emulator and the OpenGL ES SDK. Note that to run the emulator on your machine, you need an OpenGL 2.0 compliant graphics card, any nVidia 6XXX+ or ATi 95XX+ should work. BUT you do not need any special graphics hardware if you only want to compile an application on your PC, and test it on the Pandora.

  • OpenGL ES 2.0 SDK for PC[1] This works both on Linux and Windows. You will need to register with imgtec before downloading.

Running an OpenGL ES application on your PC is not as simple as just downloading the SDK, building some demos, and running them. To run the demo applications, you will need to set a few environment variables so that your system can find the necessary libraries. Or, you can add the libraries to your system path as appropriate.

Directions for the linux version of the SDK - tested on Ubuntu Gutsy:

  • LD_LIBRARY_PATH needs to be set to the SDK folder containing the OpenGL ES libraries such as libEGL.so. ($SDK_PATH/Builds/OGLES2/LinuxPC/Lib should work)
  • To run the makefiles in the Training section you need to set a PLATFORM variable to either LinuxPC or LinuxGeneric. I have had success with LinuxPC.
  • See [2] for a script that you can run to set these for you.
  • If you are not afraid to use the commandline, try "export LD_LIBRARY_PATH=$SDK_PATH/Builds/OGLES2/LinuxPC/Lib" and "export PLATFORM=LinuxPC", where $SDK_PATH is the path of the unpacked SDK, such as "/home/username/OGLES_SDK/".

Directions for the Windows version of the SDK - tested on Windows Vista with Visual C++ Express Edition [3] :

  • The SDK works almost out of the box, with some minor modifications. The default configuration on VC++ works if you just want to compile. To actually run the code or debug it, you need to link VC++ with the PowerVR OGL ES emulation libraries. This can be done in two different ways:
    • By adding the path to the libraries in VC++. Go to (Tools > Options > Projects and solutions > VC++ Directories). Choose Library files in the drop-down menu labeled as Show directories for: and add the path to the libraries (SDKPackage\Builds\OGLES2\WindowsPC\Lib by default)
    • By copying the files in the (SDKPackage\Builds\OGLES2\WindowsPC\Lib) folder (libEGL.dll, libEGLv2.dll, etc) and pasting them in the Windows folder, which is already a default path in VC++. This method is preferred, since all the executables and projects that came with the SDK were programmed to find the DLL's in the folders that are configured by the default VC++ configuration.
  • Note that the projects included in the SDK were programmed in an older version of the VC++ IDE and need conversion if you are using the express edition. [4] This procedure is almost automatic and should not cause any problems. [5]
  • GLUT|ES