OpenGL学习

您所在的位置:网站首页 opengl纹理贴图图片位置 OpenGL学习

OpenGL学习

2024-06-19 18:22| 来源: 网络整理| 查看: 265

本篇文章为纹理贴图的第一次学习,没太多时间去深入的学,把每个函数都搞得明明白白,所以这里自己的理解写的比较少。别人总结的还蛮好的,所以我主要是总结了几篇其他文章的内容,如果不去深究每个函数,我觉得足以让你明白纹理贴图的一个大致操作流程。

一、创建纹理对象,并为它指定一个纹理

启用纹理贴图

glEnable(GL_TEXTURE_2D);

定义一个纹理对象编号

static GLuint texName;

创建一个纹理对象,&texName指向纹理索引

glGenTextures(1, &texName);

绑定纹理:改变OpenGL状态,使得后续的纹理操作都对texName指向的2D纹理生效

glBindTexture(GL_TEXTURE_2D, texName);

二、载入纹理,设置纹理参数 纹理过滤函数

glTexParameteri()

图象从纹理图象空间映射到帧缓冲图象空间(映射需要重新构造纹理图像,这样就会造成应用到多边形上的图像失真),这时就可用glTexParmeteri()函数来确定如何把纹理象素映射成像素。

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

这些参数先不用管,就是说贴图时的各种限制和模式。

指定纹理贴图与材质的混合模式

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

材质这个不是太懂。

为纹理对象指定一个纹理

glTexImage2D ( GLenum target, //指定的目标,可以使用GL_TEXTURE_2D GLint level, //“多重细节层次”,不考虑多重纹理的话设置为零。 GLint internalformat,//RGB数据存储的格式,比如GL_RGB GLsizei width, GLsizei height, //二维纹理像素的宽度和高度。 GLint border, //纹理边框的大小,不使用纹理边框设置为零。 GLenum format, // GLenum type, //数据格式和数据保存形式。 const GLvoid *pixels //保存了纹理图像的内参块地址。 );

此函数的参数可以像下面这样设置:

glTexImage2D( GL_TEXTURE_2D, //target,目标纹理 0, //分辨率级数参数,默认为0 GL_RGBA, //纹理单元格式 checkImageWidth, //纹理图像的宽 checkImageHeight, //纹理图像的高 0, //纹理图像边框的宽度,0或1 GL_RGBA, //纹理像素数据的格式 GL_UNSIGNED_BYTE, //像素数据类型 checkImage //内存中指向纹理图像的指针 ); 三、纹理映射,绘制纹理图像

纹理映射跟颜色的绘制一样,需要指定每一个顶点在纹理图像中所对应的位置,OpenGL会自动计算出顶点之间的其他点在纹理图像中应该对应的位置。这里注意纹理图像的坐标范围是从(0,0)到(1,1),左下角为(0,0),右上角为(1,1)。比如,将图像映射到多个四边形上:

// 绘制底面以及纹理 glBindTexture(GL_TEXTURE_2D, texSea); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); //纹理坐标配置函数 glVertex3f(-8.0f, -8.0f, 0.0f); glTexCoord2f(0.0f, 3.0f); glVertex3f(-8.0f, 8.0f, 0.0f); glTexCoord2f(3.0f, 3.0f); glVertex3f(8.0f, 8.0f, 0.0f); glTexCoord2f(3.0f, 0.0f); glVertex3f(8.0f, -8.0f, 0.0f); glEnd();

此代码显示3行3列个位图(共9个)(如果坐标是小于1的,那就是正常的映射),坐标可以这样映射:(0.0f, 0.0f)、(0.0f, 3.0f)、(3.0f, 3.0f)、(3.0f, 0.0f)。

glTexCoord2f()主要与glVertex3f()配合使用,glTexCoord2f()是配置纹理坐标,glVertex3f()是配置图形坐标。

四、其他补充

下面这个代码的原文章有大致这样说明,读取纹理图片到内存时,位图的大小有规定的大小,宽度什么的有些要求,如果长宽有超过当前版本所支持最大长宽数值,还需要对图像进行缩放。这里我们先不管这个格式问题了,给的位图是标准的。

还有代码中关于读取位图的操作,我觉得有点麻烦,我看有些直接使用stb_image.h来加载图像,这个我还没有研究,但肯定比这篇文章的示例代码简单些。

他这个代码是手动分配内存的。 在这里插入图片描述

#define WindowWidth 400 #define WindowHeight 400 #define WindowTitle "纹理贴图" #include #include #include #define GL_BGR_EXT 0x80E0 //我这个版本找不到这个宏,需要自己定义 //定义两个纹理对象编号 GLuint texSea; GLuint texSky; #define BMP_Header_Length 54 //图像数据在内存块中的偏移量 static GLfloat angle = 0.0f; //旋转角度 //读取一个BMP文件作为纹理。如果失败,返回0,如果成功,返回纹理编号. //这个代码的处理位图的操作太麻烦了,可以先不管,知道他把位图保存到了一个字节变量pixel中就好 GLuint load_texture(const char* file_name) { GLint width, height, total_bytes; GLubyte* pixels = 0; GLuint last_texture_ID=0, texture_ID = 0; // 打开文件,如果失败,返回 FILE* pFile = fopen(file_name, "rb"); if( pFile == 0 ) { printf("Wrong!!!!\n"); return 0; } // 读取文件中图象的宽度和高度 fseek(pFile, 0x0012, SEEK_SET); fread(&width, 4, 1, pFile); fread(&height, 4, 1, pFile); fseek(pFile, BMP_Header_Length, SEEK_SET); // 计算每行像素所占字节数,并根据此数据计算总像素字节数 GLint line_bytes = width * 3; while( line_bytes % 4 != 0 ) ++line_bytes; total_bytes = line_bytes * height; // 根据总像素字节数分配内存 pixels = (GLubyte*)malloc(total_bytes); if( pixels == 0 ) { fclose(pFile); return 0; } // 读取像素数据 if( fread(pixels, total_bytes, 1, pFile) = 360.0f ) angle = 0.0f; display(); } int main(int argc, char* argv[]) { // GLUT初始化 glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(100, 100); glutInitWindowSize(WindowWidth, WindowHeight); glutCreateWindow(WindowTitle); glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); // 启用2D纹理功能 texSea = load_texture("C:\\Users\\user\\Desktop\\贴图1_方块\\sea.bmp"); texSky = load_texture("C:\\Users\\user\\Desktop\\贴图1_方块\\sky.bmp"); //加载纹理 //绘图 glutDisplayFunc(&display); glutIdleFunc(&myIdle); glutMainLoop(); return 0; }


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3