版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
STYLEREF"标题2"前言SUBJECT数字图像处理实验指导书实验五纹理映射实验一、实验目的和要求掌握纹理映射的基本原理,利用VC++OpenGL实现纹理映射技术。实验原理纹理映射是真实感图形制作的一个重要部分,运用纹理映射可以方面地制作真实感图形,而不必花更多的时间去考虑物体的表面纹理。如一张木制桌子其表面的木纹是不规范的,看上去又是那么自然,如果在图形制作中不用纹理映射,那么只是这张桌面纹理的设计,就要花费很大精力,而且设计结果也未必能像现实中那么自然。如果运用纹理映射就非常方便,可以用扫描仪将这样的一张桌子扫成一个位图。然后的具体的操作中,只需把桌面形状用多边形画出来,把桌面纹理贴上去就可以了。另外,纹理映射能够在多边形进行变换时仍保证纹理的图案与多边形保持一致性。例如,以透视投影方式观察墙面时,远端的砖会变小,而近处的砖就会大一些。此外,纹理映射也可以用于其他方面。例如,使用一大片植被的图像映射到一些连续的多边形上,以模拟地貌,或者以大理石、木纹等自然物质的图像作为纹理映射到相应的多边形上,作为物体的真实表面。在OpenGL中提供了一系列完整的纹理操作函数,用户可以用它们构造理想的物体表面,可以对光照物体进行处理,使其映射出所处环境的景象,可以用不同方式应用到曲面上,而且可以随几何物体的几何属性变换而变化,从而使制作的三维场景和三维物体更真实更自然。在OpenGL中要实现纹理映射,需要经历创建纹理、指定纹理应用方式、启用纹理映射、使用纹理坐标和几何坐标绘制场景几个过程。用于指定一维、二维和三维纹理的函数分别为:VoidglTexImage1D(GLenumtarget,Glintlevel,Glintcomponents,GLsizeiwidth,Glintborder,GLenumformat,GLenumtype,constGLvoid*texels);VoidglTexImage2D(GLenumtarget,Glintlevel,Glintcomponents,GLsizeiwidth,GLsizeiheight,GLintborder,GLenumformat,GLenumtype,constGLvoid*texels);VoidglTexImage3D(GLenumtarget,Glintlevel,Glintcomponents,GLsizeiwidth,GLsizeiheight,GLsizeidepth,Glintborder,GLenumformat,GLenumtype,constGLvoid*texels);其中,参数target取值一般为GL_TEXTURE_1D,GL_TEXTURE_2D和GL_TEXTURE_3D,分别与一维、二维和三维的纹理相对应。参数Level表示纹理多分辨率层数,通常取值为0,表示只有一种分辨率。参数components的可能取值为1~4的整数以及多种符号常量(如GL_RGBA),表示纹理元素中存储的哪些分量(RGBA颜色、深度等)在纹理映射中被使用,1表示使用R颜色分量,2表示使用R和A颜色分量,3表示使用RGB颜色分量,4表示使用RGBA颜色分量。参数width,height,depth分别指定纹理的宽度、高度、深度。参数format和type表示给出的图像数据的数据格式和数据类型,这两个参数的取值都是符号常量(比如format指定为GL_RGBA,type指定为GL_UNSIGNED_BYTE,参数texels指向内存中指定的纹理图像数据。在定义了纹理之后,需要启用纹理的函数:glEnable(GL_TEXTURE_1D);glEnable(GL_TEXTURE_2D);glEnable(GL_TEXTURE_3D);在启用纹理之后,需要建立物体表面上点与纹理空间的对应关系,即在绘制基本图元时,在glVertex函数调用之前调用glTexCoord函数,明确指定当前顶点所对应的纹理坐标,例如:glBegin(GL_TRIANGLES);glTexCoord2f(0.0,0.0);glVertex2f(0.0,0.0);glTexCoord2f(1.0,1.0);glVertex2f(15.0,15.0);glTexCoord2f(1.0,0.0);glVertex2f(30.0,0.0);glEnd();其图元内部点的纹理坐标利用顶点处的纹理坐标采用线性插值的方法计算出来。在OpenGL中,纹理坐标的范围被指定在[0,1]之间,而在使用映射函数进行纹理坐标计算时,有可能得到不在[0,1]之间的坐标。此时OpenGL有两种处理方式,一种是截断,另一种是重复,它们被称为环绕模式。在截断模式(GL_CLAMP)中,将大于1.0的纹理坐标设置为1.0,将小于0.0的纹理坐标设置为0.0。在重复模式(GL_REPEAT)中,如果纹理坐标不在[0,1]之间,则将纹理坐标值的整数部分舍弃,只使用小数部分,这样使纹理图像在物体表面重复出现。例如,使用下面的函数:glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);分别指定二维纹理中s坐标采用截断或重复处理方式。另外,在变换和纹理映射后,屏幕上的一个像素可能对应纹理元素的一小部分(放大),也可能对应大量的处理元素(缩小)。在OpenGL中,允许指定多种方式来决定如何完成像素与纹理元素对应的计算方法(滤波)。比如,下面的函数可以指定放大和缩小的滤波方法:glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);其中,glTexParameteri函数的第一个参数指定使用的是一维、二维或三维纹理;第二个参数为GL_TEXTURE_MAG_FILTER或GL_TEXTURE_MIN_FILTER,指出要指定缩小还是放大滤波算法;最后一个参数指定滤波的方法。补充:透视投影函数voidgluPerspective(GLdoublefovy,GLdoubleaspect,GLdoublezNear,GLdoublezFar);它也创建一个对称透视视景体,但它的参数定义于前面的不同。其操作是创建一个对称的透视投影矩阵,并且用这个矩阵乘以当前矩阵。参数fovy定义视野在X-Z平面的角度,范围是[0.0,180.0];参数aspect是投影平面宽度与高度的比率;参数zNear和Far分别是远近裁剪面沿Z负轴到视点的距离,它们总为正值。实验内容在OpenGL中纹理映射所使用的纹理数据,既可以是程序生成的一组数据,也可以从外部文件中直接读取,参考示范代码完成以下两项内容:利用直接创建纹理的方法生成二维纹理并映射到四边形上。参考代码:voidmakeImage(void){inti,j,r,g,b;for(i=0;i<ImageWidth;i++) { for(j=0;j<ImageHeight;j++) { r=(i*j)%255; g=(4*i)%255; b=(4*j)%255; Image[i][j][0]=(GLubyte)r; Image[i][j][1]=(GLubyte)g; Image[i][j][2]=(GLubyte)b; }}}voidmyinit(void){glClearColor(0.0,0.0,0.0,0.0);glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LESS); //生成纹理数据makeImage(); //设置像素存储模式glPixelStorei(GL_UNPACK_ALIGNMENT,1); //定义二维纹理映射glTexImage2D(……); //定义纹理映射参数glTexParameterf(……);glTexParameterf(……);glTexParameterf(……);glTexParameterf(……); //启用二维纹理glEnable(GL_TEXTURE_2D);glShadeModel(GL_FLAT);}voiddisplay(void){glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);//绘制四边形,并完成纹理映射……glFlush();}voidmyReshape(GLsizeiw,GLsizeih){……}voidmain(intargc,char*argv[]){……}从外部文件中直接读取纹理实现正方体每个面的纹理映射,并使正方体转动。整个过程需要三个步骤:创建纹理、启用纹理映射和使用纹理坐标和几何坐标绘制,下面我们对三个过程进行阐述,并给出参考代码。1)创建纹理对象并绑定纹理 纹理创建即在内存中创建保存纹理数据的数组,一般是先读入一个图像文件,将图像文件的RGBA信息存入我们创建的纹理空间中,当然图像的位图不同,创建的纹理空间结构也会有所不同。为了更加简单易懂地实现这个过程,我们使用未压缩的纹理。代码:GLuinttexture[1];//创建一个纹理空间AUX_RGBImageRec*LoadBMP(CHAR*Filename)//载入位图图像{ FILE*File=NULL;//文件句柄 if(!Filename)//确保文件名已提供 { returnNULL; } File=fopen(Filename,"r");//尝试打开文件 if(File) { fclose(File);//关闭文件 returnauxDIBImageLoadA(Filename);//载入位图并返回指针 } returnNULL;}//如果载入失败,返回NULLintLoadGLTextures()//载入位图并转换成纹理{ intStatus=FALSE;//状态指示器 AUX_RGBImageRec*TextureImage[1];//创建纹理的存储空间 memset(TextureImage,0,sizeof(void*)*1);//初始化//载入位图,检查有无错误,如果位图没找到则退出 if(TextureImage[0]=LoadBMP("data.bmp")) { Status=TRUE; glGenTextures(1,&texture[0]);//创建纹理//使用来自位图数据生成的典型纹理 glBindTexture(GL_TEXTURE_2D,texture[0]);//生成2D纹理 glTexImage2D(GL_TEXTURE_2D,0,3,TextureImage[0]->sizeX,TextureImage[0]->sizeY,0,GL_RGB,GL_UNSIGNED_BYTE,TextureImage[0]->data); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); } if(TextureImage[0])//纹理是否存在 { if(TextureImage[0]->data)//纹理图像是否存在 { free(TextureImage[0]->data);//释放纹理图像占用的内存 } free(TextureImage[0]);//释放图像结构 } returnStatus;//返回Status}2)启用纹理映射操作,初始化相关参数 在OpenGL中使用纹理映射之前,必须打开纹理映射。intInitGL(GLvoid){ if(!LoadGLTextures())//调用纹理载入子例程 { returnFALSE; } glEnable(GL_TEXTURE_2D);//启用纹理映射 glShadeModel(GL_SMOOTH);//启用阴影平滑 glClearColor(0.0f,0.0f,0.0f,0.5f);//黑色背景 glClearDepth(1.0f);//设置深度缓存 glEnable(GL_DEPTH_TEST);//启用深度测试 returnTRUE;}3)使用纹理坐标和几何坐标绘制voidDrawGLScene(void){ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(0.0f,0.0f,-5.0f); glRotatef(xrot,1.0f,0.0f,0.0f); glRotatef(yrot,0.0f,1.0f,0.0f); glRotatef(zrot,0.0f,0.0f,1.0f);//选择纹理 glBindTexture(GL_TEXTURE_2D,texture[0]);//绘制一个正方体,给每个面贴上纹理,并使之转动 glBegin(GL_QUADS); …… glEnd();xrot+=0.3f;yrot+=0.2f;zrot+=0.4f;}实验代码1、利用直接创建纹理的方法生成二维纹理并映射到四边形上。#include<stdlib.h>#include<GL/glut.h>#defineimageWidth64#defineimageHeight64GLubyteimage[imageWidth][imageHeight][3];/*绘制一个简单的二维纹理图*/voidmakeImage(void){inti,j,r,g,b;/*根据点的位置设置不同的颜色*/for(i=0;i<imageWidth;i++){for(j=0;j<imageHeight;j++){r=(i*j)%255;g=(i*i)%255;b=(j*j)%255;image[i][j][0]=(GLubyte)r;image[i][j][1]=(GLubyte)g;image[i][j][2]=(GLubyte)b;}}}voidmyInit(void){glClearColor(0.0,0.0,0.0,0.0);glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LESS);//生成纹理数据makeImage();//设置像素存储模式glPixelStorei(GL_UNPACK_ALIGNMENT,1);/*指定二维纹理映射*/glTexImage2D(GL_TEXTURE_2D,0,3,imageWidth,imageHeight,0,GL_RGB,GL_UNSIGNED_BYTE,&image[0][0][0]);//纹理过滤函数/*GL_TEXTURE_2D:操作D纹理.GL_TEXTURE_WRAP_S:S方向上的贴图模式.GL_CLAMP:将纹理坐标限制在.0,1.0的范围之内.如果超出了会如何呢.不会错误,只是会边缘拉伸填充.GL_TEXTURE_MAG_FILTER:放大过滤GL_LINEAR:线性过滤,使用距离当前渲染像素中心最近的个纹素加权平均值.GL_TEXTURE_MIN_FILTER:缩小过滤GL_LINEAR_MIPMAP_NEAREST:使用GL_NEAREST对最接近当前多边形的解析度的两个层级贴图进行采样,然后用这两个值进行线性插值.*/glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);/*设置纹理环境参数*///glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);//启用二维纹理glEnable(GL_TEXTURE_2D);glShadeModel(GL_FLAT);}voidmyDisplay(void){glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);/*将纹理映射到四边形上*/glBegin(GL_QUADS);/*纹理的坐标和四边形顶点的对应*/glTexCoord2f(0.0,0.0);glVertex3f(-0.7,-0.25,0.0);glTexCoord2f(0.0,1.0);glVertex3f(-0.2,-0.25,0.0);glTexCoord2f(1.0,1.0);glVertex3f(-0.2,0.25,0.0);glTexCoord2f(1.0,0.0);glVertex3f(-0.7,0.25,0.0);glTexCoord2f(0.0,0.0);glVertex3f(0.2,-0.25,1.875);glTexCoord2f(0.0,1.0);glVertex3f(0.6,-0.25,0.0);glTexCoord2f(1.0,1.0);glVertex3f(0.6,0.25,0.125);glTexCoord2f(1.0,0.0);glVertex3f(0.2,0.25,2.0);glEnd();glFlush();}voidmyReshape(intw,inth){glViewport(0,0,(GLsizei)w,(GLsizei)h);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(80.0,1.0-(GLfloat)w/(GLfloat)h,1.0,30.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();}intmain(intargc,char**argv){/*初始化*/glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);glutInitWindowSize(400,400);glutInitWindowPosition(200,200);glutCreateWindow("Texture");//创建窗口myInit();//绘制与显示glutReshapeFunc(myReshape);glutDisplayFunc(myDisplay);glutMainLoop();return0;}2、从外部文件中直接读取纹理实现正方体每个面的纹理映射,并使正方体转动。#include<GL/glut.h>#include<GL/glaux.h>#include<stdio.h>#include<stdlib.h>#include<windows.h>#pragmacomment(lib,"openGL32.lib")#pragmacomment(lib,"glu32.lib")#pragmacomment(lib,"glaux.lib")#pragmacomment(lib,"openGL32.lib")GLuinttexture[1];//创建纹理空间GLfloatxRot,yRot,zRot;//控制正方体的旋转//载入位图图像AUX_RGBImageRec*LoadBMP(CHAR*Filename){//载入位图图像 FILE*File=NULL;//文件句柄 if(!Filename){//确保文件名已提供 returnNULL; } File=fopen(Filename,"r");//尝试打开文件 if(File){ fclose(File);//关闭文件 returnauxDIBImageLoadA(Filename);//载入位图并返回指针 } returnNULL;//如果载入失败,返回NULL}intLoadGLTextures(){//载入位图并转换成纹理 intStatus=FALSE;//状态指示器 AUX_RGBImageRec*TextureImage[1];//创建纹理的存储空间 memset(TextureImage,0,sizeof(void*)*1);//初始化//载入位图,检查有无错误,如果位图没找到则退出 if(TextureImage[0]=LoadBMP("data.bmp")){ Status=TRUE; glGenTextures(1,&texture[0]);//创建纹理//使用来自位图数据生成的典型纹理 glBindTexture(GL_TEXTURE_2D,texture[0]);//生成D纹理 glTexImage2D(GL_TEXTURE_2D,0,3,TextureImage[0]->sizeX,TextureImage[0]->sizeY,0,GL_RGB,GL_UNSIGNED_BYTE,TextureImage[0]->data); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); } if(TextureImage[0]){//纹理是否存在 if(TextureImage[0]->data){//纹理图像是否存在 free(TextureImage[0]->data);//释放纹理图像占用的内存 } free(TextureImage[0]);//释放图像结构 } returnStatus;//返回Status}intInitGL(GLvoid){ if(!LoadGLTextures()){//调用纹理载入子例程 returnFALSE; } glEnable(GL_TEXTURE_2D);//启用纹理映射 glShadeModel(GL_SMOOTH);//启用阴影平滑 glClearColor(0.0f,0.0f,0.0f,0.5f);//黑色背景 glClearDepth(1.0f);//设置深度缓存 glEnable(GL_DEPTH_TEST);//启用深度测试 returnTRUE;}voiddisplay(){glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glLoadIdentity();glTranslatef(0.0f,0.0f,-5.0f);glRotatef(xRot,1.0f,0.0f,0.0f);glRotatef(yRot,0.0f,1.0f,0.0f);glRotatef(zRot,0.0f,0.0f,1.0f); //绘制正方体,贴上纹理并使之转动glBindTexture(GL_TEXTURE_2D,texture[0]);//选择纹理glBegin(GL_QUADS);//前glTexCoord2f(0.0f,0.0f);glVertex3f(-1.0f,-1.0f,1.0f);glTexCoord2f(1.0f,0.0f);glVertex3f(1.0f,-1.0f,1.0f);glTexCoord2f(1.0f,1.0f);glVertex3f(1.0f,1.0f,1.0f);glTexCoord2f(0.0f,1.0f);glVertex3f(-1.0f,1.0f,1.0f);glEnd();glBindTexture(GL_TEXTURE_2D,texture[0]);glBegin(GL_QUADS);//后glTexCoord2f(1.0f,0.0f);glVertex3f(-1.0f,-1.0f,-1.0f);glTexCoord2f(1.0f,1.0f);glVertex3f(-1.0f,1.0f,-1.0f);glTexCoord2f(0.0f,1.0f);glVertex3f(1.0f,1.0f,-1.0f);glTexCoord2f(0.0f,0.0f);glVertex3f(1.0f,-1.0f,-1.0f);glEnd();glBindTexture(GL_TEXTURE_2D,texture[0]);glBegin(GL_QUADS);//上glTexCoord2f(0.0f,1.0f);glVertex3f(-1.0f,1.0f,-1.0f);glTexCoord2f(0.0f,0.0f);glVertex3f(-1.0f,1.0f,1.0f);glTexCoord2f(1.0f,0.0f);glVertex3f(1.0f,1.0f,1.0f);glTexCoord2f(1.0f,1.0f);glVertex3f(1.0f,1.0f,-1.0f);glEnd();glBindTexture(GL_TEXTURE_2D,texture[0]);glBegin(GL_QUADS);//下glTexCoord2f(1.0f,1.0f);glVertex3f(-1.0f,-1.0f,-1.0f);glTexCoord2f(0.0f,1.0f);glVertex3f(1.0f,-1.0f,-1.0f);glTexCoord2f(0.0f,0.0f);glVertex3f(1.0f,-1.0f,1.0f);glTexCoord2f(1.0f,0.0f);glVertex3f(-1.0f,-1.0f,1.0f);glEnd();glBindTexture(GL_TEXTURE_2D,texture[0]);glBegin(GL_QUADS);//右glTexCoord2f(1.0f,0.0f);glVertex3f(1.0f,-1.0f,-1.0f);glTexCoord2f(1.0f,1.0f);glVertex3f(1.0f,1.0f,-1.0f);glTexCoord2f(0.0f,1.0f);glVertex3f(1.0f,1.0f,1.0f);glTexCoord2f(0.0f,0.0f);glVertex3f(1.0f,-1.0f,1.0f);glEnd();glBindTexture(GL_TEXTURE_2D,texture[0]);glBegin(GL_QUADS);//左glTexCoord2f(0.0f,0.0f);glVertex3f(-1.0f,-1.0f,-1.0f);glTexC
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026河南南阳理工学院人才招聘30人考试备考题库及答案解析
- 2026年第五师八十八团国家级公益林护林员招聘(3人)考试备考试题及答案解析
- 2026山东省淄博第十一中学招聘11人考试参考题库及答案解析
- 2026湖南长沙市雨花区育新第二小学春季合同制教师招聘考试参考试题及答案解析
- 中冶交通2026届校园招聘考试备考试题及答案解析
- 2026年怒江州贡山县公安局招聘警务辅助人员(5人)笔试备考题库及答案解析
- 2026湖北武汉市华中农业大学其他专业技术人员招聘15人笔试备考题库及答案解析
- 压伤患者的并发症护理与处理
- 智能机器全景解析
- 2026北京协和医院康复医学科合同制物理因子治疗(理疗)技术员招聘考试备考题库及答案解析
- 食品添加剂生产质量管理手册(标准版)
- 【初中 历史】2025-2026学年统编版八年级历史上册期末材料分析题练习
- 2026年2026年健康饮食防失眠培训课件
- 《马原》期末复习资料
- 绿色化学原理课件
- 《出塞》优秀课件
- 优倍流量积算仪说明书
- 苏教版六年级上册数学期末总复习(专题)课件
- YY∕T 0636.3-2021 医用吸引设备 第3部分:以真空或正压源为动力的吸引设备(高清正版)
- 北京市西城区2021届英语八年级(上)期末考试模拟试题
- 电气工程课程设计反激型开关电源设计
评论
0/150
提交评论