实验三 基于OpenGL的圆柱绘制 OpenGL纹理光照.docx
- 文档编号:30414146
- 上传时间:2023-08-14
- 格式:DOCX
- 页数:13
- 大小:295.81KB
实验三 基于OpenGL的圆柱绘制 OpenGL纹理光照.docx
《实验三 基于OpenGL的圆柱绘制 OpenGL纹理光照.docx》由会员分享,可在线阅读,更多相关《实验三 基于OpenGL的圆柱绘制 OpenGL纹理光照.docx(13页珍藏版)》请在冰豆网上搜索。
实验三基于OpenGL的圆柱绘制OpenGL纹理光照
实验三基于OpenGL的圆柱绘制
1.实验目的
通过圆柱的绘制,掌握OpenGL编程环境的设置,基本图元的使用,光照的设置以及纹理的设置,理解曲面绘制的基本原理。
2.实验内容
(1)设置OpenGL编程环境;
(2)利用三角形和四边形等基本图元绘制底面圆圆心在坐标原点,半径为r,高为h,方向沿z轴方向的圆柱;
(3)设置光照
(4)设置纹理:
在圆柱的侧面上显示一张图片
3.主要问题&结果截图
1 如何绘制圆柱?
一种方法是调用gluc中的函数gluCylinder
但本实验要求利用三角形和四边形等基本图元绘制
所以这里主要采用类似微积分的方式绘制,就是将椭圆的侧面用多个四边形,底面用多个三角形来表示
关键代码
voidCircle()底面的圆形
voidCylinder()圆柱的侧面
glBegin(GL_TRIANGLE_FAN);//扇形连续填充三角形串
glVertex3f(0.0f,0.0f,0.0f);//圆心:
这是三角形作为圆心的顶点
inti=0;
for(i=0;i<=360;i+=15)
{
floatp=i*3.14/180;
glVertex3f(sin(p),cos(p),0.0f);//圆周:
这是三角形作为扇形弧端点的顶点(p的值取0-2PI)就能画出一个类似圆形
}
glEnd();
glBegin(GL_QUAD_STRIP);//连续填充四边形串
inti=0;
for(i=0;i<=360;i+=15)
{
floatp=i*3.14/180;
glTexCoord2f(p/10,0.1f);
glVertex3f(sin(p),cos(p),1.0f);//这个1.0f指定的是高度
glTexCoord2f(p/10,0.0f);
glVertex3f(sin(p),cos(p),0.0f);
}
glEnd();
效果:
再调用画圆形的函数画上两个底面
Circle();
glTranslatef(0,0,1);//设定高度为1,画上底面
Circle();
效果:
2 如何纹理贴图?
关键代码:
glEnable(GL_TEXTURE_2D);//执行纹理映射,启用二维文理
glBindTexture(GL_TEXTURE_2D,ID);//允许建立一个绑定到目标纹理的有名称的纹理
//ID——纹理的名称,并且,该纹理的名称在当前的应用中不能被再次使用
纹理贴图的原理是纹理映射,即将纹理图片上的点和图形中的点建立对应关系。
所以,我们需要glEnable底下的点定义之前关联上与之对应的纹理坐标
即先调用glTexCoord2f设置纹理,再调用glVertex3f绘制点
例如之前的圆形:
glBegin(GL_TRIANGLE_FAN);//扇形连续填充三角形串
glTexCoord2f(0.0f,0.0f);//将纹理图(0,0)映射到圆心
glVertex3f(0.0f,0.0f,0.0f);
inti=0;
for(i=0;i<=360;i+=15)
{
floatp=i*3.14/180;
glTexCoord2f(1.0f,0.0f);//将纹理图(1,0)映射到圆周
glVertex3f(sin(p),cos(p),0.0f);
}
glEnd();
这实际上不是一个贴图的效果,因为圆心到圆周上距离相等的点对应的纹理点都是一样的,是一个同心圆的图样
效果:
纹理
那么再看圆柱侧面:
glBegin(GL_QUAD_STRIP);//连续填充四边形串
inti=0;
for(i=0;i<=360;i+=15)
{
floatp=i*3.14/180;
glTexCoord2f(p/10,0.1f);//p和圆周是相对应的,这里让纹理的横坐标随圆周扫过的角度一起改变,就能够将纹理图“刷”上去了,而纵坐标设置为图像的高度和纹理高度的对应,这里合适的参数是根据实际测试得到的
glVertex3f(sin(p),cos(p),1.0f);
glTexCoord2f(p/10,0.0f);
glVertex3f(sin(p),cos(p),0.0f);
}
glEnd();
这是最终的效果图:
是不是很像一段木桩呢?
3 如何设置光照?
//定义光源
GLfloatambient[]={0.0,0.0,0.0,1.0};
GLfloatdiffuse[]={9.0,9.0,9.0,9.0};
GLfloatposition[]={i/6,2.0,2.0,0.0};
//我把光源位置设置得和旋转时用到的角度相关联
//把定义值给GL_LIGHT1
glLightfv(GL_LIGHT1,GL_AMBIENT,ambient);//设置环境光
glLightfv(GL_LIGHT1,GL_DIFFUSE,diffuse);//设置漫反射光
glLightfv(GL_LIGHT1,GL_POSITION,position);//设置光源位置
glEnable(GL_LIGHTING);//启用光照
glEnable(GL_LIGHT1);//启用1号光源
效果:
可以观察到物体亮度明暗交替的变化
4.实验总结
这次实验,我算花了比较多心思的。
不过我也不是从零开始写的代码,其实原本对于Opengl我也没有很好的基础。
我先是从网上找到了几个demo,有的是只能完成贴图的,有的是只能画圆的,有的是只能画侧面的,这些小型的程序比较简单易懂,我通过学习它们的源码,举一反三,最终按照实验要求完成了自己的程序。
其中,自己看代码最难理解的就是纹理映射的方式,看懂了之后会发现很简单,学习Opengl,就要理解它状态机的基本思想,自己动手实践一下,改改代码,就很容易理解。
附录:
源码
main.cpp
#include
#include
#include
#include
#include
#include"texture.h"
voidCircle()
{
glClearColor(0.0,0.0,0.0,0.0);
//glClear(GL_COLOR_BUFFER_BIT);//有l这个会把圆柱侧面清掉
glEnable(GL_TEXTURE_2D);//执行纹理映射,启用二维文理
glBindTexture(GL_TEXTURE_2D,ID);//允许建立一个绑定到目标纹理的有名称的纹理
//ID——纹理的名称,并且,该纹理的名称在当前的应用中不能被再次使用
glBegin(GL_TRIANGLE_FAN);//扇形连续填充三角形串
glTexCoord2f(0.0f,0.0f);
glVertex3f(0.0f,0.0f,0.0f);
inti=0;
for(i=0;i<=360;i+=15)
{
floatp=i*3.14/180;
glTexCoord2f(1.0f,0.0f);
glVertex3f(sin(p),cos(p),0.0f);
}
glEnd();
glDisable(GL_TEXTURE_2D);
}
voidCylinder()
{
glClearColor(0.0,0.0,0.0,0.0);
//glClear(GL_COLOR_BUFFER_BIT);//有l这个会把圆柱侧面清掉
glEnable(GL_TEXTURE_2D);//执行纹理映射,启用二维文理
glBindTexture(GL_TEXTURE_2D,ID);//允许建立一个绑定到目标纹理的有名称的纹理
//ID——纹理的名称,并且,该纹理的名称在当前的应用中不能被再次使用
glBegin(GL_QUAD_STRIP);//连续填充四边形串
inti=0;
for(i=0;i<=360;i+=15)
{
floatp=i*3.14/180;
glTexCoord2f(p/10,0.1f);
glVertex3f(sin(p),cos(p),1.0f);
glTexCoord2f(p/10,0.0f);
glVertex3f(sin(p),cos(p),0.0f);
}
glEnd();
glDisable(GL_TEXTURE_2D);
Circle();
glTranslatef(0,0,1);
Circle();
}
voidrenderScene(void)
{
staticfloati=0;
i+=0.1;//旋转速度
if(i>360)
i=0;
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glPushMatrix();
//glColor3f(0,1,1);//设置颜色
glTranslatef(0.0,0.0,-7);//指定位置,大小
glRotatef(i,1,1,1);//旋转轴
//定义光源
GLfloatambient[]={0.0,0.0,0.0,1.0};
GLfloatdiffuse[]={9.0,9.0,9.0,9.0};
GLfloatposition[]={i/6,2.0,2.0,0.0};
//把定义值给GL_LIGHT1
glLightfv(GL_LIGHT1,GL_AMBIENT,ambient);//设置环境光
glLightfv(GL_LIGHT1,GL_DIFFUSE,diffuse);//设置漫反射光
glLightfv(GL_LIGHT1,GL_POSITION,position);//设置光源位置
glEnable(GL_LIGHTING);//启用光照
glEnable(GL_LIGHT1);//启用1号光源
Cylinder();//绘制圆柱
//Circle();
glDisable(GL_TEXTURE_2D);
glPopMatrix();
glutSwapBuffers();
}
voidchangeSize(intw,inth)
{
//防止除数即高度为0
//(你可以设置窗口宽度为0).
if(h==0)
h=1;
floatratio=1.0*w/h;
//单位化投影矩阵。
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//设置视口大小为整个窗口大小
glViewport(0,0,w,h);
//设置正确的投影矩阵
gluPerspective(45,ratio,1,1000);
//下面是设置模型视图矩阵
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0,0.0,5.0,0.0,0.0,-1.0,0.0f,1.0f,0.0f);//设置观测点
}
intmain(intargc,char*argv[])
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DEPTH|GLUT_DOUBLE|GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(400,400);
glutCreateWindow("圆柱by陈羽丰");
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);//指定程序空闲时调用函数
glutReshapeFunc(changeSize);//指定窗口形状变化时的回调函数
glEnable(GL_DEPTH_TEST);
init();
glutMainLoop();
return0;
}
texture.h
#include
#include
#include
usingstd:
:
vector;
usingstd:
:
cout;
usingstd:
:
endl;
unsignedintID;
intLoadBitmap(constchar*file)
{
unsignedintID;//纹理的id
intwidth,height,i;
byte*image,t;//接受图像数据
FILE*fp;//文件指针
BITMAPFILEHEADERFileHeader;//接受位图文件头
BITMAPINFOHEADERInfoHeader;//接受位图信息头
fp=fopen(file,"rb");
if(fp==NULL)
{
perror("LoadBitmap");//打开文件失败
return-1;
}
fread(&FileHeader,sizeof(BITMAPFILEHEADER),1,fp);
if(FileHeader.bfType!
=0x4D42)//确保文件是一个位图文件,效验文件类型
{
printf("Error:
Thisfileisnotabmpfile!
");
fclose(fp);
return-1;
}
fread(&InfoHeader,sizeof(BITMAPINFOHEADER),1,fp);
width=InfoHeader.biWidth;
height=InfoHeader.biHeight;
if(InfoHeader.biSizeImage==0)//确保图像数据的大小
{
InfoHeader.biSizeImage=width*height*3;
}
fseek(fp,FileHeader.bfOffBits,SEEK_SET);//将文件指针移动到实际图像数据处
image=(byte*)malloc(sizeof(byte)*InfoHeader.biSizeImage);//申请空间
if(image==NULL)
{
free(image);
printf("Error:
Noenoughspace!
");
return-1;
}
fread(image,1,InfoHeader.biSizeImage,fp);
for(i=0;i { t=image[i]; image[i]=image[i+2]; image[i+2]=t; } fclose(fp); glGenTextures(1,&ID); glBindTexture(GL_TEXTURE_2D,ID); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); gluBuild2DMipmaps(GL_TEXTURE_2D,3,width, height,GL_RGB,GL_UNSIGNED_BYTE, image); returnID; } voidUpdate() { glutPostRedisplay(); } voidReshape(intw,inth) { w=w>h? h: w; glViewport(0,0,(GLsizei)w,(GLsizei)w); } voidinit() { ID=LoadBitmap("cyf.bmp"); if(ID==-1) exit(0); }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验三 基于OpenGL的圆柱绘制 OpenGL纹理光照 实验 基于 OpenGL 圆柱 绘制 纹理 光照