最爱午后红茶

Extensive Application

日期图标
2023-06-02

纹理映射并不局限于图案,实际上纹理在 GPU 里面就是一块内存,一块支持做点查询或者范围查询的内存。因此,内存里面的数据可以是任何你想要表示的东西。而除了直接表示成图案以外,常见的纹理映射技术还包括以下的应用:

环境贴图(Environment Map)

也有人把环境贴图称作环境光贴图,当纹理表示成环境贴图时,纹理里面包含了来自物体周围所有方向的反射和折射信息。当光线照射到物体表面时,可以根据环境贴图中的反射和折射信息来计算反射和折射的颜色值,从而得到更加真实的渲染效果。它可以跟 Blinn-Phong 反射模型结合使用,在使用 Blinn-Phong 反射模型进行渲染时,环境贴图可以作为一个参数输入到漫反射和镜面反射计算中,从而增加物体表面的细节和变化。特别是在缺少局部光源的情况下,环境贴图可以为物体提供一些额外的光照信息,使得渲染结果更加真实。(注意:部分结论来自 ChatGPT

环境贴图(Environment map)
图二十三:环境贴图

上图的茶壶叫犹他茶壶(Utah Teapot),它是一种经典的三维模型,在计算机图形学领域中经常被用作测试和教学的工具。最初是由计算机科学家 Martin Newell 于 1975 年创建的,它代表了计算机图形学发展的一个历史节点。如今,犹他茶壶已成为计算机图形学领域中的一种经典符号,代表着这个领域的基础知识和文化。

球面贴图(Spherical Map)

与环境贴图不同,Spherical Map 通常只适用于球形物体,并且使用一个二维球形投影将三维球体表面的纹理映射到二维平面上。在 Spherical Map 中,一个球形物体的表面被投影到一个平面上,形成一个球形贴图。这个球形贴图可以使用多种方式生成,例如通过摄像机拍摄球形物体周围的环境或者手动制作。在渲染时,球形贴图会应用到球形物体的表面上,从而实现真实的纹理效果。(注意:结论来自 ChatGPT

球面贴图(Spherical map)
图二十四:球面贴图

球面贴图是将一个平面图像贴在一个球体表面上,因此会产生失真现象。特别是在边缘或者顶点处,会出现拉伸、压缩等变形情况,导致渲染结果不够精确和真实。

球面贴图导致画面拉伸
图二十五:球面贴图导致画面拉伸

立方体贴图(Cube Map)

与球面贴图将一个平面图片映射到一个球形上不同,立方体贴图则是将六个平面图片映射到一个立方体上,并在渲染时根据物体表面的朝向来确定应该采用哪一个面的纹理信息。这些平面图片包括了从三个坐标轴的正反两个方向中截取的环境信息。由于立方体贴图包含多个面的信息,所以相比于球面贴图具有更高的精度和更小的失真。而且立方体贴图还具有计算速度快和易于实现等优点。(注意:结论来自 ChatGPT

立方体贴图
图二十六:立方体贴图
立方体贴图展开
图二十七:立方体贴图展开

凹凸贴图(Bump Mapping)

纹理还可以定义一个点的相对高度是多少。我们知道一个常规的球可以用许多个三角形构成,而如果我们需要让一个球的表面表现出凹凸不平的效果,其中一个办法是增加更多的三角形去表现球表面的凸起和凹陷。如下图:

表面凹凸的球
图二十八:表面凹凸的球

但是通过增加三角形去表现这种效果的话,会增加不少额外的开销,有没有办法在不改变球原来的几何结构的前提下渲染出这种效果呢?我们可以通过把纹理任意点的属性定义成该点的相对高度来实现凹凸效果。而这种纹理就叫做凹凸贴图

球的部分截面
图二十九:球的部分截面

我们先从简单的一维分析。球的正视图是一个圆,上图直线 LL 可以理解为圆上的一小段(实际上它应该是曲线,为了便于分析画成直线,或者说在足够短的距离它就是直线),LL 上每个点(可认为是 Shading point)对应的纹理属性是该点的高度信息。我们知道要对每个点进行着色需要知道它的法线,如果没有给 LL 上这些点定义高度属性,那么它们的法线都垂直于 LL。我们想要改变 Shading point 的着色效果,就需要改变它的法线。

LL 上所有点的纹理的高度的终点可以近似连成一条曲线,要求解曲线的切线需要先求出曲线上某一点的导数,然后将其作为该点切线的斜率,代入点斜式公式即可求解切线方程。以点 PP 举例(不展开具体切线求解步骤),我们求解出点 OO 的切线 OMOM 后,将其逆时针旋转 90° 即可得到新的法线 n\overrightarrow{n},最后将其归一化成单位向量后用作点 PP 新的法线。将每个点都进行这样的处理,整体上就能让球面体现出凹凸效果。

跟凹凸贴图类似的是法线贴图Normal Mapping),法线贴图是一种基于颜色信息的纹理映射技术,它通过改变物体表面法线向量的方向来模拟物体表面的凹凸效果,从而增强物体表面的细节。法线贴图实际上是一张 RGB 颜色贴图,其中每个像素的颜色值代表着物体表面该点的法线向量在三维坐标系中的方向。渲染时,法线贴图中的法线向量被用于计算光照效果,从而模拟物体表面的凹凸和明暗变化,使得渲染结果更加真实和细致。因此,凹凸贴图和法线贴图之间的区别主要在于模拟物体表面凹凸效果的方式不同。凹凸贴图基于灰度图像的高度信息来模拟凹凸效果,而法线贴图则是通过 RGB 颜色信息来指定表面法线向量的朝向,以达到模拟凹凸效果的目的。(注意:结论来自 ChatGPT

位移贴图(Displacement Mapping)

跟凹凸贴图一样,位移贴图的纹理存储的也是高度信息。但跟凹凸贴图不同的是,位移贴图会真正改变模型的几何结构,因此,相比于凹凸贴图,位移贴图更加真实和精确,并且可以产生出更多的立体感和质感。

凹凸贴图和位移贴图(Displacement mapping)
图三十:凹凸贴图和位移贴图

由于凹凸贴图不真正改变模型的几何结构,因此有些地方很容易看出其缺陷,比如边缘没有表现出凹凸性,以及内部的阴影也没有处理好。而位移贴图会根据纹理高度等信息对三角形的顶点进行移动以使渲染结果更具立体感和质感,它的代价就是增加了计算的复杂度和存储量,因为模型要完整地反应纹理定义的高度变化,三角形顶点的间隔就要跟上纹理的频率,也就是三角形得足够细才行。

当我们原本的三角形不够细致的时候,我们可以通过一种叫动态曲面细分Dynamic Tessellation)的技术去根据实际需要和纹理高度计算出来的结果把原来的三角形拆分成更多的小三角形,进而得到不错的效果。

Windows 的 DirectX 提供了支持 Dynamic Tessellation 的 API。具体来说,DirectX 11 引入了 Hull ShaderDomain Shader 这两个新的着色器阶段,用于实现动态曲面细分技术。Hull Shader(外部着色器)主要用于控制物体表面网格的分布和细节层次,包括如何将一个原始网格划分成多个细分片段以及如何计算新的顶点坐标。而 Domain Shader(域着色器)则用于对每一个细分片段进行计算,例如为每个片段赋予相应的纹理坐标或者法线向量等信息。

纹理的更多应用

前面说了纹理只是一块内存,它不仅可以表示成二维的,还可以表示成三维的。比如说纹理可以定义三维空间中任意一点的值,这样的话,不仅模型表面有贴图信息,模型的内部也会有纹理的细节,而不至于把模型切开看到什么也没有。

纹理还可以定义成可以完成一系列计算的噪声函数,典型的有柏林噪声Perlin Noise),它是一种用于生成模拟自然纹理和随机图案的算法。它是由 Ken Perlin 在 1983 年发明的,被广泛应用于计算机图形学、动画、游戏等领域。Perlin Noise 算法可以生成出类似自然界中的随机图案,例如云彩、雾气、火焰、岩石等。其核心思想是通过插值来将随机噪声进行平滑化,从而生成出具有连续性且自然的纹理。

纹理定义成噪声(Perlin noise)
图三十一:纹理定义成噪声

我们知道如何给模型着色,但是还没有讲到阴影。我们可以通过环境光遮蔽Ambient Occlusion,简称 AO)技术把模型的阴影计算出来存储在纹理里面,然后把纹理贴在模型表面,就相当于给模型添加了阴影。

纹理与环境光遮蔽(Ambient occlusion)
图三十二:纹理与环境光遮蔽

另外,三维的纹理还可以用作体积渲染。比如现在医学上的磁共振或 CT 成像设备在扫描人体组织时,可以生成一些关于人体的三维空间的信息,我们可以把这些信息做成三维的纹理去做渲染。

纹理与体积渲染(Volume rendering)
图三十三:纹理与体积渲染
* 未经同意不得转载。