Half-Lambert
2 / 17
在简单球体上学习光照项(漫反射/高光/边缘光)。
让背光面也保留一定亮度,核心就是这一行:
下面拆解它。
标准 Lambert 的问题
标准 Lambert 漫反射用 max(dot(n,l), 0.0),背光面直接截断为 0,整片漆黑。在游戏和卡通渲染里,这个效果看起来太死,背光区域失去所有细节。
Half-Lambert 怎么改
把 dot(n, l) 的范围从 [-1, 1] 压缩到 [0, 1]:
效果:
- 正对光(dot = 1.0) → 1.0 × 0.5 + 0.5 = 1.0(100%,最亮)
- 垂直光(dot = 0.0) → 0.0 × 0.5 + 0.5 = 0.5(50%,中等)
- 背对光(dot = -1.0) → -1.0 × 0.5 + 0.5 = 0.0(0%,最暗)
相比标准 Lambert,暗部不再完全黑,背面仍然可见,立体感更柔和。这个技巧最早来自《半条命》的美术团队,因此得名 Half-Lambert。
试着改一改
| 改动 | 效果 |
|---|---|
* 0.5 + 0.5 改为 * 0.4 + 0.6 | 暗部更亮,对比更低 |
* 0.5 + 0.5 改为 * 0.8 + 0.2 | 更接近标准 Lambert,暗部保留少量亮度 |
在外面套 pow(diff, 2.0) | 拉高对比度,只有正对光的区域很亮 |
练习
当前练习区 diff = 0.0,球体全黑,修改 TODO 行,用 Half-Lambert 公式计算出正确的漫反射亮度。
答案解析
初始状态:diff 固定为 0.0,球体一片黑。
改动:去掉 max,直接用 dot(n, l) * 0.5 + 0.5,把整个 [-1, 1] 范围都映射到 [0, 1],背光面也能保留亮度。
试着把系数从 0.5 + 0.5 改成 0.6 + 0.4,看看暗部会不会更亮。