光照模型
如果我们希望渲染出的物体像是处于有若干光源照明的场景中。根据物体表面性质和光源的位置,每个物体不同的部分反射光的多少也不同。光照模型(lighting model)就是试图描述光源发出的光线和场景中的物体是如何相互作用。现实世界的光照过程是无法精确模拟,需要计算机近似处理。OpenGL把现实世界的光照系统近似分为三个部分:光源、材质和光照环境。
光源
OpenGL提供了许多函数用来设置光源和物体表面材质属性。理解并掌握其中所有的变化和细节会比较乏味,所以我们在这里只介绍基本的用法。OpenGL允许定义八个光源,依次用GL_LIGHT0、GL_LIGHT1等命名。每个光源可以设置不同的属性,也可以被开启或关闭。每个属性都有默认的赋值。
光源位置和类型
用于指定光源位置的OpenGL符号属性常数是 GL_POSITION。实际上,这个符号常数用来同时设置光源的两个特性:光源位置和光源类型。OpenGL中用于照明场景的光源有两个基本类:方向光源和位置光源。光源位置和光源类型用有一个四元浮点数向量来指定,如果该向量的第四个元素为0.0, 则该光源是方向光源(如light2PosType)。该光源是非常远的光源,发出的光仅允许向一个方向发射,该方向应用到场景中的所有表面,与指定的光源位置无关。该方向按从光源位置到坐标原点的方向计算。如果该向量的第四个元素为1.0, 则该光源是位置光源(如light1PosType)。该光源是局部光源或近光源,发出的光向所有方向辐射,该光源位置被光照子程序用来确定场景中每个对象的光照方向。
GLfloat light1PosType[] = {2.0, 0.0, 3.0, 1.0};
GLfloat light2PosType[] = {0.0, 1.0, 0.0, 0.0};
glLightfv(GL_LIGHT1, GL_POSITION, light1PosType);
glEnable(GL_LIGHT1);
glLightfv(GL_LIGHT2, GL_POSITION, light2PosType);
glEnable(GL_LIGHT2);
光源颜色
OpenGL允许为一个光源发出的三种不同光——环境光、漫反射和镜面反射,设置不同的颜色。我们使用符号颜色特性常量GL_AMBIENT、GL_DIFFUSE和GL_SPECULAR来设定这些颜色。每个颜色的分量按次序(R,G,B,A)指定,分量A仅用于颜色混合函数激活以后。例如:
GLfloat blackColor[] = {0.0, 0.0, 0.0, 1.0};
GLfloat whiteColor[] = {1.0, 1.0, 1.0, 1.0};
glLightfv(GL_LIGHT3, GL_AMBIENT, blackColor);
glLightfv(GL_LIGHT3, GL_DIFFUSE, whiteColor);
glLightfv(GL_LIGHT3, GL_SPECULAR, whiteColor);
光源GL_LIGHT0的默认颜色是环境光为黑色而漫反射和镜面反射为白色。所有其他光源的环境光、漫反射及镜面反射颜色特性均为黑色。
GL_AMBIENT设置环境光, 环境光是无方向性的,在场景中均匀照射所有物体。环境光成分是从某个光源发出,并由环境经多次散射得到的,难以确定其最初的方向——它看起来好像来自于四面八方。
GL_DIFFUSE设置漫反射,散射光来自一个固定方向,所以当光线垂直照射到物体表面上,要比斜照时亮一些。然而,一旦光线照到表面上,就会均匀地在各个方向都发生散射,因此,不论观察点处于哪个位置,其亮度都是一样的。来自于特定位置与方向的任何光线,都可能带有散射光成分。
GL_SPECULAR设置镜面反,镜面反射也来自于特定方向,但她趋于反射到特定的方向上。一束校准好的激光射到高质量的镜面上,几乎可以产生100%的镜面反射。镜面反射度可以看成代表着物体的光洁度。
光源的辐射强度衰减系数
我们可以为OpenGL局部光源设置辐射强度衰减系数。光线辐射强度衰减的三个OpenGL特性常量是GL_CONSTANT_ATTENUATION、GL_LINEAR_ATTENUATION和GL_QUADRATIC_ATTENUATION,每一个辐射衰减系数用正整数或正浮点数来设定。
glLightf(GL_LIGHT6, GL_CONSTANT_ATTENUATION, 1.5);
glLightf(GL_LIGHT6, GL_LINEAR_ATTENUATION, 0.75);
glLightf(GL_LIGHT6, GL_QUADRATIC_ATTENUATION, 0.4);
在衰减系数的值设定后,光线衰减函数应用于该光源的所有三种颜色(环境光、漫反射和镜面反射)。
材质属性
在相同的光源条件下,不同物体的表面呈现明显不同的视觉表现,最大的区别就是不同材料的表面有不同的视觉表现,这反映了物体表面的物理属性,一般由材质属性来设置表现的。我们需要在描述对象几何数据之前使用系列glMaterial函数来指定该对象的所有光照特性。
glMaterial*(surfFace, surfProperty, propertyvalue)
参数surfFace参数选择,GL_FRONT(为正面设置属性),GL_BACK(为背面设置反射系数),GL_FRONT_AND_BACK(为两面同时设置属性)。
示例演示
给GL_LIGHT1光源设置三种颜色、位置及类型,通过键盘L控制开启关闭灯光。
GLfloat lightAmbient[] = {1.0f, 0.5f, 0.5f, 1.0f}; //环境光参数
GLfloat lightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; //漫散光参数
GLfloat lightSpecular[] = {1.0f, 1.0f, 1.0f, 1.0f}; //镜面反射参数
GLfloat lightPosition[] = {0.0f, 0.0f, 2.0f, 1.0f}; //光源位置,局部光源
glLightfv(GL_LIGHT1, GL_AMBIENT, lightAmbient); //设置环境光
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightDiffuse); //设置漫射光
glLightfv(GL_LIGHT1, GL_SPECULAR, lightSpecular); //镜面反射后
glLightfv(GL_LIGHT1, GL_POSITION,lightPosition); //设置光源位置
glEnable(GL_LIGHT1); //启动一号光源