位置: 编程技术 - 正文

OpenGL纹理映射(opengl纹理错误变成条纹)

编辑:rootadmin
学习 texture map 纹理映射(贴图)有很多好处。比方说您想让一颗导弹飞过屏幕。根据前几课的知识,我们最可行的办法可能是很多个多边形来构建导弹的轮廓并加上有趣的颜色。使用纹理映射,您可以使用真实的导弹图像并让它飞过屏幕。您觉得哪个更好看?照片还是一大堆三角形和四边形?使用纹理映射的好处还不止是更好看,而且您的程序运行会更快。导弹贴图可能只是一个飞过窗口的四边形。一个由多边形构建而来的导弹却很可能包括成百上千的多边形。很显然,贴图极大的节省了CPU时间。现在我们在第一课的代码开始处增加五行新代码。新增的第一行是 #include 。它允许我们对文件进行操作,为了在后面的代码中使用 fopen() ,我们增加了这一行。然后我们增加了三个新的浮点变量... xrot , yrot 和 zrot 。这些变量用来使立方体绕X、Y、Z轴旋转。最后一行 GLuint texture[1] 为一个纹理分配存储空间。如果您需要不止一个的纹理,应该将数字1改成您所需要的数字。#include // Windows的头文件 #include // 标准输入/输出库的头文件 ( 新增 ) #include // OpenGL库的头文件 #include // GLu库的头文件 #include // GLaux库的头文件 HGLRC hRC=NULL; // 永久着色描述表 HDC hDC=NULL; // 私有GDI设备描述表 HWND hWnd=NULL; // 保存我们的窗口句柄 HINSTANCE hInstance; // 保存程序的实例 bool keys[]; // 用于键盘例程的数组 bool active=TRUE; // 窗口的活动标志,缺省为TRUE bool fullscreen=TRUE; // 全屏标志缺省设定成全屏模式 GLfloat xrot; // X 旋转量 ( 新增 ) GLfloat yrot; // Y 旋转量 ( 新增 ) GLfloat zrot; // Z 旋转量 ( 新增 ) GLuint texture[1]; // 存储一个纹理 ( 新增 ) LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // WndProc的定义 紧跟上面的代码在 ReSizeGLScene() 之前,我们增加了下面这一段代码。这段代码用来加载位图文件。如果文件不存在,返回 NULL 告知程序无法加载位图。在我开始解释这段代码之前,关于用作纹理的图像我想有几点十分重要,并且您必须明白。此图像的宽和高必须是2的n次方;宽度和高度最小必须是象素;并且出于兼容性的原因,图像的宽度和高度不应超过象素。如果您的原始素材的宽度和高度不是,,象素的话,使用图像处理软件重新改变图像的大小。可以肯定有办法能绕过这些限制,但现在我们只需要用标准的纹理尺寸。首先,我们创建一个文件句柄。句柄是个用来鉴别资源的数&#;,它使程序能够访问此资源。我们开始先将句柄设为 NULL 。 AUX_RGBImageRec *LoadBMP(char *Filename) // 载入位图图象 { FILE *File=NULL; // 文件句柄 接下来检查文件名是否已提供。因为 LoadBMP() 可以无参数调用,所以我们不得不检查一下。您可不想什么都没载入吧.....:) if (!Filename) // 确保文件名已提供。 { return NULL; // 如果没提供,返回 NULL } 接着检查文件是否存在。下面这一行尝试打开文件。 File=fopen(Filename,"r"); //尝试打开文件 如果我们能打开文件的话,很显然文件是存在的。使用 fclose(File) 关闭文件。 auxDIBImageLoad(Filename) 读取图象数据并将其返回。if (File) // 文件存在么? { fclose(File); // 关闭句柄 return auxDIBImageLoad(Filename); //载入位图并返回指针 } 如果我们不能打开文件,我们将返回NULL。这意味着文件无法载入。程序在后面将检查文件是否已载入。如果没有,我们将退出程序并弹出错误消息。 return NULL; // 如果载入失败,返回 NULL } 下一部分代码载入位图(调用上面的代码)并转换成纹理。 int LoadGLTextures() // 载入位图(调用上面的代码)并转换成纹理 { 然后设置一个叫做 Status 的变量。我们使用它来跟踪是否能够载入位图以及能否创建纹理。 Status 缺省设为 FALSE (表示没有载入或创建任何东东)。 int Status=FALSE; // Status 状态指示器 现在我们创建存储位图的图像记录。次记录包含位图的宽度、高度和数据。 AUX_RGBImageRec *TextureImage[1]; // 创建纹理的存储空间 清除图像记录,确保其内容为空。 memset(TextureImage,0,sizeof(void *)*1); // 将指针设为 NULL 现在载入位图,并将其转换为纹理。 TextureImage[0]=LoadBMP("Data/NeHe.bmp") 调用 LoadBMP() 的代码。载入 Data 目录下的 NeHe.bmp 位图文件。如果一切正常,图像数据将存放在 TextureImage[0] 中, Status 被设为 TRUE ,然后我们开始创建纹理。// 载入位图,检查有无错误,如果位图没找到则退出。 if (TextureImage[0]=LoadBMP("Data/NeHe.bmp")) { Status=TRUE; // 将 Status 设为 TRUE 现在使用中 TextureImage[0] 的数据创建纹理。第一行 glGenTextures(1, &texture[0]) 告诉OpenGL我们想生成一个纹理名字(如果您想载入多个纹理,加大数字)。&#;得注意的是,开始我们使用 GLuint texture[1] 来创建一个纹理的存储空间,您也许会认为第一个纹理就是存放在 &texture[1] 中的,但这是错的。正确的地址应该是 &texture[0] 。同样如果使用 GLuint texture[2] 的话,第二个纹理存放在 texture[1] 中。『译者注:学C的,在这里应该没有障碍,数组就是从零开始的嘛。』第二行 glBindTexture(GL_TEXTURE_2D, texture[0]) 告诉OpenGL将纹理名字 texture[0] 绑定到纹理目标上。2D纹理只有高度(在 Y 轴上)和宽度(在 X 轴上)。主函数将纹理名字指派给纹理数据。本例中我们告知OpenGL, &texture[0] 处的内存已经可用。我们创建的纹理将存储在 &texture[0] 的 指向的内存区域。glGenTextures(1, &texture[0]); // 创建纹理 // 使用来自位图数据生成 的典型纹理 glBindTexture(GL_TEXTURE_2D, texture[0]); 下来我们创建真正的纹理。下面一行告诉OpenGL此纹理是一个2D纹理 ( GL_TEXTURE_2D )。数字零代表图像的详细程度,通常就由它为零去了。数字三是数据的成分数。因为图像是由红色数据,绿色数据,蓝色数据三种组分组成。 TextureImage[0]->sizeX 是纹理的宽度。如果您知道宽度,您可以在这里填入,但计算机可以很容易的为您指出此&#;。 TextureImage[0]->sizey 是纹理的高度。数字零是边框的&#;,一般就是零。 GL_RGB 告诉OpenGL图像数据由红、绿、蓝三色数据组成。GL_UNSIGNED_BYTE 意味着组成图像的数据是无符号字节类型的。最后... TextureImage[0]->data 告诉OpenGL纹理数据的来源。此例中指向存放在 TextureImage[0] 记录中的数据。// 生成纹理 glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);下面的两行告诉OpenGL在显示图像时,当它比放大得原始的纹理大 ( GL_TEXTURE_MAG_FILTER )或缩小得比原始得纹理小( GL_TEXTURE_MIN_FILTER )时OpenGL采用的滤波方式。通常这两种情况下我都采用 GL_LINEAR 。这使得纹理从很远处到离屏幕很近时都平滑显示。使用 GL_LINEAR 需要CPU和显卡做更多的运算。如果您的机器很慢,您也许应该采用 GL_NEAREST 。过滤的纹理在放大的时候,看起来斑驳的很『译者注:马赛克啦』。您也可以结合这两种滤波方式。在近处时使用 GL_LINEAR ,远处时 GL_NEAREST 。 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // 线形滤波 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // 线形滤波 } 现在我们释放前面用来存放位图数据的内存。我们先查看位图数据是否存放在处。如果是的话,再查看数据是否已经存储。如果已经存储的话,删了它。接着再释放 TextureImage[0] 图像结构以保证所有的内存都能释放。if (TextureImage[0]) // 纹理是否存在 { if (TextureImage[0]->data) // 纹理图像是否存在 { free(TextureImage[0]->data); // 释放纹理图像占用的内存 } free(TextureImage[0]); // 释放图像结构 } 最后返回状态变量。如果一切OK,变量 Status 的&#;为 TRUE 。否则为 FALSE 。 return Status; // 返回 Status } 我只在 InitGL 中增加很少的几行代码。但为了方便您查看增加了哪几行,我这段代码全部重贴一遍。 if (!LoadGLTextures()) 这行代码调用上面讲的子例程载入位图并生成纹理。如果因为任何原因 LoadGLTextures() 调用失败,接着的一行返回FALSE。如果一切OK,并且纹理创建好了,我们启用2D纹理映射。如果您忘记启用的话,您的对象看起来永远都是纯白色,这一定不是什么好事。int InitGL(GLvoid) // 此处开始对OpenGL进行所有设置 { if (!LoadGLTextures()) // 调用纹理载入子例程( 新增 ) { return FALSE; // 如果未能载入,返回FALSE( 新增 ) } glEnable(GL_TEXTURE_2D); // 启用纹理映射( 新增 ) glShadeModel(GL_SMOOTH); // 启用阴影平滑 glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // 黑色背景 glClearDepth(1.0f); // 设置深度缓存 glEnable(GL_DEPTH_TEST); // 启用深度测试 glDepthFunc(GL_LEQUAL); // 所作深度测试的类型 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // 真正精细的透视修正 return TRUE; // 初始化 OK } 现在我们绘制贴图『译者注:其实贴图就是纹理映射。将术语换来换去不好,我想少打俩字。^_^』过的立方体。这段代码被狂注释了一把,应该很好懂。开始两行代码 glClear() 和 glLoadIdentity() 是第一课中就有的代码。 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) 清除屏幕并设为我们在 InitGL() 中选定的颜色,本例中是黑色。深度缓存也被清除。模型观察矩阵也使用glLoadIdentity()重置。int DrawGLScene(GLvoid) // 从这里开始进行所有的绘制 { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除屏幕和深度缓存 glLoadIdentity(); // 重置当前的模型观察矩阵 glTranslatef(0.0f,0.0f,-5.0f); // 移入屏幕 5 个单位 下面三行使立方体绕X、Y、Z轴旋转。旋转多少依赖于变量 xrot , yrot 和 zrot 的&#;。 glRotatef(xrot,1.0f,0.0f,0.0f); // 绕X轴旋转 glRotatef(yrot,0.0f,1.0f,0.0f); // 绕Y轴旋转 glRotatef(zrot,0.0f,0.0f,1.0f); // 绕Z轴旋转 下一行代码选择我们使用的纹理。如果您在您的场景中使用多个纹理,您应该使用来 glBindTexture(GL_TEXTURE_2D, texture[ 所使用纹理对应的数字 ]) 选择要绑定的纹理。当您想改变纹理时,应该绑定新的纹理。有一点&#;得指出的是,您不能在 glBegin() 和 glEnd() 之间绑定纹理,必须在 glBegin() 之前或 glEnd() 之后绑定。注意我们在后面是如何使用 glBindTexture 来指定和绑定纹理的。glBindTexture(GL_TEXTURE_2D, texture[0]); // 选择纹理 为了将纹理正确的映射到四边形上,您必须将纹理的右上角映射到四边形的右上角,纹理的左上角映射到四边形的左上角,纹理的右下角映射到四边形的右下角,纹理的左下角映射到四边形的左下角。如果映射错误的话,图像显示时可能上下颠倒,侧向一边或者什么都不是。glTexCoord2f 的第一个参数是X坐标。 0.0f 是纹理的左侧。 0.5f 是纹理的中点, 1.0f 是纹理的右侧。 glTexCoord2f 的第二个参数是Y坐标。 0.0f 是纹理的底部。 0.5f 是纹理的中点, 1.0f 是纹理的顶部。所以纹理的左上坐标是 X:0.0f,Y:1.0f ,四边形的左上顶点是 X: -1.0f,Y:1.0f 。其余三点依此类推。 试着玩玩 glTexCoord2f 的X,Y坐标参数。把 1.0f 改为 0.5f 将只显示纹理的左半部分,把 0.0f 改为 0.5f 将只显示纹理的右半部分。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); // 纹理和四边形的左上 // 后面 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); // 纹理和四边形的左下 // 顶面 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); // 纹理和四边形的右上 // 底面 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); // 纹理和四边形的右下 // 右面 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); // 纹理和四边形的左下 // 左面 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(); 现在增加 xrot , yrot 和 zrot 的&#;。尝试变化每次各变量的改变&#;来调节立方体的旋转速度,或改变&#;/-号来调节立方体的旋转方向。 xrot&#;=0.3f; // X 轴旋转 yrot&#;=0.2f; // Y 轴旋转 zrot&#;=0.4f; // Z 轴旋转 return true; // 继续运行 } 现在您应该比较好的理解纹理映射(贴图)了。您应该掌握了给任意四边形表面贴上您所喜爱的图像的技术。一旦您对2D纹理映射的理解感到自信的时候,试试给立方体的六个面贴上不同的纹理。当您理解纹理坐标的概念后,纹理映射并不难理解。!如果您有什么意见或建议请给我EMAIL。如果您认为有什么不对或可以改进,请告诉我。

推荐整理分享OpenGL纹理映射(opengl纹理错误变成条纹),希望有所帮助,仅作参考,欢迎阅读内容。

OpenGL纹理映射(opengl纹理错误变成条纹)

文章相关热门搜索词:OpenGl纹理映射实验报告,opengl 纹理映射,OpenGl纹理映射实验报告,opengl oes纹理,opengl 纹理,opengl 纹理,OpenGl纹理映射实验报告,OpenGL纹理映射实验总结,内容如对您有帮助,希望把文章链接给更多的朋友!

OpenGL 资源汇编 本文收集和汇总了OpenGL的文档、教程和在线书籍,供学习和开发人员参考。OPENGL开发教程:

【OpenGL基础篇】——使用面向对象方法封装OpenGL函数(一) OpenGL是一个开源的图形库,既可开发二维图形软件,也可开发三维图形软件。许多知名应用就是基于OpenGL开发出来,如著名的Artoolkit和Unity3D。GLUT是代表

【OpenGL基础篇】——使用面向对象方法封装OpenGL函数(二) 今天封装了一个Line类,负责在昨天写的窗口上绘制线条。OpenGL绘图是通过给glBegin函数设置参数达成的,绘制线条有三个不同的参数:GL_LINES:绘制连接两

标签: opengl纹理错误变成条纹

本文链接地址:https://www.jiuchutong.com/biancheng/373070.html 转载请保留说明!

上一篇:GLSL经典入门教程汇总(glslpe)

下一篇:OpenGL 资源汇编(opengl源码在哪里)

  • 小规模纳税人销售农产品税率是多少
  • 破产企业发放工资要不要纳税?
  • 增值税进项税额加计抵减会计处理
  • 一般进口货物的完税价格如何确定
  • 发票可不可以盖财务专用章
  • 发放工资的转账支票出票人是谁
  • 无息贷款合同要按手印吗
  • 子公司注销资金还母公司冲实收资本吗
  • 企业报税盘入账应该记入哪个科目
  • 外币账户收款如何做账务处理呢?
  • 押金无法退回
  • 房租本月入账上月的怎么摊销?
  • 营改增租金收入税率
  • 营改增施工企业哪些能退
  • 全年一次性奖金计税方式2023
  • 收到原未计入应收项目的交易性金融资产的利息
  • 代账报税软件哪个好
  • 没交社保能扣工伤保险吗
  • 工薪个人所得税扣除
  • 小规模时取得的专票在一般纳锐人之后可以抵扣吗
  • 服务费专票普票
  • 公司的差旅费
  • 公司买空调开具的进项发票可以抵扣吗?
  • 暂估成本后第二年收到发票怎么做账
  • 小规模企业税务简易注销
  • 工商企业年报网上申报时间
  • 结转基本生产成本
  • Win7/Win8/Win10单、多系统一键安装教程 只需30秒!
  • iphone6splus 充电
  • linux标准文件和链接文件
  • 奇托尔加赫城堡
  • 无痛人流多少钱?
  • php投票代码
  • windows7旗舰版最新版本
  • 融资租入的设备为什么属于资产
  • 偿还不了债务会怎么样
  • 都柏林圣三一学院图片
  • 短期资金都是债务类资金
  • 自产产品发给员工账务处理
  • 小企业会计准则财务报表至少包括
  • php 中奖概率算法
  • 车辆购置税发票图片
  • 装修阶段监理注意事项
  • ChatGPT中国电话不能注册
  • 应收债款的融资属于
  • 固定资金是什么科目
  • 增值税发票开具规定
  • c语言常用函数用法
  • 百旺税控盘汇总上传如何检查
  • sqlserver高版本数据库文件转低版本
  • 个人独资企业所得税申报流程
  • 中小型企业营业额多少
  • 个体户注销工商需要等公示时间结束吗?
  • 个人独资企业与有限公司的区别
  • 弥补亏损的会计科目有哪些
  • 商业会计和财务会计
  • 支付稿费需要发票吗
  • 企业微信收款如何交税
  • 上年的原材料发票可以算今年的成本吗
  • 一个营业执照可以开几个店铺
  • 凭证上的数字金额怎么填
  • sql删除查询结果
  • sqlserver优化的几种方法
  • 微软出win9了吗
  • 重装win7系统后鼠标键盘不能用
  • 如何使用node.js
  • perl 采集入库脚本分享
  • 分享一下什么
  • 编程用到的所有函数
  • shell脚本编程实例
  • vue中使用js
  • node.js java 性能
  • android intent作用
  • JavaScript中的this指向
  • node.js web开发
  • android assets
  • Android自定义控件
  • 公务员副处级工资待遇
  • 我国为什么不推行安乐死
  • 德国对外投资法律劣势有哪些方面
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设