纹理映射基础知识

  什么叫纹理映射,一开始我也不明白,感觉这个词好专业(毕竟没有学过图形学),后面经过网上查找资料和这次实验稍微理解了点。纹理映射简单的讲,就是把一个纹理(其实说白了,纹理可以理解为一幅图像)映射到空间物体的表面上,因此纹理映射也叫贴图,这个表明不一定是矩形,比如说我可以是球面,或者是任意曲面。在上一篇文章OpenGL_Qt学习笔记之_04(3D图形的绘制和旋转)中,我们绘制的空间体的表面都是一些光滑的颜色,如果要在其表面采用那种方法绘制图像的话,则必须利用微分的思想,一个一个的绘制小图像,然后拼接起来,可想而知,这个过程是多么的复杂,opengl的纹理映射就可以很好的解决这一问题。

下面来看看纹理映射的一个示意图片(百度百科上的):

  

  这个示意图说明,将中间的纹理(即图片)映射到左边的茶壶曲面上,就形成了右边的图了。在右边的图中,可以看到茶壶的表面上布满了图片,这就像中国古代的陶器绘图一样。

  纹理映射另外一个好处是能够保证在变换多边形时,多边形上的纹理也会随之变化。

  纹理映射相关函数

  要进行纹理映射,得先了解下opengl中有关纹理映射的一些相关函数。

  void glGenTextures(GLsizei n, GLuint *textures);

  该函数的作用是开辟存储纹理的内存空间,其中参数n为开辟纹理内存的个数,texture为存储纹理的地址索引。

  void glBindTexture(GLenum target,   GLuint texture);

  该函数的作用是把存储纹理的对象texture绑定到纹理目标target上,在opengl中纹理目标分为GL_TEXTURE_1D和GL_TEXTURE_2D。该句代码运行完后,对target的操作也对应于对texture指向的内容的操作。

  void glTexImage2D(GLenum target,GLint level,GLint components,GLsizei width, glsizei height,GLint border,GLenum format,GLenum type, const GLvoid *pixels);

  参数1为纹理目标;参数2为目标的层次,即目标的详细程度,一般情况采用0即可;参数3表示的是数据成分的个数,如果数据由RGB构成,则将该参数设置为3;参数4和5分别为创建纹理数据的长和宽;参数6为边框的值,一般也设为0;参数8为数据的通道格式;参数9为纹理的数据元素类型;参数10为纹理的数据内容。

  这个函数的功能是创建一个纹理,并为该纹理分配了数据。

  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);

  该函数表示的是当所显示的纹理比加载进来的纹理小时,采用GL_LINEAR的方法来处理。

  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

  和上面的函数类似,注意该函数的参数2为GL_TEXTURE_MAG_FILTER,不要误认为是GL_TEXTURE_MAG_FILTER。

  glTexCoord2f(x, y);

  第一个参数是X坐标。 0.0f 是纹理的左侧。 0.5f 是纹理的中点, 1.0f 是纹理的右侧。第二个参数是Y坐标。0.0f 是纹理的底部。0.5f 是纹理的中点,1.0f 是纹理的顶部。

  给定一张纹理图,它的坐标示意图如下:

  

  其中纹理的中心点坐标为(0.5, 0.5).

  实验说明:

  这个实验室在上一篇博文OpenGL_Qt学习笔记之_04(3D图形的绘制和旋转) 绘制的立方体上贴每个面上贴上一张纹理(即图片)。

  我们需要在GLWidget这个类中添加一个函数来加载纹理数据,该函数为loadTextures().

  另外,在QGLWidget这个类中,initializeGL(), paintGL(), resizeGL()这3个函数的执行顺序是该类启动时就执行initializeGL(),主要用于初始化opengl,通常用来设置一些前期的背景色,光照参数等等。paintGL()用于渲染整个场景;resizeGL()用于在widget大小变化的时候产生合理view。

  注意,本实验给的图片长和宽必须是2的n次方,最大不要超过256,最小也不要小于64。我这里采用的是256*256像素的图片。

  实验结果:

  加载纹理的图像为:

  

 

  纹理映射后的效果如下:

   

 

  实验主要部分代码及注释(附录有工程code下载地址):

#include "glwidget.h"
#include "ui_glwidget.h"#include <QtGui>
#include <QtCore>
#include <QtOpenGL>GLWidget::GLWidget(QGLWidget *parent) :QGLWidget(parent),ui(new Ui::GLWidget)
{//  setCaption("The Opengl for Qt Framework");ui->setupUi(this);fullscreen = false;rotate_angle = 0.0;
}//这是对虚函数,这里是重写该函数
void GLWidget::initializeGL()
{setGeometry(300, 150, 500, 500);//设置窗口初始位置和大小
    loadTextures();glEnable(GL_TEXTURE_2D);//允许采用2D纹理技术glShadeModel(GL_SMOOTH);//设置阴影平滑模式glClearColor(0.0, 0.0, 0.0, 0);//改变窗口的背景颜色,不过我这里貌似设置后并没有什么效果glClearDepth(1.0);//设置深度缓存glEnable(GL_DEPTH_TEST);//允许深度测试glDepthFunc(GL_LEQUAL);//设置深度测试类型glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);//进行透视校正
}void GLWidget::paintGL()
{//glClear()函数在这里就是对initializeGL()函数中设置的颜色和缓存深度等起作用glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);/*下面开始画立方体,并对其进行纹理映射*/glLoadIdentity();glRotatef(rotate_angle, -0.2f, 0.2f, -0.3f);glBegin(GL_QUADS);//上顶面glTexCoord2f(0.0, 1.0);//将2D的纹理坐标映射到3D的空间物体表面上glVertex3f(-0.3f, 0.3f, -0.3f);glTexCoord2f(0.0, 0.0);glVertex3f(-0.3f, 0.3f, 0.3f);glTexCoord2f(1.0, 0.0);glVertex3f(0.3f, 0.3f, 0.3f);glTexCoord2f(1.0, 1.0);glVertex3f(0.3f, 0.3f, -0.3f);//下顶面glTexCoord2f(0.0, 1.0);glVertex3f(-0.3f, -0.3f, -0.3f);glTexCoord2f(0.0, 0.0);glVertex3f(-0.3f, -0.3f, 0.3f);glTexCoord2f(1.0, 0.0);glVertex3f(0.3f, -0.3f, 0.3f);glTexCoord2f(1.0, 1.0);glVertex3f(0.3f, -0.3f, -0.3f);//正前面glTexCoord2f(0.0, 1.0);glVertex3f(-0.3f, 0.3f, 0.3f);glTexCoord2f(0.0, 0.0);glVertex3f(-0.3f, -0.3f, 0.3f);glTexCoord2f(1.0, 0.0);glVertex3f(0.3f, -0.3f, 0.3f);glTexCoord2f(1.0, 1.0);glVertex3f(0.3f, 0.3f, 0.3f);//右侧面glTexCoord2f(0.0, 1.0);glVertex3f(0.3f, 0.3f, 0.3f);glTexCoord2f(0.0, 0.0);glVertex3f(0.3f, -0.3f, 0.3f);glTexCoord2f(1.0, 0.0);glVertex3f(0.3f, -0.3f, -0.3f);glTexCoord2f(1.0, 1.0);glVertex3f(0.3f, 0.3f, -0.3f);//背后面glTexCoord2f(0.0, 1.0);glVertex3f(-0.3f, 0.3f, -0.3f);glTexCoord2f(0.0, 0.0);glVertex3f(0.3f, 0.3f, -0.3f);glTexCoord2f(1.0, 0.0);glVertex3f(0.3f, -0.3f, -0.3f);glTexCoord2f(1.0, 1.0);glVertex3f(-0.3f, -0.3f, -0.3f);//左侧面glTexCoord2f(0.0, 1.0);glVertex3f(-0.3f, 0.3f, -0.3f);glTexCoord2f(0.0, 0.0);glVertex3f(-0.3f, -0.3f, -0.3f);glTexCoord2f(1.0, 0.0);glVertex3f(-0.3f, -0.3f, 0.3f);glTexCoord2f(1.0, 1.0);glVertex3f(-0.3f, 0.3f, 0.3f);rotate_angle -= 3;glEnd();
}//该程序是设置opengl场景透视图,程序中至少被执行一次(程序启动时).
void GLWidget::resizeGL(int width, int height)
{if(0 == height)height = 1;//防止一条边为0glViewport(0, 0, (GLint)width, (GLint)height);//重置当前视口,本身不是重置窗口的,只不过是这里被Qt给封装好了glMatrixMode(GL_PROJECTION);//选择投影矩阵glLoadIdentity();//重置选择好的投影矩阵// gluPerspective(45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0);//建立透视投影矩阵glMatrixMode(GL_MODELVIEW);//以下2句和上面出现的解释一样
    glLoadIdentity();}
void GLWidget::keyPressEvent(QKeyEvent *e)
{switch(e->key()){//F1键为全屏和普通屏显示切换键case Qt::Key_F1:fullscreen = !fullscreen;if(fullscreen)showFullScreen();else{setGeometry(300, 150, 500, 500);showNormal();}updateGL();break;//Ese为退出程序键case Qt::Key_Escape:close();}
}/*装载纹理*/
void GLWidget::loadTextures()
{QImage tex, buf;if(!buf.load("../opengl_nehe_05/cherry.jpg")){qWarning("Cannot open the image...");QImage dummy(128, 128, QImage::Format_RGB32);//当没找到所需打开的图片时,创建一副128*128大小,深度为32位的位图
        dummy.fill(Qt::green);buf = dummy;}tex = convertToGLFormat(buf);//将Qt图片的格式buf转换成opengl的图片格式texglGenTextures(1, &texture[0]);//开辟一个纹理内存,内存指向texture[0]glBindTexture(GL_TEXTURE_2D, texture[0]);//将创建的纹理内存指向的内容绑定到纹理对象GL_TEXTURE_2D上,经过这句代码后,以后对//GL_TEXTURE_2D的操作的任何操作都同时对应与它所绑定的纹理对象glTexImage2D(GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());//开始真正创建纹理数据glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//当所显示的纹理比加载进来的纹理小时,采用GL_LINEAR的方法来处理glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//当所显示的纹理比加载进来的纹理大时,采用GL_LINEAR的方法来处理
}GLWidget::~GLWidget()
{delete ui;
}

  总结:

  了解了opengl中的纹理映射机制后,对空间体的表面进行贴图还是比较方便的。

  参考资料:

   http://nehe.gamedev.net/

   http://www.owlei.com/DancingWind/

   http://blog.csdn.net/qp120291570/article/details/7853513

http://www.qiliang.net/old/nehe_qt/

  附录:

  实验工程code下载。

转载于:https://www.cnblogs.com/tornadomeet/archive/2012/08/24/2654719.html

OpenGL_Qt学习笔记之_05(纹理映射)相关推荐

  1. OpenGL_Qt学习笔记之_05(纹理映射)(转)

    转自:http://www.cnblogs.com/tornadomeet/archive/2012/08/24/2654719.html 纹理映射基础知识 什么叫纹理映射,一开始我也不明白,感觉这个 ...

  2. OpenGL_Qt学习笔记之_07(闪烁的星星)

    OpenGL_Qt学习笔记之_07(闪烁的星星) 这一小节我们要完成的任务是:将一张背景是黑色,中间是白亮色的星星图片和五颜六色的颜色进行色彩融合,变成一颗彩色的星星.并且让这些星星自转和公转,可以控 ...

  3. WebGL three.js学习笔记 6种类型的纹理介绍及应用

    WebGL three.js学习笔记 6种类型的纹理介绍及应用 本文所使用到的demo演示: 高光贴图Demo演示 反光效果Demo演示(因为是加载的模型,所以速度会慢) (一)普通纹理 计算机图形学 ...

  4. DirectX9 ShadowMap例子学习笔记

    本文版权归博客园  mavaL所有,如有转载请按如下方式详细标明原创作者及出处,以示尊重!! 原创作者:mavaL 原文链接:DirectX9 ShadowMap例子学习笔记 学习SDK例子真是快速加 ...

  5. 3D目标检测学习笔记

    博主初学3D目标检测,此前没有相关学习背景,小白一枚-现阶段的学习重点是点云相关的3D检测. 本文是阅读文章:3D Object Detection for Autonomous Driving: A ...

  6. LearnOpenGL学习笔记—PBR:IBL

    LearnOpenGL学习笔记-PBR:IBL 0 引入 1 渲染方程的求解 2 hdr文件转成cubemap 3 预计算漫反射积分 4 预计算镜面反射积分 4.1 预滤波HDR环境贴图 4.1.1 ...

  7. 个人学习笔记——庄懂的技术美术入门课(美术向)01

    个人学习笔记--庄懂的技术美术入门课(美术向)01 0 前言 1 工程搭建示范 2 理论 2.1 结构(struct) 2.2 渲染管线 3 操作 3.1-2 向量/标量/点积等若干线代基础 3.3 ...

  8. 图形学基础 | 计算机图形学MOOC学习笔记

    计算机图形学 学习笔记 视频链接 http://www.icourse163.org/learn/CAU-45006?tid=1001746004#/learn/announce 补充一下一些图形学基 ...

  9. 《Joint 3D Face Reconstruction and Dense Alignment with Position Map Regression Network》论文学习笔记

    <Joint 3D Face Reconstruction and Dense Alignment with Position Map Regression Network>–<基于 ...

最新文章

  1. 【好文共分享】关于ora-04065和ora-04068的原理解释
  2. fastdfs删除过期文件_Spring Boot 系列:使用 Spring Boot 集成 FastDFS
  3. mysql数据库中命令行下常用命令的操作(增、删、改、查)和数据类型
  4. Debian完全卸载清理MySQL服务器
  5. java swing 复选JCheckBox组件美化
  6. python语法学习第十天--类与对象相关的BIF、魔法方法
  7. TextBox内容垂直居中
  8. 虚拟光驱xp版32位_操作系统不仅有XP、win7和win10,这些更好用的系统你都用过吗...
  9. arccatalog点要素显示不完_2020年仅剩100天,你的年假休完了吗?关于年假你不知道的7点!...
  10. “蔚来杯“2022牛客暑期多校训练营1 J Serval and Essay(图的启发式合并)
  11. ubuntu 配置登录失败次数限制
  12. QT编写的嵌入式工业控制系统
  13. 计算机应用程序无响应,Win7系统运行Word文档提示“应用程序没有响应”怎么办...
  14. 外星飞船CSS3动画代码
  15. ChatGPT能接入微信了
  16. multisim安装后无法连接数据库_计算机重装系统时遭遇错误意外重启后无法安装,这是什么原因?...
  17. html5图片与文字垂直对齐
  18. House of Force
  19. 尚硅谷MySQL笔记
  20. Windows XP Embedded (XPE)开发工具、升级包、中文包等微软官方下载地址

热门文章

  1. CXF2.7.3 与spring 3集成 .
  2. 使用JDOM解析XML
  3. python必学的模块_Python常用的模块
  4. Windows核心编程 第六章 线程基础知识 (下)
  5. 【Groovy】编译时元编程 ( 方法拦截时用到的 AST 语法树节点 MethodNode 节点 | MethodNode 节点分析 | MethodNode 节点中的BlockStatement)
  6. 【错误记录】发布 Flutter 插件包报错 ( ‘gmail.com‘ has insufficient permissions to upload new versions of package)
  7. 【Android 应用开发】Activity 状态保存 OnSaveInstanceState参数解析
  8. 破解win2003“终端服务器授权”激活许可证!
  9. Dart 调用C语言混合编程
  10. Antd组件中单选框、复选框自定义样式的优雅实现