1.1 光照
光照法向量(Light Normals)告诉OpenGL顶点的周围是怎样的反射光线。可以想像在顶点有一个很小的镜子,而光照法向量就表示镜子的方向,对于不同的法向量,反射出来的光的方向也不相同。
glNormal用来设置当前的法向量,当设置的新的法向量后,所有顶点的光照颜色将重新计算。光照法向量应该归一化以校正光照效果,使用glScale函数不仅可以对顶点坐标,几何体进行比例缩放,同样也能够适用于光照法向量。glEnable(GL_NORMALIZE)可以让OpenGL自动对光照法向量进行归一化。
OpenGL支持两种类型的光源:定向光源和点光源。定向光源是来自某一固定方向,但是光源在无限远处。点光源在场景中有一个位置,是近光源。
在OpenGL中要使用光源,必须使用glEnable(LIGHTING)启用光照,否则,对光源的任何操作都无效。若不使用光照,则使用glDisable(LIGHTING)即可。如果没有光源,启动光照后,场景中的所有物体都是黑色的,因此,还必须使用glEnable(GL_LIGHTi)建立光源才可以。i表示光源号,范围是0~7,也就是说至少可以使用8个光源。根据glGetIntegerv(GL_MAX_LIGHTS, &lightnum)得到的值也是8,说明最多可以使用8个光源。
光源本身具有各种性质,如颜色、位置、衰减因子等。如果没有事先进行设置,OpenGL对8个光源都有缺省值,其中GL_LIGHT0的环境光缺省值是黑色,也表示没有,漫射光和镜面光均为白色。仅仅使用OpenGL的缺省值肯定是不能满足应用程序的需要的。设置光源的函数是glLight,其原型如下:
void glLightf(
GLenum light,
GLenum pname,
GLfloat param
);
void glLighti(
GLenum light,
GLenum pname,
GLint param
);
void glLightfv(
GLenum light,
GLenum pname,
const GLfloat *params
);
void glLightiv(
GLenum light,
GLenum pname,
const GLint *params
);
其中light参数表示光源名称,取值GL_LIGHTi,0≤i< 8。对glLighti和glLightf两个函数,参数pname表示要设置的光源的参数,参数param是light对应的pname的值。
对于glLightfv和glLightiv两个参数,pname取值如下。pname取值不同,对应的params含义和取值也不同。如下表7-1给出了pname取不同值时,对应params的含义。
表7-1 glLight参数含义说明
pname取值 |
对应params含义 |
GL_AMBIENT |
params参数表示环境光的值,格式为(R,G,B,A),表示环境光的Red、Green、Blue、Alpha份量。整数值将被映射到[-1.0, 1.0]间。缺省值为(0.0, 0.0, 0.0, 1.0). |
GL_DIFFUSE |
params参数表示漫射光的值,格式为(R,G,B,A),表示漫射光的Red、Green、Blue、Alpha份量。整数值将被映射到[-1.0, 1.0]间。光源GL_LIGHT0的缺省值为(1.0, 1.0, 1.0, 1.0),其他光源的缺省值为(0.0, 0.0, 0.0, 1.0)。 |
GL_SPECULAR |
params参数表示镜面光的值,格式为(R,G,B,A),表示镜面光的Red、Green、Blue、Alpha份量。整数值将被映射到[-1.0, 1.0]间。光源GL_LIGHT0的缺省值为(1.0, 1.0, 1.0, 1.0),其他光源的缺省值为(0.0, 0.0, 0.0, 1.0)。 |
GL_POSITION |
params参数表示光源所在的位置,格式为(x, y, z, w),分别表示X、Y、Z坐标,w表示齐次坐标。整数值和浮点数值都直接应用到三维空间中。 如果w为0,则表示该光源是一定向光,漫射光和镜面光的计算是以方向为准,光线衰减被禁止。如果w为1,那么漫射光和镜面光的计算是以真实的位置为准,光线衰减有效。缺省值是(0,0,1,0),表示光源是一定向平行光,平行Z轴,方向是从Z轴射向-Z轴。 |
GL_SPOT_DIRECTION |
params参数表示点光源的聚光方向,格式为(x, y, z)。整数值和浮点数值均直接映射到三维空间中。当调用glLight时模型观察矩阵对聚光方向进行变换。当GL_SPOT_CUTOFF取值是180时,聚光方向是没有意义的,而GL_SPOT_CUTOFF的缺省值正是180。所以,如果要设置聚光方向,必须修改GL_SPOT_CUTOFF的值。聚光方向的缺省值是 (0,0,–1). |
GL_SPOT_EXPONENT |
params参数表示点光源聚光指数,取值范围为[0,128]。 聚光指数越高表示光源聚光能力越强,如同舞台上的聚光灯,光照圆圈中心的光强度越高。缺省值为0,表示没有聚光,整个光源内外是强度是相同的。 |
GL_SPOT_CUTOFF |
params参数是点光源的聚光截止角,表示点光源的发散范围。点光源的发散模型通常是用圆锥体来模拟,圆锥体的顶点是点光源所在位置,圆锥体的顶点角度就是聚光截止角。聚光截止角的取值范围是[0,90]和180,当取值为0时表示没有光线发射出来,当取值90时表示光源照亮的是三维空间中的一半,另一半没有光照。当取值180时表示光线向整个空间发散。缺省值是180。 |
GL_CONSTANT_ATTENUATION GL_LINEAR_ATTENUATION GL_QUADRATIC_ATTENUATION |
params参数表示光线衰减因子。GL_CONSTANT_ATTENUATION 是常数衰减因子,表示随着距离的增加,光线并没有衰减,即各处的光强度相同。GL_LINEAR_ATTENUATION是线性衰减因子,表示随着距离的增加,光强度线性衰减,距离越远,强度越弱。GL_QUADRATIC_ATTENUATION是平方衰减因子,表示随着距离的增加,强度和距离的平方呈线性关系。 参数的取值可以是正整数也可以是正的浮点数,都直接映射到三维空间中。如果是负值,OpenGL将忽略。 整个光源的衰减因子是: GL_CONSTANT_ATTENUATION+GL_LINEAR_ATTENUATION*距离+GL_QUADRATIC_ATTENUATION*距离^2。 三个参数的缺省值是 (1,0,0),表示没有衰减。 |
params和前面的param不同,它是一个指针,表示pname的具体值。
在程序中如果需要了解当前光源的各种属性,使用glGetLightfv和glGetLightiv可以达到目的。两个函数的原型如下,它们的参数含义和glLightfv、glLightiv相同。
void glGetLightfv(
GLenum light,
GLenum pname,
GLfloat *params
);
void glGetLightiv(
GLenum light,
GLenum pname,
GLint *params
);