图形学实验5Word文档下载推荐.docx
《图形学实验5Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《图形学实验5Word文档下载推荐.docx(21页珍藏版)》请在冰点文库上搜索。
![图形学实验5Word文档下载推荐.docx](https://file1.bingdoc.com/fileroot1/2023-5/2/014d4d88-9ff2-49af-84f2-f7ab6225df04/014d4d88-9ff2-49af-84f2-f7ab6225df041.gif)
参数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负轴到视点的距离,它们总为正值。
3、实验内容
在OpenGL中纹理映射所使用的纹理数据,既可以是程序生成的一组数据,也可以从外部文件中直接读取,参考示范代码完成以下两项内容:
1.利用直接创建纹理的方法生成二维纹理并映射到四边形上。
参考代码:
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(……);
//启用二维纹理
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[])
2.从外部文件中直接读取纹理实现正方体每个面的纹理映射,并使正方体转动。
整个过程需要三个步骤:
创建纹理、启用纹理映射和使用纹理坐标和几何坐标绘制,下面我们对三个过程进行阐述,并给出参考代码。
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;
}//如果载入失败,返回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]);
//生成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]->
//释放纹理图像占用的内存
}
free(TextureImage[0]);
//释放图像结构
returnStatus;
//返回Status
2)启用纹理映射操作,初始化相关参数
在OpenGL中使用纹理映射之前,必须打开纹理映射。
intInitGL(GLvoid)
LoadGLTextures())//调用纹理载入子例程
returnFALSE;
//启用纹理映射
glShadeModel(GL_SMOOTH);
//启用阴影平滑
glClearColor(0.0f,0.0f,0.0f,0.5f);
//黑色背景
glClearDepth(1.0f);
//设置深度缓存
//启用深度测试
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;
4、实验代码
1、利用直接创建纹理的方法生成二维纹理并映射到四边形上。
#include<
stdlib.h>
GL/glut.h>
#defineimageWidth64
#defineimageHeight64
GLubyteimage[imageWidth][imageHeight][3];
/*绘制一个简单的二维纹理图*/
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);
//启用二维纹理
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);
glVertex3f(0.2,-0.25,1.875);
glVertex3f(0.6,-0.25,0.0);
glVertex3f(0.6,0.25,0.125);
glVertex3f(0.2,0.25,2.0);
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);
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、从外部文件中直接读取纹理实现正方体每个面的纹理映射,并使正方体转动。
GL/glaux.h>
stdio.h>
windows.h>
#pragmacomment(lib,"
openGL32.lib"
)
glu32.lib"
glaux.lib"
#pragmacomment(lib,"
)
GLuinttexture[1];
//创建纹理空间
GLfloatxRot,yRot,zRot;
//控制正方体的旋转
//载入位图图像
AUX_RGBImageRec*LoadBMP(CHAR*Filename){//载入位图图像
Filename){//确保文件名已提供
if(File){
//如果载入失败,返回NULL
intLoadGLTextures(){//载入位图并转换成纹理
)){
//生成D纹理
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILT