每日编程实践:递归光线追踪 - 镜面反射
递归光线追踪 - 镜面反射
日期: 2026-02-18
开发时间: 约15分钟
迭代次数: 2次
技术: 递归光线追踪、镜面反射、Phong光照、阴影
项目目标
在之前的 Shadow Ray Tracing 基础上,实现递归光线追踪算法,支持镜面反射效果。通过不同的材质反射率,实现从完全漫反射到高度镜面的多样化材质表现。
核心算法
1. 递归光线追踪
1 | Vec3 trace(const Ray& ray, const Scene& scene, int depth) { |
关键技术点:
- 递归深度限制:防止无限递归(本项目最大深度5)
- 反射光线偏移:
hit_point + normal * 1e-4防止浮点误差自相交 - 能量守恒混合:
(1-r)部分漫反射 +r部分反射
2. 镜面反射向量
反射公式:R = V - 2(V·N)N
1 | Vec3 reflect(const Vec3& normal) const { |
3. 材质系统
1 | struct Material { |
场景材质配置:
- 中心银球:
reflectivity = 0.8,diffuse = 0.4(高反射 + 适量漫反射,避免纯黑) - 左侧红球:
reflectivity = 0.4(半透半反) - 右侧蓝球:
reflectivity = 0.2(轻微反射) - 地面:
reflectivity = 0.0(纯漫反射) - 顶部金球:
reflectivity = 0.6(较强反射)
光照配置:
- 主光源:
intensity = 1.5(右上方,白光) - 副光源:
intensity = 1.0(左上方,微蓝光) - 环境光:
ambient = 0.2(全局基础亮度)
开发过程
迭代历史
| 版本 | 问题 | 解决方案 |
|---|---|---|
| v1 | 编译错误:Vec3 * Vec3 未定义 |
添加逐分量乘法运算符 |
| v2 | ✅ 编译通过,运行成功 | 无需修改 |
| v3 | 中心银球过暗 | 增加 diffuse (0.1→0.3), 降低 reflectivity (0.8→0.7) |
| v4 | 中心球仍然偏暗 | 尝试纯镜面反射 (reflectivity=1.0, diffuse=0.0) |
| v5 | ❌ 中心球变成纯黑 | 回滚:保留适量漫反射 (diffuse=0.4, reflectivity=0.8) + 增强光源 |
| v6 | ❌ 中心球仍然是黑的! | 修复致命Bug:反射向量计算错误 |
迭代次数: 6次
开发时间: 约45分钟(含多次Bug修复)
v1错误原因: 颜色混合需要向量逐分量相乘,但只定义了标量乘法
v3问题原因: 过低的漫反射系数 (0.1) + 过高的反射率 (0.8) → 直接光照太弱 → 球体过暗
v4致命错误: diffuse=0.0 → 无直接光照 → 当递归深度用尽时 reflected_color = (0,0,0) → 纯黑球
v5以为修复了:增加 diffuse=0.4 + 增强光照,但球体仍然是黑的
v6根本原因: 反射向量计算错误 - 用了 (-ray.direction).reflect(normal) 导致反射方向完全错误!
v1修复方法:
1 | Vec3 operator*(const Vec3& v) const { |
v3修复方法: 调整材质参数平衡
1 | // 修改前: Material(Vec3(0.9, 0.9, 0.9), 0.1, 0.9, 0.8) |
v6致命Bug修复: 反射向量计算错误
1 | // ❌ 错误代码 (v1-v5都有这个Bug): |
效果展示

可观察到的效果:
- ✅ 中心银球高反射率镜面效果(清晰反射周围物体)
- ✅ 球体亮度正常(diffuse=0.4 提供基础亮度)
- ✅ 红球、蓝球、金球和地面在银球表面形成清晰倒影
- ✅ 不同反射率材质对比明显
- ✅ 阴影与反射正确交互
技术进步
相比之前的 Shadow Ray Tracing 项目:
| 特性 | 之前 | 现在 |
|---|---|---|
| 递归追踪 | ❌ | ✅ |
| 镜面反射 | ❌ | ✅ |
| 材质系统 | 单一 | 多样化反射率 |
| 颜色混合 | 基础 | 向量逐分量运算 |
完整光照模型:
1 | ✅ 环境光 (Ambient) |
学习收获
- 递归算法的应用 - 光线反射是经典的递归问题,理解了递归深度控制的重要性
- 能量守恒原理 - 反射率决定了直接光照与反射光照的权重分配
- 数值稳定性技巧 - 偏移量
1e-4防止自相交,这是图形学中常见的数值技巧 - 性能权衡 - 递归深度对渲染质量和速度有直接影响
下一步计划
- 折射效果 - 实现透明材质(玻璃球)
- 抗锯齿 - 多重采样提升图像质量
- 软阴影 - 面光源代替点光源
- BVH加速 - 优化光线求交性能
代码仓库
GitHub: daily-coding-practice/2026/02/18-recursive-raytracing-reflection
项目状态: ✅ 完成
输出: 800×600 PNG图像
渲染时间: 约2秒
代码行数: 324行 C++
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Chiuhou 技术博客!










