Skip to content

LessUp/ray-tracer

Repository files navigation

CUDA Ray Tracer

License: MIT CUDA C++ CMake

一个纯 CUDA 实现的光线追踪器,支持 Phong 光照和路径追踪。不依赖任何图形 API(OpenGL/Vulkan),完全使用 CUDA 计算光线与物体的交点。

功能特性

  • 几何体: 球体、平面
  • 光照模型: Phong 光照(环境光 + 漫反射 + 镜面反射)
  • 路径追踪: 蒙特卡洛全局光照
  • 加速结构: BVH(层次包围盒)
  • Warp Divergence 优化: 光线排序、BVH 栈式遍历
  • 材质: 漫反射、塑料、金属、镜面
  • 色调映射: Reinhard、ACES
  • 输出: PPM 图像格式

构建要求

  • CUDA Toolkit 11.0+ (推荐 12.0+)
  • CMake 3.18+
  • C++17 编译器 (GCC 9+, Clang 10+, MSVC 2019+)
  • NVIDIA GPU (Compute Capability 7.5+)

快速开始

构建

# 克隆项目
git clone <repository-url>
cd cuda-ray-tracer

# 构建
mkdir build && cd build
cmake ..
make -j$(nproc)

运行

# 基本渲染(Phong 光照)
./bin/ray_tracer

# 高分辨率 + 多采样
./bin/ray_tracer -w 1920 -h 1080 -s 16

# 路径追踪模式
./bin/ray_tracer -p -s 100

# 选择场景
./bin/ray_tracer --scene cornell
./bin/ray_tracer --scene random -p -s 50

# 自定义输出
./bin/ray_tracer -o my_render.ppm

命令行参数

参数 说明 默认值
-w <width> 图像宽度 800
-h <height> 图像高度 600
-s <samples> 每像素采样数 1
-d <depth> 最大光线深度 5
-p 启用路径追踪 关闭
-o <file> 输出文件名 output.ppm
--scene <name> 场景名称 demo
--sort 启用光线排序(仅 Phong + 单采样) 关闭

可用场景

  • demo - 默认演示场景,多个彩色球体和地面
  • cornell - Cornell Box 经典场景
  • random - 随机球体场景(类似 Ray Tracing in One Weekend 封面)

项目结构

cuda-ray-tracer/
├── include/                    # 头文件
│   ├── vec3.cuh               # 3D 向量数学库
│   ├── ray.cuh                # 光线结构
│   ├── camera.cuh             # 相机系统
│   ├── geometry.cuh           # 几何体(球体、平面)
│   ├── hit_record.cuh         # 命中记录
│   ├── material.cuh           # 材质定义
│   ├── texture.cuh            # 纹理支持
│   ├── light.cuh              # 点光源
│   ├── phong.cuh              # Phong 光照模型
│   ├── scene.cuh              # 场景管理和 GPU 内存
│   ├── aabb.cuh               # 轴对齐包围盒
│   ├── bvh.cuh                # BVH 加速结构
│   ├── ray_sort.cuh           # 光线排序(Warp 优化)
│   ├── random.cuh             # GPU 随机数生成
│   ├── kernels.cuh            # CUDA 渲染核心
│   ├── renderer.cuh           # 渲染器封装
│   ├── render_config.cuh      # 渲染配置
│   ├── image.cuh              # 色调映射和图像输出
│   └── cuda_utils.cuh         # CUDA 错误检查宏
├── src/
│   ├── main.cu                # 主程序入口
│   └── scenes.cuh             # 预设场景定义
├── tests/
│   ├── unit/                  # 单元测试 (58 个)
│   │   ├── test_vec3.cu
│   │   ├── test_ray.cu
│   │   ├── test_camera.cu
│   │   ├── test_geometry.cu
│   │   ├── test_material.cu
│   │   ├── test_aabb.cu
│   │   └── test_phong.cu
│   └── property/              # 属性测试 (59 个)
│       ├── test_vec3_props.cu
│       ├── test_ray_props.cu
│       ├── test_geometry_props.cu
│       ├── test_phong_props.cu
│       ├── test_bvh_props.cu
│       ├── test_scene_props.cu
│       ├── test_ray_sort_props.cu
│       ├── test_sampling_props.cu
│       └── test_image_props.cu
├── .kiro/specs/               # 设计规范文档
│   └── cuda-ray-tracer/
│       ├── requirements.md    # 需求文档
│       ├── design.md          # 设计文档
│       └── tasks.md           # 实现任务
├── CMakeLists.txt             # CMake 构建配置
└── README.md                  # 本文档

架构设计

渲染管线

┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  光线生成   │ -> │  BVH 遍历   │ -> │  着色计算   │ -> │  图像输出   │
│  Kernel     │    │  相交测试   │    │  Phong/PT   │    │  色调映射   │
└─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘

核心组件

  1. Camera - 相机系统,支持视场角和宽高比配置
  2. Geometry - 几何体相交测试(球体、平面)
  3. BVH - 层次包围盒加速结构,O(log n) 相交查询
  4. Phong - Blinn-Phong 光照模型
  5. Scene - 场景管理,处理 CPU/GPU 内存传输
  6. Renderer - 渲染器,协调所有组件

内存管理

// 场景构建(CPU 端)
SceneBuilder builder;
builder.add_material(Material::plastic(vec3(1, 0, 0)));
builder.add_sphere(vec3(0, 0, -1), 0.5f, 0);
builder.add_light(vec3(0, 5, 0), vec3(1, 1, 1), 1.0f);

// 构建并传输到 GPU
Scene scene = builder.build();  // 自动分配 GPU 内存

// 渲染完成后释放
free_scene(scene);  // 释放 GPU 内存

技术亮点

1. Warp Divergence 优化

光线追踪中,同一 Warp(32 线程)内的光线可能击中不同物体,导致执行路径分歧。本项目通过以下方式优化:

BVH 加速结构

  • 使用中点分割构建 BVH
  • 栈式遍历避免递归,使用固定大小栈(最大深度 64)
  • 早期剔除:先测试包围盒,再测试几何体

光线排序

  • 按命中物体 ID 排序光线
  • 使相邻线程处理相似光线
  • 当前实现使用奇偶转置排序,便于演示(可替换为 Thrust sort_by_key)
// 光线排序示例
struct RaySortKey {
    int object_id;    // 命中物体 ID
    int pixel_index;  // 原始像素索引
};
// 排序后,相同 object_id 的光线连续存储

2. Phong 光照模型

实现完整的 Blinn-Phong 光照:

// 环境光
vec3 ambient = mat.ambient * mat.albedo * light_color;

// 漫反射(Lambertian)
float diff = max(dot(normal, light_dir), 0.0f);
vec3 diffuse = mat.diffuse * diff * mat.albedo * light_color;

// 镜面反射(Blinn-Phong)
vec3 halfway = normalize(light_dir + view_dir);
float spec = pow(max(dot(normal, halfway), 0.0f), mat.shininess);
vec3 specular = mat.specular * spec * light_color;

3. 路径追踪

蒙特卡洛路径追踪实现全局光照:

  • 俄罗斯轮盘赌终止
  • 余弦加权半球采样
  • 多采样抗锯齿(MSAA)
  • 渐进式渲染

4. 色调映射

支持两种色调映射算法:

// Reinhard 色调映射
vec3 reinhard = color / (color + vec3(1.0f));

// ACES 电影色调映射
vec3 aces = (color * (2.51f * color + 0.03f)) / 
            (color * (2.43f * color + 0.59f) + 0.14f);

测试

项目包含完整的测试套件:

cd build

# 运行单元测试(58 个)
./unit_tests

# 运行属性测试(59 个)
./property_tests

# 运行所有测试
ctest --output-on-failure

属性测试覆盖

属性 描述 验证需求
Property 1 光线生成正确性 1.1, 1.4
Property 2 球体相交点验证 2.1
Property 3 平面相交点验证 2.2
Property 4 法向量方向一致性 2.5
Property 5 Phong 漫反射计算 3.2
Property 6 Phong 镜面反射计算 3.3
Property 7 多光源叠加线性性 3.6
Property 8 路径追踪采样平均 4.5
Property 9 光线排序连续性 5.1
Property 10 BVH 包围盒包含性 5.2, 5.3
Property 11 BVH 相交等价性 5.2
Property 12 色调映射范围约束 6.4
Property 13 场景物体计数一致性 7.2, 7.3
Property 14 向量运算不变量 1.4
Property 15 反射向量对称性 3.3

性能

在 NVIDIA GeForce RTX 3060 Laptop GPU 上的测试结果:

模式 分辨率 采样数 光线数/秒
Phong 800x600 1 ~1200 M
Phong 640x480 8 ~2900 M
Path Tracing 640x480 16 ~295 M

性能优化建议

  1. 增加采样数 - 路径追踪需要更多采样减少噪点
  2. 调整光线深度 - 深度越大,间接光照越准确,但更慢
  3. 使用 BVH - 场景物体越多,BVH 加速效果越明显
  4. 批量渲染 - 高分辨率时,GPU 利用率更高

API 参考

vec3 - 向量数学

vec3 v(1.0f, 2.0f, 3.0f);
float len = v.length();
vec3 n = v.normalized();
float d = dot(v1, v2);
vec3 c = cross(v1, v2);
vec3 r = reflect(incident, normal);

Camera - 相机

Camera camera;
camera.setup(
    vec3(0, 1, 3),    // lookfrom
    vec3(0, 0, 0),    // lookat
    vec3(0, 1, 0),    // vup
    60.0f,            // vfov (度)
    16.0f / 9.0f      // aspect_ratio
);
Ray ray = camera.get_ray(u, v);  // u, v ∈ [0, 1]

Material - 材质

// 预设材质
Material mat = Material::matte(vec3(0.8f, 0.2f, 0.2f));
Material mat = Material::plastic(vec3(0.2f, 0.8f, 0.2f));
Material mat = Material::metal(vec3(0.8f, 0.8f, 0.8f));
Material mat = Material::mirror();

// 自定义材质
Material mat(
    albedo,      // 基础颜色
    ambient,     // 环境光系数
    diffuse,     // 漫反射系数
    specular,    // 镜面反射系数
    shininess,   // 光泽度
    reflectivity // 反射率
);

SceneBuilder - 场景构建

SceneBuilder builder;

// 添加材质(返回材质 ID)
int mat_id = builder.add_material(Material::plastic(vec3(1, 0, 0)));

// 添加几何体
builder.add_sphere(center, radius, mat_id);
builder.add_plane(normal, distance, mat_id);

// 添加光源
builder.add_light(position, color, intensity);

// 构建场景(传输到 GPU)
Scene scene = builder.build();

// 清理
free_scene(scene);

扩展开发

添加新几何体

  1. geometry.cuh 中定义结构和相交函数
  2. aabb.cuh 中添加包围盒计算
  3. bvh.cuh 中更新 BVH 构建
  4. scene.cuh 中添加场景支持
  5. 添加对应的测试

添加新材质类型

  1. material.cuh 中扩展 Material 结构
  2. phong.cuh 中更新着色计算
  3. kernels.cuh 中更新渲染核心

参考资料

License

MIT License

致谢

本项目参考了 Peter Shirley 的 "Ray Tracing in One Weekend" 系列教程,并使用 CUDA 进行了 GPU 加速实现。

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published