Theme Catppuccin
Make yourself at homeCatppuccin

A softer light for long learning sessions.

Appearance

Loading your preference…

Dark palette

Choose a dark palette to try it.

Light uses Latte. Your choices stay in this browser.

Back to your source shelf

Inside the companion

Light Transport

Build a diffuse CPU path renderer and inspect its sampling, geometry, and tests.

Project files 11

Render the diffuse study

Parse the renderer options, produce an image, and report failures.

62 lines render.cpp
#include "diffuse.hpp"
#include <array>
#include <charconv>
#include <iostream>
#include <stdexcept>
#include <string_view>
#include <system_error>

int main(int argc,char* argv[]) {
    try {
        if (argc<2) throw std::runtime_error("Usage: lantern-render --trace | --constant | output.ppm [0..8 bounces]");
        const std::string_view command{argv[1]};
        if ((command=="--constant"||command=="--trace")&&argc!=2)
            throw std::runtime_error("This diagnostic takes no extra arguments.");
        if (command=="--constant") {
            const std::array<lantern::Surface,1> surface{{{{7,{0,0,0},1},{0.6,0.3,0.15},{}}}};
            const auto scene=lantern::DiffuseScene::build(surface,{2,1,0.5});
            if (!scene) throw std::runtime_error(scene.error().message);
            lantern::Rng rng{47};
            const auto trace=scene->trace({{0,0,3},{0,0,-1}},rng,1);
            if (!trace) throw std::runtime_error(trace.error().message);
            std::cout<<"Expected linear RGB: 1.2 0.3 0.075\nObserved linear RGB: "
                     <<trace->radiance.x<<' '<<trace->radiance.y<<' '<<trace->radiance.z<<'\n';
            return 0;
        }
        const auto scene=lantern::study_scene();
        if (!scene) throw std::runtime_error(scene.error().message);
        if (command=="--trace") {
            lantern::Rng rng{47};
            const auto trace=scene->trace({{-0.9,0,5},{0,0,-1}},rng,4);
            if (!trace) throw std::runtime_error(trace.error().message);
            for (std::size_t i=0;i<trace->count;++i) {
                const auto& s=trace->steps[i];
                std::cout<<"visit "<<i<<" object=";
                if (s.object) std::cout<<*s.object; else std::cout<<"environment";
                std::cout<<" local_cos="<<s.cosine<<" pdf="<<s.pdf
                         <<" beta="<<s.throughput.x<<','<<s.throughput.y<<','<<s.throughput.z
                         <<" L="<<s.radiance.x<<','<<s.radiance.y<<','<<s.radiance.z<<'\n';
            }
            const auto end=trace->end==lantern::PathEnd::environment?"environment":
                trace->end==lantern::PathEnd::depth_limit?"depth limit":"absorbed";
            std::cout<<"Path ended: "<<end<<" after "<<trace->count<<" visits.\n";
            return 0;
        }
        if (command.starts_with("--")) throw std::runtime_error("Unknown diagnostic option.");
        lantern::RenderSettings settings;
        if (argc>3) throw std::runtime_error("Too many arguments.");
        if (argc==3) {
            const std::string_view text{argv[2]};
            const auto [end,error]=std::from_chars(text.data(),text.data()+text.size(),settings.max_bounces);
            if (error!=std::errc{}||end!=text.data()+text.size()||settings.max_bounces>8)
                throw std::runtime_error("Bounce limit must be an integer in 0..8.");
        }
        const auto image=lantern::render_diffuse(*scene,settings);
        if (!image) throw std::runtime_error(image.error().message);
        if (const auto saved=lantern::write_ppm(*image,argv[1]); !saved) throw std::runtime_error(saved.error().message);
        std::cout<<"Wrote "<<settings.width<<'x'<<settings.height<<", "<<settings.samples
                 <<" samples/pixel, at most "<<settings.max_bounces<<" scatters; seed "<<settings.seed<<".\n";
        return 0;
    } catch (const std::exception& error) { std::cerr<<error.what()<<'\n'; return 1; }
}

This is the file included with the course. Copy and download give you its complete source.

Taking your work offline? Download all course companions