Show HN: 从零编写C++光线追踪器,无AI依赖

Hacker News Top 工具

摘要

一位开发者从零构建了Luz,这是一个零依赖的C++20路径追踪器,具备蒙特卡洛路径追踪、全局光照、BVH加速以及Blender到Luz导出器功能。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/06/15 11:57

themartiano/luz 源码: https://github.com/themartiano/luz

Luz

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

特性

  • 蒙特卡洛路径追踪
  • 全局光照
  • 多线程 CPU 渲染
  • 自适应采样
  • 降噪器(NFOR 风格)
  • 球体、平面、矩形、三角形、立方体、体积以及 OBJ 网格
  • 朗伯、金属、电介质、自发光和各向同性材质
  • 面光源、点光源、球面光源和定向光
  • 自定义 .luz 场景文件
  • .blend 到 .luz 的转换器
  • 通过 CLI 或场景文件完全自定义渲染参数
  • 基于 PDF 的重要性采样
  • BVH 加速,包括带分箱 SAH 构建和近邻优先遍历的打包网格 BVH
  • 带散射的大气模拟
  • 景深、抗锯齿、曝光、对比度、色调映射、伽马校正和泛光
  • BMP 和 TIFF 输出
  • 确定性基准测试框架,包含渲染、降噪、后期处理和分数分解

要求

  • C++20 编译器
  • Make 或 CMake 3.16+
  • Python 3(仅用于可选工具/脚本)

快速开始

使用 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
  • Windows

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

make windows

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

构建优化

默认情况下,Release 构建会根据构建机器进行调优。Makefile 启用 -O3-march=native(原生 CPU 调优)以及 -flto(链接时优化)。在编译器/平台支持的情况下,还会启用快速浮点模式。

CMake 使用相同的 Release 意图:-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

Usage: ./Luz [options]
  -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 文件中的对象路径首先相对于场景文件解析,然后相对于当前工作目录,最后在 assets/objects/ 下查找。这意味着 examples/scenes/blender_monkey.luz 可以引用 ../../assets/objects/blender_monkey.obj,并且仍然可以从仓库根目录运行。

OBJ 网格也可以进行偏移并分配场景材质:

obj=mesh.obj,(x,y,z),material[ metal=(0.8,0.8,0.8),0.1 ]

Blender 导出器

可以通过 Blender 的 Python API 导出 Blender 场景:

"/Applications/Blender.app/Contents/MacOS/Blender" -b scene.blend --python tools/blender_export_luz.py -- --output exports/scene.luz
./Luz --file exports/scene.luz --threads 8

导出器会写入一个 .luz 文件以及 OBJ 网格。用法和当前的保真度限制在 docs/blender-exporter.md 中有文档说明。

仓库布局

include/luz/            公共头文件
src/core/              数学、几何、材质、图像和采样代码
src/renderer/          渲染实现
src/scene/             场景模型和场景辅助
src/io/                场景文件、OBJ、BMP 和 TIFF 加载/写入
src/cli/               命令行入口和标志
examples/scenes/       示例 .luz 场景文件
assets/objects/        示例使用的 OBJ 资产
docs/images/           压缩的展示图片
tools/                 导出和实用脚本
tests/                 仅使用标准库的测试程序
docker/                基准测试容器

展示

个人说明

特别感谢《Ray Tracing in One Weekend》(https://github.com/RayTracing/raytracing.github.io)系列书籍。在 Luz 的很大一部分开发过程中,它(尤其是在 AI 时代之前)是灵感和信息的重要来源。

署名

Stormtrooper 场景由 BlendSwap 上的 @ScottGraham (https://blendswap.com/profile/120125) 提供(https://blendswap.com/blend/13953)。

Bust Statue 由 BlendSwap 上的 @geoffreymarchal (https://blendswap.com/profile/180520) 提供(https://blendswap.com/blend/21704)。

许可

MIT。参见 LICENSE

相似文章

基于SQL的光线追踪器

Hacker News Top

完全使用ClickHouse SQL查询实现的光线追踪器,无需任何外部代码或UDF即可将图像渲染为PNG格式。演示了程序化地形、CSG几何体以及并行像素计算。

用500行纯C++实现软件渲染

Hacker News Top

一个教程系列,通过用500行C++从零构建软件渲染器(无需外部库),演示OpenGL、Vulkan、Metal和DirectX的工作原理。

用500行纯C++实现软件渲染

Lobsters Hottest

本教程系列教你如何用500行C++从头编写一个软件渲染器,并解释现代3D图形API的内部工作原理。

使用四面体笼对大量动画几何体进行光线追踪

Hacker News Top

本文介绍了一种通过使用四面体笼将动画与三角形数量解耦,从而对大量动画三角形进行光线追踪的技术,使得在消费级GPU上以60 FPS处理包含数亿个动画三角形的场景成为可能。