您的位置:首页 > 运维架构

OpenGL学习记录4

2014-03-16 10:30 375 查看
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;
}


运行结果:





内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: