Show HN: AI 없이 처음부터 직접 작성한 C++ 레이 트레이서 (Ray Tracer)
요약
Luz는 외부 의존성 없이 C++20으로 처음부터 직접 구현한 경로 추적기(Path Tracer)입니다. 몬테카를로 경로 추적, BVH 가속, 적응형 샘플링 등 고성능 렌더링 기능을 지원합니다.
핵심 포인트
- C++20 기반의 제3자 의존성 없는 순수 구현
- 몬테카를로 경로 추적 및 전역 조명 지원
- BVH 가속 및 멀티스레드 CPU 렌더링 제공
- Blender 씬 파일 변환 및 벤치마크 도구 포함
Luz
Luz는 제3자 의존성(third-party dependencies) 없이 처음부터 개발된 C++20 경로 추적기 (Path Tracer)입니다.
이 프로젝트는 몬테카를로 경로 추적 (Monte Carlo path tracing), 전역 조명 (global illumination), BVH 가속 (BVH acceleration), 적응형 샘플링 (adaptive sampling), 디노이징 (denoising), 대기 산란 (atmospheric scattering), 커스텀 씬 파일 (custom scene files), 그리고 Blender-to-Luz 익스포터 (exporter)를 지원합니다.
<img src="./docs/images/bust-statue.jpg" />주요 기능 (Features)
- 몬테카를로 경로 추적 (Monte Carlo path tracing)
- 전역 조명 (Global illumination)
- 멀티스레드 CPU 렌더링 (Multithreaded CPU rendering)
- 적응형 샘플링 (Adaptive sampling)
- 디노이저 (Denoiser) (NFOR 스타일)
- 구 (Spheres), 평면 (planes), 직사각형 (rectangles), 삼각형 (triangles), 정육면체 (cubes), 볼륨 (volumes), 그리고 OBJ 메쉬 (meshes)
- 람베르시안 (Lambertian), 금속 (metal), 유전체 (dielectric), 발광 (emissive), 그리고 등방성 (isotropic) 재질
- 면 (Area), 점 (point), 구 (sphere), 그리고 방향성 조명 (directional lights)
- 커스텀
.luz씬 파일 - .blend to .luz 컨버터
- CLI 또는 씬 파일을 통한 완전한 커스텀 렌더링 파라미터 설정
- PDF를 이용한 중요도 샘플링 (Importance sampling)
- binned SAH 구축 및 near-first 순회 (traversal)를 포함한 packed mesh BVH를 포함한 BVH 가속
- 산란 (scattering)을 포함한 대기 시뮬레이션
- 피사체 심도 (Depth of field), 안티앨리어싱 (antialiasing), 노출 (exposure), 대비 (contrast), 톤 매핑 (tone mapping), 감마 보정 (gamma correction), 그리고 블룸 (bloom)
- BMP 및 TIFF 출력
- 렌더링, 디노이징, 후처리, 그리고 점수 세부 내역을 포함한 결정론적 벤치마크 하네스 (Deterministic benchmark harness)
요구 사항 (Requirements)
- C++20 컴파일러
- Make 또는 CMake 3.16+
- Python 3 (선택적 도구/스크립트용)
빠른 시작 (Quick Start)
Makefile로 빌드하세요:
make
번들된 예제 씬을 렌더링하세요:
./Luz --file examples/scenes/blender_monkey.luz --samples 50 --resolution 300x300
기본 출력은 render.bmp입니다. 씬 파일에서 outputfilename=...을 설정할 수 있으며, CLI에서 일반적인 렌더링 설정을 재정의할 수 있습니다.
테스트 스위트를 실행하세요:
make test
벤치마킹 (Benchmarking)
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
플랫폼 지원 (Platform Support)
지원되는 플랫폼:
- macOS
- Linux
- Windows
macOS 및 Linux에서는 Makefile이 기본 경로입니다. Windows에서는 MSVC와 함께 CMake를 사용하거나, MinGW 기반의 Makefile 타겟을 사용하세요:
make windows
WSL 또한 Linux 빌드 환경으로서 지원됩니다.
빌드 최적화 (Build Optimizations)
Release 빌드는 기본적으로 빌드를 수행하는 머신에 맞춰 조정됩니다. Makefile은 -O3, -march=native를 통한 네이티브 CPU 튜닝(native CPU tuning), 그리고 -flto를 통한 링크 타임 최적화 (Link-Time Optimization, LTO)를 활성화합니다. 또한 컴파일러/플랫폼이 지원하는 경우 빠른 부동 소수점 모드 (fast floating-point mode)를 활성화합니다. CMake 역시 동일한 Release 의도를 사용합니다: -O3, 네이티브 CPU 튜닝, 그리고 지원되는 경우 절차 간 최적화 (Interprocedural Optimization) / LTO를 사용합니다.
이러한 기본 설정은 로컬 렌더링 속도를 높여주지만, -march=native로 빌드된 바이너리는 오래되었거나 다른 CPU에서 실행되지 않을 수 있으며, LTO는 툴체인(toolchain) 특유의 링커 문제를 노출할 수 있습니다. 만약 잘못된 명령(illegal-instruction) 충돌, 링커 오류가 발생하거나 더 이식성 있는(portable) 바이너리가 필요한 경우, 공격적인 옵션들을 비활성화하고 클린 오브젝트(clean objects) 상태에서 다시 빌드하세요:
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 씬(scene) 파일을 로드합니다
...
적응형 샘플링 (Adaptive Sampling)
--adaptive 옵션은 --samples를 픽셀당 최대 샘플 수로 취급합니다. 각 픽셀은 점진적인 픽셀당 샘플 시퀀스 (progressive per-pixel sample sequence)를 사용하며, 최소 --adaptive-min-samples만큼 렌더링한 후, 주기적으로 휘도 (luminance) 및 RGB 신뢰 구간 (confidence intervals)을 확인합니다. 매우 어두운 픽셀은 중단하기 전에 보수적인 최소값을 사용하므로, 드문 빛의 기여 (light contributions)가 수렴된 검은색으로 오인될 가능성이 낮아집니다.
임계값 (thresholds)을 낮게 설정하면 더 많은 디테일을 유지하지만 더 많은 시간이 소요됩니다. 최종 렌더링을 위해서는 높은 최대 샘플 수로 시작하여 다음과 같은 값들로 조정하세요:
./Luz --file exports/stormtroopers.luz --samples 4096 --adaptive --adaptive-min-samples 512 --adaptive-check-interval 64 --adaptive-threshold 0.005 --denoise
디노이징 (Denoising)
--denoise 옵션은 Luz의 NFOR 스타일 피처 버퍼 (feature-buffer) 디노이저 (denoiser)를 활성화하며, 별도의 동반 이미지를 작성합니다. 기본적으로 render.bmp는 render_denoised.bmp가 되며, --denoise-output PATH를 사용하여 정확한 경로를 선택할 수 있습니다.
디노이저는 엄격한 최소 해상도나 샘플 수 제한은 없지만, 유용한 색상 및 피처 통계 (feature statistics)를 추정할 수 있을 만큼 충분한 신호 (signal)가 필요합니다. 픽셀당 1개의 샘플은 주로 스트레스 테스트용입니다. 픽셀당 분산 (variance) 추정이 이루어지지 않기 때문에, 디노이징된 이미지가 거의 변하지 않거나 잘못된 디테일을 뭉갤 수 있습니다. 미리보기를 위해서는 픽셀당 최소 몇 개의 샘플을 사용하고, 디노이저의 품질을 판단할 때는 픽셀당 대략 16개 이상의 샘플을 사용하는 것이 좋습니다. 해상도가 매우 낮으면 각 로컬 필터 윈도우 (local filter window)가 이미지의 너무 많은 부분을 차지하게 되어 평가 결과가 오해를 불러일으킬 수 있습니다.
씬 파일 (Scene Files)
예제 씬 (scenes)은 examples/scenes/에 있으며, 메시 (mesh) 에셋은 assets/objects/에 있습니다. 씬 파일 형식은 docs/scene-files.md에 문서화되어 있습니다.
.luz 파일 내의 오브젝트 경로는 먼저 씬 파일 기준 상대 경로로, 그다음 현재 작업 디렉토리 기준 상대 경로로, 마지막으로 assets/objects/ 하위 경로로 해석됩니다. 이는 examples/scenes/blender_monkey.luz가 ../../assets/objects/blender_monkey.obj를 참조하더라도 저장소 루트에서 정상적으로 실행될 수 있음을 의미합니다.
OBJ 메시 (meshes)는 오프셋 (offset)을 설정하거나 씬 재질 (scene material)을 할당할 수도 있습니다:
obj=mesh.obj,(x,y,z),material[
metal=(0.8,0.8,0.8),0.1
]
Blender 익스포터 (Blender Exporter)
Blender 씬은 Blender의 Python API를 통해 내보낼 수 있습니다:
"/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 메시를 작성합니다. 사용법 및 현재의 충실도 (fidelity) 제한 사항은 docs/blender-exporter.md에 문서화되어 있습니다.
저장소 구조 (Repository Layout)
include/luz/ 공개 헤더 파일(Public headers)
src/core/ 수학, 기하학, 재질, 이미지 및 샘플링 코드
src/renderer/ 렌더링 구현
...
전시 (Showcase)
<img src="./docs/images/stormtroopers.jpg" /> <img src="./docs/images/cornell.jpg" /> <img src="./docs/images/atmosphere-from-space.jpg" />개인적인 메모 (Personal Note)
Ray Tracing in One Weekend 책 시리즈에 특별히 감사드립니다. 이 책은 Luz 개발의 상당 부분, 특히 AI가 존재하기 이전 시기에 큰 영감과 정보의 원천이 되었습니다.
출처 (Attribution)
Stormtrooper Scene: BlendSwap의 @ScottGraham 작품입니다.
Bust Statue: BlendSwap의 @geoffreymarchal 작품입니다.
라이선스 (License)
MIT. LICENSE를 참조하십시오.
AI 자동 생성 콘텐츠
본 콘텐츠는 HN AI Posts의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기