Real-time Path Tracing

83rd 0x4C

去年に続きパストレーシングをOpenGLでリアルタイムに実行する

自己紹介

  • 名前: 0x4C
  • 役職: 副部長
  • やってること: ゲーム制作、3Dモデリング、レンダラー作成など

成果物

ソースコードはGitHubで公開しています(可読性放棄)。

GitHub - Asynchronous-0x4C/SSRenderer

Contribute to Asynchronous-0x4C/SSRenderer development by creating an account on GitHub.

github.com

image

パストレーシングとは

いきなりパストレーシングと言われても知っている人は皆無だと思うので、パストレーシングとは何なのかについて説明します。

パストレーシングについて説明するといったものの、前段階としてレイトレーシングについて知る必要があるので、まずはレイトレーシングについてです。

レイトレーシング

レイトレーシングというのは、光線をたどることで光の動きをシミュレートし、反射や屈折といった現象を再現するための手法です。

PS5などで最近流行りのレイトレーシングも、内部では膨大な量の光線を処理して正しい影や反射の像などを求めています。

Wikipediaより引用

レイトレーシング

パストレーシング

先ほど紹介したレイトレーシングは、光の経路自体は正しいものの、色の着き方まで正しく再現されているわけではありません。

それに対しパストレーシングは、確率的に光の経路を選択したり、専用の色の計算モデルを使うことで光の経路のみならず色まで正確に計算するという手法です。
色に関連する処理が追加される分、リアルタイムで動作させるのは(現在の環境では)非常に難しいです。

パストレーシング

制作するに至った経緯

実は、Path Tracerを作ったと言いつつ元はラスタライザー(軽量な描画手法)を作るつもりでした。

一応下の画像のようなシーンをレンダリングできるまでは制作しました。 ラスタライザー

ただ、昨年まで学んでいたレイトレーシングの知識とラスタライザー制作で磨いた技術を使えば高速にパストレーシングできるのでは?
と思ったので全てを放り出してパストレーサーを作りました。

実装

BSDF

パストレーシングにおいて、正確な色を計算するためには専用の計算モデルが必要になります。

その計算モデルがBSDF(双方向散乱分布関数)というものです。

BSDFはさらに2つのものに分かれており、それぞれ

  • 反射による色を計算するBRDF
  • 屈折による色を計算するBTDF

というもので、BSDFはこれらの合計値になります。

この中でもBRDFはさらに2つのものに分かれ、それぞれ

  • 拡散反射を表すDiffuse BRDF
  • 鏡面反射を表すSpecular BRDF

となります。(一応BTDFもSpecularとDiffuseに分けられますが、今回は実装していないので省略します。)

確率と重要度サンプリング

皆さんは小中学校で「光の入射角と反射角は等しい」と習ったと思いますが、現実にはほとんどの物質が様々な方向に光を反射します。
「じゃあ入射角と反射角が等しいというのは成り立たないじゃないか」と思うかもしれませんが、そう見えるのは物体をマクロに捉えているからです。

というのも、我々の目は物体のミクロな部分で発生した「入射角と反射角が等しい」反射を積分しているため、あたかも「様々な方向に光が反射している」ように見えるのです。

それを計算機上で再現するために、確率を使います。

具体的には、確率を用いて面の向きを決定し、次の光線の向きを求めます。
このとき、面の向きはそれぞれのBSDFに対応して分布が決まっており、例えば鏡のような滑らかな物質であればほぼすべての面が同じ向きに、錆びた鉄のような粗い物質であればばらばらな向きに分布します。
なので、鏡のような物質で適当に面の向きを決定した場合、本来あり得ない方向に光線を飛ばしてしまうことになります。

そこで、重要度サンプリングというものを使います。

重要度サンプリングというのは、面の向きの分布に添うように偏った方向に面の向きを決定するというものです。
これにより、より早くシミュレーションの結果が収束するようになります。

BVH

レイトレーシングやパストレーシングにおいては、光線と物体の交差判定を高速化するためにBVHというデータ構造を使います。
BVHは基本的に二分木のような構造を取りますが、派生版として四分木のQBVHや八分木版のOBVHが存在します。
部誌執筆時点では普通のBVHを実装しています。

BVHを実装するとどれぐらい早くなるのかというと、n個のポリゴンを処理する時間がnからlog(n)(底は2)まで早くなります。めっちゃはやい。

Temporal Accumulation

パストレーシングでは最終的な結果を出すためにサンプルを蓄積する必要があるのですが、カメラが動いてしまうと蓄積をやり直すことになります。
なので、motion vectorという形で画面上のピクセルの動きを追跡し、カメラが動いても蓄積を続けるTemporal Accumulationを実装しました。(ただしどこかを間違えている)

この手法を発展させることでSVGFというフィルタリングが使えるようになったりします。

画像たち

1 2 3 4

さいごに

昨年の経験を活かし、今年は約1週間ほどでパストレーシングを実装することができたものの、9月に入ると思っていたより時間が無く、あまり発展させることができませんでした。

とはいえBVHやTemporal Accumulationといった、前から実装したかった機能を実装することができたので、その点は満足です。

多分文化祭後にも少し開発を進めると思うので、良かったら見てください。