OpenGL学习记录4

来源:互联网 发布:清华同方教学软件 编辑:程序博客网 时间:2024/05/20 03:37

Exercise 4:材质

要求:

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;}


运行结果:



0 0
原创粉丝点击