← 返回日报
🌐 机器翻译 · DeepSeek · HN

Show HN: I wrote a C++ ray tracer from scratch without AI


Show HN:我从零开始用 C++ 写了一个光线追踪器,没有借助 AI

Luz 是一个完全从零开发的 C++20 路径追踪器,没有任何第三方依赖。它支持蒙特卡洛路径追踪、全局光照、BVH 加速、自适应采样、降噪、大气散射、自定义场景文件,以及一个 Blender 到 Luz 的导出器。

luz-render-vs-clay-model.mp4

特性

使用 Makefile 构建:

make

渲染一个内置示例场景:

./Luz --file examples/scenes/blender_monkey.luz --samples 50 --resolution 300x300

默认输出为 render.bmp。场景文件可以设置 outputfilename=...,CLI 可以覆盖常见的渲染设置。

运行测试套件:

make test

基准测试

Luz 包含用于渲染、降噪、后处理和整体分数比较的确定性基准测试。

make benchmark BENCH_CPUS=1 BENCH_THREADS=1 > before.csv
make benchmark BENCH_CPUS=1 BENCH_THREADS=1 > after.csv
make benchmark-compare BEFORE=before.csv AFTER=after.csv

详情请参见 docs/benchmarks.md

CMake

也可以使用 CMake 构建:

cmake -S . -B build
cmake --build build
ctest --test-dir build

平台支持

支持的平台:

在 macOS 和 Linux 上,Makefile 是主要构建方式。在 Windows 上,使用 CMake 配合 MSVC,或基于 MinGW 的 Makefile 目标:

make windows

WSL 也支持作为 Linux 构建环境。

构建优化

发布版本默认针对构建机器进行调优。Makefile 启用了 -O3、通过 -march=native 进行原生 CPU 调优,以及通过 -flto 进行链接时优化。在编译器/平台支持的情况下,还会启用快速浮点模式。CMake 使用相同的发布意图:-O3、原生 CPU 调优,以及在支持时启用过程间优化/LTO。

这些默认设置可以产生更快的本地渲染,但使用 -march=native 构建的二进制文件可能无法在较旧或不同的 CPU 上运行,并且 LTO 可能暴露特定工具链的链接器问题。如果遇到非法指令崩溃、链接器错误,或者需要更可移植的二进制文件,请禁用这些激进选项并从干净的构建对象重新构建:

make clean
make NATIVE=0 LTO=0

对于 CMake 构建,关闭优化开关进行配置:

cmake -S . -B build -DLUZ_NATIVE_OPTIMIZATIONS=OFF -DLUZ_ENABLE_LTO=OFF
cmake --build build --clean-first

CLI 用法

用法: ./Luz [选项]
-f, --file PATH                  加载 .luz 场景文件
-r, --resolution WxH             覆盖渲染分辨率
-s, --samples N                  覆盖每像素采样数
--adaptive [true|false]          启用自适应逐像素采样
--no-adaptive                    禁用自适应采样
--adaptive-min-samples N         自适应停止前的最小采样数
--adaptive-threshold F           自适应相对噪声阈值
--adaptive-check-interval N      自适应收敛检查间隔
-mlb, --maxLightBounces N        覆盖最大光线弹射次数
--max-light-bounces N            --maxLightBounces 的别名
-t, --threads N                  使用 N 个工作线程渲染
--seed N                         随机采样种子
--gamma true|false               切换伽马校正
-tm, --tonemapping true|false    切换色调映射
--bloom true|false               切换泛光
--exposure EV                    曝光补偿(以档为单位)
--contrast F                     显示对比度乘数
--denoise [true|false]           写入降噪后的配套渲染
--no-denoise                     禁用降噪
-o, --output PATH                覆盖渲染输出路径
--denoise-output PATH            覆盖降噪输出路径
--render-times                   写入 renderTime.bmp
--benchmark                      运行内置基准测试场景
--benchmark-case NAME            基准测试用例:default, many-objects, mesh-bvh, diffuse, postprocess, atmosphere, lights, emissive-geometry, primitives-materials, volumes, obj-mesh

自适应采样

--adaptive--samples 视为每像素的最大采样数。每个像素使用渐进式逐像素采样序列,至少渲染 --adaptive-min-samples 次,然后定期检查亮度和 RGB 置信区间。非常暗的像素在停止前会使用一个保守的最小值,这样罕见的光线贡献就不太可能被误认为是收敛的黑色。较低的阈值会保留更多细节,但需要更多时间。

对于最终渲染,从较高的最大采样数开始,并使用类似以下的值进行调优:

./Luz --file exports/stormtroopers.luz --samples 4096 --adaptive --adaptive-min-samples 512 --adaptive-check-interval 64 --adaptive-threshold 0.005 --denoise

降噪

--denoise 启用 Luz 的 NFOR 风格特征缓冲区降噪器,并写入一个单独的配套图像。默认情况下,render.bmp 会变成 render_denoised.bmp;使用 --denoise-output PATH 可以指定确切路径。

降噪器没有硬性的最低分辨率或采样数要求,但它需要足够的信号来估计有用的颜色和特征统计信息。每像素一个采样主要是一种压力测试:由于没有逐像素方差估计,降噪后的图像可能几乎不变,或者可能平滑掉错误的细节。预览时至少使用每像素几个采样,评估降噪器质量时最好使用大约 16 个或更多采样。非常低的分辨率也会使评估产生误导,因为每个局部滤波窗口覆盖了图像中过多的区域。

场景文件

示例场景位于 examples/scenes/。网格资源位于 assets/objects/。场景文件格式在 docs/scene-files.md 中有文档说明。.luz 文件中的对象路径相对于场景文件所在目录进行解析。

📖 阅读原文 →