第三章光照模型及纹理映射基本光照模型1.在现实生活中,当光照在非透明物体上时,部分光线被物体吸收,剩余的部分光线被反射。
人眼依靠这种反射光来感知物体的形状、颜色和其他细节。
从光源投向物体的光称为入射光,从物体表面反射回的光称为反射光。
1.1光照模型概述当光照射到物体表面上时,将出现3种情况:●光从物体表面反射,形成反射光●光穿透物体,形成透射光●光被物体吸收,转化成为物体的内能在上述三种情形的光线中,通常只有前2种情形的光线会对人眼产生视觉效果,使人察觉到物体的色彩变化。
OpenGL用一种近似的光照模型模拟现实世界的光照效果。
在该模型中,仅当物体表面吸收和反射光线时,光源才会起做作用。
每一个物体表面都假定是由某种特性的材料构成的。
一种材料可能发出自己的光线,也可能在各个方向上发散一些射入的光线,还有可能像镜子一样在某个方向强烈地反射入射光。
1.2光照分量在OpenGL的简化光照模型中,将光照分为4个独立的组成部分:辐射光、环境光、漫反射光和镜面反射光。
1)辐射光辐射光是直接从物体或光源发出的,不受任何其他光源的影响。
2)环境光环境光是这样一种光线,它被环境多次反射,以致于连初始方向也难以确定。
这种光线看起来就像来自于所有的方向,当它照在一个物体表面时,它在所有的方向上等量地反射。
3)漫反射光在被照射物体表面的反射光中,那些均匀地向各个方向反射出去的光,称为漫反射光,如黑板反射就属于漫反射光4)镜面反射光镜面反射光是指超一定方向的反射光,如点光源照射光滑金属球表面时,会在球表面形成一个特别亮的区域,呈现所谓的高亮(Highlight>,这就是光源在该物体表面形成的镜面反射光(SpecularLight>。
点光源照射表面光滑的物体时,高亮区域小而亮;而点光源照射表面粗糙的物体时,高亮区域大而不亮。
1.3创建光源光源有许多特性,如颜色、位置、方向等。
不同特性的光源,作用在物体上的效果是不一样的。
1.3.1定义一个简单光源在OpenGL中,定义一个光源是由函数glLight(>来实现的,该函数的原型为:void glLight(GLenum light,GLenum pname>;light为一个光源,pname为光源light指定一个单值的光源参数,其取值及其含义如下表所示:光源的数目与具体的实现的系统有关,但至少支持8个光源。
它们用符号名称GL_LIGHTi相互区别,这里0≤i≤GL_MAX_LIGHTS,如GL_LIGHT0,GL_LIGHT1,…GL_LIGHT7等。
以下的代码定义了一个编号为GL_LIGHT0的光源的例子:GLfloat light_ambient[]={0.0,0.0,0.0,1.0}。
GLfloat light_diffuse[]={1.0,1.0,1.0,1.0}。
GLfloat light_specular[]={1.0,1.0,1.0,1.0}。
GLfloat light_position[]={1.0,1.0,1.0,1.0}。
glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient>。
glLightfv(GL_LIGHT0,GL_DIFFUSE,light_diffuse>。
glLightfv(GL_LIGHT0,GL_SPECULAR,light_specular>。
glLightfv(GL_LIGHT0,GL_POSITION,light_position>。
光源定义完毕后,必须调用glEnable(GL_LIGHT0>打开该光源,否则该光源对场景中的物体不起作用。
1.3.2 启用光源和激活光源在OpenGL中,如果需要使用光源,首先必须启用光照。
启动光照的函数为:glEnable(GL_LIGHTING>。
取消光照的函数为:glDisable(GL_LIGHTING>。
对于具体定义的各个光源,可以为每个光源指定是否使用和停止使用。
以上一个光源GL_LIGHT0为例。
使用GL_LIGHT0光源的函数为:glEnable(GL_LIGHT0>,停止使用GL_LIGHT0光源的函数为:glDisab le(GL_LIGHT0>。
1.4光源属性光源属性主要有光的颜色强度、光源的位置、光源的衰减特性和光源的聚光效果等。
1.4.1光源颜色定义光源的GL_AMBIENT,GL_DIFFUSE和GL_SPECULAR属性时,参数params包含4个整数值或浮点值,它们分别用来指定光源的RGBA环境光、RGBA漫反射光和RGBA镜面反射光。
整数型数值被线性地映射为浮点格式:最大的正数映射为1.0,最小点的负数映射为-1.0,。
浮点型数值则直接映射。
二者不被截断。
所有光源的GL_AMBIENT环境光强度缺省为(0.0,0.0,0.0,1.0>,光源GL_LIGHT0的DIFF USE漫反射光强度缺省值为(1.0,1.0,1.0,1.0>,其他光源的漫反射光强度缺省值为(0.0,0.0,0.0,0.0>。
光源GL_LIGHT0的GL_SPECULA R镜面反射光强度缺省值为(1.0,1.0,1.0,1.0> ,其他光源的镜面反射光强度缺省值为(0.0,0.0,0.0,0.0>。
以下代码将光源GL_LIGHT0的环境光颜色设置为蓝色:GLfloat light_ambient[]={0.0,0.0,1.0,1.0}。
glLightfv(GL_LIGHT0,GL_AMBIENT,light_ambient>。
1.4.2光源的位置光源的位置有2种,一种离场景无限远,另一种在附近。
远的称为方向光源,它射到物体上的光可以认为是平行的,现实生活中,太阳就是这样的光源。
近的称为位置光源,它的具体位置决定了它对场景的作用效果,尤其是决定了光线的投射方向,台灯就是这样的位置光源。
定义光源的GL_POSITION属性时,参数params包含4个整数值或者浮点值,它们用来指定光源在齐次坐标中的位置。
整数型和浮点型都直接映射,不被截断。
下面的代码定义了光源GL_LIGHT0为方向光源,光源方向为(1.0,1.0,1.0>。
GLfloat light_position[]={1.0,1.0,1.0,0.0}。
glLightfv(GL_LIGHT0,GL_POSITION,light_position>。
下面的代码定义了光源GL_LIGHT0为位置光源,光源位置为(1.0,1.0,1.0>。
GLfloat light_position[]={1.0,1.0,1.0,1.0}。
glLightfv(GL_LIGHT0,GL_POSITION,light_position>。
1.4.3光源的衰减自然世界中的光,光线的强度随光源距离的增加而减少。
因为方向光源的距离是无限远的,随距离的增加而衰减其光线强度是没有意义的,因此对方向光源的光线不进行衰减处理。
对于位置光源,OpenGL使用下面的衰减因子来衰减光线的强度。
衰减因子=其中,d为光源位置到物体顶点之间的距离。
●k c为常数衰减因子(GL_CONSTANT_ATTENUATION>,默认值为1.0。
●k e为线性衰减因子(GL_LINEAR_ATTENUATION>,默认值为0.0。
●k q为二次衰减因子(GL_QUADRATIC_ATTENUATION>,默认值为0.0。
注意:GL_CONSTANT_ATTENUATION,GL_LINEAR_ATTENUATION 和GL_QUADRATIC_ATTENUATION属性时,参数params是一个整数值或浮点值,且只能取非负值。
1.4.4聚光效果控制光源聚光效果的参数有3个,它们分别是:聚光的方向GL_ SPOT_DIRECTION、聚光的发散角GL_SPOT_CUTOFF和光源的强度分布GL_SPOT_EXPONENT。
定义光源的GL_SPOT_DIRECTION属性时,参数params包含3个整数值或浮点值,它们用来指定光源在齐次对象坐标中的方向。
整型数值和浮点数值都直接映射。
二者不被截断。
定义光源的GL_SPOT_CUTOFF属性时,参数params是一个整数值或浮点值,它们用来指定一个光源的最大发散角。
整型数值和浮点数值都直接映射。
其取值范围是[0,90]和特殊值180。
如果光照方向与它所照射的顶点的方向之间夹角大于聚光灯的截止角,光线将被完全屏蔽。
否则,光的强度将受到聚光指数和发散因子所控制。
缺省的聚光灯截止角是180,它产生了均匀的发散光。
定义光源的GL_SPOT_EXPONENT属性时,参数params是一个整数值或浮点值,它们用来指定一个光源的强度分布。
整型数值和浮点数值都直接映射。
其取值范围为[0,128]。
有效的光强度是按照光照方向与它所照射的顶点之间的方向之间的夹角的余弦规律衰减的,一直衰减到聚光指数的幂。
因此,较高的聚光指数就会导致一个较高的汇聚光源,而不管其截止角究竟如何。
缺省的聚光指数是0,它产生了均匀的光强衰减方式。
下面的代码定义了光源GL_LIGHT0的聚光方向为(1.0,1.0,1.0 >,发散角为45°:glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,45.0>。
GLfloat spot_direction[]={1.0,1.0,0.0}。
glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,spot_direction>。
1.5小结下面介绍使用一个多光源的实例,其中一个光源是标准的蓝色光源,另一个是红色的聚光灯。
代码见附录。
2.纹理映射纹理映射是真实图形制作的一个重要部分,运用纹理映射可以方便地制作真是图形,而不必花更多的时间去考虑物体的表面纹理。
如一张木制桌子其表面的木纹是不规范的,看上去又是那么自然,如果在图形制作中不用纹理映射,那么只是这张桌子面纹理的设计,就要花费很大精力,而且设计结果也未必能像现实中那么自然。
如果运用纹理映射就非常方便,可以用扫描仪将这样的一张桌子扫成一个位图。
然后具体的操作中,只需把桌面形状用多边形画出来,把桌面纹理贴上去就可以了。
另外,纹理映射能够在多边形进行变换时仍保证纹理的图案与多边形保持一致性。
例如,以透视投影方式观察墙面时,远端的砖会变小,而近处的砖就会大一些。
此外,纹理映射也可以用于其他方面。
例如,使用一大片植物的图像映射到一些一些连续的多边形上,以模拟地貌,或者大理石,木纹等自然物质的图像作为纹理映射到相应的多边形上,作为物体的真实表面。