Appearance
第10回 レイトレースの原理
今回の授業内容
- ラスタライズ、レイマーチ、レイトレースを区別する
- 複数形状の交差から最近傍交点を選ぶ
- 交点と法線から材質色を計算する
- 影レイで光源までの遮蔽を判定する
- 反射レイで1バウンスの鏡を描画する
3つの描画手法を比較する
| 手法 | 形状への到達方法 | 得意なこと |
|---|---|---|
| ラスタライズ | 三角形を画面へ投影 | 多数のメッシュを高速に描画 |
| レイマーチ | 距離場を使って歩進 | SDF、ボリューム、有機的合成 |
| レイトレース | レイと形状の交差方程式 | 影、反射、屈折の経路 |
今回は URP のフルスクリーンシェーダー上で、球と平面に限定したソフトウェア的なレイトレーサーを実装します。HDRP のハードウェアレイトレーシング機能を使う授業ではありません。
最近傍の交点を選ぶ
各形状との交差距離を求め、0より大きく最も小さい距離を採用します。
hlsl
struct Hit
{
float distance;
float3 position;
float3 normal;
float3 albedo;
float reflectivity;
};
void SelectNearer(inout Hit current, Hit candidate)
{
if (candidate.distance > 0.0 && candidate.distance < current.distance)
{
current = candidate;
}
}初期値の distance には十分大きな値を設定します。球ごとに中心、半径、色、反射率を持たせ、交差結果へ材質情報も保存します。
影レイで光の遮蔽を確認する
hlsl
float3 toLight = lightPosition - hit.position;
float lightDistance = length(toLight);
float3 lightDirection = toLight / lightDistance;
float3 shadowOrigin = hit.position + hit.normal * 0.002;
Hit blocker = TraceNearest(shadowOrigin, lightDirection);
float visibility = blocker.distance < lightDistance ? 0.0 : 1.0;光源までの距離より手前に交点があれば影です。始点を法線方向へずらし、自分自身とすぐ再交差する問題を避けます。
反射レイを追加する
hlsl
float3 reflectedDirection = reflect(rayDirection, hit.normal);
float3 reflectedOrigin = hit.position + hit.normal * 0.002;
Hit reflectedHit = TraceNearest(reflectedOrigin, reflectedDirection);
float3 reflectedColor = Shade(reflectedHit);
float3 finalColor = lerp(localColor, reflectedColor, hit.reflectivity);反射先でさらに反射を計算すると再帰的に処理が増えます。授業では1バウンスに固定し、直接光と鏡面反射の流れを確認します。
実習:球と平面のミニレイトレーサー
- 第04回の球交差関数を再利用する
- 異なる位置と色の球を3個用意する
- 平面交差を追加する
- 最近傍交点の材質色を表示する
- Lambert と鏡面反射でライティングする
- 影レイを追加する
- 1つの球に反射率を設定し、1バウンスの反射を追加する
授業内課題:描画手法を説明する
同じ球のシーンを、次の3方式で比較します。
- Unity の Sphere メッシュ
- 第05回の SDF レイマーチ
- 今回の球交差レイトレース
形状の保持方法、交差の求め方、影と反射の追加方法、得意な表現を表にまとめます。
完成条件
- 複数形状から最近傍交点を選択できる
- 影レイで光源までの遮蔽を判定できる
- 1バウンスの反射を描画できる
- レイマーチとレイトレースの違いを説明できる
今回のまとめ
レイトレースは、視線レイの最近傍交点を探し、交点から新しい影レイや反射レイを追跡します。URP 上の小さな実装でも、現代のレイトレーシングが使う光線追跡の基本的な考え方を確認できます。
次回: 第11回 品質とパフォーマンス