阅读:1693回复:0
OpenGL系列讲座(13续)
7.4.4 材质改变
在实际应用的许多情况下,不同的物体或同一物体的不同部分都有可能设置不同的材质, OpenGL函数库提供了两种方式实现这种要求。下面一例chgmat1.c采用的是设置矩阵堆栈来 保存不同物体的材质信息: 例 2-13 矩阵堆栈改变材质例程 chgmat1.c #include "glos.h" #include <GL/gl.h> #include <GL/glu.h> #include <GL/glaux.h> void myinit(void); void CALLBACK display(void); void CALLBACK myReshape(GLsizei w, GLsizei h); /* 初始化z-buffer、光源和光照模型, 在此不具体定义材质。 */ void myinit(void) { GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat position[] = { 0.0, 3.0, 2.0, 0.0 }; GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 }; glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT0, GL_POSITION, position); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glClearColor(0.0, 0.1, 0.1, 0.0); } void CALLBACK display(void) { GLfloat no_mat[] = { 0.0, 0.0, 0.0, 1.0 }; GLfloat mat_ambient[] = { 0.7, 0.7, 0.7, 1.0 }; GLfloat mat_ambient_color[] = { 0.8, 0.8, 0.2, 1.0 }; GLfloat mat_diffuse[] = { 0.1, 0.5, 0.8, 1.0 }; GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat no_shininess[] = { 0.0 }; GLfloat low_shininess[] = { 5.0 }; GLfloat high_shininess[] = { 100.0 }; GLfloat mat_emission[] = {0.3, 0.2, 0.2, 0.0}; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* 第一行第一列绘制的球仅有漫反射光而无环境光和镜面光。 */ glPushMatrix(); glTranslatef (-3.75, 3.0, 0.0); glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat); glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); auxSolidSphere(1.0); glPopMatrix(); /* 第一行第二列绘制的球有漫反射光和镜面光,并有低高光, 而无环境光 。 */ glPushMatrix(); glTranslatef (-1.25, 3.0, 0.0); glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); auxSolidSphere(1.0); glPopMatrix(); /* 第一行第三列绘制的球有漫反射光和镜面光,并有很亮的高光, 而无环境光 。 */ glPushMatrix(); glTranslatef (1.25, 3.0, 0.0); glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); auxSolidSphere(1.0); glPopMatrix(); /* 第一行第四列绘制的球有漫反射光和辐射光, 而无环境和镜面反射光。 */ glPushMatrix(); glTranslatef (3.75, 3.0, 0.0); glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat); glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission); auxSolidSphere(1.0); glPopMatrix(); /* 第二行第一列绘制的球有漫反射光和环境光, 而镜面反射光。 */ glPushMatrix(); glTranslatef (-3.75, 0.0, 0.0); glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat); glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); auxSolidSphere(1.0); glPopMatrix(); /* 第二行第二列绘制的球有漫反射光、环境光和镜面光, 且有低高光。 */ glPushMatrix(); glTranslatef (-1.25, 0.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, low_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); auxSolidSphere(1.0); glPopMatrix(); /* 第二行第三列绘制的球有漫反射光、环境光和镜面光, 且有很亮的高光。 */ glPushMatrix(); glTranslatef (1.25, 0.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, high_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); auxSolidSphere(1.0); glPopMatrix(); /* 第二行第四列绘制的球有漫反射光、环境光和辐射光, 而无镜面光。 */ glPushMatrix(); glTranslatef (3.75, 0.0, 0.0); glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat); glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission); auxSolidSphere(1.0); glPopMatrix(); /* 第三行第一列绘制的球有漫反射光和有颜色的环境光, 而无镜面光。 */ glPushMatrix(); glTranslatef (-3.75, -3.0, 0.0); glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_color); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat); glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); auxSolidSphere(1.0); glPopMatrix(); /* 第三行第二列绘制的球有漫反射光和有颜色的环境光以及 镜面光,且有低高光。 */ glPushMatrix(); glTranslatef (-1.25, -3.0, 0.0); glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_color); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); auxSolidSphere(1.0); glPopMatrix(); /* 第三行第三列绘制的球有漫反射光和有颜色的环境光以及 镜面光,且有很亮的高光。 */ glPushMatrix(); glTranslatef (1.25, -3.0, 0.0); glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_color); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, no_mat); auxSolidSphere(1.0); glPopMatrix(); /* 第三行第四列绘制的球有漫反射光和有颜色的环境光以及 辐射光,而无镜面光。 */ glPushMatrix(); glTranslatef (3.75, -3.0, 0.0); glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_color); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat); glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess); glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission); auxSolidSphere(1.0); glPopMatrix(); glFlush(); } void CALLBACK myReshape(GLsizei w, GLsizei h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= (h * 2)) glOrtho (-6.0, 6.0, -3.0*((GLfloat)h*2)/(GLfloat)w, 3.0*((GLfloat)h*2)/(GLfloat)w, -10.0, 10.0); else glOrtho (-6.0*(GLfloat)w/((GLfloat)h*2), 6.0*(GLfloat)w/((GLfloat)h*2), -3.0, 3.0, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); } void main(void) { auxInitDisplayMode (AUX_SINGLE | AUX_RGBA); auxInitPosition (0, 0, 600, 450); auxInitWindow ("Material"); myinit(); auxReshapeFunc (myReshape); auxMainLoop(display); } 图 2-7-5 多种光和材质的变化效果 以上程序运行结果是绘制12个球(3行4列)。第一行的球材质都没有环境反射光, 第二行的都有一定的环境反射光,第三行的都有某种颜色的环境光。而第一列的球材质 仅有蓝色的漫反射光;第二列的不仅有蓝漫反射光,而且还有镜面反射光,较低的高光 ;第三列的不仅有蓝漫反射光,而且还有镜面反射光,很亮的高光;第四列的还包括辐 射光,但无镜面光。 这个程序运用矩阵堆栈多次调用glMaterialfv()来设置每个球的材质,也就是改变 同一场景中的不同物体的颜色。但由于这个函数的应用有个性能开销,因此建议最好尽 可能少的改变材质,以减少改变材质时所带来的性能开销,可采用另一种方式即改变材 质颜色,相应函数为glColorMaterial(),说明如下: void glColorMaterial(GLenum face,GLenum mode); 函数参数face指定面,值有GL_FRONT、GL_BACK或GL_FRONT_AND_BACK(缺省值)。mode 指定材质成分,值有GL_AMBIENT、GL_DIFFUSE、GL_AMBIENT_AND_DIFFUSE(缺省值)、 GL_SPECULAR或GLEMISSION。 注意,这个函数说明了两个独立的值,第一个参数说明哪一个面和哪些面被修改,而 第二个参数说明这些面的哪一个或哪些材质成分要被修改。OpenGL并不为每一种face保 持独立的mode变量。在调用glColorMterial()以后,首先需要用GL_COLOR_MATERIAL作为 参数调用glEnable()来启动颜色材质,然后在绘图时调用glColor*()来改变当前颜色, 或用glMaterial()来改变材质成分。当不用这种方式来改变材质时,可调用 glDisable(GL_COLOR_MATERIAL)来关闭取消。如下面一段代码: glColorMaterial(GL_FRONT,GL_DIFFUSE); glEnable(GL_COLOR_MATERIAL); glColor3f(0.3,0.5,0.7); /* draw some objects here. */ glcolor3f(0.0,1.0,0.0); /* draw other objects here.*/ glDisable(GL_COLOR_MATERIAL); 当需要改变场景中大部分方面的单个材质时,最好调用glColorMaterial();当需要 修改不止一个材质参数时,最好调用glMaterial*()。注意,当不需要颜色材质时一定要 关闭它,以避免相应的开销。下面来看一个颜色材质的具体应用例子chgmat2.c: 例 2-14 颜色定义改变材质例程 chgmat2.c #include "glos.h" #include <GL/gl.h> #include <GL/glu.h> #include <GL/glaux.h> void myinit(void); void CALLBACK myReshape(GLsizei w, GLsizei h); void CALLBACK display(void); void myinit(void) { GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; glLightfv(GL_LIGHT0, GL_POSITION, light_position); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); glColorMaterial(GL_FRONT, GL_DIFFUSE); glEnable(GL_COLOR_MATERIAL); } void CALLBACK display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* draw one yellow ball */ glLoadIdentity(); glTranslatef(-0.7,0.0,0.0); glColor3f(1.0,1.0,0.0); auxSolidSphere(0.5); /* draw one red cone */ glLoadIdentity(); glRotatef(-65.0,1.0,0.0,0.0); glTranslatef(0.7,0.0,0.0); glColor3f(1.0,0.0,0.0); auxSolidCone(0.4,0.6); 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_RGB | AUX_DEPTH16); auxInitPosition (0, 0, 500, 500); auxInitWindow ("ColorMaterial Mode"); myinit(); auxReshapeFunc (myReshape); auxMainLoop(display); } 以上程序改变的是漫反射颜色。场景中显示了一个黄色的球和一个红色的锥体。 图 2-7-6 漫反射材质改变 |
|
|