01 / 先把所有方向放进同一空间
计算一个表面点的局部光照,至少需要单位法线 N、指向光源的单位向量 L、指向相机的单位向量 V,以及材质和光源颜色。它们必须位于同一坐标空间。
光源类型决定 L 和强度:方向光在各处方向相同;点光源从表面指向某个位置,强度随距离衰减;聚光灯还会根据锥角衰减。
02 / Lambert 漫反射
粗糙表面会把入射光向许多方向散射。Lambert 模型假设从任意观察方向看,表面亮度都相同;受光量由法线与光线夹角决定。
diffuse = albedo × lightColor × max(dot(N, L), 0)
正对光源时点积为 1,掠射时趋近 0,背向光源时用 max 截为 0。基础模型常再加一个常量环境项避免暗部全黑,但它不能真实描述间接光。
Albedo 不是“最终颜色”。它表示表面对各颜色通道的基础反射比例,还要与入射光和其他光照项共同作用。
03 / 镜面高光反映表面光滑度
光滑表面会让更多光集中在理想反射方向附近。Phong 模型比较观察方向与反射方向;Blinn-Phong 则比较法线与光线、视线的半程向量。
H = normalize(L + V)
specular = lightColor × pow(max(dot(N, H), 0), shininess)
specular = lightColor × pow(max(dot(N, H), 0), shininess)
shininess 越高,高光越小且集中;越低则更宽。它是经验参数,不直接等同于物理粗糙度。
| 分量 | 主要输入 | 视觉作用 |
|---|---|---|
| 环境项 | 常量颜色 | 粗略填充暗部 |
| 漫反射 | N、L、Albedo | 表现表面朝向 |
| 镜面反射 | N、L、V、光滑度 | 表现高光与材质 |
04 / 光照必须在线性颜色空间计算
常见图像以 sRGB 编码保存,数值经过非线性压缩以适应人眼。直接在这些数值上相加或点乘会得到偏暗、能量不正确的结果。
读取颜色纹理:sRGB → linear
执行光照与混合:linear
写入显示目标:linear → sRGB
执行光照与混合:linear
写入显示目标:linear → sRGB
法线、粗糙度、金属度等数据纹理不是颜色,不应做 sRGB 解码。现代图形 API 通常能通过纹理和渲染目标格式自动完成转换。
距离衰减
点光源的辐照度在理想情况下按距离平方反比衰减。实际项目常对影响半径做平滑截断,以控制性能和艺术效果。
attenuation ∝ 1 / distance²
05 / 从经验模型走向基于物理渲染
PBR 并不是单个公式,而是一组约束:能量守恒、符合微表面统计的高光、菲涅耳效应,以及可跨光照环境复用的材质参数。常见金属度工作流使用基础色、粗糙度和金属度。
- 绝缘体同时具有漫反射和较弱、有色程度低的镜面反射。
- 金属几乎没有传统漫反射,高光会带有金属本身颜色。
- 表面越粗糙,高光分布越宽、峰值越低。
- 掠射角处的镜面反射通常更强,这是菲涅耳效应。
学习顺序:先让 Lambert 与 Blinn-Phong 的向量方向、空间和颜色正确,再进入 PBR;否则更复杂的公式只会掩盖基础错误。