笔记10 图形 2.5 BUMP图改进

铁名_IronName Lv4

图形 2.5 BUMP图改进

相关笔记:读书笔记06《Unity Shader入门精要》

Bump Mapping

凹凸贴图映射技术是对物体表面贴图进行变化,然后再进行光照计算的一种技术。
例如给法线分量添加噪音,或者在一个保存扰动值的纹理图中进行查找。这是一种提升物体真实感的有效方法,但却不需要额外的提升物体的几何复杂度。这种方式在提升物体的表面细节或者表面的不规则性方面有显著效果。

分类

BumpMapping的种类主要有:法线映射、视差映射、浮雕映射。
这几种方法或者贴图,被广泛使用,用于增加模型的细节效果,或者用来做特殊的画面表现效果。最常用的是法线映射,一般的增加法线贴图后,会对局部的物体表面进行法线扰动,进而改变明暗关系,从而达到增加表面细节的效果。其中三种映射中都用到的法线贴图也是本次介绍的重点内容。

Normal Mapping 法线映射

Normal Map 是一张存有物体局部表面法线信息的一张贴图。在计算光照的时候,程序会去读取法线图,并获取到当前像素点的法线信息,结合光线信息进行光照计算。使用法线贴图计算光照,可以让物体表现出更加丰富的细节,并随着光照方向的变换实时变化。这是普通纹理贴图不能表现出的。

法线贴图一般由高模映射到对应的底模上来生成。但像金属,木头等这些细节丰富的物体,可借助程序化的软件如:Photo Shop,SubstanceDesigner等生成对应法线贴图。

切线空间

读书笔记06《Unity Shader入门精要》中讲过)
法线的存储,一般会放到模型的切线空间中。切线空间是以物体表面的切线,副切线和法线组成的几何空间。
当我们计算光照时,需要把光照运算的向量放到统一坐标系下。读取切线空间法线,需要世界坐标转切线空间的转换矩阵或切线空间转世界空间的转换矩阵,将向量统一到同一坐标系后再进行光照操作。

世界-切线 空间转换

将世界坐标系下的顶点法线(Normal)和切线(Tangent)以及副切线(Bitangent)作为切线空间坐标系的正交基。并用这三个向量的标准正交基来构建转换矩阵。
对应关系为法线作为Z轴,切线作为X轴,副切线作为Y轴。构建一个 333*3 的矩阵来做空间向量的坐标系转换。一般称为 TBNTBN 矩阵。其逆矩阵就是从切线空间到世界空间的转换矩阵记TBN1TBN^{-1},因为 TBNTBN 为正交阵,所以其逆矩阵为 TBNTBN 的转置矩阵。

Unity 中法线贴图的压缩格式

在unity中,非移动平台上,Unity会把法线贴图转换成 DXRT5nm格式。这种格式只有两个有效通道GA通道,这样可以节省空间,而移动平台 Unity 使用传统的RGB通道。在DXRT5nm格式中,GA存储对应法线的 x、y分量,z分量需要通过一个简单的运算求得。

Parallax Mapping 视差映射

法线映射只能改变法线进而改变光照,并不能让模型表面产生让人信服的遮挡效果。
而视差映射是一种用提高模型表面细节并赋予其遮挡关系的技术。
视差映射的核心是改变纹理坐标,需要一张存储模型信息的高度图,利用模型表面高度信息来对纹理进行偏移。

  • 高度图作为顶点位移来使用时,需要模型包含大量的三角形才能获得比较不错的效果,否则看起来会成块状。
  • 可以和法线贴图一起使用提供令人信服的逼真的效果。

过程

模型的一个三角面(即切线空间)中,所有点都位于切线和副切线组成的平面内,但实际物体有更多的丰富细节。当计算我们当前视角的片元A时,真正应该计算的点是视线与物体表面的实际交点,即B点。

计算B点,我们就需要知道A、B两点在平面上 uv 偏差。这个其实是不太好计算的。不过可以近似计算,根据高度图以及切线空间下的视角方向,近似的求解偏移量,并可以通过一个缩放值(scale)来控制。

d=v.xyhascale/v.z\textbf{d}=\textbf{v}.xy * h_a * scale/\textbf{v}.z

更精确的近似:陡峭视差映射

想获得更加准确的结果就需要陡峭视差映射(Steep Parallax Mapping),陡悄视差也是一个近似的解,但相比于普通视差映射要精确的多,效果表现上也更好。并且会对纹理坐标偏移进行合理性检查。
随峭视差映射的基本思想是将深度分为等距的若干层,然后从最顶端开始采样,并且每次沿着视角方向偏移一定的值,若当前层的深度大于采样出的深度,则停止检查并返回最后的结果。

Relief Mapping 浮雕映射

想要有更好更准确的表现效果,视差映射是不够的,使用更大的uv偏移,视差映射就会导致失真。浮雕映射更容易提供更多的深度,还可以做自阴影以及闭塞效果。

过程

浮雕映射一般采用 射线步进 和 二分查找 来决定uv偏移量。
第一步,使用射线步进来确定交点位于哪个步进内。之后在该步进内使用二分查找,快速确定交点位置。(先用二分查找可能会漏掉较薄的区域导致结果不准确)

介于陡视差和浮雕之间:视差闭塞贴图

视差闭塞贴图(Parallax Occlusion Mapping, POM)主要是为了解决浮雕映射最后一步二分查找性能开销的问题。区别:步进结束后,对步进区域两端uv采样,再对这两端的结果进行插值,作为最终的偏移值。

  • 性能比浮雕映射好,精度比陡视差好。
  • 局限:最后区间内是比较平滑连续的,效果才好

-作业-

将本课内容在基础光照介绍的作业中实现。
好参考:蛋白胨-Parallax Mapping (Steep, POM, Relief, Secant, Shadow, PDO)

实践

在Unity中,基于 Phong 着色 Blinn-Phong 光照模型,使用法线贴图和高度贴图,实现基础视差,陡峭视差,视差闭塞,浮雕映射 的 Shader。

代码:视差映射在 Unity Shader 的实现

🔍 为什么需要 tex2Dgrad 而不是 tex2D

在普通的纹理采样(如 tex2D)中,GPU 会自动计算当前 UV 的导数来决定使用哪一层 mipmap,以保证远处纹理清晰且无锯齿。但在视差映射的循环中,uv 是动态变化的(每次迭代都减去 deltaUV),如果直接使用 tex2D 采样,GPU 会基于这个变化后的 UV 计算导数,导致 mipmap 选择错误,出现闪烁或过度模糊。

而 tex2Dgrad 允许我们手动指定导数,这里传入的是原始 UV 的导数 ddx(i.uv) 和 ddy(i.uv),因为无论我们如何偏移 UV,纹理坐标在屏幕空间的变化率(即相邻像素间的 UV 差异)应该保持不变(偏移量本身在同一像素块内是相同的)。通过强制使用原始导数,我们告诉 GPU:“纹理坐标变了,但它的变化率还和原来一样”,从而保证 mipmap 层级计算正确,避免 artifacts。

为什么一步的陡视差不是基础视差?
  • 基础视差:假设表面高度为 height(0~1),则沿视线方向偏移的距离正比于 height,偏移量为 height * deltadelta 是视线方向的最大偏移)。
  • 陡峭视差:将深度范围[0,1]均匀分为 _MaxSteps 层,每层步进固定长度 delta(等于最大偏移除以层数)。当 _MaxSteps=1 时,只步进一次,移动距离就是完整的 delta完全不考虑当前采样的高度值,因此它相当于假设表面高度始终为1。
  • 标题: 笔记10 图形 2.5 BUMP图改进
  • 作者: 铁名_IronName
  • 创建于 : 2026-02-22 21:30:34
  • 更新于 : 2026-02-24 10:13:02
  • 链接: https://blog.ironname.top/2026/02/22/笔记10-技术美术百人计划/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论