光照

来源:互联网 发布:淘宝客流量是什么意思 编辑:程序博客网 时间:2024/04/29 05:41

一、光照

  OpenGL场景描述中可以包含多个光源,光源的各种属性设置使用函数:

  void glLight{if} (GLenum light, GLenum pname, TYPE param);

 void glLight{if}v (GLenum light, GLenum pname, TYPE *param);

指定。其中,参数light指定进行参数设置的光源,其取值可以是符号常量GL_LIGHT0GL_LIGHT1GL_LIGHT7;参数pname指定对光源设置何种属性,其取值参见表1;参数param指定对于光源lightpname属性设置何值,非矢量版本中,它是一个数值,矢量版本中,它是一个指针,指向一个保存了属性值的数组。


1 参数pname的取值及其含义

1点光源的颜色

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

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

3)聚光灯

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

4)光强度衰减

属性GL_CONSTANT_ATTENUATIONGL_LINEAR_ATTENUATIONGL_QUADRATIC_ATTENUATION分别指定了衰减系数kcklkq,用于指定光强度的衰减。

OpenGL中,必须明确启用或禁用光照。默认情况下,不启用光照,此时使用当前颜色绘制图形,不进行法线矢量、光源、光照模型、材质属性的相关的计算。要启用光照,可以使用函数:

glEnable(GL_LIGHTING);

指定了光源的参数后,需要使用函数:

glEnable(light);

启用light指定的光源。当然也可以用light参数调用glDisable函数,禁用light指定的光源。需要特别说明的是,点光源的位置和方向是定义在场景中的,与景物一起通过几何变换和观察变换变换到观察坐标系中,因此光源既可以与场景中对象的相对位置保持不变,也可以使光源随观察点一起移动。

5光照模型

  OpenGL中,还需要设定全局光照(相当于背景光)。OpenGL提供了下面的函数对全局光照的属性进行定义。

void glLightMode{if} (GLenum pnameTYPE param);

void glLightMode{if}v (GLenum pnameTYPE *param);

其中,参数pname指定全局光照的属性,其取值参见表2;参数param指定进行设置的属性的值。

 

 


2 参数pname的取值及含义

 属性GL_LIGHT_MODEL_AMBIENT指定OpenGL场景中的背景光,如果不指定,系统使用低强度的白色(0.20.20.21.0)光。

镜面反射时,视点的位置影响反射区的计算,那么当视点在无穷远时,场景中的所有顶点到视点方向都相同,当采用的是近视点时,则需要计算每个顶点的方向,因此总体的性能有所降低,但结果的真实感更强。而在默认的情况下,认为视点位于无穷远处,要使用近视点,我们就可以把属性值 GL_LIGHT_MODEL_LOCAL_VIEWER指定为GL_TRUE

在有些应用中,需要看到物体的后面,例如实体的内部剖视图。此时需要打开双面光照,即对物体的前向面和后向面都进行光照计算。

光照计算中,通常是分别计算环境光、表面散射光、漫反射光和镜面反射光的贡献,然后将其叠加。默认情况下,纹理映射在光照处理之后进行。但这样镜面高光区的纹理图案会变得不太理想。为此,可以将GL_LIGHT_MODEL_COLOR_CONTROL指定为GL_SEPARATE_SPECULAR_COLOR,在纹理映射之后应用镜面颜色。这样,对于光照计算将生成两个颜色:镜面反射颜色和非镜面反射颜色。纹理图案先和非镜面反射颜色混合,然后再和镜面反射颜色混合。

6OpenGL表面材质   

在启用了光照后,物体表面的颜色将由照射在其上的光的颜色以及物体的材质属性决定。所谓物体的材质属性,就是物体表面对各种光的反射系数。在OpenGL中使用下面的函数设定:

void glMaterial{if} (GLenum face, GLenum pname, TYPE param);

void glMaterial{if}v (GLenum face, GLenum pname, TYPE *param);

其中,face的取值可以是符号常量GL_FRONTGL_BACKGL_FRONT_AND_BACK,指定当前设定的材质属性应用于物体表面的前向面、后向面还是前后向面,这使得可以对物体内外表面设置不同的材质属性,在打开双面光照的情况下产生特殊的效果。参数pname指定设置的材质属性,其取值参见表3;参数param设置属性的值。


3 参数pname的取值及含义

属性GL_AMBIENTGL_DIFFUSE的值定义了物体表面对环境光和漫射光中RGB颜色分量的反射系数。如果使用属性GL_AMBIENT_AND_DIFFUSE,那么物体表面的环境光和漫射光将使用相同的反射系数。

镜面反射可以在物体表面形成高光区域。OpenGL中通过改变属性GL_SPECULAR的值改变物体表面对镜面反射光的反射率,还可以通过属性GL_SHININESS的值改变高光区域的形状和大小。GL_SHININESS属性值的取值范围为[0.0128.0],值越大,高光区域越小、光线集中程度越高。

在很多的应用中,有时希望物体亮一些,特别是对于一些表示光源的物体,此时可以通过GL_EMISSION属性使物体表面看起来有点发光。

在设定了材质属性之后,物体的最终颜色是由其材质属性的RGB值和光照属性的RGB值共同决定的。例如,如果当前环境光源的RGB值为(0.51.00.5),而物体材质的环境反射系数为(0.50.50.5),那么物体表面的环境光颜色为:

0.5×0.51.0×0.50.5×0.5=0.250.50.25

即将每个环境光源的成分与材质的环境反射率相乘。这样,物体表面的颜色为多项RGB值的叠加:包括材质对环境光的反射率与环境光结合的RGB值,材质对漫反射光的反射率与漫反射光结合的RGB值,材质对镜面光的反射率与镜面反射光结合的RGB值等。当叠加的RGB中任何一个颜色分量的值大于1.0,那么就用1.0计算。

但是,在这种设定下,有时很难判断出物体在光照环境中的颜色,为此OpenGL提供了另一种材质模式,即颜色材质模式

7颜色材质模式

可以通过函数:void glColorMaterial (GLenum face, GLenum mode);设置。

其中,参数face可以取GL_FRONTGL_BACKGL_FRONT_AND_BACK,指定物体的哪个面的材质属性使用颜色材质模式;而参数mode允许的取值是GL_AMBIENTGL_DIFFUSEGL_SPECULARGL_AMBIENT_AND_DIFFUSEGL_EMISSION,指定将更新哪种材质属性。

在使用了颜色材质模式后,需要调用:

glEnable(GL_COLOR_MATERIAL);

这样,可以通过glColor函数来指定物体表面的颜色,而相应的材质属性将通过颜色值和光源的RGB值计算出来

8)光源的光强度数学计算:

发射光 + 传播衰减系数 * 聚光衰减系数 * ( 环境光 + 漫射光 + 高光 )

1. 传播衰减系数


表示光源与物体间距d对光强的影响,OpenGL  ES实际上可指定常量衰减因子kc, 线性衰减因子k1, 平方衰减因子kq,三者合起来( kc + k1*d + kq*d2 )才是总的传播衰减系数。

2)聚光衰减因子

表达的是聚光灯的聚光特性——光锥的中心最亮,越往边缘越暗,与光线偏离中心线的角度有关。


 

3)漫射光(diffuse


OpenGLOpenGL ES中,漫反射的光照模型是通过朗伯反射定律(Lambertian Reflection)模拟的,在该定律中,单位面积所反射的光量跟观察者的位置无关。


则漫反射的光照方程为:

其中, = N * LMd为材质的漫反射系数,Ld是光源的亮度。

3)环境光(ambient

      由于环境光是没有方向的光源,它从各个方向均衡的照射到物体表面,所以光照方程为:

I = Ia * Ma

其中,Ia是环境光的光亮度,Ma为材质的环境反射系数。

4)镜面高光(specular

假设 L向量:光源--->顶点,N: 法向量,Eye向量: 顶点--->EyeR: 反射光。

Phong模型:

Phong模型表明分量正比于反射光与观察点向量的夹角的余弦值(cosine)。当EyeR的夹角越大,specular越衰减, 衰减系数由shininess控制。shininess越大,衰减越快。


由于RL关于N的对称向量,由于LN都已经规格化,LN上的投影为N ,注意,这里R = S - N ,其中S = L - N ,所以R =

L - 2N ,所以得到:


所以镜面高光的光照方程:

其中,Ls为镜面光的光亮度,Ms为材质的镜面反射系数,sshininess

Blinn-Phong光照模型:


OpenGLES中,我们使用的是Blinn-Phong光照模型,该模型是Phong的简化版, 它是基于Half-Vector的,Half-Vector是入射光与Eye的中间向量。如下图:


新的镜面反射项系数:

其中HHalf-Vector = Eye – L,当LOCAL_VIEWERFALSE时,Eye为(001)。这时候,镜面高光的光照方程:

其中,Ls为镜面光的光亮度,Ms为材质的镜面反射系数,sshininess


因此,最终的顶点颜色的计算公式是:


 

      

 

原创粉丝点击