OpenGL学习记录4
2014-03-16 10:30
375 查看
Exercise 4:材质
要求:
1. 在练习3的基础中为每个茶壶加入不同的材质;
2. 将练习3中的点光源改为不同的颜色;
考察目的:
1. OpenGL中的材质的使用;
2. 理解光源和材质如何综合影响最终的光照结果;
by/scu xx
运行结果:
![](http://img.blog.csdn.net/20140316103019750?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzcwNjY5NQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://img.blog.csdn.net/20140316103028281?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzcwNjY5NQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
要求:
1. 在练习3的基础中为每个茶壶加入不同的材质;
2. 将练习3中的点光源改为不同的颜色;
考察目的:
1. OpenGL中的材质的使用;
2. 理解光源和材质如何综合影响最终的光照结果;
by/scu xx
#include <iostream> #include <gl\glew.h> #define GLUT_DISABLE_ATEXIT_HACK//若没有这一句会出现无法解析外部符号的错误,在glut.h前加上这一句就正确了 #include <glut.h> #pragma comment(lib,"glew32.lib") using namespace std; bool isRotatef[4]; // 控制要旋转的茶壶或旋转视图 bool isLightOpen[3]; //定义光源是否打开的bool值 float lightRotatefSpeed = 0; //第一个光源绕三个茶壶的中心旋转的角度 GLfloat LightPosition1[] = {0.0f, 0.0f, 0.0f, 1.0f}; //第一个点光源的位置 GLfloat LightPosition2[] = {4.0f, 4.0f, 6.0f, 1.0f}; //第二个点光源的位置 GLfloat LightPosition3[] = {-1.0f, 1.0f, 2.0f, 1.0f}; //第三个点光源的位置 static int mousePosX = 0,mousePosY = 0, tempX, tempY; bool isMosDownMove=false;//鼠标按下是否移动的判断变量 struct simpleCamera { float camera[3]; float lookat[3]; float cam[3]; }; simpleCamera camera; GLfloat no_mat[] = {0.0, 0.0, 0.0, 1.0}; //材质发射光颜色 //1号茶壶的材料属性 GLfloat Ambient_Teapot1[] = {0.1, 0.1, 0.1, 1.0}; //材质的环境颜色 GLfloat Diffuse_Teapot1[] = {0.9, 0.8, 0.0, 1.0}; //材质的散射颜色 GLfloat Specular_Teapot1[] = {0.9, 0.8, 0.1, 1.0}; //材质的镜面反射颜色 GLfloat Shininess_Teapot1[] = {110.0}; //镜面反射指数 //2号茶壶的材料属性 GLfloat Ambient_Teapot2[] = {0.5, 0.0, 0.1, 1.0}; GLfloat Diffuse_Teapot2[] = {0.1, 0.5, 0.99, 1.0}; GLfloat Specular_Teapot2[] = {0.2, 0.1, 0.4, 1.0}; GLfloat Shininess_Teapot2[] = {10.0}; GLfloat Emission_Teapot2[] = {0.5, 0.5, 0.0, 1.0}; //3号茶壶的材料属性 GLfloat Ambient_Teapot3[] = {0.0, 0.0, 0.99, 1.0}; GLfloat Diffuse_Teapot3[] = {0.5, 0.99, 0.5, 1.0}; GLfloat Specular_Teapot3[] = {0.0, 0.0, 0.99, 1.0}; GLfloat Shininess_Teapot3[] = {110.0}; void display(); void init(); void keyboard(unsignedchar key, int x, int y); void motion(int x,int z); void mouse(int button,int state, int x,int z); void reshape(int w,int h); void createLight(); void init(void) { glClearColor(0.7f,0.7f, 0.7f, 0.0f); glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); isLightOpen[0] =isLightOpen[1] = isLightOpen[2] = true; //三个光源都开启 glEnable(GL_DEPTH_TEST); if (GLEW_OK != glewInit()) { cout << "Fail to initialize GLEW!\n"; exit(1); } createLight(); isRotatef[3] = true; //默认移动鼠标旋转整个视图 } void createLight() { glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); GLfloatLightAmbient1[]= { 0.0f, 1.0f, 0.0f, 1.0f }; //环境光参数 GLfloatLightDiffuse1[]= { 0.0f, 1.0f, 0.0f, 1.0f }; //漫射光参数(由参数可知识最亮的漫射光) GLfloatLightSpecular1[]= { 0.0f, 1.0f, 0.0f, 1.0f }; //镜面光参数 //指定光源属性,个参数决定了它所指定的哪个光源的属性、具体的属性以及该属性的预想值 glLightfv(GL_LIGHT0,GL_AMBIENT, LightAmbient1); glLightfv(GL_LIGHT0,GL_DIFFUSE, LightDiffuse1); glLightfv(GL_LIGHT0,GL_SPECULAR, LightSpecular1); glEnable(GL_LIGHT1); GLfloatLightAmbient2[] = {1.0f, 0.0f, 0.0f, 1.0f}; GLfloatLightDiffuse2[] = {1.0f, 0.0f, 0.0f, 1.0f}; GLfloatLightSpecular2[]= {1.0f, 0.0f, 0.0f, 1.0f}; glLightfv(GL_LIGHT1,GL_AMBIENT, LightAmbient2); glLightfv(GL_LIGHT1,GL_DIFFUSE, LightDiffuse2); glLightfv(GL_LIGHT1,GL_SPECULAR, LightSpecular2); glEnable(GL_LIGHT2); GLfloatLightAmbient3[] = {0.0f, 0.0f, 1.0f, 1.0f}; GLfloatLightDiffuse3[] = {0.0f, 0.0f, 1.0f, 1.0f}; GLfloatLightSpecular3[]= {0.0f, 0.0f, 1.0f, 1.0f }; glLightfv(GL_LIGHT2,GL_AMBIENT, LightAmbient3); glLightfv(GL_LIGHT2,GL_DIFFUSE, LightDiffuse3); glLightfv(GL_LIGHT2,GL_SPECULAR, LightSpecular3); } void display(void) { glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); //进行视图变换前调用下面两个函数,接下来的变换函数将影响模型变换矩阵 glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //3组参数:指定了观察点的位置,定义照相机瞄准的参考点,提示哪个方向是朝上的(个为一组) //设置照相机的位置 gluLookAt(camera.camera[0],camera.camera[1], camera.camera[2], camera.lookat[0], camera.lookat[1],camera.lookat[2], 0, 1, 0); //通过平移与旋转按照预想的方式移动观察点 glTranslatef(camera.cam[0],camera.cam[1],camera.cam[2]); /*************************************光源*****************************************************/ //处理绕三个茶壶的中心旋转的点光源 glPushMatrix(); //以下三句表示光源在z轴的.0f范围内和x轴.0f的范围内以lightRotatefSpeed的角度变化的速度移动(不知正确与否,目前这样理解) glTranslatef(0.0f,0.0f, 6.0f); glRotatef((GLfloat)lightRotatefSpeed,0.0, 1.0, 0.0); glTranslatef(6.0f,0.0f, 0.0f); glDisable(GL_LIGHTING); //使用glColor3f需要禁用光照 if (isLightOpen[0]) { glColor3f(0.0f,0.0f, 1.0f); } else { glColor3f(0.0f,0.0f, 0.0f); } //用于渲染一个球体函数原型voidglutSolidSphere(GLdouble radius , GLint slices , GLint stacks); //radius球体的半径 //slices以Z轴上线段为直径分布的圆周线的条数(将Z轴看成地球的地轴,类似于经线) //stacks围绕在Z轴周围的线的条数(类似于地球上纬线) //一般而言,后两个参数赋予较大的值,渲染花费的时间要长,效果更逼真 glutSolidSphere(0.2,10.0, 10.0); glEnable(GL_LIGHTING); glLightfv(GL_LIGHT0,GL_POSITION, LightPosition1); //光源绕中心旋转 glPopMatrix(); lightRotatefSpeed +=0.4f; //固定的一个速度 if (lightRotatefSpeed > 360) //角度大于则把角度设为 { lightRotatefSpeed = 0; } /*************************************光源*****************************************************/ //复制一份当前矩阵,并把这份复制添加到堆栈的顶部(记住自己的位置) glPushMatrix(); glTranslatef(LightPosition2[0],LightPosition2[1], LightPosition2[2]); glDisable(GL_LIGHTING); //使用glColor3f需要禁用光照 if (isLightOpen[1]) { glColor3f(0.0f,1.0f, 0.0f); //打开时颜色变亮 } else { glColor3f(0.0f,0.0f, 0.0f); //关闭时颜色变暗 } glutSolidSphere(0.2,10.0, 10.0); glEnable(GL_LIGHTING); glLightfv(GL_LIGHT1,GL_POSITION, LightPosition2); //光源设在观察坐标系 glPopMatrix(); //丢弃堆栈顶部的那个矩阵(回到原来的位置) if (isRotatef[3]) //判断是否需要旋转视图 { glRotatef((GLfloat)mousePosX, -1.0, 0.0, 0.0); glRotatef((GLfloat)mousePosY, 0.0, -1.0, 0.0); } /************************第个茶壶,光源的坐标设置在茶壶的坐标系中***************************/ glPushMatrix(); glTranslatef(-4.0f,0.0f, 4.0f); if (isRotatef[0]) //判断是否旋转 { glRotatef((GLfloat)mousePosX, -1.0, 0.0, 0.0); glRotatef((GLfloat)mousePosY, 0.0, -1.0, 0.0); } //指定用于光照计算的当前材质属性函数原型voidglMaterial{if}(GLenum face, GLenum pname, TYPE param); //参数face的取值可以是GL_FRONT、GL_BACK或GL_FRONT_AND_BACK,指出材质属性将应用于物体的哪面 //pname指出要设置的哪种材质属性,GL_AMBIENT的默认值是(.2,.2,.2,.0)表示材质的环境颜色 //param为要设置的属性值,是一个指向数组的指针(向量版本)或一个数值(非向量版本) glMaterialfv(GL_FRONT,GL_AMBIENT, Ambient_Teapot1);//GL_AMBIENT的默认值是(.2,.2,.2,.0)表示材质的环境光颜色 glMaterialfv(GL_FRONT,GL_DIFFUSE, Diffuse_Teapot1);//GL_DIFFUSE的默认值是(.8,.8,.8,.0)表示材质的散射颜色 glMaterialfv(GL_FRONT,GL_SPECULAR, Specular_Teapot1);//GL_SPECULAR的默认值是(.0,.0,.0,.0)表示材质的镜面反射颜色 glMaterialfv(GL_FRONT,GL_SHININESS, Shininess_Teapot1);//GL_SHININESS的默认值是.0表示镜面反射指数 glMaterialfv(GL_FRONT,GL_EMISSION, no_mat);//GL_EMISSION的默认值是(.0,.0,.1,.0)表示材质的发射光颜色 glutSolidTeapot(1.0);//显示一个茶壶,参数为茶壶的大小 glTranslatef(LightPosition3[0],LightPosition3[1], LightPosition3[2]); //把局部坐标系移动到需要放点光源的地方 glDisable(GL_LIGHTING); //使用glColor3f需要禁用光照 if (isLightOpen[2]) { glColor3f(1.0f,0.0f, 0.0f); } else { glColor3f(0.0f,0.0f, 0.0f); } glutSolidSphere(0.2,10.0, 10.0); glEnable(GL_LIGHTING); glLightfv(GL_LIGHT2,GL_POSITION, LightPosition3); //光源的坐标设置在茶壶的坐标系中 glPopMatrix(); /********************************茶壶************************************************/ glPushMatrix(); glTranslatef(0.0f,3.0f, 4.0f); if (isRotatef[1]) //判断是否旋转 { glRotatef((GLfloat)mousePosX, -1.0, 0.0, 0.0); glRotatef((GLfloat)mousePosY, 0.0, -1.0, 0.0); } glMaterialfv(GL_FRONT,GL_AMBIENT, Ambient_Teapot2); glMaterialfv(GL_FRONT,GL_DIFFUSE, Diffuse_Teapot2); glMaterialfv(GL_FRONT,GL_SPECULAR, Specular_Teapot2); glMaterialfv(GL_FRONT,GL_SHININESS, Shininess_Teapot2); glMaterialfv(GL_FRONT,GL_EMISSION, Emission_Teapot2); glutSolidTeapot(1.0); glPopMatrix(); /**********************************茶壶*************************************************/ glPushMatrix(); glTranslatef(4.0f,0.0f, 4.0f); if (isRotatef[2]) //判断是否需要旋转 { glRotatef((GLfloat)mousePosX, -1.0, 0.0, 0.0); glRotatef((GLfloat)mousePosY, 0.0, -1.0, 0.0); } glMaterialfv(GL_FRONT,GL_AMBIENT, Ambient_Teapot3); glMaterialfv(GL_FRONT,GL_DIFFUSE, Diffuse_Teapot3); glMaterialfv(GL_FRONT,GL_SPECULAR, Specular_Teapot3); glMaterialfv(GL_FRONT,GL_SHININESS, Shininess_Teapot3); glMaterialfv(GL_FRONT,GL_EMISSION, no_mat); glutSolidTeapot(1.0); glPopMatrix(); glutSwapBuffers(); } void reshape(int w,int h) { float aspect = (float)w/((h)?h:1);//平截头体的纵横比,也就是宽度除以高度,(h)?h:1意思是若h=0,则h=1 glViewport(0,0, w,h); //进行投影变换前调用下面两个函数,接下来的变换函数将影响投影矩阵 glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f,aspect, 1.0f, 100.0f);// glViewport(0,0,w,h); glMatrixMode(GL_MODELVIEW); } void keyboard(unsignedchar key, int x, int y) { switch (key) { case 'w': camera.cam[1] +=0.1;//向上 break; case 's': camera.cam[1] -=0.1;//向下 break; case 'a': camera.cam[0] -=0.1;//向左 break; case 'd': camera.cam[0] +=0.1;//向右 break; case 'r': camera.cam[2] +=0.2;//放大视图(向外) break; case 'f': camera.cam[2] -=0.2;//缩小视图(向内) break; case 'm': lightRotatefSpeed+= 5.0f;//加快光源的速度 break; case 'n': lightRotatefSpeed-= 5.05f; break; case '4': //鼠标控制整个视图旋转(光源不会跟着旋转) isRotatef[3] = true; isRotatef[0] =isRotatef[1] = isRotatef[2] = false; break; case '5': //清除所做的任何旋转和缩放 camera.cam[0] =camera.cam[1] = camera.cam[2] = 0.0f; tempX = 0; tempY = 0; mousePosY = 0; mousePosX = 0; break; case '1': //鼠标控制茶壶旋转 (光源会跟着旋转) isRotatef[0] = true; isRotatef[1] =isRotatef[2] = isRotatef[3] =false; break; case '2': //鼠标控制茶壶旋转 isRotatef[1] = true; isRotatef[0] =isRotatef[2] = isRotatef[3] = false; break; case '3': //鼠标控制茶壶旋转 isRotatef[2] = true; isRotatef[0] =isRotatef[1] = isRotatef[3] = false; break; case 'i': //打开/关闭0号光源 isLightOpen[0] =!isLightOpen[0]; if (!isLightOpen[0]) { glDisable(GL_LIGHT0); } else { glEnable(GL_LIGHT0); } break; case 'o': //打开/关闭1号光源 isLightOpen[1] =!isLightOpen[1]; if (!isLightOpen[1]) { glDisable(GL_LIGHT1); } else { glEnable(GL_LIGHT1); } break; case 'p': //打开/关闭2号光源 isLightOpen[2] =!isLightOpen[2]; if (!isLightOpen[2]) { glDisable(GL_LIGHT2); } else { glEnable(GL_LIGHT2); } break; case 27: //退出程序 exit(0); break; } } void mouse(int button,int state, int x,int z) { switch(button) { case GLUT_LEFT_BUTTON: if (state == GLUT_DOWN) { tempX = x; tempY = z; isMosDownMove = true; //鼠标移动时需要用到的判断变量 } else { isMosDownMove = false; } break; } } void motion(int x,int z) { if(isMosDownMove) { mousePosY =(mousePosY + (x - tempX))%360; mousePosX =(mousePosX + (z - tempY))%360; tempX = x; tempY = z; glutPostRedisplay(); } } void refresh(void) { //刷新屏幕 glutPostRedisplay(); } int main(int argc,char* argv[]) { //定义刚开始时观察点的位置 camera.camera[0] =0.0f; camera.camera[1] =0.0f; camera.camera[2] =20.0f; //平移观察点时的变量参数 camera.cam[0] =camera.cam[1] = camera.cam[2] = 0.0f; //相机瞄准的参考点的参数 camera.lookat[0] =0.0f-camera.camera[0]; camera.lookat[1] =0.0f-camera.camera[1]; camera.lookat[2] =20.0f-camera.camera[2]; glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE| GLUT_DEPTH | GLUT_RGB); glutInitWindowSize(800,600); glutInitWindowPosition(100,100); glutCreateWindow("Teaports"); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutMouseFunc(mouse); glutMotionFunc(motion); glutIdleFunc(refresh); glutMainLoop(); return 0; }
运行结果:
相关文章推荐
- Nginx学习笔记(十六):worker进程的循环工作
- redhat Linux 安装 VMware tools方法
- 让你的sharepoint2013具有EMS快递查询的功能
- CentOS 6.5搭建Apache整合SVN 1.8.5服务器(多版本库权限配置)
- Apache Mina的SSL连接API
- SharePoint2013网站添加切换用户登录
- linux基础之bash基础
- OpenCV Mat类详解
- 从 Yarn 回滚到 Hadoop 1.x
- LINUX 下 JNA 调用 so--正确版
- C# .Net三层架构[转]
- 一篇关于su和sudo以及visudo的很好的介绍性文档
- CentOS最常用命令及快捷键整理
- strophe与openfire模拟的XMPP简单hello程序
- Strophe.Status的所有值
- 在shell输入复杂语句
- OpendTect软件交流
- Linux时间转标准时间
- Topology and Geometry in OpenCascade-Vertex
- 短信猫在linux 连接问题 解决