Skip to content

Architecture Overview

This project intentionally uses a small architecture: one executable, a short rendering pipeline, explicit data ownership, and no workflow or AI control frameworks in the repository.

Design Principles

  1. One binary, one job - ray_tracer builds scenes, launches kernels, and writes a PPM image.
  2. CPU orchestrates, GPU executes - scene setup, BVH construction, and CLI parsing stay on the host; intersection and shading stay on the device.
  3. Modules by responsibility - code is organized by rendering concerns, not by abstract patterns or framework layers.
  4. Prefer deletion over knobs - remove dead branches and duplicate pathways instead of keeping rarely used switches alive.
  5. Explicit data flow - upload scene data once, render, download the framebuffer once.

System Flow

Module Boundaries

ModuleResponsibilityKeep it limited to
include/core/Math primitives and CUDA helpersvec3, rays, constants, CUDA error utilities, random helpers
include/geometry/Spatial queries and hit dataAABB, BVH, primitive intersection, hit records
include/rendering/Rendering algorithmscamera, materials, lights, shading, kernels, validation
include/scene/Scene assemblyscene containers and built-in scene factories
include/image/Output formattingtone mapping and PPM writing
src/Program entryCLI parsing and top-level orchestration only
tests/Behavioral verificationunit and property tests

Core Features Kept

  • Blinn-Phong shading
  • Monte Carlo path tracing
  • BVH acceleration
  • Ray sorting for the supported Phong single-sample path
  • Built-in demo, Cornell, and random scenes
  • PPM output and tone mapping

Explicitly Out of Scope

  • AI workflow frameworks or repository-side agent control layers
  • Duplicate architecture tracks for the same rendering step
  • Secondary changelog systems outside the root CHANGELOG.md
  • Half-integrated features that are neither tested nor documented
  • Configuration-heavy abstractions that do not improve performance or clarity

Refactoring Rules

  1. Put new logic in an existing module unless a new boundary is clearly justified.
  2. Prefer plain structs and free functions over indirection-heavy abstractions.
  3. Reuse existing scene, material, and geometry types before adding variants.
  4. Handle CUDA failures explicitly with CUDA_CHECK() / CUDA_CHECK_LAST().
  5. Remove dead code instead of hiding it behind unused flags.
  6. Update tests and documentation when behavior changes.
  7. Record project history only in the root CHANGELOG.md.

Data Ownership

  • Host code owns CLI parsing, scene construction, BVH construction, and file output.
  • Device code owns the hot rendering path.
  • Scene buffers are copied to the GPU before rendering.
  • The framebuffer is copied back once rendering is complete.

Practical Guidance

  • If a feature does not improve image quality, performance, or maintainability, do not add it.
  • If two code paths solve the same problem, converge on one.
  • If a document describes a system that no longer exists, delete or rewrite it.

Technical Whitepaper · Built with VitePress