本项目由 DeepSeek V4 Flash 编写
一个使用 Rust + Vulkan (ash) 编写的实时 3D 光线追踪演示程序。它渲染经典场景:黑色虚空中心悬浮着一颗玻璃球,玻璃球下方是大型棋盘格地板,由左侧的红色点光源和右侧的绿色点光源照亮。地板具有镜面反射效果,左半部分带暖色调(橙/红),右半部分为亮绿色;玻璃球投下柔和的椭圆形阴影,并呈现红/绿高光。
- 硬件光线追踪(可用时):
VK_KHR_acceleration_structure+VK_KHR_ray_tracing_pipeline,包含底层/顶层加速结构以及着色器绑定表(raygen / miss / shadow-miss / closest-hit / shadow-hit 组)。 - 光栅化回退(在不支持光线追踪的设备上):同一场景在片元着色器中按像素解析式追踪(显式光线栈、玻璃折射、镜面地板、面光源柔和阴影)——演示程序始终可运行。
- 递归反射/折射,采用 Schlick Fresnel、IOR 1.5 玻璃、玻璃内部吸收、面光源柔和阴影、棋盘格随距离淡入黑色虚空、Reinhard 风格色调映射和伽马校正。
- 完整的 Vulkan 管道:实例、物理/逻辑设备、队列、支持大小调整的交换链、命令缓冲区、栅栏/信号量、描述符、管线、缓冲区、图像、验证层(存在时自动启用)。
- Rust(MSVC 工具链):https://rustup.rs —
rustup default stable-msvc - Vulkan SDK(可选但推荐):https://vulkan.lunarg.com/sdk/home
- SDK 在
Bin/中附带glslangValidator.exe(由build.rs在构建时用于将 GLSL 着色器编译为 SPIR-V)。 - 如果未安装 SDK,
build.rs会回退使用shaders/spv/中的预编译 SPIR-V 二进制文件,因此项目仍可构建——Vulkan 运行时本身随现代 GPU 驱动一起提供。
- SDK 在
- GPU + 驱动:任何 Vulkan 1.1+ 驱动均可运行回退路径。 硬件光线追踪可在 NVIDIA(RTX 20 系列及更新,或使用较新驱动的 GTX 16 系列)、AMD(Radeon RX 6000+ / 7000)、Intel(Arc)上运行——演示程序会自动检测支持情况并选择最佳路径。
cargo run --release控制:
| 输入 | 动作 |
|---|---|
Esc |
退出 |
W/A/S/D |
移动相机(前进/后退/平移) |
Q/E |
相机下移/上移 |
| 鼠标拖动 | 围绕玻璃球环绕相机 |
| 鼠标滚轮 | 推近/拉远 |
R |
重置相机 |
窗口标题:classic_raytrace — red light / green light / center object。
窗口可流畅调整大小(交换链 + 存储图像会重新创建)。
可选环境变量:
CLASSIC_RT_FORCE_FALLBACK=1— 强制使用光栅化路径(用于比较两种渲染器,或在支持 RT 的硬件上进行调试)。CLASSIC_RT_GLSLANG=/path/to/glslangValidator— 覆盖着色器编译器。
build.rs 在构建时运行,并对 shaders/ 中的每个着色器执行以下操作:
- 定位
glslangValidator:CLASSIC_RT_GLSLANG(显式路径),%VULKAN_SDK%\Bin\glslangValidator.exe(Windows SDK 安装),PATH上的glslangValidator。
- 使用
glslangValidator -V --target-env vulkan1.2 -o out.spv src.glsl将每个 GLSL 源码编译到target/.../out/shaders/*.spv。 - 如果不存在 glslangValidator,则改为复制
shaders/spv/中的预编译二进制文件,因此该 crate 始终可构建。
Rust 代码使用 include_bytes!(src/shaders.rs)嵌入 SPIR-V,并在启动时据此创建 vk::ShaderModule。
GLSL 源码使用标准阶段扩展,因此任何支持 GL_EXT_ray_tracing 的 GLSL 编译器都会产生相同的结果:
rt_raygen.rgen(raygen)、rt_miss.rmiss / rt_shadow_miss.rmiss(miss)、
rt_closest_hit.rchit(材质)、rt_shadow_hit.rchit(无操作 shadow hit)、
fallback.vert / fallback.frag(光栅化回退)。
Cargo.toml 依赖(ash、winit、glam、bytemuck、anyhow)
build.rs GLSL -> SPIR-V 编译(或预编译回退)
shaders/ GLSL 源码(.rgen/.rmiss/.rchit/.vert/.frag)
shaders/spv/ 预编译 SPIR-V(无 glslangValidator 时使用)
src/main.rs 入口点 + winit 事件循环
src/app.rs 窗口/输入/App 状态、大小调整处理、清理
src/context.rs Vulkan 实例、设备、交换链、渲染通道、内存
src/renderer.rs 场景、BLAS/TLAS、SBT、管线、描述符、帧
src/camera.rs 环绕相机(WASD + 鼠标)
src/geometry.rs 程序化 UV 球体 / 地板四边形顶点
src/shaders.rs 内嵌 SPIR-V + u32 字转换
- 玻璃球:中心
(0, 1, 0),半径1.0,IOR1.5,Fresnel F0 0.04,在穿过玻璃时发生吸收。 - 地板:
y = 0,棋盘格单元为 1 单位,左侧为暖色调,右侧为亮绿色(在x = 0处柔和混合),镜面反射系数 0.55,距离淡出范围为 45–130 单位,融入黑色虚空。 - 红光:位置
(-3.2, 2.4, -1.8),半径 0.18,颜色(1, 0.06, 0.05),强度 42。绿光在(+3.2, 2.4, -1.8)处镜像对称。 - 两个光源同时也是场景中的小型自发光球体,因此它们会出现在反射中,并在玻璃球上产生镜面高光。
- 柔和阴影:每条阴影光线会分裂为 3–4 条光线,指向光源正面上的一个圆盘(面光源采样,逐像素哈希种子)。该圆盘与光源球体相切,因此阴影光线永远不会击中光源本身——任何驱动上都无需特殊情况剔除。
- 材质通过几何位置(球体表面 / 地板平面 / 光源球体)而非
gl_InstanceCustomIndexEXT来选择,这使得即使在不传播实例数据的驱动(例如软件光栅化器)上,渲染器也能保持正确。
- 找不到
vulkan-1.dll— 安装 Vulkan 运行时(现代 GPU 驱动已包含)或完整的 LunarG SDK。 - 出现黑色窗口并带有回退提示 — GPU 不支持光线追踪;演示程序有意回退到片元着色器路径。
- 退出时出现验证错误 — 请安装 Vulkan SDK 运行;消息会打印到 stderr 并可上报。
- 一切都能编译但什么都不渲染 — 检查 stderr 输出中的
[vulkan ...]消息以及驱动更新。