Monday, May 4, 2009

OpenGL ES From the Ground Up, Part 1 Addendum: Alphabet Soup

One problem with blog postings is that they are self-edited. For my postings here, I have no external technical review and no copy editing done. Mostly, it's not too much of a problem, as smart people read this blog and quickly point out my errors, and people seem to be pretty forgiving of the occasional grammatical or spelling gaffe.

But, sometimes, the result of this being a one-man production is that I miss something that I really, really should have included. While re-reading part 4, I realized that I used both glLightfv() and glLightf() and it occurred to me that I never explained the naming format for OpenGL function calls. Back in part 1, I went through all the trouble of explaining the different OpenGL datatypes, but I didn't explain how they related to the alphabet soup at the end of the function call.

So, let me rectify this for those of you that haven't figured it out already.

OpenGL calls that don't take any parameters don't have alphabet soup at the end.There is only one version of those methods. Here's an example:

    GL_ENUM error = glGetError();

The same is basically true for methods that take only a specific type of parameter, such as GL_ENUM:

    glEnable(GL_COLOR_ARRAY);

However, the vast majority of OpenGL function calls can be made using more than one dataype. This is much more pronounced in regular OpenGL, where most function calls have at least a half-dozen different variants, allowing you to pass GLshort, GLbyte, GLint, GLfloat, GLDouble, or GLfixed by value or by reference. In OpenGL ES, there's a much smaller subset of function calls and datatypes, so it's not quite as daunting or confusing, however OpenGL ES still follows the same naming convention, so it's a good idea to understand what that alphabet soup means.

The first and sometimes the second letter after the name of the function specify the datatype that this method takes. Here is a chart that explains what each suffix refers to:
  • b    GLbyte
  • s    GLshort
  • i    GLint
  • f    GLfloat
  • ub   GLubyte
  • us   GLushort
  • ui   GLuint
So, glFoof() would expect a glFloat to be passed in, while glFoos() would expect a GLshort.
Note: In regular OpenGL, there might also be a number as part of the suffix. This number would represent the number of that datatype that is needed. So, for example, the function glVertex3f() takes three GLfloats. Since this naming convention is mostly used in direct mode, which OpenGL ES doesn't have, you won't see this naming convention as often in OpenGL ES, however there are a few functions that follow this naming convention like glColor4f(). OpenGL ES doesn't support, for example, glColor3f(), but keeps the number as part of the prefix to maximize compatibility between the two APIs

As you saw back in Part 4, sometimes functions serve a more generic purpose, such as glLightf(). You call this method to set many different attributes of a given light. You use this call to set, for example, the spot cutoff as well as the light's position in 3D space. Spot cutoff requires a single value, but the light's position requires three.

For these functions, there is an additional variant marked by a v at the end of the method name, after the datatype letters. If you need to pass a regular datatype to OpenGL, you don't use this suffix and just pass in the datatype you need by value. But, if you need to provide more than a single OpenGL native datatype (in other words, that list from Part 1), then you have to put the values into an array and pass a pointer to the beginning of that array. When you pass values into OpenGL by reference like this, then you use the function call with the v suffix.

So, back in Part 4, when we told OpenGL the spot cuttoff value ,we used the regular non-v version, like this:

    glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 45.0);

but, when we passed in the light's position, which takes three GLfloats, we used the v variant and passed in an array, which is exactly the same thing as passing a pointer to the first value of the array:

    const GLfloat light0Position[] = {0.0, 10.0, 10.0, 0.0}; 
glLightfv(GL_LIGHT0, GL_POSITION, light0Position);

I hope this helps anyone who was confused by the function names. At some point, I'll try and integrate this information into part 1, but I since it was kind of an obvious oversight on my part, I wanted to post it.

No comments:

Post a Comment