3D游戏图形学实验四.docx
《3D游戏图形学实验四.docx》由会员分享,可在线阅读,更多相关《3D游戏图形学实验四.docx(10页珍藏版)》请在冰豆网上搜索。
3D游戏图形学实验四
《3D游戏图形学》
实验指导书
指导老师:
马文娟
姓名:
学号:
浙江理工大学
2013年12月
实验四纹理映射实验
实验项目性质:
设计性实验
所属课程名称:
3D游戏图形学
实验计划学时:
3学时
一、实验目的和要求
了解简单光照明模型的基本原理,利用VC++OpenGL实现物体的光照和材质处理。
二、实验原理
1.光照模型
当光照射到一个物体表面上时,会出现三种情形。
首先,光可以通过物体表面向空间反射,产生反射光;其次,对于透明物体,光可以穿透该物体并从另一端射出,产生透射光;最后,部分光被物体表面吸收而转换成热。
在上述三部分光中,仅仅是透射光和反射光能够进入人眼产生视觉效果。
此外,物体本身还有可能发光,比如发光的灯泡。
这里我们暂时不考虑透明物体,这样场景中可能存在以下几种类型的光,即环境光、散射光、镜面光和辐射光。
1)环境光(AmbientLight)
环境光有光源,但是由于被周围的环境,如地面、天空、墙壁等多次反射,变得无法确定其方向。
环境光均匀地从周围环境入射至景物表面并等量地向各个方向反射出去。
一般说来,房间里的环境光成分要多些,户外的相反要少得多,因为大部分光按相同的方向照射,而在户外很少有其他物体反射的光。
2)漫射光(DiffuseLight)
漫射光来自某个方向,它垂直于物体时比倾斜时更明亮。
一旦它照射到物体上,则在各个方向上均匀地发散出去。
于是,无论视点在哪里它都一样亮。
来自特定位置和特定方向的任何光,都可能有散射成分。
3)镜面光(SpecularLight)
镜面光也具有方向性,但被物体强烈地反射到另一个特定的方向。
如一个点光源照射一个金属球时会在球面上形成一块特别亮的区域,呈现所谓“高光(Highlight)”,它是光源在金属球面上产生的镜面反射光。
对于较光滑物体,其镜面反射光的高光区域小而亮;相反,粗糙表面的镜面反射光呈发散状态,其高光区域大而不亮。
4)辐射光
辐射光是最简单的一种光,它直接从物体发出并且不受任何光源影响。
在OpenGL中,任何一种光源都由三种光照成分组成:
环境光、散射光和镜面光,当然光源本身还有可能发出辐射光。
由于我们知道光是一种波,而颜色仅仅是我们可以看见的一种光波,所以每种光照成分都是由RGBA值定义的。
2.材质属性
当我们使用光照来描述多边形,总是说它由具有某些反射属性的材质组成,而不说它具有特殊的颜色。
这样我们指定物体的颜色,就必须指定物体材质对环境光、漫射光和镜面光源的反射属性。
通常,我们用材质对光的红、绿、蓝三原色的反射率来近似定义材质属性。
象光源一样,材质颜色也分成环境、漫反射和镜面反射成分,它们决定了材质对环境光、漫反射光和镜面反射光的反射程度。
在进行光照计算时,物体的最终颜色是由其材质属性的RGB值和光照属性的RGB值共同决定的。
例如,如果当前的环境光源的RGB值为(0.5,1.0,0.5),而物体的材质的环境反射成分的RGB值为(0.5,0.5,0.5),那么物体最终的颜色为:
(0.5×0.5,1.0×0.5,0.5×0.5)=(0.25,0.5,0.25)
即将每个环境光源的成分与材质的环境反射率相乘。
这样,物体表面的颜色为三项RGB值的叠加:
材质对环境光的反射率与环境光结合的RGB值;材质对漫反射光的反射率与漫反射光结合的RGB值;材质对镜面光的反射率与镜面反射光结合的RGB值。
注意,当叠加的RGB中任何一个颜色分量的值大于1.0,那么就用1.0计算。
三、实验内容
1.利用OpenGL函数实现一个简单的光照模型,显示一个具有灰色光影的球。
调整球的材质属性,使其呈现不同的颜色。
源代码:
#include
#include
//初始化z缓冲区,投影矩阵,光源和光照模型
voidinit(void)
{
GLfloatambient[]={0.0,0.0,0.0,1.0};
GLfloatdiffuse[]={1.0,1.0,1.0,1.0};
GLfloatspecular[]={1.0,1.0,1.0,1.0};
GLfloatposition[]={0.0,3.0,2.0,0.0};
GLfloatlmodel_ambient[]={0.4,0.4,0.4,1.0};
GLfloatlocal_view[]={0.0};
glClearColor(0.0,0.1,0.1,0.0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glLightfv(GL_LIGHT0,GL_AMBIENT,ambient);
glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse);
glLightfv(GL_LIGHT0,GL_POSITION,position);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,lmodel_ambient);
glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER,local_view);
//设置光照属性
glEnable(GL_LIGHTING);//开启光照计算
glEnable(GL_LIGHT0);//设置光源GL_LIGHT0
}
voiddisplay(void)
{
GLfloatposition[]={0.0,0.0,1.5,1.0};
GLfloatno_mat[]={0.0,0.0,0.0,1.0};
GLfloatmat_ambient[]={0.7,0.7,0.7,1.0};
GLfloatmat_ambient_color[]={0.8,0.8,0.2,1.0};
GLfloatmat_diffuse[]={0.5,0.5,0.5,1.0};
GLfloatmat_specular[]={1.0,1.0,1.0,1.0};
GLfloatno_shininess[]={0.0};
GLfloatlow_shininess[]={5.0};
GLfloathigh_shininess[]={100.0};
GLfloatmat_emission[]={0.2,0.2,0.2,0.0};
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLightfv(GL_LIGHT0,GL_POSITION,position);
glPushMatrix();
glTranslatef(0.0,0.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);//自发光
glutSolidSphere(1.0,16,16);
glPopMatrix();
glFlush();
}
voidreshape(intw,inth)
{
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);
glLoadIdentity();
}
voidkeyboard(unsignedcharkey,intx,inty)
{
switch(key){
case27:
exit(0);
break;
}
}
intmain(intargc,char**argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(600,450);
glutCreateWindow(argv[0]);
init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMainLoop();
return0;
}
运行结果:
2.绘制一个会移动的光源,要求光源用一个球来表示,使其围绕一个三维圆环旋转,呈现在不同位置照射圆环的效果。
绘制三维圆环的函数
glutSolidTorus(GLdoubleinnerRadius,GLdoubleouterRadius,
GLintnsides,GLintrings);
glutWireTorus(GLdoubleinnerRadius,GLdoubleouterRadius,
GLintnsides,GLintrings);
innerRadiusInnerradiusofthetorus.
outerRadiusOuterradiusofthetorus.
nsidesNumberofsidesforeachradialsection.
ringsNumberofradialdivisionsforthetorus.
例:
glutSolidTorus(0.275,0.85,50,50);
源代码:
#include
#include
voidinit(void)
{
GLfloatambient[]={0.0,0.0,0.0,1.0};
GLfloatdiffuse[]={1.0,1.0,1.0,1.0};
GLfloatspecular[]={1.0,1.0,1.0,1.0};
GLfloatposition[]={0.0,3.0,2.0,0.0};
GLfloatlmodel_ambient[]={0.4,0.4,0.4,1.0};
GLfloatlocal_view[]={0.0};
glClearColor(0.0,0.1,0.1,0.0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glLightfv(GL_LIGHT0,GL_AMBIENT,ambient);
glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse);
glLightfv(GL_LIGHT0,GL_POSITION,position);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,lmodel_ambient);
glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER,local_view);
//设置光照属性
glEnable(GL_LIGHTING);//开启光照计算
glEnable(GL_LIGHT0);//设置光源GL_LIGHT0
}
voidInitial()
{
glEnable(GL_DEPTH_TEST);//启用深度测试
glClearColor(0.0f,0.0f,0.0f,1.0f);//背景为白色
}
voidChangeSize(intw,inth)
{
if(h==0)h=1;
glViewport(0,0,w,h);//设置视区尺寸
glMatrixMode(GL_PROJECTION);//指定当前操作投影矩阵堆栈
glLoadIdentity();//重置投影矩阵
GLfloatfAspect;
fAspect=(float)w/(float)h;//计算视区的宽高比
gluPerspective(45.0,fAspect,1.0,500.0);//指定透视投影的观察空间
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
voidDisplay(void)
{
staticfloatfElect1=0.0f;//绕原子旋转的角度
GLfloatposition[]={0.0,0.0,1.5,1.0};
GLfloatno_mat[]={0.0,0.0,0.0,1.0};
GLfloatmat_ambient[]={0.7,0.7,0.7,1.0};
GLfloatmat_ambient_color[]={0.8,0.8,0.2,1.0};
GLfloatmat_diffuse[]={0.1,0.5,0.8,1.0};
GLfloatmat_specular[]={1.0,1.0,1.0,1.0};
GLfloatno_shininess[]={0.0};
GLfloatlow_shininess[]={5.0};
GLfloathigh_shininess[]={100.0};
GLfloatmat_emission[]={0.3,0.2,0.2,0.0};
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//清除颜色和深度缓冲区
glMatrixMode(GL_MODELVIEW);//指定当前操作模型视图矩阵堆栈
glLoadIdentity();//重置模型视图矩阵
glTranslatef(0.0f,0.0f,-250.0f);//将图形沿z轴负向移动
glLightfv(GL_LIGHT0,GL_POSITION,position);
//绘制圆环
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,mat_specular);
glMaterialfv(GL_FRONT,GL_SHININESS,low_shininess);
glMaterialfv(GL_FRONT,GL_EMISSION,no_mat);
glutSolidTorus(5,30,50,50);
glPopMatrix();//恢复模型视图矩阵
//画出旋转球
glPushMatrix();//保存当前的模型视图矩阵
glRotatef(-45.0f,0.0f,0.0f,1.0f);//绕z轴旋转-45°
glRotatef(fElect1,0.0f,1.0f,0.0f);
glTranslatef(0.0f,0.0f,60.0f);
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);
glutSolidSphere(6.0f,15,15);
glPopMatrix();
glEnable(GL_LIGHTING);//开启
fElect1+=10.0f;//增加旋转步长,产生动画效果
if(fElect1>360.0f)fElect1=10.0f;
glutSwapBuffers();
glFlush();
}
voidTimerFunc(intvalue)
{
glutPostRedisplay();
glutTimerFunc(100,TimerFunc,1);
}
intmain(intargc,char*argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);
glutCreateWindow("test2");
glutReshapeFunc(ChangeSize);
glutDisplayFunc(Display);
glutTimerFunc(500,TimerFunc,1);//指定定时器回调函数
init();
Initial();
glutMainLoop();
return0;
}
运行结果: