QT之OpenGL 2D纹理使用

1. 基础概念

纹理通常用来给物体添加细节,它可以是2D图片(甚至也有1D和3D的纹理)。

1.1 纹理坐标

纹理坐标是用来表述纹理位置的坐标,它的范围是(0,0)(1,1)。示例如下:

float texCoords[] = {
    0.0f, 0.0f, // 左下角
    1.0f, 0.0f, // 右下角
    0.5f, 1.0f // 上中
};

这个纹理坐标是对应的原始纹理为:
在这里插入图片描述
根据纹理坐标采样后的输出如下:
在这里插入图片描述
:

  1. 在实际过程中,纹理坐标的设置范围可以超过(0,0)(1,1),而超过的部分则会使用到纹理环绕方式处理稍后说明

1.2 纹理像素

纹理像素屏幕物理像素并不是一一对应的关系,如下所示:
在这里插入图片描述
将其放大如下:
在这里插入图片描述
当一个纹理产生后,其纹理像素就固定了,上面的图片其纹理像素是342*78

1.3 纹理单元

纹理单元是用来给shader中设置多个纹理使用的。在shader中用uniform来声明一个sampler2D类型变量,这就表示在shader中给纹理采样器(sampler2D)分配了一个位置,这个位置就是纹理单元

OpenGL至少保证有16个纹理单元供你使用,也就是说你可以激活从GL_TEXTURE0GL_TEXTRUE15。它们都是按顺序定义的,所以我们也可以通过GL_TEXTURE0 + 8的方式获得GL_TEXTURE8,这在当我们需要循环一些纹理单元的时候会很有用。

2. 纹理加载

QT中对OpenGL的纹理有一个QOpenGLTexture类。可以使用QOpenGLTexture对纹理进行加载,其使用步骤如下:

  1. 加载纹理单元
  2. 设置shader中采样器的纹理单元
  3. 绑定纹理单元
  4. 解绑纹理单元

代码示例如下:

// 设置纹理,并将y轴进行镜像
m_texture = std::make_unique<QOpenGLTexture>(QImage(":/images/images/small.png").mirrored());

// 设置纹理单元
m_shaderProgram.bind();
m_shaderProgram.setUniformValue("texture", 0);
m_shaderProgram.release();

// 绑定纹理单元
m_texture->bind();

// 解绑纹理单元
m_texture->release();

3. 纹理环绕方式

纹理环绕方式的产生是在纹理坐标超过(0,0)(1,1)时,对超出范围的处理方式,主要由以下四种方式:

  1. GL_REPEAT 对纹理的默认行为。重复纹理图像。
  2. GL_MIRRORED_REPEATGL_REPEAT一样,但每次重复图片是镜像放置的。
  3. GL_CLAMP_TO_EDGE 纹理坐标会被约束在0到1之间,超出的部分会重复纹理坐标的边缘,产生一种边缘被拉伸的效果。
  4. GL_CLAMP_TO_BORDER 超出的坐标为用户指定的边缘颜色。

4. 纹理过滤

从拉伸或者压缩的纹理图片中采样出来像素颜色的过程叫做纹理过滤
纹理过滤是用来处理放大或缩小时,不同纹理像素之间最终显示的一种方式。
最长常见的是GL_NEAREST(也叫邻近过滤,Nearest Neighbor Filtering)
GL_LINEAR(也叫线性过滤,(Bi)linear Filtering),两者的区别如下

GL_NEAREST是其就近的值作为最终的显示值。
在这里插入图片描述
GL_LINEAR是对采样点附近的值进行混合处理,最终输出一个混合后的值,使得颜色过渡更柔和
在这里插入图片描述
两者产生的效果如下:
在这里插入图片描述

4.1 多级渐远过滤

多级渐远纹理(Mipmap),它简单来说就是一系列的纹理图像,后一个纹理图像是前一个的二分之一。多级渐远纹理背后的理念很简单:距观察者的距离超过一定的阈值,OpenGL会使用不同的多级渐远纹理,即最适合物体的距离的那个。由于距离远,解析度不高也不会被用户注意到。同时,多级渐远纹理另一加分之处是它的性能非常好。

示例图:
在这里插入图片描述
多级渐远过滤的方式:

  1. GL_NEAREST_MIPMAP_NEAREST 使用最邻近的多级渐远纹理来匹配像素大小,并使用邻近插值进行纹理采样
  2. GL_LINEAR_MIPMAP_NEAREST 使用最邻近的多级渐远纹理级别,并使用线性插值进行采样
  3. GL_NEAREST_MIPMAP_LINEAR 在两个最匹配像素大小的多级渐远纹理之间进行线性插值,使用邻近插值进行采样
  4. GL_LINEAR_MIPMAP_LINEAR 在两个邻近的多级渐远纹理之间使用线性插值,并使用线性插值进行采样

多级渐远过滤是用在缩小的过程中的!!!

最终的demo中并没有演示出这一效果!!!

5. demo效果演示

  1. 纹理加载demo
    在这里插入图片描述

  2. 环绕方式及纹理过滤demo
    在这里插入图片描述

6. 源码

  1. 纹理加载demo
  2. 环绕方式及纹理过滤demo

参考:

  1. OpenGL 纹理
NEHE的OPENGL教程 第42课 多视窗口… NEHE的OPENGL教程 第42课 多视窗口… NeHe的OPENGL中文教程:第41课 体… NeHe的OPENGL中文教程:第40课 绳… NeHe的OPENGL中文教程:第39课 物… NeHe的OPENGL中文教程:第39课 物… NeHe的OPENGL中文教程:第38课 从… NeHe的OPENGL中文教程:第37课 卡… 愚人节十大IT假新闻:Opera浏览器… NeHe的OPENGL中文教程:第36课 放… NeHe的OPENGL中文教程:第35课 AVI… NeHe的OPENGL中文教程:第35课 AVI… NeHe的OPENGL中文教程:第34课 从… NeHe的OPENGL中文教程:第33课 加… NeHe的OPENGL中文教程:第32课 Alp… NeHe的OPENGL中文教程:第32课 Alp… NeHe的OPENGL中文教程:第32课 Alp… NeHe的OPENGL中文教程:第31课 模… NEHE的OPENGL中文教程:第30课 碰… NEHE的OPENGL中文教程:第30课 碰… NeHe的OPENGL中文教程:第29课 Bli… NeHe的OPENGL中文教程:第28课 贝… NeHe的OPENGL中文教程:第27课 影… NeHe的OPENGL中文教程:第26课剪裁… NeHe的OPENGL中文教程:第25课 变… NeHe的OPENGL中文教程:第24课 TAG… NeHe的OPENGL中文教程:第23课 球… NeHe的OPENGL中文教程:第22课 凸… NeHe的OPENGL中文教程:第22课 凸… NeHe的OPENGL中文教程:第21课 反… NeHe的OPENGL中文教程:第21课 反… NeHe的OPENGL中文教程:第20课 蒙… NeHe的OPENGL中文教程:第19课 粒… NeHe的OPENGL中文教程:第18课 二… NeHe的OPENGL中文教程:第17课 2D… NeHe的OPENGL中文教程:第16课 雾 NeHe的OPENGL中文教程:第15课 图… NeHe的OPENGL中文教程:第14课 图… NeHe的OPENGL中文教程:第13课 位… NeHe的OPENGL中文教程:第12课 显… NeHe的OPENGL中文教程:第11课 飘… NeHe的OPENGL中文教程:第十课 漫… NeHe的OPENGL中文教程:第九课 漂… NeHe的OPENGL中文教程:第八课 Alp… NeHe的OPENGL中文教程:第七课 纹… NeHe的OPENGL中文教程:第七课 纹… NeHe的OPENGL中文教程:第六课 纹… NeHe的OPENGL中文教程:第五课 向3… NeHe的OPENGL中文教程:第四课 旋… NeHe的OPENGL中文教程:第三课 着… NeHe的OPENGL中文教程:第二课 多… NeHe的OPENGL中文教程:第一课 新… NeHe的OPENGL中文教程:第一课 新… DirectX与OpenGL方面的经典电子书… VC++ 6.0下OpengGL配置以及glut配… 怎样开始学习OpenGL
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值