标题 | OpenGL纹理函数应用方法研究 |
范文 | 童立靖 陈静![]() ![]() ![]() 摘 要:OpenGL(Open Graphics Library)是目前流行的用于计算机图形处理的程序接口。纹理贴图是其中常用的操作,可以加强图形和动画的美观和真实程度。OpenGL提供了功能强大的贴图函数,可以帮助用户完成贴图操作,贴图操作可以分为在平面上贴纹理图和为网格模型添加纹理两种。 关键词:图形处理;动画;纹理贴图;OpenGL DOIDOI:10.11907/rjdk.151294 中图分类号:TP301 文献标识码:A 文章编号:1672-7800(2015)007-0033-03 0 引言 OpenGL是通用的专业图形程序接口[1],可跨平台使用,功能十分强大。 它提供了预包装功能,开发人员所编写的程序可以直接使用,OpenGL作为它的应用程序编程接口(API)。 OpenGL提供了功能强大的贴图函数,可供用户在平面上贴纹理操作和为网格模型添加纹理。本文梳理主要的贴图函数,并介绍这两种贴图方法。 1 OpenGL函数命名约定 绝大多数OpenGL函数都遵循一种命名约定,可看出来自哪个函数库及其基本功能,还提示函数将接受的参数个数和类型[2]。所有函数都具有一个根名称,表示函数所发挥的功能属于哪一个功能大类。所有OpenGL函数都采用以下格式: <函数库前缀><根命令><可选的参数数量><可选的参数类型> 比如,glColor3f()函数名中的“Color”表示函数用于设置当前绘图颜色,后缀中的“3”表示函数接受3个参数,Color函数还存在接受4个参数的版本;f表示这些参数都是浮点数。OpenGL为同一个函数定义了不同参数类型,允许用户根据自己的数据格式向OpenGL传递参数。 2 OpenGL所定义的贴图函数 OpenGL定义了功能强大的贴图函数,都以Texture作为根命令。 2.1 glGenTexture():创建纹理对象 使用纹理对象时,首先生成一个纹理名[3]。纹理名可以是任何一个非0的无符号整数,为了保证不重复使用同一个纹理名,应调用glGenTexture()函数。 glGenTextures (GLsizei n, GLuint *textureNames) 参数n指定了将有多少个纹理名被生成并存入textureNames数组中。例如,如果用一个有3个元素的数组来存储纹理名,使用glGenTextures()函数如下: Unsigned int textureNames[3]; ... glGenTextures(3, textureNames); 2.2 glBindTexture():绑定纹理对象 生成纹理名后必须将纹理名绑定到纹理数据上, 可以调用glBindTexture( ) 函数来实现: glBindTexture(Glenum target, GLuint texture-Name) 参数target指明了纹理维度,其可能的情况是:GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP。参数texture-Name即为与之绑定的纹理编号。 2.3 glTextureImage2D():载入纹理对象 将纹理贴图应用到几何图形的一个必要步骤是将纹理载入内存。载入后,这个纹理就成为当前纹理状态的一部分,其函数如下: glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *texels) 2.4 glParameteri():设置滤波方式 由于纹理图被应用于变形多边形后,将发生扭曲变形,一个单一像素可能仅仅代表纹理图的一个纹素(texel)的一小部分,也可能代表多个texel的集合。这时就要使用纹理过滤来告诉OpenGL应该如何计算这些像素和texel,以得到最后的图像。其函数表示如下: glTexParameteri (GLenum target, GLenum pname, GLint param) 2.5 glTexCoord():为顶点设置纹理坐标 该函数有两个参数:GLfloat s, GLfloat t 第一个参数代表X坐标,第二个参数代表Y坐标。一个完全纹理的4个顶点的坐标为:(0.0f, 0.0f)、(0.0f, 1.0f)、(1.0f, 1.0f)、(1.0f, 0.0f),分别对应左下、左上、右上、右下角。通常认为,纹理一个挨着一个粘在坐标轴上,是否显示多个,显示哪部分完全由4个顶点坐标决定。比如显示3行2列个位图(共6个),坐标为:(0.0f, 0.0f)、(0.0f, 3.0f)、(2.0f, 3.0f)、(2.0f, 0.0f)。 在OpenGL中,指定纹理空间中的点=()和面片上的顶点Vi的对应关系,使用函数glTexCoord2f(s, t)设置当前的纹理坐标为(s, t),这个坐标就和随后定义的顶点联系到一起[4]。通常glVertex2f()调用前都要调用glTexCoord2f(),这样每个顶点都有一对不同的纹理坐标。例如,为定义一个四边形并且设置一个纹理,通过如下程序传给OpenGL四个纹理坐标和四个三维顶点。 glBegin(GL_QUADS); //为顶点设置纹理坐标,贴四边形图 glNormal3f(0.0,0.0,1.0); glTexCoord2f(0.0f,0.0f); glVertex3f(-6.0f,-2.6f,0.0f); glTexCoord2f(1.0f,0.0f); glVertex3f(6.0f,-2.6f,0.0f); glTexCoord2f(1.0f,1.0f); glVertex3f(6.0f,2.6f,0.0f); glTexCoord2f(0.0f,1.0f); glVertex3f(-6.0f,2.6f,0.0f); glEnd() 2.6 glTexEnv() 修改纹理环境 在大多情况下,纹理图像表面的颜色值都直接作为被贴图表面的颜色。可以使用纹理图像对物体表面的颜色进行调整,而不直接贴图。也可以将纹理图像的颜色与物体表面的原先颜色进行组合。可以通过glTexEnv*( )函数提供适当的参数来选择纹理函数。 Void glTexEnvi ( GLenumtarget, GLenumpname, Glint param) ; param参数可以设为表1中的任何一个值,用来指示纹理与原有像素的显示关系。 3 在平面上贴纹理 图1为在C++环境下的一幅有跳跃火焰的壁炉的动画截屏。图2是该动画用到的有关纹理的材料。 可以看出,墙壁的肌理是由Wall.bmp图片作为素材的贴图,壁炉整体由一个Fileplace.bmp图片贴图完成。跳跃火焰效果由15张不断轮转的不同状态的火焰图片完成。以鹿头周围的大理石墙面贴图为例,OpenGL在以VS2005为编译环境的C++代码中将Wall.bmp作为纹理附着,产生大理石墙面逼真效果。方法如下: BOOL BuildTexture(char *szPathName, GLuint & texid) //该函数载入图片并把该图片转换为纹理,其函数中包括如下语句 glGenTextures(1,&texid); //创建纹理,生成纹理号 glBindTexture(GL TEXTURE 2D, texid); //绑定纹理,参数指明了纹理的维度和纹理编号 glTexImage2D(GL_TEXTURE_2D,0,3,lWithPixels,lHeightPixels,0,GL_RGBA,GL_UNSINGED_BYTE,pBits); //载入二维纹理 然后,在Main.cpp中: BuildTexture("wall.bmp", texture[0]); 在绘图函数中绘制墙面,代码如下: glEnable(GL_TEXTURE_2D); glColor3f(1.0f,1.0f,1.0f); glPushMatrix(); glBindTexture(GL_Texture2D. texture[0]); glBegin(GL_QUADS); glNormal3f(0.0,0.0,1.0); glTexCoord2f(0.0f,0.0f); glVertex3f(-6.0f,-2.6f,0.0f); glTexCoord2f(1.0f,0.0f); glVertex3f(6.0f,-2.6f,0.0f); glTexCoord2f(1.0f,1.0f); glVertex3f(6.0f,2.6f,0.0f); glTexCoord2f(0.0f,1.0f); glVertex3f(-6.0f,2.6f,0.0f); glEnd(); 这就完成了对于大理石墙壁平面的贴图操作,它引用了整幅图片Wall.bmp。 4 为网格模型添加纹理 随着三维扫描仪的普及和逆向工程的兴起,可以利用三维扫描仪等设备的激光传感器采集不同物体的形状信息,构成网格模型,并用摄像头采集其颜色信息,然后通过软件合成形状和颜色,达到在计算机中恢复所拍摄的对象或场景的目的。举例如下: 首先,运用三维扫描仪采集书籍的单页文本点云数据(见图3),点云数据构成的网格模型存储在扫描仪生成的OBJ格式文件中,其颜色信息存储在MTL格式文件和JPG格式文件中[5]。 其次,采用OpenGL库中的贴图操作,在VS2005中将三维扫描仪采集到的阿特拉斯贴图贴到相应的三角面片上。其效果如图4所示。 图3 文本点云数据 图4 书本原貌显示 介绍如何利用OBJ格式文件和MTL格式文件中的信息和JPG图片,完成对上图点云的贴图操作。 4.1 在OBJ类型文件中保存顶点和材质的映射信息 OBJ文件类型是目前流行的3D文件类型,适合用于3D软件模型之间的互导[6]。OBJ文件是一种文本文件,可以直接用写字板打开进行查看和编辑修改。三维扫描仪扫描生成的书籍的OBJ文件内容如下(括号内为解释): # File exported by Artec Group 3D Scanning Solutions(以#开头为注释) # 366447 vertices(显示顶点数量) # 726521 triangular faces(显示面的数量) mtllib BOOK.mtl (OBJ 文件不包含面的颜色定义信息,不过可以引用材质库,材质库信息储存在一个后缀是".mtl"的独立文件中。 关键字"mtllib"即材质库) v -249.12631225585937 5.5140132904052734 -23.952362060546875(v表示本行指定一个顶点,三个单精度浮点数,分别表示该定点的xyz坐标值) vt 0.45740783214569092 0.079434990882873535(vt表示本行指定一个纹理坐标,两个单精度浮点数,分别表示此纹理坐标的U,V值) f 45527/45527 45271/45271 45273/45273(f表示本行指定一个表面,一个表面实际上就是一个三角形图元。) usemtl material_1(usemtl指定材质后,后续面都使用这一材质,直到遇到下一个usemtl来指定新的材质) 4.2 在MTL格式的文件中保存纹理信息 OBJ 文件不包含面的颜色定义信息,不过可以引用材质库,材质库信息储存在一个后缀是".mtl"的独立文件中。关键字"mtllib"即材质库。MTL文件的内容如下: # File exported by Artec Group 3D Scanning Solutions(以#开头为注释) # www.artec-group.com newmtl material_0 Ka 1 1 1(材质颜色光照定义) Kd 1 1 1(纹理贴图定义) Ks 1 1 1(反射贴图定义) Ns 1000 map_Kd BOOK_0.jpg(为漫反射指定位图文件。所指定的图片如图5,其保存了索引到的颜色信息) 图5 BOOK_0.jpg 4.3 基于索引格式的贴图代码实现 首先,在OpenGL中定义结构体t_Visual用来存放OBJ文件存储的顶点、面和贴图信息。 其次,将文件中的信息导入结构体的对象visual中。 在画图函数如下: 5 结语 本文介绍了以OpenGL为基础的贴图操作,其方法分为在平面上贴纹理和为网格模型添加纹理两种。纹理贴图操作是处理计算机图形中十分常用的操作,其应用将推动计算机图形学及3D动画产业更好发展。 参考文献: [1] SHREINER D,WOO M,NEIDER J,et al.OpenGL编程指南(第四版)[M].邓郑祥,译. 北京:人民邮电出版社,2005,1-3. [2] WRIGHT R S JR,SWEET M. OpenGL超级宝典(第二版)[M].潇湘工作室,译. 北京:人民邮电出版社,2001,31-32. [3] HOCKING K,ASTOR D. OpenGL游戏程序设计(第二版)[M].田昱川,译. 北京:科学出版社,2006,167-170. [4] HILL F S JR,KELLEY S M.计算机图形学(OpenGL版)(第3版)[M]. 胡事民,刘利刚,刘永进,等,译.北京:清华大学出版社,2009,367-369. [5] 王金峰,姚国清. 三维模型文件中的OBJ格式在OpenGL中的输入与处理[J].电脑知识与技术,2011(7):2393-2399. [6] 周德芳,刘京南,余玲玲.基于OpenGL实现三维重构点云处理[J]. 计算机应用,2003(29):1-3. (责任编辑:陈福时) |
随便看 |
|
科学优质学术资源、百科知识分享平台,免费提供知识科普、生活经验分享、中外学术论文、各类范文、学术文献、教学资料、学术期刊、会议、报纸、杂志、工具书等各类资源检索、在线阅读和软件app下载服务。