
什么是纹理
宏观的角度上来说就是一张2D图片,一个像素上有 RGB 值
为什么要出现纹理
Ⅰ.降低建模工作量 = 牺牲几何细节
Ⅱ.降低存储空间
Ⅲ.提高读取速度
如果一个模型我们要把所有的细节都表现出来,那无疑是一个巨大工作量,对于简单的模型还好说,但是当我们把工作转换到人体模型上面,人体结构的复杂,外加服装可能各式各样,花式不同,这无疑增大了建模师的工作量。
但是我们如果将一个纹理贴到这些模型上,能保证模拟物体表面的技术没有太大变化,在省略了很多细节之后,也能大致还原原来的表现形式
纹理管线

模型空间位置 → 投影函数 → 纹理映射 → 纹理坐标 → 通讯函数 → 新纹理坐标 → 纹理采样 [避免依赖纹理读取] → 纹理值
※ 投影函数这里与摄像机投影不同,这里是指展UV的技术
假设 我们将模型空间的一个点投影到 UV 坐标,获得一个 UV 坐标值,假设这个纹理的大小是256 * 256,那么这个纹理就会跟这个点投影的 UV 坐标进行相乘,得到纹理的坐标,后续这个位置的颜色需要看你的纹理采样的设置进行设置

纹理采样设置之 Wrap Mode
决定 UV 值在[0,1]以外的表现
OpenGL — “包装模式”(Wrapping Model)
DirectX — “纹理寻址模式”(Texture Addressing Mode)

- Repeat —— 重复
- Mirror —— 镜像
- Clamp —— 这个图形的边界
- Border —— 当超过这个范围的其他位置的颜色需要设置
纹理采样设置之 Filter Model
过滤设置,当纹理通过变化产生拉伸的时候,要使用哪种滤波来进行纹理的表现

用来描述不同大小,缩放比,角度,形状该应用那种滤波形式进行纹理采样比较合理
**最近邻 **—— 向最近的像素进行纹理取样表现,这个形式带来的问题就是,因为是从邻近像素采集的信息,所以很容易出现块状像素,也就让纹理变得像素化,处理效果最差,但是因为是从邻近纹理取样的,所以所涉及的计算要少很多,在性能上表现不错
**双线性插值 **—— 对于每一个像素点都寻找邻近的四个像素点,在二维空间进行的线性插值得到的最终混合值

相比较最近邻所涉及的采样点变多,画面表现上比最近邻好一些,最起码不会出现块状像素的情况,但是提升的效果也是有限的,因为只是取得了最邻近的四个像素点
立方卷积插值 —— 相比较双线性插值,在这个计算方法中不仅采取周围一圈的像素点,还考虑到了它们变化率的影响,画面表现效果比前两种都要好,也正是牺牲了性能提高了表现效果

Quilez 的光滑曲线插值 —— 在立方卷积插值与双线性插值的一个折中效果,画面表现效果要比双线性插值好,比立方卷积插值差

在纹理坐标带入到双线性插值过程之前再额外进行了一步处理

效果对比

纹理缩小的情况
纹理缩小的情况下,最近邻与双线性插值的问题:颜色丢失与闪烁

对于一般纹理来说,每个像素最多应该有一个纹理坐标来避免闪烁和丢失,所以要么就提高像素的采样频率,要么就降低纹理的频率,降低纹理频率最典型的方法就是 MipMap
MipMap
它是通过预处理纹理,创建数据结构,来有助于在实时计算中快速计算一组纹理对一个像素效果的近似值,将 2x2 的4个相邻的纹理值作为下一级的新的纹理值,所以新一级的纹理是上一级的\frac{1}{4}大。直到 1x1 ,所以在存储空间上多了\frac{1}{3}大

如何选择正确的 level
使用像素单元格所形成的一个四边形的最长边来近似这个像素覆盖的范围,在 GPU 中并不是一个像素一个像素的去渲染执行,而是分成 2x2 一组并行进行处理,这样做的原因是用来计算 ddx ddy,以及用来计算法线


缺陷:过度模糊
因为我们一直假设这个 Texture 在投射屏幕上是各向同性的,如果一个像素单元格在 U 上覆盖了大量的纹理,但是在 V 上覆盖了少量的纹理,在 MipMap 处理中缩小使用的是上一张纹理相邻四个纹理的平均值,也就是说在 MipMap 情况下,那些被平均过的纹理就会被限制到这些正方形中,于是就产生了各向异性过滤处理部分问题