前言
上节讲述了双线性插值算法,虽然也有提到主要应用的点就是纹理采样,但是对于这一块有些小小白可能还不了解,所以这一节补充一下纹理采样的内容!
请叫我贴心航火火!梦想为小白而生!
正文
1、为什么需要纹理采样?
想象一个场景: 如果有这么一个需求,需要在屏幕的一块400x400目标区域显示一张图片,正好这张图片的尺寸也是400x400像素,怎么做?
答: 啥都不需要做,是的,根本不需要做什么处理,直接一一对应像素显示即可!
但是,实际情况中,往往几乎不可能这么巧合的一一对应,要么纹理图片过大,要么纹理图片过小,没法一一对应,怎么办呢?
答: 通过引入一种机制,进行等比例对应,这就是uv坐标的由来,它本质上就表示百分比,一般地,uv坐标的标准取值范围是:0.0 - 1.0。
举个纹理图片过小的例子,如下图: 当我们需要绘制 400x400 窗口区域,图片纹理大小是 200x200,如果要在窗口 (20, 20) 位置绘制,那么我们就相当于取纹理图片的 (20/400,20/400)=(0.05,0.05) 比例位置的像素数据,也就是 (0.05∗200,0.05∗200)=(10,10) 位置的数据!这里的 (0.05,0.05) 其实就是uv坐标!

这里引申一下,由于上述举的例子是绘制区域大,纹理图片小。所以自然而然会存在多个绘制区域对应一个纹理像素位置的情况。这时候就应用到上节的内容。是直接采用最邻近的采样方式,还是双线性插值的方式,来缓解像素化的情况,取决于自身的需求!
2、什么是纹理采样?
在屏幕上某一像素绘制时,根据像素所在位置,去图片上寻找对应像素值的过程,这个过程就是纹理采样!如下图所示:

3、如何进行纹理采样?
其实需要采样的情形无非就是两种情况,上面也说了!纹理太大或太大。这里咱们只说纹理太小的情况,需要用到上一节的双线性插值的知识。
纹理太大的时,解决的思路无非就是让纹理变小,变到一个最适合绘制窗口的大小。如果想要适应各种绘制窗口大小,就需要利用MipMap的知识,后面章节有空的话,会把这部分给补上哦,童鞋们!
(1)假设绘制区域为矩形
需要在一个分辨率为 screen_width X screen_height 的矩形窗口区域绘制一张图片,这张图片分辨率为picture_width X picture_height,假设绘制区域左下角的uv坐标为 (ux0,uy0),右上角的uv坐标为 (ux1,uy1) ,且满足 0=<ux0、ux1、uy0、uy1<=1.0 ,则对于任何绘制区域坐标为 (x,y) 的uv坐标为
ux=screen_widthx∗ux1+(1−screen_widthx)∗ux0uy=screen_heighty∗uy1+(1−screen_heighty)∗uy1
既然已经有了绘制区域每一个位置的uv坐标,咱么只需要根据uv坐标,去纹理图片进行采样像素值即可,至于采取何种采样方法,可以参考上一片文章,既可以采用最邻近取整的方式,也可以采取双线性插值的方式!这里根据用户需求,自行决定,不多赘述!
(2)假设绘制区域为三角形
给定三个顶点 p1=(x1,y1)、p2=(x2,y2)、p3=(x3,y3) 并且给定三个顶点的uv坐标分别为 u1=(ux1,uy1),u2=(ux2,uy2),u3=(ux3,uy3),如何得知三角形内每一个顶点 p(x,y) 的uv坐标呢?
这时候重心坐标插值公式,又派上用上了,之前的章节已经介绍过,就不过多阐释了!
这时候 每一个三角形内的顶点 p(x,y) 的uv坐标up=αu1+βu2+γu3 ,三个系数根据重心坐标公式即可算得!这时候同样,根据uv坐标去纹理图片进行采样像素值即可!
简单给个参考图:

4、什么是纹理的Wrap方式?
虽然标准规定的uv坐标范围为:(0.0,1.0) ,但是如果越界了,对应的uv坐标的采样值如何取呢?这个问题的答案就是纹理的Wrap属性!
5、有哪些纹理的Wrap方式?
常见的Wrap方式有四种:
- Repeat
- Mirror_Repeat
- Clamp_To_Edge
- Clamp_To_Border
这里分别简单介绍并给出示例图:
(1)Repeat
超出部分,不断循环重复

(2)Mirror_Repeat
超出部分,不断循环镜像重复

(3)Clamp_To_Edge
纹理坐标会被约束在0到1之间,超出的部分会重复纹理坐标的边缘,产生一种边缘被拉伸的效果

(4)Clamp_To_Border
超出的坐标为用户指定的边缘颜色

6、如何实现纹理的Wrap方式?
上述的第(3)和第(4)很好理解,咱们就讨论下第(1)种和第(2)种的计算方式吧!
(1)Repeat
计算公式:
记f(x)函数表示取浮点数x的小数部分,则坐标(ux,uy)的最终坐标为ux=f( f(ux)+1 )uy=f( f(uy)+1 )
举例佐证:
-
(1.2,2.2)=>( f(0.2+1),f(0.2+1) )=>(0.2,0.2) ok
-
(0.3,0.8)=>( f(0.3+1),f(0.8+1) )=>(0.3,0.8) ok
-
(−0.5,−2.2)=>( f(−0.5+1),f(−0.2+1) )=>(0.5,0.8) ok
(2)Mirror_Repeat
计算公式:
记f(x)函数表示取浮点数x的小数部分,则坐标(ux,uy)的最终坐标为ux=1−f( f(ux)+1 )uy=1−f( f(uy)+1 )
举例佐证:
- (1.2,2.2)=>( 1−f(0.2+1),1−f(0.2+1) )=>(1−0.2,1−0.2)=>(0.8,0.8) ok
- (0.3,0.8)=>( 1−f(0.3+1),1−f(0.8+1) )=>(1−0.3,1−0.8)=>(0.7,0.2) ok
- (−0.5,−2.2)=>( 1−f(−0.5+1),1−f(−0.2+1) )=>(1−0.5,1−0.8)=>(0.5,0.2) ok
结尾:喜欢的小伙伴可以点点关注+赞哦
希望对各位小伙伴能够有所帮助哦,永远在学习的道路上伴你而行, 我是航火火,火一般的男人!