收藏 分销(赏)

OPENGL的纹理.doc

上传人:xrp****65 文档编号:7504449 上传时间:2025-01-06 格式:DOC 页数:14 大小:58.50KB 下载积分:10 金币
下载 相关 举报
OPENGL的纹理.doc_第1页
第1页 / 共14页
OPENGL的纹理.doc_第2页
第2页 / 共14页


点击查看更多>>
资源描述
OPENGL的纹理 在3D图形中,纹理映射是广泛使用的。纹理映射也是相当复杂的过程: 一 定义纹理 二 控制滤波 三 说明映射方式 四 绘制场景给出顶点的纹理坐标和几何坐标 注意!!纹理映射只能在RGBA模式下使用,不适用于颜色索引模式 1.纹理定义 void glTexImage2D( GLenum target, GLint level, GLint components, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels ); 定义一个二维纹理映射。 target是常数 GL_TEXTURE_2D level表示多级分辨率的纹理图象的级数。若只有一种分辨率,level为0。 components是从1到4的整数,1:选择R;2:选择R A;3:选择R G B; 4:选择R G B A; width height是纹理的尺寸。 format和type描述映射格式和数据类型。它们与前面讲的glDrawPixels()中 OPENGL的纹理 在3D图形中,纹理映射是广泛使用的。纹理映射也是相当复杂的过程: 一 定义纹理 二 控制滤波 三 说明映射方式 四 绘制场景给出顶点的纹理坐标和几何坐标 注意!!纹理映射只能在RGBA模式下使用,不适用于颜色索引模式 1.纹理定义 void glTexImage2D( GLenum target, GLint level, GLint components, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels ); 定义一个二维纹理映射。 target是常数 GL_TEXTURE_2D level表示多级分辨率的纹理图象的级数。若只有一种分辨率,level为0。 components是从1到4的整数,1:选择R;2:选择R A;3:选择R G B; 4:选择R G B A; width height是纹理的尺寸。 format和type描述映射格式和数据类型。它们与前面讲的glDrawPixels()中 GL_NEAREST_MIPMAP_NEAREST GL_NEAREST_MIPMAP_LINEAR GL_LINEAR_MIPMAP_NEAREST GL_LINEAR_MIPMAP_LINEAR 2.1 滤波 原始纹理图象是个方形图象,把它映射到奇形怪状的物体上,一般不可能图象 上的一个象素对应屏幕的一个象素。因此局部放大缩小时,就要定义合适的滤 波方式(以2D为例): void glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); void glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); 前者是放大滤波(GL_TEXTURE_MAG_FILTER), 后者是缩小滤波(GL_TEXTURE_MIN_FILTER); 另外,GL_NEAREST是利用最坐标最靠近象素中心的纹理元素,这有可能使图样 走型,但计算速度快;GL_LINEAR利用线形插值,效果好但计算量大。 2.2重复与缩限 纹理映射可以重复映射或者缩限映射,重复映射时纹理可以在自己的坐标S T方 向重复。 对于重复映射: void glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); void glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); 参数GL_REPEAT改为GL_CLAMP,则缩限,所有大于1的纹理元素值置为1。所有小于 0的纹理元素值置为0。 0的纹理元素值置为0。 3. 映射方式 处理纹理本身图案颜色和物体本身颜色的关系: void glTexEnv{if}[v](GLenum target,GLenum pname,TYPE param); target必须是GL_TEXTURE_ENV; pname是GL_TEXTURE_ENV_MODE,则param可以是 GL_DECAL GL_MODULATE或 GL_BLEND,说明纹理值与原来颜色不同的处理方式。 pname是GL_TEXTURE_ENV_COLOR,则参数param是包含4个浮点数(R、G、B、A) 的数组。这些值只在采用GL_BLEND纹理函数时才采用。 4. 纹理坐标 坐标的定义:纹理图象是方形的,纹理坐标可定义成s,t,r,q坐标,仿照齐次 坐标系的x,y,z,w坐标。 void glTexCoord{1234}{sifd}[v](TYPE coords); 设置当前纹理坐标,此后调用glVertex*()所产生的顶点都赋予当前的纹理坐标。 5. 坐标自动产生 有时不需要为每个物体顶点赋予纹理坐标,可以使用 void glTexGen{if}(GLenum coord,GLenum pname,TYPE param); coord为:GL_S GL_T GL_R或GL_Q,指明哪个坐标自动产生 pname为GL_TEXTURE_GEN_MODE时 param为常数:GL_OBJECT_LINEAR GL_EYE_LINEAR或GL_SPHERE_MAP,它们决定用 哪个函数来产生纹理坐标 pname为GL_OBJECT_PLANE或GL_EYE_PLANE,param时一个指向参数数组的指针。 先请看一个简单的例子: //////////////////////////////////////////// //sample.cpp #include "glos.h" #include <GL/gl.h> #include <GL/glaux.h> #include "windows.h" void myinit(void); void CALLBACK display(void); void CALLBACK reshape(GLsizei w,GLsizei h); //创建纹理图象的子程序 #define TEXTUREWIDTH 64 #define TEXTUREHEIGHT 64 GLubyte Texture[TEXTUREWIDTH][TEXTUREHEIGHT][3]; void makeTexture(void) void makeTexture(void) { int i,j,r,g,b; for(i=0;i<TEXTUREWIDTH;i++) { for(j=0;j<TEXTUREHEIGHT;j++) { r=(i*j)%255; g=(4*i)%255; b=(4*j)%255; Texture[i][j][0 =(GLubyte)r; Texture[i][j][1 =(GLubyte)g; Texture[i][j][2 =(GLubyte)b; } } } void myinit(void) { auxInitDisplayMode(AUX_SINGLE|AUX_RGBA); auxInitPosition(0,0,500,500); auxInitWindow("sample1"); auxInitWindow("sample1"); glClearColor(0.0,0.0,0.0,0.0); glClear(GL_COLOR_BUFFER_BIT); //创建纹理图象的原始数据保存在Texture[][][]中 makeTexture(); glPixelStorei(GL_UNPACK_ALIGNMENT,1); //定义二维纹理 glTexImage2D(GL_TEXTURE_2D,0,3,TEXTUREWIDTH, TEXTUREHEIGHT,0,GL_RGB,GL_UNSIGNED_BYTE, &Texture[0][0][0]); //控制滤波 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_LINEAR); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); //说明映射方式 glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL); //这个应该很熟了,启用纹理模式 glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D); // glShadeModel(GL_FLAT); } void CALLBACK reshape(GLsizei w,GLsizei h) { glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); //定义立体视景体 gluPerspective(60.0,1.0*(GLfloat)w/(GLfloat)h,1.0,30.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0,0.0,-3.6); } void CALLBACK display(void) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glBegin(GL_QUADS);//绘制四边形 //先绘制正方形,用来显示实际未变形的纹理图样 //先绘制正方形,用来显示实际未变形的纹理图样 glTexCoord2f(0.0,0.0);glVertex3f(-2.0,-1.0,0.0); glTexCoord2f(0.0,1.0);glVertex3f(-2.0,1.0,0.0); glTexCoord2f(1.0,1.0);glVertex3f(0.0,1.0,0.0); glTexCoord2f(1.0,0.0);glVertex3f(0.0,-1.0,0.0); //绘制一个不规则四边形,用来显示纹理是如何随物体形状而变形的。 glTexCoord2f(0.0,0.0);glVertex3f(0.0,-1.0,0.0); glTexCoord2f(0.0,1.0);glVertex3f(0.0,1.0,0.0); glTexCoord2f(1.0,1.0);glVertex3f(1.41421,1.0,-1.41421); glTexCoord2f(1.0,0.0);glVertex3f(1.41421,-1.0,-1.41421); glEnd(); glFlush(); } void main(void) { myinit(); auxReshapeFunc(reshape); auxMainLoop(display); } //end of sample 从例子来看,除了纹理的定义和控制比较麻烦和不容易理解外,其应用是十分 方便的。只须从纹理的坐标系选出合适点附在实际物体顶点上即可。对于复杂 的纹理定义和控制,你也可以自行改变一些参数,看看效果如何。例如把 GL_LINEAR改成GL_NEAREST,则纹理的明显变的粗糙,但计算结果却快的多。 你也可以改动glTexCoord2f()的参数,看看如何选定纹理的一部分(例子中是 选定全部纹理)来贴图。例如1.0改成0.5则选择实际纹理的左上1/4部分来贴图。 下次将给出一个更复杂的纹理应用的例子和说明。18:03 98-1-21 --------------------------------------------- 这次将结束纹理的内容。紧接上次,在上次平面纹理贴图中,我们先 定义了一个数组(一维或二维...)来定义纹理的数据,所以纹理本身 是一个N维空间,有自己的坐标和顶点。在上次的例子中,我们学会了 如何把纹理数据中的坐标和屏幕物体坐标相结合,就象把一块布料扯成 合适的形状贴在物体表面。而上次唯一没有使用的函数是纹理坐标的自 动产生(最后一个给出的函数),它的意义是产生一个环境纹理,所有 环境内的物体都赋予此纹理,很象一个特殊光源。 ///////////////////////////////////////////////////////////// //sample.cpp #include "glos.h" #include <GL/gl.h> #include <GL/glaux.h> #include "windows.h" void myinit(void); void CALLBACK display(void); void CALLBACK reshape(GLsizei w,GLsizei h); //定义一个一维纹理的数据,从生成来看,保持红色、兰色分量255(MAX), //所以是渐变的紫色纹理,饱和度不断变化。 //所以是渐变的紫色纹理,饱和度不断变化。 #define TEXTUREWIDTH 64 GLubyte Texture[3*TEXTUREWIDTH]; void makeTexture(void) { int i; for(i=0;i<TEXTUREWIDTH;i++) { Texture[3*i =255; Texture[3*i+1 =255-2*i; Texture[3*i+2 =255; } } GLfloat sgenparams[]={1.0,1.0,1.0,0.0}; void myinit(void) { auxInitDisplayMode(AUX_SINGLE|AUX_RGBA); auxInitPosition(0,0,500,500); auxInitWindow("sample1"); glClearColor(0.0,0.0,0.0,0.0); glClear(GL_COLOR_BUFFER_BIT); //创建纹理 makeTexture(); glPixelStorei(GL_UNPACK_ALIGNMENT,1); //控制纹理 glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); glTexParameterf(GL_TEXTURE_1D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameterf(GL_TEXTURE_1D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameterf(GL_TEXTURE_1D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexImage1D(GL_TEXTURE_1D,0,3,TEXTUREWIDTH,0, GL_RGB,GL_UNSIGNED_BYTE,Texture); //唯一与前面例子不同的地方:启用纹理坐标自动产生,生成环境纹理 //纹理的方向S glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR); glTexGenfv(GL_S,GL_OBJECT_PLANE,sgenparams); //启用纹理 glEnable(GL_TEXTURE_1D); glEnable(GL_TEXTURE_GEN_S); //启用消隐 glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glDepthFunc(GL_LESS); //一些绘图控制,详细可参阅VC5联机帮助 glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_AUTO_NORMAL); glEnable(GL_NORMALIZE); glFrontFace(GL_CW); glCullFace(GL_BACK); glMaterialf(GL_FRONT,GL_SHININESS,64.0); // glShadeModel(GL_FLAT); } void CALLBACK reshape(GLsizei w,GLsizei h) { glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if(w<=h) glOrtho(-4.0,4.0,-4.0*(GLfloat)h/(GLfloat)w, glOrtho(-4.0,4.0,-4.0*(GLfloat)h/(GLfloat)w, 4.0*(GLfloat)h/(GLfloat)w,-4.0,4.0); else glOrtho(-4.0*(GLfloat)h/(GLfloat)w, 4.0*(GLfloat)h/(GLfloat)w,-4.0,4.0,-4.0,4.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void CALLBACK display(void) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(30.0,1.0,0.0,0.0); //功能强大的辅助库函数:呵呵画出一个大茶壶。 auxSolidTeapot(1.5); glPopMatrix(); glFlush(); } void main(void) { myinit(); { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glPushMatrix(); glRotatef(30.0,1.0,0.0,0.0); //功能强大的辅助库函数:呵呵画出一个大茶壶。 auxSolidTeapot(1.5); glPopMatrix(); glFlush(); } void main(void) { myinit(); auxReshapeFunc(reshape); auxMainLoop(display); } //end of sample //////////////////////////////////////////////////////////// 至此纹理的全部内容已经完毕。从运行结果来看,一个物体全部进行 了表面的纹理映射。 -12--------------------------------------------- 此次讲解OPENGL复杂建模方式,将分几个部分完成,这篇先介绍图原扩展: 如何利用专用函数精确绘制平面图形。下次会讲解如何利用法向量生成曲面。 1.点和线 void glPointSize(GLfloat size); 设置点的宽度,size必须>0,缺省1 void glLineWidth(GLfoat width); 设置线宽,width>0,缺省为1 void glLineStipple(GLint factor,GLushort pattern); 设置线的模式,factor用于对模式进行拉伸的比例因子,pattern是线的模式 例如11001100是虚线(1绘制,0不绘制) 必须要启用glEnable(GL_LINE_STIPPLE)才能使用以上函数,不再使用时调用 glDisable(GL_LINE_STIPPLE)关闭,这与以前的glEnable();glDisable();的 用法都是类似的。请看下面例子: /////////////////////////////////////////////////////////////////// //sample.cpp #include "glos.h" #include "glos.h" #include <GL/gl.h> #include <GL/glaux.h> #include "windows.h" void myinit(void); void CALLBACK display(void); void CALLBACK reshape(GLsizei w,GLsizei h); void myinit(void) { auxInitDisplayMode(AUX_SINGLE|AUX_RGBA); auxInitPosition(0,0,600,500); auxInitWindow("sample1"); glClearColor(0.0,0.0,0.0,0.0); glClear(GL_COLOR_BUFFER_BIT); glShadeModel(GL_FLAT); } /* void CALLBACK reshape(GLsizei w,GLsizei h) { glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if(w<=h) glOrtho(-4.0,4.0,-4.0*(GLfloat)h/(GLfloat)w, 4.0*(GLfloat)h/(GLfloat)w,-4.0,4.0); else glOrtho(-4.0*(GLfloat)h/(GLfloat)w, 4.0*(GLfloat)h/(GLfloat)w,-4.0,4.0,-4.0,4.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } */ //自定义的绘制直线的函数,参数为起始点和终止点坐标 void line2i(GLint x1,GLint y1,GLint x2,GLint y2) { glBegin(GL_LINES); glVertex2f(x1,y1); glVertex2f(x2,y2); glEnd(); glEnd(); } void CALLBACK display(void) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //首先绘制一系列点,点的大小不断增加 int i; glColor3f(0.8,0.6,0.4); for(i=1;i<=10;i++) { glPointSize(i*2); glBegin(GL_POINTS); glVertex2f(30.0+((GLfloat)i*50.0),330.0); glEnd(); } //再绘制两条虚线,第二条比第一条松散一些,由pattern参数即可看出 glEnable(GL_LINE_STIPPLE); glLineStipple(1,0x0101);//间隔1位 glColor3f(1.0,0.0,0.0); line2i(20,250,250,250); glLineStipple(1,0x00ff);//间隔2位 glLineStipple(1,0x00ff);//间隔2位 glColor3f(0.0,0.0,1.0); line2i(300,250,550,250); //改变线的绘制宽度的效果--加宽 //重新画出上面两条虚线 glLineWidth(5.0); glEnable(GL_LINE_STIPPLE); glLineStipple(1,0x0101); glColor3f(1.0,0.0,0.0); line2i(50,150,250,150); glLineStipple(1,0x00ff); glColor3f(0.0,0.0,1.0); line2i(300,150,550,150); glFlush(); } void main(void) { myinit(); // auxReshapeFunc(reshape); auxMainLoop(display); auxMainLoop(display); } //end of sample ////////////////////////////////////////////// 2.多边形 void glPolygonMode(GLenum face,GLenum mode); 控制多边形指定面的绘图模式, face为:GL_FRONT GL_BACK或GL_FRONT_AND BACK mode为:GL_POINT GL_LINE或GL_FILL表示多边型的轮廓点、轮廓线和填充模式 的绘制方式。缺省是填充方式。 void glPolygonStipple(const GLubyte *mask); 其中mask必须是指向32*32的位图指针,1是绘制、0不绘制 使用上述函数也要调用: glEnable(GL_POLYGON-STIPPLE); glDisable(GL_POLYGON_STIPPLE); 请看下面例子: ///////////////////////////////////////////// //sample.cpp #include "glos.h" #include <GL/gl.h> #include <GL/gl.h> #include <GL/glaux.h> #include "windows.h" void myinit(void); void CALLBACK display(void); void CALLBACK reshape(GLsizei w,GLsizei h); //定义填充模式32*32点阵 GLubyte pattern[]={ 0x00,0x01,0x80,0x00, 0x00,0x03,0xc0,0x00, 0x00,0x07,0xe0,0x00, 0x00,0x0f,0xf0,0x00, 0x00,0x1f,0xf8,0x00, 0x00,0x3f,0xfc,0x00, 0x00,0x7f,0xfe,0x00, 0x00,0xff,0xff,0x00, 0x01,0xff,0xff,0x80, 0x03,0xff,0xff,0xc0, 0x07,0xff,0xff,0xe0, 0x0f,0xff,0xff,0xf0, 0x1f,0xff,0xff,0xf8, 0x3f,0xff,0xff,0xfc, 0x3f,0xff,0xff,0xfc, 0x7f,0xff,0xff,0xfe, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0x7f,0xff,0xff,0xfe, 0x3f,0xff,0xff,0xfc, 0x1f,0xff,0xff,0xf8, 0x0f,0xff,0xff,0xf0, 0x07,0xff,0xff,0xe0, 0x03,0xff,0xff,0xc0, 0x01,0xff,0xff,0x80, 0x00,0xff,0xff,0x00, 0x00,0x7f,0xfe,0x00, 0x00,0x3f,0xfc,0x00, 0x00,0x1f,0xf8,0x00, 0x00,0x0f,0xf0,0x00, 0x00,0x07,0xe0,0x00, 0x00,0x03,0xc0,0x00, 0x00,0x01,0x80,0x00 }; void myinit(void) void myinit(void) { auxInitDisplayMode(AUX_SINGLE|AUX_RGBA); auxInitPosition(0,0,400,400); auxInitWindow("sample1"); glClearColor(0.0,0.0,0.0,0.0); glClear(GL_COLOR_BUFFER_BIT); glShadeModel(GL_FLAT); } /* void CALLBACK reshape(GLsizei w,GLsizei h) { glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if(w<=h) glOrtho(-4.0,4.0,-4.0*(GLfloat)h/(GLfloat)w, 4.0*(GLfloat)h/(GLfloat)w,-4.0,4.0); else glOrtho(-4.0*(GLfloat)h/(GLfloat)w, glOrtho(-4.0*(GLfloat)h/(GLfloat)w, 4.0*(GLfloat)h/(GLfloat)w,-4.0,4.0,-4.0,4.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } */ void CALLBACK display(void) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //选用兰色作为填充色 glColor3f(0.0,0.0,1.0); //启用多边形绘制模式 glEnable(GL_POLYGON_STIPPLE); //利用定义好的填充模式绘制多边形 glPolygonStipple(pattern); //绘制长方形 glRectf(48.0,80.0,210.0,305.0); glFlush(); } void main(void) { //选用兰色作为填充色 glColor3f(0.0,0.0,1.0); //启用多边形绘制模式 glEnable(GL_POLYGON_STIPPLE); //利用定义好的填充模式绘制多边形 glPolygonStipple(pattern); //绘制长方形 glRectf(48.0,80.0,210.0,305.0); glFlush(); } void main(void) { myinit(); // auxReshapeFunc(reshape); auxMainLoop(display); } //end of sample 例子中的运行结果是给出一个表面有定义图样的长方形 -13--------------------------------------------- 这里讲解OPENGL的曲线生成 1.曲线定义 void glMap1{fd}(GLenum target,TYPE u1,TYPE u2,GLint stride, GLint order,const TYPE *points); target指出控制点的意义以及在points参数中需要多少值。具体如下: target 意义 GL_MAP1_VERTEX_3 X Y Z顶点坐标 GL_MAP1_VERTEX_4 X Y Z W顶点坐标 GL_MAP1_INDEX 颜色索引 GL_MAP1_COLOR_4 R G B A GL_MAP1_NORMAL 法向量 GL_MAP1_TEXTURE_COORD_1 S 纹理坐标 GL_MAP1_TEXTURE_COORD_2 S T纹理坐标 GL_MAP1_TEXTURE_COORD_3 S T R纹理坐标 u1,u2是曲线变量U的范围(具体可以参阅图形学书籍)一般是0到1 stride是跨度,表示points中控制点偏移量(或说是控制点的维数)
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 应用文书 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服