
はじめに
本稿は,Peter Shirleyらが出版した,以下の3つの本について,自己学習目的で作成している文書です。
- Ray Tracing in One Weekend (v3.2.3)(v.4.0.2)(日本語版)
- Ray Tracing: The Next Week (v3.2.3)(v.4.0.2)(日本語版)
- Ray Tracing: The Rest of Your Life (v3.2.3)(v.4.0.2)(日本語版)
『週末レイトレーシング』は実践的なプログラミング学習の題材としてよく知られています。原著はC++11(std::shared_ptrを使っている)の,あまりモダン寄りではない堅実なコーディングスタイルで書かれています。レイトレーシングやC++のよい学習教材として参照されているだけでなく,多言語への移植のベースとしても利用しやすいため,GolangやPythonなど人気の言語のほか,C++と同じシステムプログラミング言語で,学習曲線が急峻なことで知られるRust実装を試みた猛者が多い印象です。
本稿でもRustで再実装することにしました。さらに,WebAssemblyによりクライアントサイドで実行して,実行結果として得られるPPM画像をVitePress内にVueコンポーネントを使って表示することにしました。One Weekend(週末)という題名ですが,私にはおよそOne Weekendで終えることはできす,バナーにある「A Final Render(最後のシーン)」を出力するのに7ヶ月(30週)かかりました。
この試みはいくつかの壁を乗り越える必要がありました。そこで,別項としてWebAssemblyのVitePressでの取扱について説明することにしました。VueやViteについて調べるところから始め,WebAssemblyバイナリーとCanvasにより表示する設計とし,初めてグラデーション画像を表示できたときの喜びは今でも覚えています。
Rustを選んだ副産物のひとつは,WASMバイナリの軽量さです。第1週のすべてのデモを含む raytracing_demos_bg.wasm は,圧縮なしでわずか66KBに収まります。Rustのゼロコスト抽象化とwasm-packのリリースビルドが不要なコードを徹底的に除去するためで,RustとWebAssemblyの相性の良さを端的に示しています。昨今のネットワーク環境では,この程度のサイズはページ表示の妨げになりません。
本稿の構成
0. 技術
raytracing_demos を VitePress から呼び出すために必要な技術を2本のページで解説します。1本目は Cargo ワークスペースの3層構成(common・r1XX-*・raytracing-demos)・クレートの命名規則・新デモを追加するときの手順・ビルド方法に加え,Rust から JavaScript へ PPM 文字列を受け渡す設計の意図を取り上げます。2本目は VitePress 上でその PPM 文字列を受け取り Canvas に描画する Vue コンポーネント PPMRenderer の実装を扱い,Vue のリアクティビティとの競合をどう回避したかも解説します。
1. 週末レイトレーシング

Figure 1: 第1編の最終シーン
書籍の進行に沿って第1週の全13章を扱います。原著は C++11 で書かれており,本稿の Rust 移植はその差異を読み解くことを学習のひとつの軸としています。具体的には,出力パラメータの代わりに Option<T> で戻り値を表現すること,shared_ptr の代わりに Arc<dyn Trait> を使うこと,純粋仮想関数をトレイトとして定義すること,演算子オーバーロード,式指向の制御構造,所有権・借用規則など,Rust らしいイディオムについて C++ との対比を交えながら説明しています。
2. 翌週末レイトレーシング

Figure 2: 第2編の最終シーン
第 2 編『Ray Tracing: The Next Week』は,第 1 編で組み上げた common/ クレートを土台に,より凝ったシーンを描くための機能を順次追加していきます。各章で扱うトピックは,モーションブラー(時刻つきレイと MovingSphere),BVH による交差判定の高速化(Aabb・BvhNode),ソリッドテクスチャと UV 座標(Texture トレイト・CheckerTexture),格子ノイズによる手続き的テクスチャ(Perlin・NoiseTexture),画像テクスチャ(ImageTexture と build.rs でのアセット埋め込み),矩形面の導入と発光マテリアル(XyRect/XzRect/YzRect・DiffuseLight),軸並行直方体とインスタンス変換(RectBox・Translate/RotateY),定密度ボリューム(ConstantMedium・Isotropic),そして最終章でこれらすべてを盛り込んだ統合シーンです。