微观结构造就各向异性光效

文章摘要

各向异性反光现象源于物体表面微观结构的定向排列(如头发的发丝、拉丝金属的划痕、光盘的同心圆槽等)。这种定向结构导致光线反射被引导至特定方向,形成动态高光条带或彩虹色带(如丝绸的柔光闪动、CD的彩虹效应)。其本质是表面微法线集中在某一方向,使反射光随观察角度变化而移动。简言之,各向异性反光是表面纹路对光线的定向"引流"结果。


1. 微观结构决定各向异性

这些物体(比如头发、缎面、拉丝金属、光盘、镲片、黑胶唱片)之所以会有各向异性的光照效果,都是因为它们表面的微观结构具有“定向性”,而不是像普通平滑物体那样杂乱无章。

举例说明:

  • 头发:由成千上万根细小的发丝平行排列,每根发丝的表面其实像一根小圆柱,局部的镜面反射全都朝着发丝走向排列。
  • 缎面/丝绸:纤维长丝都沿同一个方向编织,表面形成定向的纤维沟槽。
  • 拉丝金属:表面处理时,机械工具反复沿一个方向抛光,留下大量微小平行划痕。
  • CD、黑胶唱片、镲片:表面有大量同心圆环形的凹槽和细线,这些凹槽/线条都按照固定方向排列。
  • 镲片:鼓镲上反复手工或机械拉出的圆形线纹;
  • 黑胶唱片:刻录时刻出的沟槽沿着圆周展开。

2. 光的反射方式受定向影响

光线照射到这些有方向性的微观结构时,光线的反射结果就不再是简单的漫反射或者均匀镜面反射,而是受定向沟槽/线条/表面微面引导,出现特殊的反光效果

具体表现

  • 发亮条带 & 色彩变幻:比如拉丝金属板、头发在阳光下会有明显的高光带,而且只在某个方向看得到,就是因为大量小划痕都把光反射到同一“主向”;换个角度,那条亮带就跟着移动。
  • 彩虹光效(CD、黑胶唱片等):定向的凹槽还会干涉折射出彩虹效应。
  • 缎面/丝绸的柔光闪动:纤维的定向排列让光线被沿一个方向“集中”反射,远远看去会有光带在移动。

3. 各向异性反射的本质——定向分布的微表面法线

用物理和计算机图形学术语来说,这些特殊现象本质上都来自于:

  • 这些材料表面的微观法线分布不是各方向均匀的,而是集中在某一个方向的平面上(比如,都垂直于发丝,或垂直于沟槽走向)。
  • 因此,光的反射“高光”不是面状(如普通塑料),而是被定向拉伸成条带、斑点或者特殊色带。
  • 你的眼睛和光源在和物体表面的特定角度时,微表面结构就会把大部分反射光聚到某一个方向,这也是为什么你转动头发、金属或光盘时,亮带跟着动、色彩发生变化。

小结:「各向异性现象」的本质原因

  1. 微观结构定向分布(沟槽/线条/纤维):表面不是随机分布的微面,而是聚集在某个“主方向”。
  2. 决定光线反射特点:光线被引导,导致反光随观察方向或灯光方向发生变化。
  3. 视觉上的动态高光条带/色带/斑点:因定向微结构的选择性反射。

一句话总结:
这些物体的奇妙反光,是因为它们的表面“纹路”把光像排水沟那样定向引导了出来,形成随角度移动的各向异性亮斑或色带。


下面用通俗易懂的方式为你详细解释,计算机图形学里是怎么“模拟”这些现实中的各向异性光照现象的。


1. 标准各向同性光照模型回顾

大多数游戏和图形软件的默认光照模型(比如 Phong、Blinn-Phong),假设物体表面无特定方向,微表面法线均匀分布。渲染出来的高光总是圆斑状,不会随着表面划痕或纤维走向改变。

但现实中的头发、CD、拉丝金属等关键在于“主方向”,这些靠普通模型就做不出那种随角度变化的动态光带。


2. 各向异性光照模拟思路

A. 给顶点或像素增加“主方向”信息

  • 多数各向异性模型会在每个顶点(或像素)除了表面法线以外,再记录一个“切线”或“主方向向量”——通常叫"Tangent"(走向)、“Bitangent”(副走向)。
  • 这样,渲染时不仅知道表面“正面朝哪”,还知道“纹理/丝线”朝哪。

例如渲染头发时,每根头发纤维自身就有一个主方向;渲染金属拉丝时,表面每点都标记划痕方向。

B. 改写高光和漫反射公式

普通材质的高光只考虑法线和光向:

  • Ispecular=(V⋅R)sI_{specular} = (V \cdot R)^sIspecular=(VR)s

各向异性模型,比如 Kajiya-Kay、Ashikhmin-Shirley、Heidrich-Seidel 等,会改用带主方向参数的公式,或直接查表(如你文章里提到的查二维纹理):

  • 利用切线 T⃗\vec{T}T 修正高光的拉伸方向。
  • 模型计算时,引入 (L⋅T)(L \cdot T)(LT)(V⋅T)(V \cdot T)(VT) 等参数,让高光沿主方向变宽或拉伸成条带。

C. 用二维查找表(Lookup Table)或贴图加速

  • 复杂的各向异性公式往往不直接在着色器里一条条算,而是提前做成“二维光照查找表”。
  • 顶点(或像素)用它自己的切线等信息查表拿高光值。比如,“s”坐标代表光线和切线夹角,“t”坐标代表视线和切线夹角,查二维贴图得结果。
  • 这样能高效、快速地在GPU上做出高质量的各向异性效果。

D. Shader代码实现简述

在GLSL/HLSL等着色器中,实际流程大致如下:

  1. 顶点/像素采样得到:法线 N⃗\vec{N}N,切线 T⃗\vec{T}T,光线方向 L⃗\vec{L}L,视线方向 V⃗\vec{V}V
  2. 计算 L⋅TL \cdot TLTV⋅TV \cdot TVT 等点积。
  3. 应用公式(如 Heidrich-Seidel、Kajiya-Kay 或查表法)得到N⋅LN \cdot LNL(漫反射系数)、V⋅RV \cdot RVR(高光系数)。
  4. 生成纹理坐标用于查找表贴图(如代码里:tex2D(lightLUT,texcoord))。
  5. 最后混合材质颜色和灯光,输出片元颜色。

代码片段(例)

vec3 T = Tangent; // 切线
float s = dot(L, T);
float t = dot(V, T);
float NdL = sqrt(1.0 - s*s);
float VdR = sqrt(1.0 - s*s) * sqrt(1.0 - t*t) - (s*t);
float diffuse = NdL;
float specular = pow(VdR, shininess);
// 结合查表方式替代公式也可以

3. 图形学中的实际应用案例

  • 头发Shader(Kajiya-Kay模型):适合细长物体如头发、羊毛,能做出真实的长型高光。
  • 拉丝金属Shader(Heidrich-Seidel模型):适合金属表面,能做出随着观察角度变化的拉丝光带。
  • CD/黑胶Shader(周期性切线+光栅效果):利用同心圆方向和干涉公式,做出动态彩虹高光。
  • 丝绸Shader(Ashikhmin-Shirley模型):高光、柔光会变成带状但更分散。

4. 其他纹理方法补充

  • 可以用法线贴图(Normal Map)存储和微调主方向信息,让高光条带在表面复杂变化。
  • 也可用切线空间贴图,增加物体表面定向纹理效果。

5. 总结

模拟各向异性光照的核心就是在渲染过程中,不仅仅计算法线反射,还把表面主方向的信息也算进去,让高光和反光能够根据纹路/切线的真实走向动态变化

现实模拟的效果,就是你在游戏、美术或渲染工具里能看到头发、金属、丝绸表面的光带随着你的视角和灯光的变化而“流动”和“拉伸”,尽可能逼真还原了生活中的美丽视觉!


这里以拉丝金属/丝绸这种典型的各向异性材质为例,给你详细讲解常用各向异性高光Shader的实现思路和代码:


1. 各向异性高光(Heidrich-Seidel模型)理论

最常见的方式之一是Heidrich-Seidel各向异性高光模型,它的实际高光公式是:

Specular∝[(H⃗⋅T⃗)2]k\text{Specular} \propto \left[ (\vec{H} \cdot \vec{T})^2 \right]^kSpecular[(HT)2]k

  • 这里,H⃗\vec{H}H 是半程向量(光方向与视线方向的归一化和)。
  • T⃗\vec{T}T 是切线方向(拉丝/纤维方向)。
  • kkk 用于控制高光的锐度(越大越尖锐)。

也可以用H⃗\vec{H}H和表面法线N⃗\vec{N}N的组合来进一步精细调整。


2. 简单各向异性高光Shader代码实现(GLSL/HLSL通用思想)

假设你在片段着色器中已有以下输入:

  • vec3 normal 表面法线(世界空间或切线空间)
  • vec3 tangent 切线方向(主方向,已归一化)
  • vec3 lightDir 入射光单位向量(已归一化,从表面指向光源)
  • vec3 viewDir 视线方向单位向量(已归一化,从表面指向相机)

代码示例(GLSL,供主流引擎稍适配即可)

// 必须保证所有向量归一化!!!
vec3 N = normalize(normal);
vec3 T = normalize(tangent);
// 计算环绕主方向、法线的正交基(可选)
vec3 B = normalize(cross(N, T));

vec3 L = normalize(lightDir);
vec3 V = normalize(viewDir);

vec3 H = normalize(L + V); // 半程向量

// 各向异性高光分量
float tDotH = dot(T, H);
float shine = 40.0; // 高光锐度可调(小更宽,大更尖锐)
float spec = pow(tDotH * tDotH, shine); // 取平方让它更集中在某一方向

// ---- 漫反射一般处理,不变
float NdotL = max(dot(N, L), 0.0);
vec3 diffuse = baseColor * NdotL;

// ---- 最终颜色叠加
vec3 finalColor = diffuse + spec * vec3(1.0, 1.0, 1.0) * specularColor; // 高光白色

gl_FragColor = vec4(finalColor, 1.0);

说明与拓展

  • 你可动态从贴图或顶点获得tangent方向。
  • shine参数越高,高光带越细锐;可调节模拟不同金属。
  • 高光色(specularColor)可变(比如金色、银色等)。
  • 可以再加上各向异性散射/漫反射项做出丝绸更柔和的亮条。

3. 进阶:查找表实现(更真实、可艺术定制)

可以把不同光向和主方向的高光亮度提前做成一张二维纹理贴图(Lookup Table,LUT),在shader里用(L⋅N)(L\cdot N)(LN)(H⋅T)(H\cdot T)(HT)查表,得到更复杂、艺术化的高光分布。例如:

float coordS = dot(T, H);              // 或 dot(T, L) 视需求
float coordT = dot(N, L);              // 漫反射分布
vec2 lutCoord = vec2(coordS * 0.5 + 0.5, coordT * 0.5 + 0.5);
float anisotropicSpec = texture2D(lightLUT, lutCoord).r; // 查表获取亮度
...
vec3 finalColor = diffuse + anisotropicSpec * specularColor;

这样美术可以直接画出你想要的光斑形状,查表就能表现复杂材质变化!


4. 典型场景推荐参数

材质shine(锐度)高光颜色说明
拉丝金属40~80灰色/银白明显条带
金属车漆120~300彩色/强白高光窄且尖锐
丝绸/绸带5~15漫反射主导,略带高光白色柔亮带,高光模糊
头发10~30白色+主色mixin柔性亮条条

5. 参考资料与进一步阅读

  • SIGGRAPH经典论文:“Anisotropic Highlights Using A Tangent Vector Texture Map”, Heidrich & Seidel, 1998
  • Unity3D/Unreal官方文档搜索“Anisotropic Hair/Metal Shader”
  • glTF 2.0 、Unreal等现代引擎都支持各向异性参数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你一身傲骨怎能输

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值