这一篇的目标:不用公式,只用身边能看到的东西,讲清楚两件事:
- 什么是“各向异性”
- 什么是“各向异性高光”
看懂之后,再回头看上一篇里的 Kajiya-Kay、各向异性 GGX,会容易很多。
一、先说结论
| 词 | 大白话 |
|---|---|
| 各向同性 | 不管从哪个方向看、摸、用,性质都一样 |
| 各向异性 | 换个方向,性质就不一样 |
| 普通高光 | 灯光在物体表面的反光,通常是圆形光斑 |
| 各向异性高光 | 因为表面在不同方向上“光滑程度不同”,反光被拉成一条长带或一个光环 |
如果只记一句话:
表面有“纹路方向”,反光就会被拉长,这就是各向异性高光。
二、什么是“各向异性”:先忘掉渲染
“各向异性”不是图形学专有的词,它来自物理和材料学。拆开看:
- 各向:各个方向
- 异性:性质不同
也就是:沿不同方向,这个东西的表现不一样。
1. 生活中的各向异性
| 例子 | 方向 A | 方向 B | 说明 |
|---|---|---|---|
| 劈木头 | 顺着木纹劈,一下就开 | 横着木纹劈,很难劈开 | 木纤维有方向 |
| 撕纸 | 某个方向撕,裂口很直 | 换个方向撕,裂口歪歪扭扭 | 纸纤维在造纸时朝一个方向排列 |
| 切肉 | 顺纹切,肉丝很长、嚼不烂 | 横纹切,肉丝短、口感嫩 | 肌肉纤维有方向(厨师常说“横切牛羊肉”) |
| 摸猫 | 顺毛摸,很顺滑 | 逆毛摸,扎手 | 毛的倾斜方向 |
| 拉布料 | 沿经线、纬线拉,几乎拉不动 | 斜着拉,很有弹性 | 纱线的编织方向 |
| 劈竹子 | 顺着竹子劈,一刀到底 | 横着砍,很费力 | 竹纤维纵向排列 |
这些东西的共同点:内部或表面有“纹路”,纹路有方向。
2. 生活中的各向同性
| 例子 | 说明 |
|---|---|
| 玻璃 | 往哪个方向敲,碎法都差不多 |
| 橡皮泥 | 往哪个方向捏、拉,手感都一样 |
| 水 | 没有方向可言 |
| 一块抛光的钢球 | 表面朝哪个方向都一样光滑 |
这些东西没有纹路,或者纹路是杂乱无章、不分方向的。
3. 一个判断方法:转一转
把物体原地转一下(例如旋转 90°),它的表现变不变?
- 不变 → 各向同性
- 变了 → 各向异性
木头转 90° 之后,原来好劈的方向变成了难劈的方向——各向异性。
玻璃怎么转都一样——各向同性。
后面判断高光时,也用同一个方法。
三、什么是“高光”
高光,本质上就是灯在物体表面的倒影。
1. 越光滑,倒影越清楚
| 表面 | 看到的高光 |
|---|---|
| 镜子 | 灯的清晰倒影,灯是什么形状,倒影就是什么形状 |
| 台球、汽车漆 | 一个很小、很亮的光点 |
| 苹果、塑料玩具 | 一个稍大、边缘柔和的光斑 |
| 磨砂塑料、橡胶 | 一大片模糊的微弱亮光 |
| 粉笔、纸 | 几乎看不到高光 |
越光滑 ──────────────────────────────────────────→ 越粗糙 镜子 台球 苹果 磨砂塑料 ✦ ● ⬤ ░░░░░ 清晰倒影 小亮点 中光斑 一大片模糊2. 为什么粗糙的表面光斑大
在显微镜下看,“粗糙”其实就是表面有很多朝向各不相同的小斜面。
光滑表面(像一面大镜子) 粗糙表面(像很多小镜子,朝向乱七八糟) ───────────────────── ╱╲╱‾╲_╱╲╱‾╲╱╲_╱ 所有地方朝向一致 每一小块朝向都不一样 → 光只往一个方向反射 → 光被反射到各个方向 → 光斑小而集中 → 光斑大而分散关键结论:光斑的大小,反映的是表面的粗糙程度。
- 光滑 → 光斑窄
- 粗糙 → 光斑宽
注意:普通的粗糙表面,小斜面是乱的、不分方向的,所以光斑往各个方向散开得一样多——光斑是圆的。这就是各向同性高光。
四、把两者合起来:各向异性高光
1. 如果表面“一个方向光滑,另一个方向粗糙”会怎样?
想象一块不锈钢板,用砂纸只沿左右方向反复打磨,表面会留下无数条平行的细槽——这就是拉丝不锈钢。
俯视:拉丝不锈钢板(细槽沿左右方向) ════════════════════════════ ════════════════════════════ ════════════════════════════ ════════════════════════════现在分别从两个方向“切开”看它的表面:
① 沿着细槽方向(左右)切开,看侧面: ────────────────────────── 几乎是平的,像镜子 → 这个方向上,光不会散开 → 光斑“窄” ② 垂直细槽方向(上下)切开,看侧面: ⌒⌒⌒⌒⌒⌒⌒⌒⌒⌒⌒⌒⌒⌒⌒⌒ 一个个小圆弧,朝向各不相同 → 这个方向上,光被散开 → 光斑“宽”一个方向窄、一个方向宽,合起来就是——一条长带:
普通抛光钢板的高光 拉丝钢板的高光(细槽沿左右方向) ┌──────────────┐ ┌──────────────┐ │ │ │ ┃ │ │ ● │ │ ┃ │ │ │ │ ┃ │ ← 光斑沿上下方向被拉长 │ │ │ ┃ │ └──────────────┘ └──────────────┘ 圆形光斑 细长光带这就是各向异性高光:
表面在不同方向上的光滑程度不同,所以反光在一个方向上集中、在另一个方向上散开,光斑被拉成了长条。
2. 一个反直觉但很重要的规律
高光带的方向,与纹路的方向垂直。
- 细槽是左右方向 → 高光带是上下方向
- 头发是上下生长 → 高光是一圈横向的光环
原因就是上面那张剖面图:光是在“横穿纹路”的方向上被散开的,所以光斑往这个方向拉长。
3. 用“转一转”来验证
还记得第二节的判断方法吗?
| 操作 | 抛光钢球 / 抛光钢板 | 拉丝钢板 |
|---|---|---|
| 把物体原地旋转 90° | 光斑还是圆的,没有变化 | 光带跟着转了 90°(从竖条变成横条) |
| 结论 | 各向同性 | 各向异性 |
五、大量案例:身边的各向异性高光
案例 1:拉丝不锈钢(直线纹路)
在哪能看到:电梯门、冰箱门、不锈钢水槽、笔记本电脑外壳、拉丝不锈钢保温杯、厨房抽油烟机面板。
| 纹路 | 高光 |
|---|---|
| 平行的直线细槽 | 一条与细槽垂直的光带,边缘发虚 |
特征:手电照上去,看到的不是一个光点,而是一道“光柱”。走动时,光柱会跟着移动。
案例 2:锅底、金属锅盖(同心圆纹路)
在哪能看到:不锈钢锅的锅底、铝制锅盖、车床加工过的金属圆盘、汽车轮毂的车削面。
锅底的纹路:一圈圈同心圆 看到的高光:穿过圆心的放射状光带 ╭──────╮ ╲ ╱ ╭─┤╭────╮├─╮ ╲ ╱ │ ││ ◯ ││ │ ─────◯───── (或一条斜向光带) ╰─┤╰────╯├─╯ ╱ ╲ ╰──────╯ ╱ ╲为什么:纹路是一圈圈的圆,每个位置的纹路方向都是“绕着圆心转”,按照“高光与纹路垂直”的规律,高光就沿半径方向——从圆心往外放射。
特征:移动灯光时,光带像钟表指针一样绕着圆心转动。
案例 3:手表表盘(太阳纹)
在哪能看到:很多手表的表盘,纹路从中心向外放射,像太阳光线,表盘行业称为“太阳纹”。
| 纹路 | 高光 |
|---|---|
| 从中心向外放射的直线 | 一道弧形或环形的光 |
为什么:纹路沿半径方向,高光就沿垂直于半径的方向——也就是圆周方向。
案例 2 和案例 3 正好相反:纹路是圆的,高光就是放射的;纹路是放射的,高光就是圆的。这是理解“高光与纹路垂直”的最好例子。
案例 4:头发的“天使环”
在哪能看到:黑色长直发、动漫角色的头发、洗发水广告。
头顶 ╭──────╮ │││││││││ 发丝从头顶竖直向下 │││││││││ ═══════════ ← 高光是一圈横向的光环(天使环) │││││││││ │││││││││| 纹路 | 高光 |
|---|---|
| 每根发丝都是一根细长的圆柱,整体沿上下方向排列 | 一圈环绕头部的横向光环 |
特征:
- 头发越顺、越直,光环越明显;
- 头发乱了、卷了,发丝方向变得杂乱,光环就消失或变成零散的亮点;
- 扎成马尾、编成辫子后,发丝方向改变,高光的形状也跟着改变。
游戏中的对比:
| 做法 | 效果 |
|---|---|
| 头发用普通高光 | 头上一个圆形亮斑,看起来像塑料头盔 |
| 头发用各向异性高光 | 出现横向光环,看起来像一根根发丝 |
这是各向异性高光在游戏中最常见、最重要的用途,几乎所有二次元角色的头发都会处理。
案例 5:丝绸、缎面
在哪能看到:丝巾、缎面礼服、旗袍、领带。
| 纹路 | 高光 |
|---|---|
| 纤维沿织物的经纬方向排列 | 高光沿褶皱“流动”,形成长条状的光泽 |
特征:
- 同一块缎子,横着放和竖着放,亮度和光泽完全不同;
- 布料摆动时,光泽像水一样在褶皱间流动。
普通棉布没有这种效果,因为纤维短而杂乱,接近各向同性。
案例 6:其他例子
| 物体 | 纹路 | 你会看到 |
|---|---|---|
| 黑色猫狗的毛、马的鬃毛 | 毛顺着一个方向倒伏 | 顺毛方向上的光带 |
| 天鹅绒 | 绒毛方向一致 | 用手往不同方向抚过,颜色深浅不同 |
| 磨过的金属刀面、拉丝铝合金手机边框 | 打磨方向的细纹 | 与打磨方向垂直的光带 |
| CD / 唱片的背面 | 同心圆细槽 | 放射状光带(CD 上的彩虹色是另一个现象“衍射”,不属于本文内容) |
| 刷过清漆的木地板 | 木纹方向 | 沿木纹方向会有轻微拉长的反光 |
六、自己动手验证
不需要任何工具,用手机手电就能看到:
实验 1:勺子 vs 拉丝保温杯
- 关灯,打开手机手电;
- 照一照不锈钢勺子的背面(抛光):看到一个圆形小光点;
- 再照一照拉丝不锈钢保温杯或冰箱门:看到一条长长的光带。
前者是各向同性高光,后者是各向异性高光。
实验 2:转一转
- 找一块拉丝金属(拉丝笔记本外壳、拉丝金属名片、拉丝铝片);
- 平放在桌上,手电从上方照;
- 把它原地旋转 90°:光带的方向跟着转了 90°。
同样的操作对勺子做,光点不会变形。这就是“各向异性”的直接证据。
实验 3:观察锅底
找一个不锈钢锅翻过来,用手电照锅底,然后绕着锅移动手电:会看到一条光带像指针一样绕着中心转。
七、容易混淆的情况
1. 高光被拉长,不一定是各向异性
雨夜马路、湖面上的路灯倒影,常常被拉成长长的竖条。但这不是材质的各向异性,而是因为你在很低的角度看水面(掠射角)——即使是普通的粗糙表面,在这种角度下反光也会被拉长。
区分方法还是转一转:
| 现象 | 把表面原地旋转后 | 原因 |
|---|---|---|
| 湖面的路灯倒影 | 倒影方向不变,始终指向你 | 观察角度造成,与材质无关 |
| 拉丝金属的光带 | 光带跟着旋转 | 材质本身有方向,各向异性 |
2. 各向异性过滤 ≠ 各向异性高光
游戏画质设置里的“各向异性过滤(Anisotropic Filtering)”,是让斜着看的地面贴图更清晰的技术,属于贴图采样,与光照、高光无关。只是都用了“各向异性”这个词,描述的都是“不同方向上处理方式不同”。
3. 高光只是“更大”,不是各向异性
粗糙表面的光斑更大、更模糊,但仍然是圆的,这是各向同性高光。只有光斑在某个方向上比另一个方向明显更长,才是各向异性。
八、程序里怎么表达
理解了原理,代码就很好懂了。
1. 需要的信息不同
| 普通高光(各向同性) | 各向异性高光 | |
|---|---|---|
| 表面朝向 | 法线 N | 法线 N |
| 光滑程度 | 一个数:粗糙度 | 两个数:沿纹路方向的粗糙度、垂直纹路方向的粗糙度 |
| 纹路方向 | 不需要 | 需要:切线 T(纹路方向)和副切线 B(垂直方向) |
也就是说,各向异性高光比普通高光多问了一个问题:
“这个表面的纹路朝哪个方向?”
在模型数据里,这个方向通常由切线(Tangent)提供,切线又取决于模型 UV 的展开方向。这就是为什么做头发时,美术必须按发丝方向展开 UV。
2. 用代码对比
// ===== 普通高光(Blinn-Phong)===== // 只关心:半角向量 H 离法线 N 有多远 // 不管 H 往哪个方向偏,容忍度都一样 → 圆形光斑 float specIso = pow(saturate(dot(N, H)), shininess); // ===== 各向异性高光(简化示意,思路来自 Ward 模型)===== // 把“H 偏离 N 的程度”拆成两部分: // 沿纹路方向 T 偏了多少、沿垂直方向 B 偏了多少 // 两个方向使用不同的“宽度”,宽的方向光斑就被拉长 float ht = dot(H, T) / widthT; // widthT:沿纹路方向的宽度(纹路方向光滑 → 取小值) float hb = dot(H, B) / widthB; // widthB:垂直纹路方向的宽度(横穿纹路粗糙 → 取大值) float hn = max(dot(H, N), 1e-4); float specAniso = exp(-(ht * ht + hb * hb) / (hn * hn));调参时的直观效果:
| 参数设置 | 光斑形状 | 对应的真实材质 |
|---|---|---|
widthT == widthB | 圆形 | 抛光金属、塑料(退化为普通高光) |
widthT小,widthB大 | 沿 B 方向拉长的光带 | 拉丝金属,细槽沿 T 方向 |
widthT大,widthB小 | 沿 T 方向拉长的光带 | 拉丝金属,细槽沿 B 方向 |
| 两者都小 | 小而亮的圆点 | 镜面抛光 |
| 两者都大 | 大而模糊的圆斑 | 磨砂表面 |
对照第四节的剖面图:
- 沿纹路方向光滑→
widthT小 → 这个方向上光不散开; - 横穿纹路方向粗糙→
widthB大 → 这个方向上光被散开; - 结果:光斑沿 B 方向拉长,也就是高光带与纹路垂直。
代码里的两个参数,对应的就是“一个方向光滑、另一个方向粗糙”这件事。
3. 头发的写法:换个角度想
头发常用Kajiya-Kay 模型,思路和上面略有不同,但同样可以用大白话理解。
一根头发是一根细圆柱。圆柱的侧面朝向四面八方:朝上的、朝下的、朝左的、朝右的都有。
一根发丝的横截面(圆形) ↑ ↖ ● ↗ 圆柱侧面的法线,绕着发丝一圈,朝向各个方向 ← ● → ↙ ● ↘ ↓所以,判断一根头发能不能把光反射到眼睛里,不需要看某个具体的法线,只需要看:
H(光线和视线的“中间方向”)是否垂直于发丝方向 T?
只要 H 垂直于发丝,圆柱侧面上总能找到一个正好朝向 H 的位置,反光就会进入眼睛。
// 普通高光:H 和法线 N 越接近,越亮 float specIso = pow(saturate(dot(N, H)), shininess); // Kajiya-Kay:H 和发丝方向 T 越垂直,越亮 float TdotH = dot(T, H); float sinTH = sqrt(saturate(1.0 - TdotH * TdotH)); // 越垂直,sin 越接近 1 float specHair = pow(sinTH, shininess);整头头发的发丝都是上下走向,满足“H 垂直于发丝”的位置会连成一圈横向的线——这就是天使环。
4. 切线方向错了会怎样
各向异性高光完全依赖“纹路方向”,而程序里的纹路方向来自切线,切线又来自UV 的展开方向。
用拉丝金属来类比:
| 情况 | 相当于现实中 | 游戏里的现象 |
|---|---|---|
| 切线方向正确 | 整块钢板沿同一方向拉丝 | 一条连续、干净的光带 |
| 切线方向整体错 90° | 把拉丝方向转了 90° | 光带方向不对,例如头发高光变成竖条 |
| 切线方向东一块西一块 | 钢板被拼成很多小块,每块拉丝方向不同 | 光带断成碎片、扭曲、闪烁 |
| UV 接缝两侧方向不同 | 两块拉丝方向不同的钢板拼在一起 | 接缝处高光突然断开 |
这就是上一篇反复强调的:头发 UV 要按发丝方向展开。不是美术习惯问题,而是各向异性高光的“纹路方向”就写在 UV 里。
九、游戏中的典型应用
| 材质 | 常见做法 | 不做各向异性时的问题 |
|---|---|---|
| 角色头发 | Kajiya-Kay,或贴图高光模拟 | 像塑料头盔,没有发丝感 |
| 拉丝金属(枪械、机甲、家电、载具零件) | 各向异性 GGX + 方向贴图 | 看起来像普通抛光金属,缺少工业质感 |
| 车削金属(轮毂、表盘、锅具) | 各向异性 GGX + 绕圆心的切线方向 | 圆形零件缺少旋转纹的光泽 |
| 丝绸、缎面服装 | 各向异性高光或专门的布料模型 | 像普通塑料布,没有“流动”的光泽 |
| 动物毛发 | 毛发着色模型(类似头发) | 毛发显得僵硬 |
并不是所有项目都需要。移动端、风格化项目通常只在头发上做各向异性;写实项目才会在金属、布料上大量使用。
十、自测:这些是不是各向异性高光?
| 现象 | 是否各向异性 | 理由 |
|---|---|---|
| 不锈钢勺子背面的圆形光点 | 否 | 表面没有纹路方向,光斑是圆的 |
| 冰箱拉丝门板上的竖直光柱 | 是 | 横向拉丝纹路,光带与纹路垂直 |
| 黑色长发头顶的横向光环 | 是 | 发丝竖直排列 |
| 雨夜马路上被拉长的路灯倒影 | 否 | 低角度观察造成,旋转路面倒影不跟着转 |
| 锅底绕中心转动的光带 | 是 | 同心圆纹路 |
| 磨砂塑料上一大片模糊亮光 | 否 | 只是粗糙,光斑仍然是圆的 |
| 缎面礼服褶皱上流动的光泽 | 是 | 纤维方向一致 |
| 游戏设置里的“16x 各向异性过滤” | 否 | 那是贴图采样技术,不是光照 |
小结
把整个思路串起来:
有纹路方向的表面(拉丝、发丝、纤维) │ ▼ 沿纹路方向光滑,横穿纹路方向粗糙 │ ▼ 反光在一个方向集中,在另一个方向散开 │ ▼ 光斑被拉成长条或光环 —— 各向异性高光 │ ▼ 高光带的方向与纹路垂直| 问题 | 答案 |
|---|---|
| 什么是各向异性 | 沿不同方向,性质不一样。判断方法:原地转一转,表现会变 |
| 什么是高光 | 灯在表面的倒影。越光滑,光斑越小;越粗糙,光斑越大 |
| 什么是各向异性高光 | 表面在不同方向上光滑程度不同,光斑被拉长成带状或环状 |
| 最典型的例子 | 拉丝不锈钢、锅底、手表太阳纹、头发天使环、缎面 |
| 最重要的规律 | 高光带与纹路方向垂直 |
| 程序里多需要什么 | 纹路方向(切线 T / 副切线 B),以及两个方向各自的粗糙度 |
| 最常见的问题 | 切线方向不对:高光方向错、断裂、扭曲,根源多在 UV 展开 |
一句话概括:普通高光只问“表面朝哪”,各向异性高光还要问**“表面的纹路朝哪”**——纹路决定了光往哪个方向散开,于是光斑就被拉成了一条带。