高级 #graphics#lighting#shading
光照与着色模型
着色(Shading)计算每个像素的最终颜色——Phong 模型分解为环境光+漫反射+高光,Blinn-Phong 是更高效的变体。BRDF 描述材质对光的反射特性
💡 一个没有光照的 3D 世界——都是平的
没有光照,所有物体只有本身的颜色——看起来像一个扁平的世界。光照让物体有立体感:朝阳面亮、背阴面暗、高光点反射。
着色(Shading) = 计算每个像素的最终颜色。光照模型告诉你:给定光源、材质和观察角度——这个像素应该是什么颜色。
🔦 Phong 光照模型
Phong 把光照分解为三个独立的部分:
最终颜色 = 环境光 + 漫反射 + 高光(镜面反射)
① 环境光(Ambient)——最基础的均匀照明
没有直接光源时,房间也不是全黑的——光线经过多次反射均匀照亮了物体。
环境光 = Ka × Ia
(Ka:材质的反射系数,Ia:环境光强度)
比如:暗处也有 10% 的底色可见
② 漫反射(Diffuse)——粗糙表面的均匀反射
光线照到粗糙表面——向各个方向均匀反射,从任何角度看都一样亮。
关键:表面越正对光源越亮(兰伯特余弦定律)。
漫反射 = Kd × I × max(0, n·l)
n:表面法线方向
l:指向光源的方向
n·l = cos(θ):法线和光源方向的点积
当表面正对光源时(θ=0°):最亮
当表面和光源平行时(θ=90°):最暗
③ 高光(Specular)——光滑表面的镜面反射
光线照到光滑表面——在反射方向集中反射。从特定角度能看到”亮点”。
高光 = Ks × I × max(0, r·v)^p
r:反射向量
v:视线方向
p:高光指数——越大,高光点越小越亮
(塑料 p≈10,金属 p≈100+)
🆚 Blinn-Phong——更高效的改进
Blinn-Phong 用半程向量 h 代替反射向量 r:
h = (l + v) / |l + v| — 半程向量(l 和 v 的中间方向)
Blinn-Phong 高光 = Ks × I × max(0, n·h)^p'
优势:计算量更小,效果接近——是 OpenGL 固定管线的默认光照模型。
Phong:需算 r(反射向量)
Blinn-Phong:只需算 h(l 和 v 加起来归一化)
🎨 着色频率——从粗糙到精细
| 方式 | 方法 | 效果 | 性能 |
|---|---|---|---|
| Flat Shading | 每三角形一个颜色 | 块状感 | 最快 |
| Gouraud Shading | 每顶点算颜色,像素插值 | 平滑但高光可能丢失 | 快 |
| Phong Shading | 每像素插值法线再算光照 | 最真实 | 最慢 |
Flat:三角形面 {颜色=A的着色结果}
Gouraud:顶点 {颜色A, 颜色B} → 插值到像素
Phong:顶点 {法线A, 法线B} → 插值法线 → 每个像素算光照
📝 小结
| 概念 | 一句话 |
|---|---|
| 环境光 | 均匀背景照明——让暗处可见 |
| 漫反射 | 粗糙表面——正对光源更亮(n·l) |
| 高光 | 光滑表面——特定角度反射亮点(h^n) |
| Blinn-Phong | 半程向量代替反射向量——更高效 |
| Phong Shading | 每像素插值法线算光照——最真实 |
为什么先学这个? 理解了直接光照,接下来看间接光照——阴影与环境光遮蔽。