文章目录

  • 一、前置知识
  • 二、效果展示、
  • 三、完整代码
  • 附、给立方体每个面渲染不同的纹理

一、前置知识

经过前面的学习,我们已经知道了立方体怎么创建了,接下来学习怎么给立方体贴图;


为了将纹理正确的映射到四边形上,您必须:

  • 将纹理的 右上角 映射到四边形的 右上角
  • 纹理的 左上角 映射到四边形的 左上角
  • 纹理的 右下角 映射到四边形的 右下角
  • 纹理的 左下角 映射到四边形的 左下角

如果映射错误的话,图像显示时可能上下 颠倒,侧向一边或者什么都不是


glTexCoord2f(x, y)

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

二、效果展示、



三、完整代码

#ifndef GL_TEST_H
#define GL_TEST_H#include <qgl.h>        //因为QGLWidget类被包含在qgl.h头文件中
#include <glut.h>       //使用glut库中的API
#include <QKeyEvent>
#include <QTimer>//继承QGLWidget得到OPenGL窗口部件类
class GL_Test : public QGLWidget
{public:GL_Test(QWidget* parent = 0, bool fs = false);~GL_Test();protected:/*************************************************************************************************QGLWidget 类已经内置了对 OpenGL 的处理,就是通过对 initializeGL()、 paintGL()和 resizeGL()这个三个函数实现*************************************************************************************************/void initializeGL() override;           //用来初始化OPenGL窗口,可以在里面设定一些有关选项void paintGL() override;                //用来绘制OPenGL的窗口,只要有更新发生,这个函数就会被调用void resizeGL(int w, int h) override;   //用来处理窗口大小变换这一事件,resizeGL()在处理完后会自动刷新屏幕void keyPressEvent(QKeyEvent* e) override;  //Qt键盘事件处理函数void loadGLTextures();  //载入指定的图片并生成相应的纹理protected:bool fullscreen;    //用来保存窗口是否处于全屏状态的变量GLfloat xRot, yRot, zRot;   //用来处理立方体的旋转GLuint texture[1];  //用来存储纹理(长度为1的数组)
};#endif // GL_TEST_H
#include "gl_test.h"GL_Test::GL_Test(QWidget* parent, bool fs): QGLWidget(parent)
{fullscreen = fs;xRot = 0.0;yRot = 0.0;zRot = 0.0;setGeometry(500,500,640,480);               //设置窗口大小、位置setWindowTitle("The first OpenGL Window");  //设置窗口标题if(fullscreen) {showFullScreen();}QTimer* timer = new QTimer(this);connect(timer,&QTimer::timeout,[=]{updateGL();});timer->start(50);
}GL_Test::~GL_Test()
{}void GL_Test::initializeGL()
{loadGLTextures();   //载入纹理glEnable(GL_TEXTURE_2D);    //启用纹理glShadeModel(GL_SMOOTH);    //启用smooth shading(阴影平滑)glClearColor(0.0, 0.0, 0.0, 0.5);   //清除屏幕时所用的颜色,rgba【0.0(最黑)~1.0(最亮)】glClearDepth(1.0);  //设置深度缓存glEnable(GL_DEPTH_TEST);    //启动深度测试glDepthFunc(GL_LEQUAL); //所作深度测试的类型glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  //真正精细的透视修正,告诉OPenGL我们希望进行最好的透视修正,这会十分轻微的影响性能,但使得透视图看起来好一点
}void GL_Test::paintGL()
{glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除屏幕和深度缓存//-----------------------------------------glLoadIdentity();   //重置当前的模型观察矩阵glTranslatef(0.0, 0.0, -5.0);glRotatef(xRot, 1.0, 0.0, 0.0); //绕X轴旋转xRot度glRotatef(yRot, 0.0, 1.0, 0.0); //绕X轴旋转yRot度glRotatef(zRot, 0.0, 0.0, 1.0); //绕X轴旋转zRot度//选择我们使用的纹理glBindTexture(GL_TEXTURE_2D, texture[0]);//如果您在您的场景中使用多个纹理,您应该使用来 glBindTexture(GL_TEXTURE_2D, texture[所使用纹理对应的数字]) 选择要绑定的纹理;//当您想改变纹理时,应该绑定新的纹理。并且您不能在glBegin()和glEnd()之间绑定纹理,必须在glBegin()之前或glEnd()之后绑定;//绘制正方形开始glBegin(GL_QUADS);//前面glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 );glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 1.0, 1.0 );//后面glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0, -1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0, 1.0, -1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 1.0, -1.0 );glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, -1.0, -1.0 );//顶面glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 1.0, -1.0 );glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, 1.0, 1.0 );glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 1.0, 1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, -1.0 );//底面glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0, -1.0, -1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, -1.0, -1.0 );glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 );glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 );//右面glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, -1.0, -1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, -1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 );glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 );//左面glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, -1.0, -1.0 );glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0, 1.0, 1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 1.0, -1.0 );glEnd();//绘制正方形结束//-----------------------------------------xRot += 2;yRot += 3;zRot += 4;
}void GL_Test::resizeGL(int w, int h)
{if(h == 0) {    //防止h为0h = 1;}glViewport(0, 0, (GLint)w, (GLint)h);   //重置当前的视口(Viewport)glMatrixMode(GL_PROJECTION);    //选择投影矩阵glLoadIdentity();   //重置投影矩阵gluPerspective( 45.0, (GLfloat)w/(GLfloat)h, 0.1, 100.0 );  //建立透视投影矩阵glMatrixMode(GL_MODELVIEW); //选择模型观察矩阵glLoadIdentity();   //重置模型观察矩阵
}void GL_Test::keyPressEvent(QKeyEvent* e)
{switch (e->key()) {case Qt::Key_Q: {fullscreen = !fullscreen;if(fullscreen) {showFullScreen();}else {showNormal();setGeometry(500,500,640,480);}updateGL();break;}//case Qt::Key_Qcase Qt::Key_Escape: {close();}//Qt::Key_Escape}//switch (e->key())
}void GL_Test::loadGLTextures()
{QImage tex,buf;if(!buf.load(":/Images/1591561503-gB5rD.jpg")) {    //用QImage类载入纹理图片QImage dummy(128,128,QImage::Format_RGB32); //如果载入不成功,生成一个128*128的32位色的绿色图片dummy.fill(Qt::green);buf = dummy;}tex = QGLWidget::convertToGLFormat(buf);    //QGLWidget的静态函数,专门用来转换图片glGenTextures(1,&texture[0]);   //创建一个纹理glBindTexture(GL_TEXTURE_2D,texture[0]);    //使用来自位图数据生成的典型纹理/*告诉OPenGL将纹理名字texture[0]绑定到纹理目标上;2D纹理只有高度(在Y轴上)和宽度(在X轴上)*///真正的创建纹理//GL_TEXTURE_2D:告诉 OpenGL 此纹理是一个 2D 纹理;//数字0:代表图像的详细程度;//数字3:是数据的成分数;//tex.width():是纹理的宽度//tex.height():是纹理的高度;//GL_RGBA:告诉 OpenGL 图像数据由红、绿、蓝三色数据以及 alpha 通道数据组成;//GL_UNSIGNED_BYTE:意味着组成图像的数据是无符号字节类型的;//tex.bits():告诉 OpenGL 纹理数据的来源;glTexImage2D(GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());//告诉 OpenGL 在显示图像时,当它比放大得原始的纹理大(GL_TEXTURE_MAG_FILTER)或缩小得比原始得纹理小(GL_TEXTURE_MIN_FILTER)时,//OpenGL 采用的滤波方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//我们都采用 GL_LINEAR,这使得纹理从很远处到离屏幕很近时都平滑显示;//使用 GL_LINEAR 需要 CPU 和显卡做更多的运算,如果您的机器很慢,您也许应该采用 GL_NEAREST;//过滤的纹理在放大的时候,看起来斑驳的很,您也可以结合这两种滤波方式: 在近处时使用 GL_LINEAR,远处时 GL_NEAREST;
}

附、给立方体每个面渲染不同的纹理

1、创建多个纹理

void GL_Test::loadGLTextures()
{QStringList Images;Images << ":/Images/1591561503-gB5rD.jpg";Images << ":/Images/AI.png";Images << ":/Images/wallhaven-283q5m.png";Images << ":/Images/wallhaven-q2oxx7.png";Images << ":/Images/wallhaven-y85ojk.png";Images << ":/Images/wallhaven-z8pm7y.png";for(int i=0; i<6; ++i) {QImage tex,buf;if(!buf.load(Images.at(i))) {    //用QImage类载入纹理图片QImage dummy(128,128,QImage::Format_RGB32); //如果载入不成功,生成一个128*128的32位色的绿色图片dummy.fill(Qt::green);buf = dummy;}tex = QGLWidget::convertToGLFormat(buf);    //QGLWidget的静态函数,专门用来转换图片glGenTextures(1,&texture[i]);   //创建1个纹理,存储在texture[i]中//---------------------------------------------------------------------------------------glBindTexture(GL_TEXTURE_2D,texture[i]);    //使用来自位图数据生成的典型纹理/*告诉OPenGL将纹理名字texture[0]绑定到纹理目标上;2D纹理只有高度(在Y轴上)和宽度(在X轴上)*///真正的创建纹理//GL_TEXTURE_2D:告诉 OpenGL 此纹理是一个 2D 纹理;//数字0:代表图像的详细程度;//数字3:是数据的成分数;//tex.width():是纹理的宽度//tex.height():是纹理的高度;//GL_RGBA:告诉 OpenGL 图像数据由红、绿、蓝三色数据以及 alpha 通道数据组成;//GL_UNSIGNED_BYTE:意味着组成图像的数据是无符号字节类型的;//tex.bits():告诉 OpenGL 纹理数据的来源;glTexImage2D(GL_TEXTURE_2D,0,3,tex.width(),tex.height(),0, GL_RGBA,GL_UNSIGNED_BYTE,tex.bits());//告诉 OpenGL 在显示图像时,当它比放大得原始的纹理大(GL_TEXTURE_MAG_FILTER)或缩小得比原始得纹理小(GL_TEXTURE_MIN_FILTER)时,//OpenGL 采用的滤波方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//我们都采用 GL_LINEAR,这使得纹理从很远处到离屏幕很近时都平滑显示;//使 用 GL_LINEAR 需要 CPU 和显卡做更多的运算,如果您的机器很慢,您也许应该采用 GL_NEAREST;//过滤的纹理在放大的时候,看起来斑驳的很,您也可以结合这两种滤波方式: 在近处时使用 GL_LINEAR,远处时 GL_NEAREST;}
}

2、不同面使用不同纹理

void GL_Test::paintGL()
{glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除屏幕和深度缓存glLoadIdentity();   //重置当前的模型观察矩阵glTranslatef(0.0, 0.0, zoom);glRotatef(xRot, 1.0, 0.0, 0.0); //绕X轴旋转xRot度glRotatef(yRot, 0.0, 1.0, 0.0); //绕X轴旋转yRot度//    //选择我们使用的纹理
//    glBindTexture(GL_TEXTURE_2D, texture[filter]);
//    //如果您在您的场景中使用多个纹理,您应该使用来 glBindTexture(GL_TEXTURE_2D, texture[所使用纹理对应的数字]) 选择要绑定的纹理;
//    //当您想改变纹理时,应该绑定新的纹理。并且您不能在glBegin()和glEnd()之间绑定纹理,必须在glBegin()之前或glEnd()之后绑定;//-----------------------------------------glBindTexture(GL_TEXTURE_2D, texture[0]);//绘制正方形开始glBegin(GL_QUADS);//前面glNormal3f(0.0, 0.0, 1.0);  //x、y、z,垂直于面的法线向量glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 );glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 1.0, 1.0 );glEnd();//绘制正方形结束//-----------------------------------------//-----------------------------------------glBindTexture(GL_TEXTURE_2D, texture[1]);//绘制正方形开始glBegin(GL_QUADS);//后面glNormal3f(0.0, 0.0, -1.0); //x、y、z,垂直于面的法线向量glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0, -1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0, 1.0, -1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 1.0, -1.0 );glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, -1.0, -1.0 );glEnd();//绘制正方形结束//-----------------------------------------//-----------------------------------------glBindTexture(GL_TEXTURE_2D, texture[2]);//绘制正方形开始glBegin(GL_QUADS);//顶面glNormal3f(0.0, 1.0, 0.0);  //x、y、z,垂直于面的法线向量glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 1.0, -1.0 );glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, 1.0, 1.0 );glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 1.0, 1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, -1.0 );glEnd();//绘制正方形结束//-----------------------------------------//-----------------------------------------glBindTexture(GL_TEXTURE_2D, texture[3]);//绘制正方形开始glBegin(GL_QUADS);//底面glNormal3f(0.0, -1.0, 0.0); //x、y、z,垂直于面的法线向量glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0, -1.0, -1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, -1.0, -1.0 );glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 );glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 );glEnd();//绘制正方形结束//-----------------------------------------//-----------------------------------------glBindTexture(GL_TEXTURE_2D, texture[4]);//绘制正方形开始glBegin(GL_QUADS);//右面glNormal3f(1.0, 0.0, 0.0);  //x、y、z,垂直于面的法线向量glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, -1.0, -1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, -1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 );glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 );glEnd();//绘制正方形结束//-----------------------------------------//-----------------------------------------glBindTexture(GL_TEXTURE_2D, texture[5]);//绘制正方形开始glBegin(GL_QUADS);//左面glNormal3f(-1.0, 0.0, 0.0);glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, -1.0, -1.0 );glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0, 1.0, 1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 1.0, -1.0 );glEnd();//绘制正方形结束//-----------------------------------------xRot += xSpeed;yRot += ySpeed;
}

OPenGL笔记--给立方体贴图(纹理)相关推荐

  1. OpenGL 核心技术之立方体贴图

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D ...

  2. 【OpenGL ES】立方体贴图(6张图)

    1 前言 本文通过一个立方体贴图的例子,讲解三维纹理贴图的应用,案例中使用 6 张不同的图片给立方体贴图,图片如下: 本文涉及到的知识点主要包含:三维绘图.MVP 矩阵变换.纹理贴图,读者如果对 Op ...

  3. OpenGL进阶之立方体贴图

    参考: https://learnopenglcn.github.io/04%20Advanced%20OpenGL/06%20Cubemaps/ 立方体贴图就是一个包含了6个2D纹理的纹理,每个2D ...

  4. OpenGL Cube Map立方体贴图的实例

    OpenGL Shadow Mapping阴影贴图 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include "vermilion.h" ...

  5. 使用OpenGL 立方体贴图

    openGL系列文章目录 文章目录 openGL系列文章目录 前言 一.OpenGL 立方体贴图 二.使用步骤 1.代码 2.着色器程序 运行结果 注意 源码下载 参考 前言 对于室外3D 场景,通常 ...

  6. LearnOpenGL 高级OpenGL—立方体贴图

    文章目录 写在前面 立方体贴图 创建立方体贴图 天空盒 加载天空盒 显示天空盒 优化 环境映射 反射 折射 动态环境贴图 总结 写在前面 原文链接.原文应该是github上的一个项目,本文主要用来记录 ...

  7. LearnOpenGL学习笔记——立方体贴图

    立方体贴图 在本节中,我们将讨论的是将多个纹理组合起来映射到一张纹理上的一种纹理类型:立方体贴图(Cube Map).简单来说,立方体贴图就是一个包含了6个2D纹理的纹理,每个2D纹理都组成了立方体的 ...

  8. LearnOpenGL->立方体贴图

    立方体贴图 立方体贴图 在本节中,我们将讨论的是将多个纹理组合起来映射到一张纹理上的一种纹理类型:立方体贴图(Cube Map). 简单来说,立方体贴图就是一个包含了6个2D纹理的纹理,每个2D纹理都 ...

  9. 第三十七章 立方体贴图总结

    立方体贴图:将多个纹理组合起来映射到一张纹理上的一种纹理类型. 一个立方体贴图时包含了6个2D纹理的纹理,每个2D纹理都组成了立方体的一个面,相当于是一个有纹理的立方体. 创建立方体贴图: 首先需要生 ...

最新文章

  1. 010 并发的三个特性
  2. canvas之webgl的浏览器开启方式
  3. JVM-02内存区域与内存溢出异常(中)【hotspot虚拟机对象】
  4. java的接口理解_原来Java的接口可以这样理解
  5. UNITY编辑器模式下static变量的坑
  6. OpenGL Gamma Correction伽马校正的实例
  7. XJOJ - 选信封(离散化+增广路)
  8. mysql操作数据库
  9. Java面试日常总结大杂烩
  10. CentOS 安装中文语言包 教程
  11. TCP传输的三次握手四次挥手策略
  12. 《A Sub-Pixel Edge Detector: an Implementation of the Canny/Devernay Algorithm》
  13. 成功编译无错MAC OpenJDK8:Terminating app due to uncaught exception ‘NSInternalInconsistencyException‘
  14. 安卓模拟器按键_51模拟器app下载|51模拟器 3.2.1.2 最新版
  15. Matlab实现无标度网络生成及其分析
  16. 免安装版MySQL的配置——详细教程
  17. UCHome二次开发 模板基础语法
  18. CUDA开源 轻松跑AMD GPU/Intel x86 CPU
  19. 数据过多 如何实现页面滚动
  20. 我的awk常用命令备忘 xargs备忘

热门文章

  1. 高仿支付宝增加减少item功能和动画效果
  2. Python GUI编程(Tk)--聊天窗口--键盘值查询
  3. 银行卡开户银行、名称缩写等信息查询
  4. 2023软考 中级软件设计师备考
  5. 修改apache上传文件大小限制
  6. 计算机一级RGB怎么弄,用时半个月,我终于也有了属于自己的RGB电脑平台
  7. c语言多功能简易计算机,c语言编写“多功能计算器”的代码
  8. “IP+空格+域名”方式解决外国网站访问慢问题
  9. Java动态编译优化——URLClassLoader 内存泄漏问题解决
  10. ShellCode原理以及编写