Inside the companion
Light Transport
Build a diffuse CPU path renderer and inspect its sampling, geometry, and tests.
Project files 11
Describe the diffuse renderer
The scene, image, and bounded rendering interfaces for the diffuse study.
#pragma once
#include "lantern.hpp"
#include <array>
#include <cstddef>
#include <cstdint>
#include <expected>
#include <filesystem>
#include <optional>
#include <span>
#include <vector>
namespace lantern {
// A small, explicit RGB transport model: two-sided Lambertian spheres and
// two-sided surface emission, constant environment, no light sampling or MIS.
struct Surface { Sphere sphere; Vec3 reflectance; Vec3 emission; };
struct Frame { Vec3 tangent, bitangent, normal; };
[[nodiscard]] std::expected<Frame, Error> frame_from_normal(Vec3 normal);
[[nodiscard]] Vec3 to_world(const Frame& frame, Vec3 local) noexcept;
enum class PathEnd { environment, depth_limit, absorbed };
struct PathStep {
std::optional<std::uint32_t> object;
Vec3 point{}, normal{}, local_direction{};
double pdf{}, cosine{};
Vec3 throughput{1,1,1}, radiance{};
};
struct PathTrace {
Vec3 radiance{};
PathEnd end{};
std::size_t count{};
std::array<PathStep,9> steps{}; // At most eight scatters plus the terminal visit.
};
class DiffuseScene {
public:
[[nodiscard]] static std::expected<DiffuseScene, Error>
build(std::span<const Surface> surfaces, Vec3 environment);
// max_bounces counts scattered rays, not visits. At the terminal visit,
// emission or the environment is still accumulated before stopping.
[[nodiscard]] std::expected<PathTrace, Error>
trace(Ray ray, Rng& rng, unsigned max_bounces) const;
private:
std::vector<Surface> surfaces_;
SceneIndex index_;
Vec3 environment_{};
};
struct Image { std::size_t width{}, height{}; std::vector<Vec3> linear; };
struct RenderSettings {
std::size_t width{96}, height{64}, samples{32};
unsigned max_bounces{4};
std::uint64_t seed{47};
};
[[nodiscard]] std::expected<DiffuseScene, Error> study_scene();
[[nodiscard]] std::expected<Image, Error> render_diffuse(const DiffuseScene&, RenderSettings);
[[nodiscard]] std::expected<void, Error> write_ppm(const Image&, const std::filesystem::path&);
} // namespace lantern
This is the file included with the course. Copy and download give you its complete source.
Taking your work offline? Download all course companions
