Qt中的OpenGL (4)[纹理]
文章说明
本文是学习OpenGL的笔记,主要参考大神JoeyDeVries
的LearnOpenGL第六课《纹理》,并将教程中的代码基于Qt进行实现。
学习目标
- 掌握纹理基本知识
- 掌握纹理贴图
目录结构
|-
|-- HelloTextures|--- hello_textures.cpp|--- hello_textures.h|--- main.cpp|--- CMakeLists.txt
|-- CMakeLists.txt
整个项目的全部CMakeLists.txt文件与上一篇 Qt中的OpenGL (3)[着色器] 中的内容基本一致,只需要将全部HelloShader替换成HelloTextures就可以了。
在前边的教程中绘制三角形的时候用到顶点的位置和颜色两个属性,三个顶点属性数据可以完成一个纯色(三点颜色一致)或者彩色(三点颜色不一致)的三角形,但下面这种颜色的三角形应该就不会只有三个顶点属性这么简单了。
要绘制上面这个三角形就需要用到大量的顶点属性,并且每个顶点属性都需要带有颜色属性,并且颜色属性的设置要细致到每个像素,这种做法会增加额外的开销。这个时候就需要用到纹理了,简单来说纹理就是将图片按照规则贴到物体模型上。
纹理坐标
在现实生活中如果需要给一个物体贴上图片正常情况下是要先测量物体大小然后准备一个合适的贴纸,最后物体的边角对应贴纸的边角完全贴合,在开发过程中模型与纹理图片之间经常存在不匹配的情况,如下图所示:
上图中纹理图片的像素是200 * 200而三角形在屏幕上显示的像素是1000 * 1000这无论如何也无法一一对应了。此时,就需要使用纹理坐标(UV),一般使用U和V表示纹理坐标,其中U表示横坐标百分比而V表示纵坐标百分比,使用百分比的方式代替实际数值的对应方式,纹理坐标起始于左下角(0, 0),终止于右上角(1, 1)。
类似于上面纹理图映射到图形的场景,纹理设置如下:
- 三角形左下角对应纹理图左下角因此纹理坐标就是(0.0, 0.0),对应的像素值就是w=0, h=0
- 三角形右下角对应纹理图右下角因此纹理坐标就是(1.0, 0.0),对应的像素值就是w=200, h=0
- 三角形顶角对应纹理图的上中点因此纹理坐标就是(0.5, 1.0),对应的像素值就是w=100, h=200
注意:除了设置的纹理坐标外,其他纹理坐标都是根据已设置的纹理坐标经过插值计算而来的。
纹理过滤
单独使用纹理坐标也不能解决需要绘制的像素和实际纹理图片像素不匹配问题,解决绘制像素与纹理像素不匹配问题有两种方式,分别是Nearest Neighbor Filtering和Linear Filtering。
邻近过滤(Nearest Neighbor Filtering)
这是一种默认的过滤方式,根据UV坐标计算出来的小数坐标,取最近的整数坐标像素,这种取值方式可能回去到会多次相同的像素色块,导致颗粒感比较强是一种像素风格。
线性插值过滤(Linear Filtering)
另外一种是根据UV计算出来的小数坐标,综合周边像素得到新的像素。这种方式根据周围像素产生新的像素色块,相当于对原始纹理图片进行扩充。
这两种过滤方式在解决像素不匹配问题上并没有绝对的使用规则。一般情况使用情况如下:
- 需要绘制像素超过图片纹理像素,使用线性过滤。
- 需要绘制像素少于图片纹理像素,使用邻近过滤。
设置过滤方式的函数如下,这个函数包含了纹理的过滤方式设置和纹理的环绕方式,这里先说过滤方式相关参数
void glTexParameteri(GLenum target, GLenum pname, GLint param);
-
设置纹理过滤方式
- target: 指定纹理目标类型,它表示要设置参数的纹理类型。
- pname: 指定要设置的纹理参数名称。
- param: 指定过滤方式。
-
target可设置参数,不区分过滤设置和环绕设置
-
GL_TEXTURE_1D
:一维纹理,常用于模拟渐变效果,如颜色渐变条。 -
GL_TEXTURE_2D
:二维纹理,最常用的纹理类型,用于给物体表面贴图,像给立方体的每个面贴上不同的图片。 -
GL_TEXTURE_3D
:三维纹理,包含深度信息,可用于表示体积数据,例如医学上的 CT 扫描数据。 -
GL_TEXTURE_CUBE_MAP
:立方体贴图,由 6 个二维纹理组成,用于模拟环境反射,比如天空盒效果。 -
GL_TEXTURE_1D_ARRAY
:一维纹理数组,由多个一维纹理组成,可用于存储多个相关的一维纹理数据。 -
GL_TEXTURE_2D_
-