外观
光照模型
光照模型是 3D 图形学中模拟光线与物体表面交互的数学方法,它决定了物体在场景中的视觉外观。在 Web 3D 开发中,合理的光照模型能够显著增强场景的真实感和沉浸感,是创建逼真视觉效果的关键技术。
光照模型基础
光照模型描述了光线如何与材质表面相互作用,包括吸收、反射和透射等物理现象。计算机图形学中的光照模型是对真实光照的近似,平衡计算成本和视觉效果。
特点:
- 基于物理的简化模型,而非完全物理准确
- 分离光照计算与材质属性
- 支持实时渲染的性能要求
示意图 (光线与表面交互):
入射光线 → 表面 → 反射光线 + 吸收 + 透射
↓ ↓ ↓
方向 材质属性 方向/强度局部光照与全局光照
光照模型分为局部光照和全局光照两大类。局部光照只考虑直接光照,全局光照还包含间接光照和光线反弹效果。
特点:
- 局部光照:计算简单,适合实时渲染
- 全局光照:效果真实,计算成本高
- Web 3D 主要使用局部光照模型
示意图对比:
局部光照: 全局光照:
光源 → 表面 → 眼睛 光源 → 表面A → 表面B → 眼睛
↓
间接光照环境光照
环境光照模拟场景中的间接光照,为物体提供基础亮度。这是最简单的光照分量,不考虑光线方向。
特点:
- 恒定照明,无方向性
- 防止完全黑暗的区域
- 通常与场景环境贴图结合
环境光计算公式:
颜色 = 材质环境色 × 环境光强度示意图 (环境光效果):
无环境光: 有环境光:
[暗部全黑] [暗部可见]
/ \ / \
| 暗面 | | 灰色面 |
\ / \ /漫反射光照
漫反射模拟光线在粗糙表面的均匀散射,遵循 Lambert 余弦定律。反射强度与表面法线和光线方向的夹角余弦成正比。
特点:
- 方向敏感,与观察角度无关
- 产生柔和的明暗过渡
- 使用点积计算光照强度
Lambert 定律示意图:
表面法线 光线方向
↑ ↗
| /
| /
| /
| θ /
表面-------
强度 ∝ cos(θ) = 点积(法线, 光线)漫反射计算公式:
强度 = max(点积(法线, 光线方向), 0)
颜色 = 材质漫反射色 × 光颜色 × 强度镜面反射光照
镜面反射模拟光线在光滑表面的集中反射,产生高光效果。常见模型包括 Phong 和 Blinn-Phong 模型。
特点:
- 观察角度敏感
- 产生明亮的高光点
- 受表面光滑度影响
镜面反射示意图:
光线方向 视线方向
↗ ↘
\ /
\ /
\ /
\ /
表面
反射方向 = 反射(光线方向, 法线)Phong 镜面模型
Phong 模型通过反射方向与视线方向的点积计算高光,再通过指数控制高光集中度。
特点:
- 直观的物理意义
- 计算反射方向向量
- 高光指数控制光泽度
Phong 计算公式:
反射方向 = 反射(-光线方向, 法线)
高光强度 = max(点积(反射方向, 视线方向), 0)^光泽度Blinn-Phong 模型
Blinn-Phong 使用半角向量替代反射向量,计算更高效且高光更自然,是现代图形 API 的默认模型。
特点:
- 计算成本低于 Phong 模型
- 高光过渡更平滑
- 广泛用于实时渲染
半角向量示意图:
光线方向 视线方向
↗ ↘
\ /
\ /
\ /
\ /
H (半角向量)
法线 → ↑Blinn-Phong 计算公式:
半角向量 = 归一化(光线方向 + 视线方向)
高光强度 = max(点积(法线, 半角向量), 0)^光泽度完整光照方程
将各光照分量组合得到完整的光照模型,通常采用环境光、漫反射和镜面反射的加和模型。
完整 Phong 光照模型:
最终颜色 = 环境光 + 漫反射 + 镜面反射
= 材质环境 × 光环境
+ 材质漫反射 × 光颜色 × max(点积(法线, 光线), 0)
+ 材质镜面 × 光颜色 × max(点积(反射方向, 视线), 0)^光泽度各分量效果示意图:
环境光: 漫反射: 镜面反射: 组合效果:
均匀灰色 方向明暗 高光亮斑 完整光照
[ ] [亮/暗] [ 亮斑 ] [真实感]
/ \ / \ / \ / \
| 灰 | | 渐变 | | 亮点 | | 综合 |
\ / \ / \ / \ /光源类型
不同类型的光源影响光照计算的方式,Web 3D 中常见的光源包括定向光、点光源和聚光灯。
定向光
定向光模拟无限远处的光源 (如太阳),所有光线平行且强度不变。
特点:
- 方向恒定,无位置概念
- 计算简单高效
- 适合室外场景
示意图 (定向光):
平行光线:
↓↓↓↓↓
↓↓↓↓↓ → 表面
↓↓↓↓↓
方向一致点光源
点光源从特定位置向所有方向发射光线,强度随距离衰减。
特点:
- 有明确位置
- 强度随距离衰减
- 适合灯泡、蜡烛等效果
示意图 (点光源):
光源
●
/|\
/ | \ 光线辐射
/ | \点光源衰减公式:
衰减 = 1.0 / (常数 + 线性×距离 + 二次×距离²)聚光灯
聚光灯发射锥形光线,具有位置、方向和锥角限制。
特点:
- 锥形照明区域
- 内外锥角控制边缘软化
- 适合手电筒、车灯效果
示意图 (聚光灯):
光源
●
/|\
/ | \ 照明锥体
/ | \
---θ--- 锥角聚光灯强度计算:
角度 = 点积(光线方向, 聚光方向)
强度 = (角度 - 外锥角) / (内锥角 - 外锥角)
强度 = clamp(强度, 0, 1)法线向量处理
法线向量在光照计算中至关重要,但需要正确处理变换和插值才能获得准确结果。
特点:
- 必须使用模型矩阵的逆转置矩阵变换
- 片段着色器中需要重新归一化
- 支持法线贴图增强细节
法线变换示意图:
顶点法线 → 模型矩阵逆转置 → 世界空间法线
↓ ↓ ↓
局部空间 特殊变换 光照计算法线贴图效果:
无法线贴图: 有法线贴图:
平滑表面 细节凹凸
[ ] [ /\/\ ]
/ \ / \
| 平 | | 凹凸 |
\ / \ /着色频率
着色频率决定光照计算的粒度,影响视觉效果和性能。主要分为逐顶点着色和逐片段着色。
逐顶点着色
在顶点着色器中计算光照,结果在三角形内插值。
特点:
- 计算量小,性能高
- 细节不足,出现马赫带
- 适合简单场景或低性能设备
示意图 (逐顶点着色):
顶点计算光照 → 插值颜色 → 片段输出
v0(红) 渐变 像素
/ \ 红---绿
v1(绿)-v2(蓝) \ /
蓝逐片段着色
在片段着色器中为每个像素计算光照。
特点:
- 视觉效果平滑准确
- 计算量较大
- 现代渲染的标准做法
示意图 (逐片段着色):
顶点传递数据 → 逐像素计算 → 精确光照
法线、位置 每个像素 平滑过渡WebGL 中的光照实现
在 WebGL 中实现光照需要精心设计着色器和 JavaScript 代码,合理管理光源参数和材质属性。
顶点着色器示例:
glsl
attribute vec3 position;
attribute vec3 normal;
uniform mat4 modelViewProjection;
uniform mat4 modelMatrix;
uniform mat3 normalMatrix;
varying vec3 vNormal;
varying vec3 vPosition;
void main() {
gl_Position = modelViewProjection * vec4(position, 1.0);
vNormal = normalMatrix * normal;
vPosition = vec3(modelMatrix * vec4(position, 1.0));
}片段着色器示例:
glsl
varying vec3 vNormal;
varying vec3 vPosition;
uniform vec3 lightPosition;
uniform vec3 lightColor;
uniform vec3 ambientColor;
uniform vec3 diffuseColor;
uniform vec3 specularColor;
uniform float shininess;
void main() {
// 向量计算
vec3 normal = normalize(vNormal);
vec3 lightDir = normalize(lightPosition - vPosition);
vec3 viewDir = normalize(-vPosition);
vec3 reflectDir = reflect(-lightDir, normal);
// 环境光
vec3 ambient = ambientColor * diffuseColor;
// 漫反射
float diff = max(dot(normal, lightDir), 0.0);
vec3 diffuse = lightColor * diff * diffuseColor;
// 镜面反射 (Blinn-Phong)
vec3 halfwayDir = normalize(lightDir + viewDir);
float spec = pow(max(dot(normal, halfwayDir), 0.0), shininess);
vec3 specular = lightColor * spec * specularColor;
gl_FragColor = vec4(ambient + diffuse + specular, 1.0);
}性能优化策略
光照计算是渲染管线中的性能瓶颈之一,需要采用合适的优化策略。
特点:
- 减少光照计算复杂度
- 使用光照贴图预计算静态光照
- 限制动态光源数量
优化技术对比:
完整逐像素光照 → 简化光照模型 → 光照贴图 + 球谐光照
高质量 平衡质量性能 高性能静态场景
↓ ↓ ↓
计算密集 实时友好 预计算为主