纹理 (Texturing)

"所需要做的就是使渲染出来的图像看起来正确。" — Jim Blinn

这句话点明了纹理技术的精髓:它是一种用图像或函数来欺骗眼睛、高效增加视觉细节的手段。我们不是去模拟砖墙的每一个几何凹凸,而是通过贴图(颜色、粗糙度、法线等)来让一个简单的平面“看起来”像一堵复杂的墙。


6.1 纹理管线 (The Texturing Pipeline)

纹理化的本质是修改着色方程中的参数。这些参数(如表面颜色、粗糙度、法线方向)不再是整个物体统一的,而是根据物体表面的具体位置而变化。这个从“表面位置”到“修改参数”的过程,就是纹理管线。

  1. 起始点: 物体表面的一个三维位置 (x, y, z)
  2. 投影函数 (Projector Function): 将三维位置 (x, y, z) 映射到一组纹理坐标 (Texture Coordinates),通常是二维的 (u, v)。这一步决定了纹理如何“贴”到模型上。
  3. 转换函数 (Corresponder Function):(u, v) 坐标进行变换(如平移、旋转、缩放)或解释(如重复、镜像),得到最终用于采样纹理的坐标。
  4. 纹理采样/计算: 使用最终的坐标从纹理资源中获取一个纹理值 (Texture Value)。这个资源可以是一张图片,也可以是一个程序化函数。
  5. 值转换与应用: (可选)对获取到的纹理值进行处理(如色彩空间转换、数值范围重映射),然后用它来修改着色计算中的某个参数。

6.1.1 投影函数 (Projector Function)

核心观点: 投影函数的任务是为模型的每个顶点生成一套纹理坐标 (UVs),这个过程俗称“分UV”。它定义了二维纹理图像与三维模型表面之间的映射关系。

  • 常见投影方式:
    • 平面投影 (Planar Projection): 像幻灯片一样,从一个方向将纹理投射到物体上。适用于相对平坦的表面,如地面、墙壁、贴花(Decal)。
    • 柱面投影 (Cylindrical Projection): 将纹理包裹在一个虚拟的圆柱上。适用于类似圆柱或旋转体的物体,如瓶子、树干。
    • 球面投影 (Spherical Projection): 将纹理包裹在一个虚拟的球体上。适用于球形物体。
  • 网格展开 (Mesh Unwrapping):
    • 对于复杂模型,单一投影方式无法满足需求,会导致严重的拉伸和扭曲。
    • 因此,艺术家会使用DCC工具(如Blender, Maya)手动或半自动地将模型“剪开”并“摊平”到一张二维平面上,这个过程就是网格展开
    • 关键目标: 最小化纹理拉伸,并隐藏UV接缝 (UV seams)。

6.1.2 转换函数 (Corresponder Function)

核心观点: 转换函数增加了纹理应用的灵活性,它决定了当UV坐标超出 [0, 1] 范围时如何表现,以及如何对纹理进行动态变换。

  • 纹理寻址模式 (Texture Addressing Mode):

    • Wrap / Repeat (重复): 最常用的模式。纹理像瓷砖一样在表面上无限重复平铺。当UV坐标的整数部分被舍弃时,效果自然达成。
    • Mirror (镜像): 纹理重复平铺,但每隔一个单位就进行一次镜像翻转。有助于在边界处创建无缝过渡。
    • Clamp / Clamp to Edge (钳制): 将超出 [0, 1] 范围的坐标强制拉回 [0, 1] 区间。效果是纹理边缘的颜色被无限延伸。
    • Border / Clamp to Border (边框色): 超出范围的坐标会采样一个预设的边框颜色
  • 纹理变换 (Texture Transformation):

    • 可以在着色器中通过矩阵运算对UV坐标进行平移、旋转、缩放,从而实现纹理在物体表面的动态效果(如流动的岩浆、滚动的履带)。
    • 专家提示: 对纹理坐标的变换效果与对物体本身的变换是相反的。例如,放大UV坐标会导致纹理在表面上看起来被缩小(因为它重复得更多了)。

6.1.3 纹理值 (Texture Value)

核心观点: 纹理不仅可以存储颜色(纹素,Texel),还可以存储任何用于着色计算的数据。

  • 常见数据类型:
    • RGB(A): 颜色和透明度。
    • 灰度值: 用于控制粗糙度 (Roughness)、金属度 (Metallic) 或其他单通道属性。
    • 法线向量 (Normal Vector): 用于凹凸贴图,后面会详述。
    • 高度/位移值: 用于视差或位移贴图。
  • 值转换:
    • 从纹理中取出的值经常需要转换。一个典型的例子是将存储在 [0, 1] 范围内的法线分量,重映射到 [-1, 1] 范围,以便进行光照计算。

6.2 图像纹理 (Image Textures)

这是实时渲染中最常见的纹理形式。核心问题在于:屏幕上的一个像素 (Pixel) 在采样时,可能对应纹理上的区域远大于一个纹素 (Texel)(缩小),或远小于一个纹素(放大)。如何处理这两种情况,直接决定了渲染质量。

6.2.1 放大 (Magnification)

当镜头靠近物体表面时,一个纹素会被拉伸到覆盖多个屏幕像素。

  • 邻近过滤 (Nearest Neighbor):

    • 核心算法: 直接选择离采样点最近的那个纹素的颜色。
    • 效果: 速度最快,但会产生明显的像素化/马赛克效果。
    • 适用场景: 像素艺术风格游戏,或者对性能要求极高的场合。
  • 双线性插值 (Bilinear Interpolation):

    • 核心算法: 找到离采样点最近的4个纹素,根据采样点与这4个纹素中心的距离进行加权平均。
    • 效果: 画面平滑,消除了马赛克,但可能会显得模糊
    • 实现: 其中 (u', v') 是采样点在4个纹素中心构成的局部坐标系中的位置。
  • 双三次插值 (Bicubic Interpolation):

    • 核心算法: 使用更大的采样核心(例如4x4或5x5的纹素)进行更复杂的加权平均。
    • 效果: 质量更高,图像更清晰锐利,但计算成本也更高。通常不由硬件直接支持,需在Shader中实现。

6.2.2 缩小 (Minification)

当物体远离摄像机时,一个屏幕像素可能需要代表纹理上一大片区域的颜色。如果处理不当,会产生严重的走样 (Aliasing),表现为闪烁、摩尔纹等现象。

  • 核心问题: 采样频率远低于纹理频率,违反了奈奎斯特定理。我们需要对纹理进行低通滤波。

  • Mipmap:

    • 核心思想: 预先生成一系列低分辨率的、经过滤波的纹理版本,形成一个“图像金字塔”。这个集合称为 Mipmap 链
    • 生成过程: 原始纹理为第0级 (Level 0)。第 i+1 级的每个纹素是第 i 级对应的 2x2 区域纹素的平均值。
    • 专家提示: 为了获得高质量的Mipmap,应在线性空间中进行滤波,并使用高质量的滤波器(如Gaussian),否则会导致远处物体变暗、细节丢失。
    • 三线性插值 (Trilinear Interpolation):
      1. 根据像素在屏幕上的覆盖范围,计算出一个浮点数 d,表示需要在哪一级Mipmap之间采样。
      2. floor(d)ceil(d) 这两级Mipmap上,分别进行双线性插值,得到两个颜色值。
      3. 最后,根据 d 的小数部分,对这两个颜色值再进行一次线性插值
    • 缺点: 过度模糊 (Over-blurring)。当以一个掠射角度(grazing angle)观察表面时,像素在纹理空间中的投影是一个细长的矩形,但Mipmap只能采样一个正方形区域,为了避免走样,它会按矩形的长边来选择Mipmap层级,导致不必要的模糊。
  • Summed-Area 表 (SAT):

    • 核心思想: 创建一个与原纹理等大的表,每个单元 (x, y) 存储从原点 (0, 0)(x, y) 构成的矩形区域内所有纹素值的总和
    • 优点: 仅需4次查询,就能快速计算出任意矩形区域的平均值,能很好地处理各向异性情况(细长矩形),解决了Mipmap的过度模糊问题。
    • 缺点: 内存开销大(需要更高精度存储),且对于斜向的细长矩形区域,其轴对齐包围盒会包含大量无关纹素,导致新的模糊问题。
  • 无约束的各向异性过滤 (Anisotropic Filtering):

    • 核心思想: 目前最先进且广泛使用的技术。它不是采样一个正方形区域,而是沿着像素在纹理空间中投影的细长矩形的长轴方向进行多次采样
    • 工作方式:
      1. 选择一个合适的Mipmap层级(基于投影矩形的短边)。
      2. 确定矩形的长轴方向(各向异性线)。
      3. 沿着这条线进行多次(如2x, 4x, 8x, 16x)三线性插值采样,然后将结果平均。
    • 优点: 质量极高,能清晰地渲染以掠射角度观察的表面,同时有效抑制走样。
    • 缺点: 计算开销高于三线性插值,但现代GPU都有专门的硬件支持。

6.2.3 - 6.2.5 纹理表示与管理

为了提升性能,我们需要高效地管理和使用大量纹理,核心目标是减少渲染状态的切换

  • 体积纹理 (Volume Textures): 3D纹理,使用 (u, v, w) 坐标进行采样。适用于程序化材质(如木纹、大理石)或体积数据(如云、烟雾、医学扫描)。
  • 立方体贴图 (Cube Maps): 由6个正方形纹理面组成的立方体。使用一个3D方向向量进行采样,常用于环境映射(天空盒、反射)
  • 纹理图集 (Texture Atlas): 将多个小纹理打包到一张大纹理中。
    • 优点: 减少Draw Call,因为只需要绑定一次大纹理。
    • 缺点: Mipmap生成时子纹理间会“串色”;无法对子纹理单独使用 RepeatMirror 寻址模式。
  • 纹理数组 (Texture Array):
    • 更现代的解决方案。将多个尺寸、格式相同的纹理组织成一个数组。
    • 优点: 解决了纹理图集的所有缺点,可以独立为每个子纹理生成Mipmap和设置寻址模式。着色器通过一个索引来访问不同的纹理。
  • 无绑定纹理 (Bindless Textures):
    • 最先进的API特性。不再将纹理“绑定”到固定的纹理单元插槽,而是直接在着色器中通过一个64位的句柄(handle)或指针来访问GPU内存中的任何纹理。
    • 优点: 极大地降低了CPU开销,几乎消除了纹理切换的性能瓶颈,允许在一次Draw Call中使用海量纹理。

6.2.6 纹理压缩 (Texture Compression)

核心动机: 纹理是游戏中最耗费显存和内存带宽的资源之一。纹理压缩旨在大幅减少纹理数据量,同时保持可接受的视觉质量

  • 通用原理:

    • 有损压缩 (Lossy): 原始图像信息会部分丢失。
    • 块压缩 (Block Compression): 将纹理划分为固定的 4x4 纹素块,独立进行压缩。
    • 快速硬件解码: GPU硬件能够极速解压,对性能影响微乎其微。
    • 不对称性: 压缩过程(离线进行)可以很慢很复杂,以换取高质量;解压过程(实时进行)必须极快。
  • 主流压缩格式:

    • BC (Block Compression) / DXTC: PC和主机平台的标准。
      • BC1 (DXT1): 用于RGB或1-bit Alpha纹理。基本原理是为一个 4x4 块存储两个16位的端点颜色 (endpoint colors) 和一个 16x2-bit 的查找表,每个纹素通过2-bit索引在4个插值颜色中选择一个。压缩比为 6:1 (对于24位RGB)。
      • BC3 (DXT5): 用于RGBA纹理,颜色部分与BC1相同,Alpha通道独立压缩(存储两个端点alpha和 16x3-bit 索引)。
      • BC4/BC5: 分别用于单通道和双通道数据(如Roughness、法线贴图)。
      • BC6H/BC7: 更现代的格式,质量更高,分别用于HDR和LDR纹理。
    • ETC/EAC: 移动平台的标准 (OpenGL ES)。
    • ASTC: 新一代的、非常灵活的压缩格式,支持可变的块大小,允许开发者在压缩率和质量之间做精细的权衡。
  • 法线贴图压缩的特殊技巧:

    • 法线是单位向量 (nx, ny, nz),满足
    • 通常我们只存储 nxny 两个分量(例如使用 BC5 格式),然后在着色器中实时计算出 nz
    • 这样不仅节省了一个通道的存储,也完美适配了BC5这种为双通道数据设计的压缩格式。

6.3 程序化纹理 (Procedural Textures)

核心观点: 程序化纹理是通过函数计算而非图像查找来生成纹理值。随着GPU计算能力的增强和访存/带宽成为瓶颈,这项技术在实时渲染中正变得越来越重要。

  • 动机:

    • 节省内存: 对于体积纹理这类存储成本极高的资源,程序化生成是极具吸引力的替代方案。
    • 无限细节: 理论上可以无限放大而不会像素化。
    • 动态变化: 纹理可以响应游戏状态(如物理模拟)而变化,创造出传统贴图无法实现的动态效果。
  • 核心技术:噪声函数 (Noise Functions)

    • 噪声是程序化生成的基础,最著名的是 Perlin 噪声Simplex 噪声。它能产生一种可控的、自然的随机感。
    • Octaves (八度): 通过将不同频率和振幅的噪声函数叠加,可以创造出更复杂的图案。低频噪声决定大尺度特征,高频噪声添加细节。
    • 湍流 (Turbulence): 将多个八度的噪声加权求和,常用于模拟云、火焰、大理石等自然纹理。
  • 挑战与解决方案:

    • 性能开销: 实时计算噪声函数可能很昂贵。
      • 解决方案: 预计算一个小的3D噪声纹理(tileable),然后在着色器中通过采样和插值来获取噪声值,这是一种计算与存储之间的折衷。
    • 参数化问题: 程序化纹理无法像美术师那样手动处理UV接缝和拉伸。
      • 解决方案: 发展出了在物体表面直接合成纹理的技术,完全绕开UV。
    • 抗锯齿: 无法使用 Mipmap 这样的预计算方法。
      • 解决方案: 利用程序化纹理的“白盒”特性。因为我们知道函数的构成,可以在计算时主动丢弃掉会产生走样的高频部分(即进行频带限制 Band-limiting),这甚至能降低计算成本。

6.4 纹理动画 (Texture Animation)

核心观点: 让纹理动起来,可以极大地增强场景的生动性。

  • 主要方法:
    • 视频纹理 (Video Textures): 直接将视频源作为纹理使用,适用于游戏中的屏幕、广告牌等。
    • 纹理坐标动画 (UV Animation):
      • 这是最常用且高效的方法。通过在着色器中随时间平移、旋转或缩放UV坐标,来实现视觉上的动态效果。
      • 经典案例:
        • 平移UV: 模拟水流、瀑布、熔岩、坦克履带、传送带。只需在每一帧为 v 坐标减去一个小的偏移量。
        • 旋转UV: 模拟漩涡、风扇。
    • 纹理混合 (Texture Blending):
      • 在两个或多个纹理之间进行插值(淡入淡出),可以创造出材质变换的效果。
      • 经典案例: 雕像石材质地逐渐变为肉体质感。

6.5 材质映射 (Material Mapping)

核心观点: 纹理的终极目标是驱动着色。通过使用多张贴图来控制材质的不同属性,可以用一个通用的着色器(Shader)实现千变万化的表面效果。这是基于物理的渲染 (PBR) 工作流的基础。

  • 常见材质贴图:

    • 反照率/漫反射颜色贴图 (Albedo/Diffuse Map): 定义了物体最基础的表面颜色。
    • 粗糙度贴图 (Roughness Map): 控制表面的微观粗糙程度。值越低表面越光滑(镜面反射),值越高越粗糙(漫反射)。
    • 金属度贴图 (Metallic Map): 定义表面是金属还是电介质(非金属)。
    • 凹凸/法线贴图 (Bump/Normal Map): 修改表面法线,制造凹凸细节的假象(详见6.7节)。
  • 高级应用:

    • 材质ID贴图 (Material ID Map): 可以用一张贴图的不同颜色区域来控制着色器执行不同的代码逻辑。例如,一个像素采样到红色,就执行金属着色模型;采样到蓝色,就执行生锈材质的着色模型。
  • 专家提示:非线性参数的滤波问题

    • 对于颜色(Albedo)这种线性参数,使用标准Mipmap滤波是正确的。
    • 但对于粗糙度法线非线性参数,简单的平均会导致错误的着色结果(如高光失真)。这类贴图需要特殊的滤波技术(将在第9章详细讨论)。

6.6 Alpha 映射 (Alpha Mapping)

核心观点: 利用纹理的Alpha通道来控制像素的透明度,可以用非常低的多边形数量,创建出轮廓极其复杂的物体。

  • 主要应用:
    • 贴花 (Decals): 将一张带有透明区域的纹理“贴”在另一个表面上,例如墙上的涂鸦、地上的血迹。
    • 镂空 (Cutouts): 将带有复杂轮廓(如树叶、铁丝网)的纹理应用到一个简单的多边形(通常是四边形)上,通过Alpha剔除透明部分,形成复杂的剪影。
      • 经典技巧:“交叉树” (Crossed-Trees),用两个相互垂直的四边形来模拟一个简单的3D树木或灌木丛,成本极低。

渲染技术与挑战

渲染带有Alpha映射的物体,尤其是大量重叠的物体(如植被),会带来一系列挑战。

  1. Alpha 混合 (Alpha Blending):

    • 问题: 需要严格的从后向前的渲染顺序才能得到正确结果。对于交叉的面片或者成千上万的草叶,排序几乎是不可能的。
  2. Alpha 测试 (Alpha Test):

    • 核心算法: 在像素着色器中,当Alpha值低于某个阈值时,直接丢弃 (discard) 该片元。这是一个“全有或全无”的二元决策。
    • 优点: 无需排序,可以和深度缓冲(Z-Buffer)正常工作。
    • 缺点:
      • 硬边缘: 产生锯齿状的边缘,没有平滑过渡。
      • Mipmap 问题: 标准的Mipmap会平均Alpha值,导致远处物体的Alpha值普遍降低。当低于阈值时,整个物体会“消失”或“变薄”,而不是自然地变模糊。
    • Mipmap问题解决方案:
      • 覆盖率保持 (Coverage Preservation): 在生成Mipmap时,调整每一级的Alpha值或测试阈值,以确保被剔除的像素比例与原始纹理保持一致。
      • 随机透明 (Stochastic Transparency): 用一个随机/哈希函数来代替固定的阈值。一个alpha为0.3的像素,有30%的概率被剔除。在宏观和时间上,这能平均得到正确的透明度。
  3. Alpha to Coverage (A2C):

    • 核心思想: 一种利用多重采样抗锯齿 (MSAA) 硬件的巧妙技术。它将像素的Alpha值转换为一个子像素的覆盖遮罩 (coverage mask)
    • 工作方式: 例如,在一个4x MSAA的像素上,一个Alpha为0.75的片元会被渲染成完全不透明,但只覆盖4个子采样点中的3个。
    • 优点: 能够为镂空物体(如叶子、铁丝网)的边缘提供高质量的抗锯齿效果,且无需排序,因为所有写入的片元都是不透明的。这是渲染植被的理想方案。

专家提示:预乘 Alpha (Premultiplied Alpha) 的重要性

  • 问题:黑色/暗色光环
    • 当一个不透明的彩色纹素(如红色 (1,0,0,1))与一个完全透明的纹素(通常存储为黑色 (0,0,0,0))进行双线性插值时,结果会是一个半透明的暗红色 (0.5, 0, 0, 0.5)。这个“被污染”的暗红色在渲染时会在物体边缘产生难看的黑色或深色描边
  • 解决方案:
    • 正确的做法是在进行任何滤波或混合之前,将RGB通道预先乘以Alpha通道。即 (R*A, G*A, B*A, A)
    • 工作流实践: 在纹理预处理阶段,将不透明区域的颜色**“渗透”或“延伸” (bleed)** 到邻近的透明区域中。这样,即使在透明区域,RGB值也携带着正确的颜色信息,插值时就不会引入黑色。

这部分内容的主题是在不增加任何几何顶点的前提下,创造出丰富的表面几何细节的假象。这些技术针对的是介观几何 (Meso-geometry)——那些比单个像素大,但又小到不适合用三角形来建模的细节,例如皮肤的毛孔、砖块的缝隙、衣服的褶皱。

6.7 凹凸映射 (Bump Mapping)

核心观点: 凹凸映射的本质,是逐像素地扰动(Perturb)用于光照计算的表面法线,使得平坦的表面看起来凹凸不平。原始的几何体并未发生任何改变。

这个思想是整个技术族群的基石。就像顶点法线让多个三角形看起来像一个平滑的曲面一样,逐像素修改法线可以让我们感知到三角形内部的起伏。

切线空间 (Tangent Space)

为了能有意义地“扰动”一个法线,我们需要一个参照系。这个参照系就是切线空间,一个位于表面每个点的局部坐标系。

  • TBN 矩阵: 这个坐标系由三个相互正交(理想情况下)的向量定义:
    • 法线 (Normal, N): 垂直于表面的向量,即原始的几何法线。
    • 切线 (Tangent, T): 沿着表面UV坐标U方向的向量。
    • 副切线 (Bitangent, B): 沿着表面UV坐标V方向的向量。
  • 作用: TBN矩阵用于将向量(如光照方向、观察方向)从世界空间转换到切线空间。在切线空间中,未经扰动的法线永远指向 (0, 0, 1),这极大地方便了后续的计算和贴图的复用。

6.7.1 Blinn 的原始方法

这是凹凸映射的两种早期形式,如今主要被法线贴图取代,但其思想值得理解。

  1. 高度图 (Height Map):
    • 使用一张灰度图来表示表面的相对高度(白高黑低)。
    • 在着色器中,通过比较相邻纹素的高度差来动态计算出表面的梯度(斜率),进而推导出扰动后的法线。
  2. 偏移图 (Offset Map):
    • 直接在纹理中存储两个值 (bu, bv),表示法线应该沿着切线T和副切线B方向分别偏移多少。

6.7.2 法线映射 (Normal Mapping)

核心观点: 这是当今业界最主流的凹凸映射技术。它不再存储高度或偏移,而是直接在纹理中存储扰动后的法线向量本身

  • 工作原理:

    • 法线向量 (x, y, z) 的每个分量(范围 [-1, 1])被映射到纹理的 (R, G, B) 通道(范围 [0, 1][0, 255])。
    • 在切线空间中,一个平坦、无扰动的表面法线是 (0, 0, 1)。经过映射后,它在法线贴图中的颜色是 (0.5, 0.5, 1.0),即 RGB(128, 128, 255),呈现为一种标志性的浅蓝色
    • 切线空间法线贴图是标准,因为它与特定模型和方向解耦,可以被轻松复用在不同模型上,并且压缩效果好。
  • 专家提示:法线贴图的滤波难题

    • 颜色是线性数据,对其进行Mipmap滤波(平均)是正确的。但法线是非线性数据,直接对法线向量进行平均会导致错误的光照结果,尤其是在高光(Specular)计算中。
    • 这种错误的滤波会导致远处物体的高光闪烁、跳动,或者细节“糊掉”而不是自然变柔和。
    • 近似正确的场景: 对于纯漫反射(Lambertian)表面,简单的法线平均还能得到近似正确的结果。但只要有高光,问题就会显现。
    • 正确思路: 更好的方法是在滤波时考虑整个着色模型,而不仅仅是法线本身(详见第9章)。

6.8 视差映射 (Parallax Mapping)

核心观点: 视差映射是法线映射的进阶版。它不仅修改法线,还根据高度图和视角,对纹理坐标本身进行位移,从而模拟出视差效果(即从不同角度观察时,物体位置会发生相对移动)。

  • 解决的问题: 法线贴图的“凹凸”是纯粹的光照戏法,在掠射角度(grazing angles)观察时,其扁平的本质会暴露无遗。凸起部分不会遮挡凹陷部分。

  • 基本原理:

    1. 需要一张高度图 (Height Map)
    2. 在像素着色器中,读取当前位置的高度值。
    3. 根据该高度值和观察向量,计算出一个UV偏移量。
    4. 使用偏移后的UV坐标去采样颜色贴图和法线贴图。
    • 公式: 其中 是原始UV,h是高度, 是切线空间中的观察向量。
  • 缺点: 基础的视差映射是一种近似,它假设偏移后的位置与原始位置高度相同,这在高度变化剧烈或掠射角度下会失效,产生“纹理游动”的瑕疵。

6.8.1 视差遮挡映射 (Parallax Occlusion Mapping, POM)

核心观点: 也称为浮雕映射 (Relief Mapping),是视差映射的“终极形态”。它不再满足于简单的UV偏移近似,而是在像素着色器中,沿着视线方向对高度场进行光线步进 (Ray Marching),以找到真实的交点。

  • 核心算法:

    1. 在像素着色器中,将观察向量投影到表面上。
    2. 沿着这个投影方向,以固定的步长进行多次迭代采样
    3. 在每一步,比较当前光线的高度从高度图中采样到的表面高度
    4. 当光线高度首次低于表面高度时,意味着光线已经“钻入”了虚拟的表面之下。
    5. 在最后两个采样点(一上一下)之间,通过二分查找割线法等方式精确地定位交点。
    6. 使用这个最终交点的UV坐标来完成最终的着色。
  • 优点:

    • 能实现令人信服的自遮挡 (Self-Occlusion) 效果(砖块挡住砂浆)。
    • 可以扩展实现自阴影 (Self-Shadowing)
    • 立体感和真实感远超普通法线贴图。
  • 挑战:轮廓问题 (Silhouette Problem)

    • POM 及其所有变种的“幻觉”仅发生在几何体内部。在物体的轮廓剪影处,其原始的、平滑的几何边缘会暴露出来,破坏真实感。
    • 解决轮廓问题需要更昂贵的技术,如外壳映射 (Shell Mapping),它会渲染一个被“撑开”的棱柱体来捕捉轮廓处的视差效果。

6.9 纹理光源 (Textured Lights)

核心观点: 纹理不仅能定义物体表面,还能定义光源本身的强度和颜色分布,为照明增添丰富的细节和艺术控制力。

  • 投影纹理 (Projective Texturing):

    • 应用: 主要用于聚光灯 (Spotlights)
    • 原理: 像幻灯片投影仪一样,将一张2D纹理投射到场景中。纹理的亮度和颜色调节了光锥内的光照强度。
    • 俗称: GoboCookie,源自舞台灯光术语。
    • 用途: 模拟窗户透光、树叶缝隙的斑驳光影、有图案的舞台灯等。
  • 其他应用:

    • 全向光 (Omni Lights): 使用立方体贴图 (Cube Map) 来控制一个点光源在所有方向上的光照分布。
    • 衰减函数: 使用一维纹理来定义一个任意复杂的、非物理的距离衰减曲线。
    • 体积光: 使用三维纹理可以定义复杂的光束形状和体积光效果。