OpenGL提供了多种形式的光源,如点光源
、平行光源
和聚光灯光源
等。全部光源都使用 glLight*接口来设置光源属性,其中包括 glLight{if} 和 glLight{if}v 两类。code
GLfloat ambient[] = {0.3f, 0.3f, 0.3f, 1.0f}; // 环境强度 GLfloat diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; // 散射强度 GLfloat specular[] = {1.0f, 1.0f, 1.0f, 1.0f}; // 镜面强度 // 点光源, GL_POSITION属性的最后一个参数为1 GLfloat position[] = {-3.0f, -3.4f, -8.8f, 1.0f}; glLightfv(GL_LIGHT0, GL_POSITION, position); glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, specular); // 平行光源, GL_POSITION属性的最后一个参数为0 GLfloat direction[] = {-3.0f, -3.4f, -8.8f, 0.0f}; glLightfv(GL_LIGHT1, GL_POSITION, direction); glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT1, GL_SPECULAR, specular); // 聚光灯光源, 须要指定位置、方向、光锥半角 GLfloat spot_direction[] = {-3.0f, -3.4f, -8.8f}; glLightfv(GL_LIGHT2, GL_POSITION, position); glLightfv(GL_LIGHT2, GL_SPOT_DIRECTION, spot_direction); glLightfv(GL_LIGHT2, GL_SPOT_CUTOFF, 45.0); glLightfv(GL_LIGHT2, GL_AMBIENT, ambient); glLightfv(GL_LIGHT2, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT2, GL_SPECULAR, specular);
GL_LIGHT0、GL_LIGHT一、GL_LIGHT二、...、GL_LIGHT七、...
等。在片断着色中可经过gl_LightSource[0]、gl_LightSource[1]、gl_LightSource[2]、...、gl_LightSource[7]、...
等内建变量访问各个光源的参数;glEnable(GL_LIGHTING)
启用光照机制,而后使用glEnable(GL_LIGHTx)
与glDisable(GL_LIGHTx)
打开或关闭相应光源(其中x表明光源序号);控制光源的矩阵变换和控制图元的矩阵变换相同,故最终光源表现出来的性质(如点光源位置是固定在世界坐标系某点仍是跟随镜头移动,平行光源的方向在世界坐标系下是不变的仍是跟随相机移动等)与提交光源位置或朝向(glLight*())和视点变换(gluLookAt())的前后顺序是息息相关的。据此咱们能够定义出各式各样的常见光源,如太阳光、白炽灯、汽车前照灯等。对象
若是在视点变换后提交光源位置或朝向,那么光源就能够看做一个普通的几何对象,提交的坐标是在世界坐标系中度量的,对普通几何对象的各类变换一样适用于光源。可通俗的理解为视图变换矩阵做用于光源的位置或朝向参数上,此过程就如同世界坐标系下的普通物体转换至观察坐标系下。
若是程序里没有视点变换,说明世界坐标系和摄像机坐标系重合,光源也能够看做一个普通的几何对象。表现出这种性质的常见光源有太阳光,家里的白炽灯等。示例代码以下:接口
void myDisplay() { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0, 0, 0, 0, 0, -1, 0, 1, 0); GLfloat sun_light_position[] = {-139.5f, -153.4f, -68.8f, 0.0f}; glLightfv(GL_LIGHT0, GL_POSITION, sun_light_position); // 光源的其余参数可在程序初始化时设置 glPushMatrix(); glTranslated(-2.5, 6.9, -184.8); glRotated(87.4, 0, 0, 1); drawOBJ(); glPopMatrix(); ... }
注意:
光源位置或朝向的指定不能处于某个模型的模型变换代码之间(如上例中的glPushMatrix()与glPopMatrix()之间),不然光源参数会受到影响。因此最好将光源位置或朝向设置代码放在紧跟gluLookAt以后。it
若是在视点变换前提交光源位置,视点和光源将捆绑在一块儿,即两者相对位置不变,一块儿运动。此时,能够理解为提交的光源位置是在相机坐标系中度量的(位置参数的默认值是(0.0, 0.0, 1.0, 0.0), 就是在摄像机坐标系中度量的)。亦可通俗的理解为视图变换矩阵未做用于光源的位置或朝向参数上。光源的位置朝向参数在观察坐标系的值会保持不变。
表现出这种性质的常见光源有汽车前照灯(以驾驶员的视角观察视角)或矿工头上的矿灯。示例代码以下:io
void myDisplay() { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); GLfloat sun_light_position[] = {-139.5f, -153.4f, -68.8f, 0.0f}; glLightfv(GL_LIGHT0, GL_POSITION, sun_light_position); // 光源的其余参数可在程序初始化时设置 gluLookAt(0, 0, 0, 0, 0, -1, 0, 1, 0); glPushMatrix(); glTranslated(-2.5, 6.9, -184.8); glRotated(87.4, 0, 0, 1); drawOBJ(); glPopMatrix(); ... }