阅读:1468回复:0
OpenGL系列讲座(13)
7.4 材 质
7.4.1 材质颜色 OpenGL用材料对光的红、绿、蓝三原色的反射率来近似定义材料的颜色。象光源一样, 材料颜色也分成环境、漫反射和镜面反射成分,它们决定了材料对环境光、漫反射光和镜面 反射光的反射程度。在进行光照计算时,材料对环境光的反射率与每个进入光源的环境光结 合,对漫反射光的反射率与每个进入光源的漫反射光结合,对镜面光的反射率与每个进入光 源的镜面反射光结合。对环境光与漫反射光的反射程度决定了材料的颜色,并且它们很相似。 对镜面反射光的反射率通常是白色或灰色(即对镜面反射光中红、绿、蓝的反射率相同)。镜 面反射高光最亮的地方将变成具有光源镜面光强度的颜色。例如一个光亮的红色塑料球,球 的大部分表现为红色,光亮的高光将是白色的。 7.4.2 材质定义 材质的定义与光源的定义类似。其函数为: void glMaterial{if}[v](GLenum face,GLenum pname,TYPE param); 定义光照计算中用到的当前材质。face可以是GL_FRONT、GL_BACK、GL_FRONT_AND_BACK, 它表明当前材质应该应用到物体的哪一个面上;pname说明一个特定的材质;param是材质的 具体数值,若函数为向量形式,则param是一组值的指针,反之为参数值本身。非向量形式 仅用于设置GL_SHINESS。pname参数值具体内容见表2-7-2。另外,参数 GL_AMBIENT_AND_DIFFUSE表示可以用相同的RGB值设置环境光颜色和漫反射光颜色。 ______________________________________________________________________________ 参数名 缺省值 说 明 ______________________________________________________________________________ GL_AMBIENT (0.2,0.2,0.2,1.0) 材料的环境光颜色 GL_DIFFUSE (0.8,0.8,0.8,1.0) 材料的漫反射光颜色 GL_AMBIENT_AND_DIFFUSE 材料的环境光和漫反射光颜色 GL_SPECULAR (0.0,0.0,0.0,1.0) 材料的镜面反射光颜色 GL_SHINESS 0.0 镜面指数(光亮度) GL_EMISSION (0.0,0.0,0.0,1.0) 材料的辐射光颜色 GL_COLOR_INDEXES (0,1,1) 材料的环境光、漫反射光 和镜面光颜色 ______________________________________________________________________________ 表2-7-2 函数glMaterial*()参数pname的缺省值 下面举出一个例子light1.c: 例 2-11 材质定义例程 light1.c #include "glos.h" #include <GL/gl.h> #include <GL/glaux.h> void myinit(void); void CALLBACK myReshape(GLsizei w, GLsizei h); void CALLBACK display(void); void myinit(void) { /* 设置材质的各种光的颜色成分反射比率*/ GLfloat mat_ambient[]={0.8,0.8,0.8,1.0}; GLfloat mat_diffuse[]={0.8,0.0,0.8,1.0}; /* 紫色 */ GLfloat mat_specular[] = { 1.0, 0.0, 1.0, 1.0 }; /* 亮紫色 */ GLfloat mat_shininess[] = { 50.0 }; GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); glLightfv(GL_LIGHT0, GL_POSITION, light_position); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); } void CALLBACK display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); auxSolidSphere(1.0); glFlush(); } void CALLBACK myReshape(GLsizei w, GLsizei h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho (-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0); else glOrtho (-1.5*(GLfloat)w/(GLfloat)h, 1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void main(void) { auxInitDisplayMode (AUX_SINGLE | AUX_RGBA | AUX_DEPTH16); auxInitPosition (0, 0, 500, 500); auxInitWindow ("Lighting_1 "); myinit(); auxReshapeFunc (myReshape); auxMainLoop(display); } 以上程序运行结果是一个紫色的球。在函数myinit()中定义了球的材质颜色,光源的定 义仍延用light0.c 中的,而light.c物体的光源定义为缺省形式。从例子中明显地看出,物 体的材质颜色定义与光源颜色定义几乎一样,物体反射到眼中的颜色与二者都有关系,具体 关系请看下一小节。 7.4.3 材质RGB值和光源RGB值的关系 材质的颜色与光源的颜色有些不同。对于光源,R、G、B值等于R、G、B对其最大强度 的百分比。若光源颜色的R、G、B值都是1.0,则是最强的白光;若值变为0.5,颜色仍为白 色,但强度为原来的一半,于是表现为灰色;若R=G=1.0,B=0.0,则光源为黄色。对于 材质,R、G、B值为材质对光的R、G、B成分的反射率。比如,一种材质的R=1.0,G=0.5, B=0.0,则材质反射全部的红色成分,一半的绿色成分,不反射蓝色成分。也就是说,若OpenGL 的光源颜色为(LR,LG,LB),材质颜色为(MR,MG,MB),那么,在忽略所有其他反射效果的情况 下,最终到达眼睛的光的颜色为(LR*MR,LG*MG,LB*MB)。 同样,如果有两束光,相应的值分别为(R1,G1,B1)和(R2,G2,B2),则OpenGL将各个颜色 成分相加,得到(R1+R2,G1+G2,B1+B2),若任一成分的和值大于1(超出了设备所能显示的亮 度)则约简到1.0。 下面一例light2.c就说明了二者之间的关系。 例 2-12 材质与光源的RGB关系例程 light2.c #include "glos.h" #include <GL/gl.h> #include <GL/glaux.h> void myinit(void); void CALLBACK myReshape(GLsizei w, GLsizei h); void CALLBACK display(void); void myinit(void) { GLfloat mat_ambient[]= { 0.8, 0.8, 0.8, 1.0 }; GLfloat mat_diffuse[]= { 0.8, 0.0, 0.8, 1.0 }; /* 紫色 */ GLfloat mat_specular[] = { 1.0, 0.0, 1.0, 1.0 }; GLfloat mat_shininess[] = { 50.0 }; GLfloat light_diffuse[]= { 0.0, 0.0, 1.0, 1.0}; /* 蓝色 */ GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_POSITION, light_position); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); } void CALLBACK display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); auxSolidSphere(1.0); glFlush(); } void CALLBACK myReshape(GLsizei w, GLsizei h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho (-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0); else glOrtho (-1.5*(GLfloat)w/(GLfloat)h, 1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void main(void) { auxInitDisplayMode (AUX_SINGLE | AUX_RGBA | AUX_DEPTH16); auxInitPosition (0, 0, 500, 500); auxInitWindow ("Lighting_2 "); myinit(); auxReshapeFunc (myReshape); auxMainLoop(display); } 以上程序运行结果是一个蓝色的球,其中高光部分仍为上一例的亮紫色。从上可看出,球 漫反射光的结果是mat_diffuse[]与light_diffuse[]中的三个颜色分量值相乘,即 (0.0*1.0,0.0*1.0,0.8*1.0,1.0*1.0)=(0.0,0.0,0.8,1.0),所以球大部分呈现蓝色。 |
|
|