【转】OpenGL光照处理

转自:http://cs.hust.edu.cn/webroot/courses/csgraphics/jiaocai.php?bookpage=10_e

10.5 OpenGL中的光照处理

OpenGL点光源

 

    在OpenGL场景描述中可以包含多个点光源,光源的各种属性设置使用函数:
        void glLight{if} (GLenum light, GLenum pname, TYPE param);
        void glLight{if}v (GLenum light, GLenum pname, TYPE *param);
指定。其中,参数light指定进行参数设置的光源,其取值可以是符号常量GL_LIGHT0,GL_LIGHT1,…,GL_LIGHT7;参数pname指定对光源设置何种属性,其取值参见表10-1;参数param指定对于光源light的pname属性设置何值,非矢量版本中,它是一个数值,矢量版本中,它是一个指针,指向一个保存了属性值的数组。

表10-1 参数pname的取值及其含义

 

 

    (1)点光源的颜色
    点光源的颜色由环境光、漫反射光和镜面光分量组合而成,在OpenGL中分别使用GL_AMBIENT、GL_DIFFUSE和GL_SPECULAR指定。其中,漫反射光成分对物体的影响最大。

    (2)点光源的位置和类型
    点光源的位置使用属性GL_POSITION指定,该属性的值是一个由4个值组成的矢量(x,y,z,w)。其中,如果w值为0,表示指定的是一个离场景无穷远的光源,(x,y,z)指定了光源的方向,这种光源被称为方向光源,发出的是平行光;如果w值为1,表示指定的是一个离场景较近的光源,(x,y,z)指定了光源的位置,这种光源称为定位光源。

    (3)聚光灯
    当点光源定义为定位光源时,默认情况下,光源向所有的方向发光。但通过将发射光限定在圆锥体内,可以使定位光源变成聚光灯。属性GL_SPOT_CUTOFF用于定义聚光截止角,即光锥体轴线与母线之间的夹角,它的值只有锥体顶角值的1/2。聚光截止角的默认值为180.0,意味着沿所有方向发射光线。除默认值外,聚光截止角的取值范围为[0.0,90.0]。GL_SPOT_DIRECTION属性指定聚光灯光锥轴线的方向,其默认值是(0.0,0.0,-1.0),即光线指向z轴负向。而GL_SPOT_EXPONENT属性可以指定聚光灯光锥体内的光线聚集程度,其默认值为0。在光锥的轴线处,光强最大,从轴线向母线移动时,光强会不断衰减,衰减的系数是:轴线与照射到顶点的光线之间夹角余弦值的聚光指数次方。

    (4)光强度衰减
    属性GL_CONSTANT_ATTENUATION、GL_LINEAR_ATTENUATION、GL_QUADRATIC_ATTENUATION分别指定了衰减系数c0,c1和c2,用于指定光强度的衰减。

    在OpenGL中,必须明确启用或禁用光照。默认情况下,不启用光照,此时使用当前颜色绘制图形,不进行法线矢量、光源、光照模型、材质属性的相关的计算。要启用光照,可以使用函数:
        glEnable(GL_LIGHTING);
指定了光源的参数后,需要使用函数:
        glEnable(light);
启用light指定的光源。当然也可以用light参数调用glDisable函数,禁用light指定的光源。需要特别说明的是,点光源的位置和方向是定义在场景中的,与景物一起通过几何变换和观察变换变换到观察坐标系中,因此光源既可以与场景中对象的相对位置保持不变,也可以使光源随观察点一起移动。

 

OpenGL全局光照

 

    在OpenGL中,还需要设定全局光照(相当于背景光)。OpenGL提供了下面的函数对全局光照的属性进行定义。
        void glLightMode{if} (GLenum pname,TYPE param);
        void glLightMode{if}v (GLenum pname,TYPE *param);
其中,参数pname指定全局光照的属性,其取值参见表10-2;参数param指定进行设置的属性的值。

表10-2 参数pname的取值及含义

 

    属性GL_LIGHT_MODEL_AMBIENT指定OpenGL场景中的背景光,如果不指定,系统使用低强度的白色(0.2,0.2,0.2,1.0)光。
    镜面反射时需要几个矢量参数,包括从物体表面到观察位置的矢量V,它指出表面位置与观察位置的关系。矢量V的默认方向为正z方向(0.0,0.0,1.0),如果不希望用默认值而使用位于观察坐标原点的实际观察位置来计算V,则将GL_LIGHT_MODEL_LOCAL_VIEWER属性值指定为GL_TRUE。
    在有些应用中,需要看到物体的后向面,例如实体的内部剖视图。此时需要打开双面光照,即对物体的前向面和后向面都进行光照计算。
    在光照计算中,通常是分别计算环境光、表面散射光、漫反射光和镜面反射光的贡献,然后将其叠加。默认情况下,纹理映射在光照处理之后进行。但这样镜面高光区的纹理图案会变得不太理想。为此,可以将GL_LIGHT_MODEL_COLOR_CONTROL指定为GL_SEPARATE_SPECULAR_COLOR,在纹理映射之后应用镜面颜色。这样,对于光照计算将生成两个颜色:镜面反射颜色和非镜面反射颜色。纹理图案先和非镜面反射颜色混合,然后再和镜面反射颜色混合。

 

OpenGL表面材质

 

    在启用了光照后,物体表面的颜色将由照射在其上的光的颜色以及物体的材质属性决定。所谓物体的材质属性,就是物体表面对各种光的反射系数。在OpenGL中使用下面的函数设定:
        void glMaterial{if} (GLenum face, GLenum pname, TYPE param);
        void glMaterial{if}v (GLenum face, GLenum pname, TYPE *param);
其中,face的取值可以是符号常量GL_FRONT,GL_BACK,GL_FRONT_AND_BACK,指定当前设定的材质属性应用于物体表面的前向面、后向面还是前后向面,这使得可以对物体内外表面设置不同的材质属性,在打开双面光照的情况下产生特殊的效果。参数pname指定设置的材质属性,其取值参见表10-3;参数param设置属性的值。

表10-3 参数pname的取值及含义

 

    属性GL_AMBIENT和GL_DIFFUSE的值定义了物体表面对环境光和漫射光中R,G,B颜色分量的反射系数。如果使用属性GL_AMBIENT_AND_DIFFUSE,那么物体表面的环境光和漫射光将使用相同的反射系数。
    镜面反射可以在物体表面形成高光区域。OpenGL中通过改变属性GL_SPECULAR的值改变物体表面对镜面反射光的反射率,还可以通过属性GL_SHININESS的值改变高光区域的形状和大小。GL_SHININESS属性值的取值范围为[0.0,128.0],值越大,高光区域越小、光线集中程度越高。
    在很多的应用中,有时希望物体亮一些,特别是对于一些表示光源的物体,此时可以通过GL_EMISSION属性使物体表面看起来有点发光。
    在设定了材质属性之后,物体的最终颜色是由其材质属性的RGB值和光照属性的RGB值共同决定的。例如,如果当前环境光源的RGB值为(0.5,1.0,0.5),而物体材质的环境反射系数为(0.5,0.5,0.5),那么物体表面的环境光颜色为:
                                                  (0.5×0.5,1.0×0.5,0.5×0.5)=(0.25,0.5,0.25)
即将每个环境光源的成分与材质的环境反射率相乘。这样,物体表面的颜色为多项RGB值的叠加:包括材质对环境光的反射率与环境光结合的RGB值,材质对漫反射光的反射率与漫反射光结合的RGB值,材质对镜面光的反射率与镜面反射光结合的RGB值等。当叠加的RGB中任何一个颜色分量的值大于1.0,那么就用1.0计算。

但是,在这种设定下,有时很难判断出物体在光照环境中的颜色,为此OpenGL提供了另一种材质模式,即颜色材质模式,可以通过函数:
        void glColorMaterial (GLenum face, GLenum mode);
设置。其中,参数face可以取GL_FRONT,GL_BACK,GL_FRONT_AND_BACK,指定物体的哪个面的材质属性使用颜色材质模式;而参数mode允许的取值是GL_AMBIENT、GL_DIFFUSE、GL_SPECULAR、GL_AMBIENT_AND_DIFFUSE或GL_EMISSION,指定将更新哪种材质属性。
    在使用了颜色材质模式后,需要调用:
        glEnable(GL_COLOR_MATERIAL);
这样,可以通过glColor函数来指定物体表面的颜色,而相应的材质属性将通过颜色值和光源的RGB值计算出来。

posted on 2012-07-06 21:17  没有什么能够阻挡  阅读(803)  评论(0编辑  收藏  举报

导航