1. 週末レイトレーシング
書籍の進行に沿って第 1 週の全 13 章を扱います。原著は C++11 で書かれており,本稿の Rust 移植はその差異を読み解くことを学習のひとつの軸としています。具体的には,出力パラメータの代わりに Option<T> で戻り値を表現すること,shared_ptr の代わりに Arc<dyn Trait> を使うこと,純粋仮想関数をトレイトとして定義すること,演算子オーバーロード,式指向の制御構造,所有権・借用規則など,Rust らしいイディオムについて C++ との対比を交えながら説明しています。
1. はじめに
Ray Tracing in One Weekendは,Peter Shirley,Trevor David Black,Steve Hollaschによって執筆されたレイトレーシングの入門書です。C++によるシンプルな実装を積み重ねながら物理ベースレンダリングの基礎を解説するこの小冊子は,raytracing.git…
2. 画像の出力
この章では,まずPPM形式の説明があり,サンプル出力が提示されています。C++コードは標準出力にPPM形式で出力します。しかし,本稿ではWebAssemblyを使用するため,結果をStringとして返す関数にしました。原典では,レンダリング処理の進捗を示すためstd::cerrに残り行数を随時出力する機能が実装されてい…
3. ベクトルクラス
原典では,色・位置・方向のすべてに使うvec3クラスをC++で定義します。本稿ではこれをRustの構造体として実装します。Vec3は以降のすべてのチャプターで使用するため,ワークスペースのcommonクレートに配置します。common/src/vec3.rsを新規作成します。以下が完全な実装です。#[derive]マク…
4. レイ・簡単なカメラ・背景
この章では,レイトレーサーの根幹である「レイを放ち,その方向から色を求める」処理を実装します。レイは数学的に次の式で表されます:$$ \mathbf{P}(t) = \mathbf{A} + t \cdot \mathbf{b} $$$t$を変えると,レイ上の異なる点$\mathbf{P}(t)$が得られます。これをa…
5. 球のレンダリング
この章では,初めて「物体」をシーンに配置します。題材は最もシンプルな立体である球です。レイと球の交差判定を数学的に導出し,当たった部分を赤く塗ります。中心$\mathbf{C} = (C_x, C_y, C_z)$,半径$r$の球上の点$\mathbf{P}$は次の条件を満たします:$$ (\mathbf{P} - \…
6. 法線と複数オブジェクト
前章では球のシルエットを赤一色で塗りました。この章では法線ベクトルを使って球の表面をカラフルに可視化します。さらに,複数の物体を扱うための抽象化(Hittableトレイト,Sphere,HittableList)を導入し,地面の球を追加した2オブジェクトのシーンを完成させます。球の表面上の点$\mathbf{P}$にお…
7. アンチエイリアシング
前章でシーンが完成しました。しかし,球の輪郭をよく見るとギザギザした「ジャギー」が目立ちます。これはピクセルの色を1本のレイだけで決定しているためです。この章では,各ピクセルに複数のサンプルを放って色を平均する「スーパーサンプリング」によるアンチエイリアシングを実装します。1ピクセルを1本のレイで計算する場合,そのレイ…
8. 拡散マテリアル
この章では拡散マテリアル(非光沢マテリアル)を実装します。拡散マテリアルは光を吸収しながらランダムな方向に散乱させます。今章では3通りの実装を順に紹介しています。それぞれ散乱方向の確率分布が異なり,仕上がりの明るさや影の雰囲気に違いが生じます。拡散マテリアルに当たった光は次の2つを同時に行います。1.吸収:光の一部が表…
9. 金属マテリアル
この章では金属マテリアル(鏡面反射)を実装します。そのためにまず,マテリアルを表す抽象インタフェースを導入し,散乱処理を各マテリアルクラスにカプセル化します。これにより1.8章のランバーティアン拡散もマテリアルクラスとして整理し直します。異なるマテリアルを分岐なく扱えるよう,マテリアルの抽象インタフェースを導入します…
10. 誘電体マテリアル
この章では誘電体マテリアル(水・ガラス・ダイヤモンドなど透明な物体)を実装します。光が誘電体に当たると,一部は反射し,残りは屈折(透過)します。この実装では1回の交差判定ごとにランダムにどちらか一方を選択します。光が異なる媒質の境界を通過するとき,進行方向が変わります。これを屈折といい,スネルの法則で記述されます。$$…
11. カメラの移動
この章ではカメラを自由に配置・向き変更できるように拡張します。これまでカメラは原点固定・Z軸方向固定でしたが,任意の位置から任意の方向を向けるようにします。あわせて垂直視野角(vfov)のパラメータ化も行います。視野角(field of view, FOV)は,カメラが何度の範囲を映すかを表します。θ(垂直FOV)とビ…
12. 焦点ぼけ
この章では焦点ぼけ(defocus blur)を実装します。写真で被写体の前後がぼける,いわゆる被写界深度(depth of field)効果です。ピンホールカメラはすべての物体に焦点が合い,ぼけが生じません。実際のカメラは大きな開口部(aperture,絞り)を持つレンズで光を集めるため,特定の平面(焦点平面)以外の…
13. 最後のシーン
この章では「週末レイトレーシング」の最後のシーンを実装します。本のカバー画像として使われている,第1週のすべての技術を結集した集大成のシーンです。新しい仕組みは何も追加しません。これまで実装してきた要素をすべて組み合わせるだけです。シーン全体を生成する関数です。半径1000の大きなランバーティアン球を$y = -100…
13. 最後のシーン・高品質版
←標準版(13最後のシーン)に戻る高品質版では原典の22×22グリッドを完全再現しているため,球の数が増え,シーンの奥行き方向により多くの小球が並びます。r113-final-scene-hqはグリッドのループ範囲を変更しただけで,それ以外のコードはr113-final-sceneと同一です。解像度とサンプル数の違いは…
補講:ネイティブ並列レンダラー
これまでの実装はすべてWebAssembly(WASM)として動かすことを前提にしていました。WASMはシングルスレッドの同期実行であるため,上の図のような1200×800ピクセル・500 samples/pxの最終シーンはブラウザ上では30分以上かかります。この補講では,r113-final-scene-hqのコード…