一、了解纹理
1. 纹理是什么
说到纹理,大家可能不太理解。但我们可以吧纹理简单地理解成二维图片,并
且是可以贴在立体物体上的二维图片。比如一个立体正方形,周围就有 6 个面,可以贴 6 个纹理,也就是 6 个二维图像。这么一说,大家应该就对纹理有了一个通俗的理解。
但虽然理解了,这个工具又是为何而生?假如我们想在屏幕上画一个砖墙, 我们需要绘制成千上万个像素点,并且在色彩上模拟砖块的颜色。这个工作太过
于繁琐,那我们如果只需要画一个矩形,再将砖墙的图片贴上去,岂不是美滋滋。
于是,纹理就这样诞生了。
图 1.1 砖墙纹理
2. 纹理的映射方式
既然纹理是将图片贴上,那自然有不同的方式贴上,在 OPENGL 中就有多种函数输入让我们选择不同的贴图方式,我们可以横贴、竖贴、斜着贴,虽然说是贴,在程序中是使用类似矩阵的方式映射到对应的坐标系上。
图 1.2 纹理坐标
以左下为坐标原点,设定纹理在对应的位置贴图。
3. 纹理的环绕方式
首先我们明确一点,纹理的坐标默认是 0 ~ 1 之间,我们可以设定一张图映射到某个矩形上,但我们的纹理坐标选择 (0,0) 到 (2,2),那纹理将会在多出的部分使用环绕的方式,而环绕的方式将由我们自己决定。 默认情况下将会单纯的重复绘制纹理。
3.1 默认方案,重复绘制纹理
图 1.3 重复绘制纹理
3.2 镜像重复
图 1.4 镜像重复
3.3 边缘扩展
图 1.5 边缘扩展
将坐标限制在 0 ~ 1 之间,超出边缘部分将会重复图像边缘的像素,边缘进行扩展。
3.4 指定边界外颜色
图 1.6 指定边界外颜色
3.5 环绕方式概览
大概有这样四类纹理环绕映射方式,而纹理的环绕方式设置,由以下的 API 进行实现
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); //横坐标 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); //纵坐标 |
当你设定为 “边界外颜色指定的” 纹理环绕方式,你就还需要调用一下
以下API:
float borderColor[] = { 1.0f, 1.0f, 0.0f, 1.0f }; //指定成黄色 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
|
记得这是要设置环绕方式以后使用
二、纹理深入
1. 纹理过滤
纹理的范围为 0 ~ 1,说明跟分辨率无关,那也就是说纹理必定会需要放大或者缩小。而 OPENGL 提供了几种方式来进行放大缩小的插值或者删减像素。
这里介绍使用最普遍的两种:GL_NEAREST和GL_LINEAR。
1.1 GL_NEAREST
最近点过滤,指的是新插入的像素点离周围哪个像素点最近,就用哪个像素。
这是 OPENGL 默认的纹理过滤方式,速度最快,效果差。
1.2 GL_LINEAR
线性过滤,指的是根据周围的像素,进行线性插值运算以后,来生成新的像
素点。也就是根据周围的四个点来计算中间像素的值。
这是应用最广泛的一种方式,速度也较快,效果一般。
网上有相对的例子可以很好的展示这两个方法的区别:
图 2.1 最近点过滤和线性过滤的区别
最近点过滤我们可以明显的看到一颗一颗的聚集像素点,而线性过滤则显得平
滑许多,第二张图虽然显得模糊,但相对来说在小图变为大图,模糊是可以理
解的。
设置过滤方式的 API 如下:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); //缩小时的过滤方式 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //放大时的过滤方式 |
2. Mipmaps
Mipmaps 是一种渐进的纹理,但 OPENGL 是可以调整相对渲染物体的远近的,那当我们将镜头拉远时,难道还要使用高分辨率的图像吗?使用太多精细的图像将浪费大量的计算资源,而且没有意义。所以我们将使用 Mipmaps 来进行处理这种情况,将一张纹理图像分为一个系列,每一个图像是前一个图像的 1/4 ,直到最后一个像素为止。如下图:
图 2.2 Mipmaps
这里我们只需要调用一个函数即可使用 Mipmaps
glGenerateMipmaps |
而他是如何考虑将哪一个大小的图像放入呢?我们可以参考纹理过滤的办法,
最近点或者线性过滤。如果在两个大小的 Mipmaps 之间,就会将一或两幅图像进行线性过滤得到一个契合大小的图像来进行贴图。
2.1 最近点过滤
GL_NEAREST_MIPMAP_NEAREST:采用最近的 mipmap 图,在纹理采样的时候使用最近点过滤采样。
2.2 线性过滤
GL_LINEAR_MIPMAP_NEAREST:采用最近的 mipmap 图,纹理采样的时候使用线性过滤采样。
2.3 两张图像的最近点过滤
GL_NEAREST_MIPMAP_LINEAR:采用两张 mipmap 图的线性插值纹理图,纹理采样的时候采用最近点过滤采样。
2.4 两张图像的线性过滤
GL_LINEAR_MIPMAP_LINEAR:采用两张 mipmap 图的线性插值纹理图,纹理采样的时候采用线性过滤采样。
那这 4 种方法该如何使用呢?函数还是一样的函数,只需要修改关键词
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); //都是线性过滤 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
三、 参考文献
- 《 OPENGL ES 3.0 》
- 简书——《 OPENGL 入门 》
四、 预告
经过这篇博文,大家应该对 OPENGL 中最重要的纹理有所了解。
接下来的博文,将转为机器学习系列
敬请期待!
评论