在写第四部分文章时,当我使用了 glLightfv()glLightf()两种版本时,我突然意识到我还从来没有解释过OpenGL的命名规则。这部分应该属于第一部分,随OpenGL数据类型一起介绍。

 

在OpenGL中,没有使用任何参数并在函数尾不具有数据类型代号的函数只有一个:

    GL_ENUM error = glGetError();

 

另外,只具有一个参数(GL_ENUM)而且不具有函数尾数据类型代号的函数有:

 glEnable(GL_COLOR_ARRAY);

 

大部分OpenGL函数都是适用于不止一种数据类型。这在普通版OpenGL中尤为明显,大部分函数都有至少半打变种,允许你传递诸如 GLshort, GLbyte, GLint, GLfloat, GLDouble,或 GLfixed值或参考。在OpenGL ES中,函数调用的变种和数据类型少得多。然而,OpenGL ES仍然遵循同样的命名规则,所以最好还是要理解这些数据类型代号的含义。

 

函数名后的第一或者第二个字母代表了数据类型。下面是说明:

   
   
   
   
  • b    GLbyte
  • s    GLshort
  • i    GLint
  • f    GLfloat
  • ub   GLubyte
  • us   GLushort
  • ui   GLuint

 

所以 glFoof()需要传递一个glFloat,glFoos()则需要一个 GLshort

注意: 在常规 OpenGL中,后缀中可能还包括数字。这些数字代表需要的数据类型的数量。例如,函数glVertex3f()使用三个GLfloat。由于此命名模式大部分用于直接模式,而OpenGL ES并不支持,所以在OpenGL ES中你不会常见到这种命名规则,然而有些函数还是遵循这种规则的,例如, glColor3f()。保持后缀中的数字可以使这两类API最大限度地兼容。

 

再回头看看第四部分,有时函数提供更通用的功能,如glLightf()。你可以调用此函数设置指定光的不同属性。例如,你可以设定点光源的截止角或者光源在3D空间的位置。点光源截止角需要一个值,但光源位置需要三个值。

 

对于这类函数,通过在函数尾加上一个 v 来表示。如果你想要传递常规数据类型给OpenGL,那么你不要使用此后缀,而是直接传递数据类型值。但是,如果你想要传递不止一个OpenGL原生数据类型( 即第一部分列表中的数据类型),那么你需要将这些值放入数组中并将数组开始的指针传递给OpenGL。当你像这样传递参考值给 OpenGL 时,你想要在函数后加上v后缀。

 

所以,回到第四部分的例子,当我们设置点光源的截止角时,我们使用了没有 -v的版本:

 glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 45.0);

 

而当我们传递光源位置时,它需要三个GLfloats值,所以我们使用有v的版本:

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