图形学的数学基础(三十二):纹理应用(上)

722 阅读4分钟

本文已参与[新人创作礼]活动,一起开启掘金创作之路

转载请注明出处.

图形学的数学基础(三十二):纹理应用(上)

在计算机图形学中,纹理贴图是使用图像、函数或其他数据源来改变物体表面外观的技术。例如,可以将一幅砖墙的彩色图像应用到一个多边形上,而不用对砖墙的几何形状进行确表示。通过这种方式将图像和物体表面结合起来,可以在建模、存储空间和速度方面节省很多资源。当然纹理不仅仅用于改变物体表面漫反射颜色,纹理本质上是一个数据集,可以用来存储任何我们需要的顶点数据,因此在方方面面得到了广泛的应用.本文将介绍MaterialMap、AlphaMap、BumpMap、NormalMap、ReliefMap、DisplacementMap、ParallaxMap、TexturedLight、ShadowMap、EnvironmentMap。 我们将以上纹理贴图的应用划分为6个大类:

  • 控制着色信息
  • 控制片元透明度
  • 改变顶点法线
  • 改变表面结构
  • 阴影贴图
  • 环境贴图

控制着色信息

根据Blinnphong  ModelBlinn-phong\;Model可知,物体表面着色信息有以下因子来控制:

15.png

L=La+Ld+Ls=KaEa+KdEr2max(0,n^l^)+KsEr2max(0,n^h^)pL = L_a+L_d+L_s = K_aE_a + K_d\dfrac{E}{r^2}max(0, \hat{n}\cdot\hat{l}) + K_s\dfrac{E}{r^2}max(0, \hat{n}\cdot\hat{h})^p

符号解释
KaK_a物体表面环境光吸收率
EaE_a环境光强度
Er2\dfrac{E}{r^2}到达物体表面的光线
KdK_d漫反射系数
n^\hat{n}着色点法线
l^\hat{l}光线单位矢量
KsK_s高光系数
pp高光衰减因子

可以看到有许多可以调节的参数来控制着色点的着色表现。虽然可以赋予顶点更多的属性来改变这些参数,但是要做到亚三角形的细节,就需要使用各种纹理,对每个片元的着色参数进行调节,这些纹理映射方法统称为材质映射(Material  MapMaterial\;Map)。

最简单的就是漫反射映射,将纹理采样得到的值直接用于KdK_d项,很直观也很简单,这里不做过多赘述。

2.png

此外还可以改变镜面反射系数,如粗糙度(决定高光衰减)和高管反射系数。

1.jpg

控制片元透明度

纹理都是矩形的,但当我们要实现各种贴画(decaldecal)或者镂空(cutoutcutout)效果时,往往不想让纹理贴满整个表面,也就是说一些地方的透明度为0,这时候alphaMapalphaMap就登场了。

3.png

所以不需要把片元当作半透明进行混合,而是进行透明度测试 (Alpha Test),将透明度小于阈值的 texel 认为是完全透明,直接抛弃片元,否则为完全不透明,测试完成后,再用 z-buffer 算法进行对所有完全不透明片元进行混合。透明度测试的伪代码如下:

if(texture.a < alphaThreshold)  discard

但是透明度测试在使用mipmapmipmap时会存在问题:如下图,第0级纹理连续四个texel的透明度为 [0.0, 1.0, 1.0, 0.0],第1级纹理就为 [0.5, 0.5],假设我们设定alphaThreshold为0.75,可知第0级纹理有1.5/4通过测试,但是在第一级纹理中,所有的纹素的值都变成了0.5, 0.5 < 0.75所以,所有像素都被抛弃。

4.png

于是在不同的mipmapmipmap纹理等级中,经过透明度测试留下来的像素占比也不一样,因为高等级纹理是对低等级纹理的范围平均,因此随着levelD的增大,纹素值会趋于平均化,之前在阈值之上的值,被平均化以后很有可能到阈值线之下,因此被抛弃的像素就越来越多:

5.jpg

我们来看一个例子,如下图所示,当相机距离树较近时,看起来一切正常:

6.png

当相机拉远后,树叶消失了一部分(由于mimmap均值化后,导致被抛弃像素占比增加):

7.png

当相机拉远到相当一段距离后,发现树叶消失的更多:

8.png

一般解决办法有两个:

  1. 手动调节每级mipmap透明度,或者在shader中根据纹理等级d对透明度缩放
  2. 限制d的最大值

但这两种方法都只能是近似,不能很好解决问题,出现这个 问题的关键在于:不同 mipmapmipmap,用同样的透明度阈值会得到不同的 Coverage(代表测试留存的像素比例)

Castano提出了一种:保证coverage一致的情况下,自适应确定透明度阈值,并对原透明度缩放调整的方法。

9.png

经过这种特殊处理后,我们发现远处的树木表现恢复正常了。

10.png

11.png

另外在对RGBA值进行线性插值时,要注意把alpha分量预乘到RGB分量,再进行插值:

12.png

比较实际的情况是:希望插值的结果偏向于不透明那边颜色的色调,所以通常而言,预乘后插值会比较合理。

参考

图形学基础 - 纹理 - 纹理映射盘

Real-Time Rendering Fourth Edition

Computing Alpha Mipmaps