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,看看暗部会不会更亮。

GLSL 代码编辑器

正确代码预览

当前代码预览