12. 写実的表現と大域照明計算
第10章と第11章では、全てのピクセルが1つの問いだけを立てていました:「光源から真っ直ぐ此の点に届く光はどれだけか?」
其れで綺麗で速い画像は出来ますが、カメラで撮った写真の様にはなりません。
本物の部屋では、赤いソファの隣の床がほんのりピンクになり、どの照明も当たっていない天井が明るく、水の入ったグラスがテーブルに明るい模様を落とし、窓は正面からより斜めから見た方が良く映り込みます。
此れらは全て、目に届く前に少なくとも1回跳ね返った光です。
此の章では其の光を追い掛けます。
先ず必要な物理です:光の測り方、表面が光をどう反射するか(BRDF)、ガラスや水が光をどう反射し曲げるか(フレネルとスネル)、そして肌や霧や空の中で何が起きるか。
次に、全ての写実的な画像の背後にある1つの方程式、レンダリング方程式と、其れを解く古典的な手法を見ます:レイトレーシング法、パストレーシング法、ラジオシティ法、フォトンマッピング法です。
どれも数値の計算例と小さなレンダリング画像付きです。
最後に問題を逆転させ、形状ではなく写真からレンダリングします:イメージベーストレンダリングです。
此の章で扱うシラバス項目(分野4、レンダリング):
- 写実的表現法:局所照明と大域照明、BRDF、フレネル、屈折、表面下散乱、関与媒質、コースティクス。
- 大域照明計算:レンダリング方程式、レイトレーシング法と其の高速化、分散レイトレーシング、パストレーシング法、ラジオシティ法、フォトンマッピング法。
- イメージベーストレンダリング:イメージベーストライティング、パノラマ、視点補間、ライトフィールド、ビルボード。
第10章の反射モデルとシェーディング、第11章の影と環境マッピングを前提とします。
数学は線型代数 第4章の内積と反射の式、線型代数 第3章の単位ベクトル、そして学校で習った2次方程式の解の公式です。
積分が幾つか出てきますが、読むだけです:何を足し合わせているかは必ず言葉でも説明します。
12.1 局所照明と大域照明
1つの部屋を横から見た図です。
光が目に届く迄に出来る事を4つ描きました:
- 直接光:光源 → 床 → 目。第10章で計算したのは此れです。
- 影:球が光源を遮るので、床の一部には直接光が届きません(第11章)。
- 相互反射:光源 → 赤い壁 → 床 → 目。床は壁が既に色付けした光を受け取るので、壁の近くでは少し赤くなります。此の色移りをカラーブリーディングと呼びます。
- コースティクス:光源 → ガラス球 → 床 → 目。球が光を曲げて1点に集め、球自身の影の真ん中に明るい点を作ります。
局所照明のモデルは、点の色を其の点自身、法線、材質、光源だけから計算します。
シーンに他の物が無いかの様に扱う訳です。
第10章のフォンのモデルは局所照明です:周りに何があるかを一切問いません。
大域照明のモデルは、他の面を経由して届く光も考えます:反射、屈折、相互反射、コースティクス、そして当然影もです。
大域照明こそが画像を写実的にする物ですが、計算は重くなります。
全ての点が他の全ての点に依存するからです。
局所照明のモデルは、足りない光を第10章の環境光項で誤魔化します。
暗い部分を持ち上げる定数です。
シーン全体で1つの数なので、赤い壁の近くの床を赤くする事も、部屋の隅を暗くする事も出来ません。
光の経路の名前
或る手法がどの経路を扱えるかを簡潔に表すのが、ヘックバートの光路表記(Paul Heckbert、1990年)です。
経路を文字の列で書きます:Lは光源、Eは目、Dは拡散反射、Sは鏡面反射(鏡やガラス)で、パターンの記号は普通の意味です:*は「0回以上」、+は「1回以上」、?は「0回か1回」、|は「又は」。
- 艶消しの床に当たる直接光:
LDE。カラーブリーディング:LDDE。床のコースティクス:LSDE(一般にはLS+DE)。 - 起こり得る全て:
L(D|S)*E。
此の表記は、12.12節で此の章の手法を比べる時に使います。
12.2 光を測る
第10章では単位を気にせずに色を掛け合わせていました。
跳ね返る光を扱うには、少しだけ放射測定(光のエネルギーの測定)が必要です。
第3章の光はエネルギーを運ぶ電磁波でした。
此処では、どれだけのエネルギーがどう流れるかだけを数えます。
立体角は角度の3次元版で、方向の円錐が半径1の球から切り取る面積です。
単位はステラジアン(sr)です。
球全体は sr、半球は srです。
距離から正面に見える面積の小さな面は、約ステラジアンを占めます。
知っておきたい4つの量:
| 量 | 記号 | 単位 | 意味 |
|---|---|---|---|
| 放射束 | W | 光の全パワー(例:ランプ1つの) | |
| 放射強度 | W/sr | 立体角あたりのパワー。点光源の或る方向への明るさ | |
| 放射照度 | W/m² | 面に全方向から届く、面積あたりのパワー | |
| 放射輝度 | W/(m²·sr) | 面積あたり・立体角あたりのパワー。1本の光線に沿って進む光 |
放射輝度は、カメラの画素や目が測る量であり、レンダラーが全てのピクセルについて計算する量です。
放射輝度には、レイトレーシングを可能にする性質があります:何も無い空間では、放射輝度は光線に沿って一定です。
2倍遠くの壁は立体角が4分の1になりますが、各点が送り出す放射輝度は同じです。
其の為、白い壁は近くからでも遠くからでも同じ明るさに見えます。
第3章の測光量は、同じ考え方を目の感度で重み付けした物です:第3章の輝度(cd/m²)は放射輝度の、照度(ルクス)は放射照度の相棒です。
計算例:放射照度
点光源。
放射強度 W/srの点光源が床の点から m離れていて、光は床の法線からの向きで届きます。
放射照度は距離の2乗で減り(第10章のの減衰)、角度の余弦で減ります(第10章のランバートの余弦則):
一様な空。
今度は半球の全ての方向から、同じ放射輝度で光が来ます。
各方向はステラジアンあたりを寄与するので:
は点の上の半球、は小さな立体角の欠片で、積分記号は「全ての方向について足し合わせる」と言う意味に過ぎません。
結果が(半球の大きさ)ではなくなのは、地平線近くの方向が0に近い余弦で重み付けされるからです。
W/(m²·sr)の空なら、放射照度は W/m²です。
此のは直ぐにまた出てきます。
12.3 BRDF
表面が入って来た光をどう出て行く光に変えるかを表すのがBRDF(双方向反射率分布関数)で、と書きます。
方向から届く光について、方向にどれだけの放射輝度が出て行くかを、入射する放射照度1あたりで表します:
入る方向と出る方向の2つに依存するので「双方向」です。
BRDFは、第10章の「材質」を物理的にした物です。
ローブ(各矢印の長さが其の方向への反射量)として描くと、典型的な3つの形は次の様になります:
- 拡散反射:反射された放射輝度が全ての方向で同じなので、どこから見ても同じ明るさに見えます(紙、艶消し塗料、漆喰)。理想的な場合が完全拡散反射面(ランバート面)です。
- 光沢:殆どの光が鏡の方向の近くに、ローブ状に広がって出て行きます(プラスチック、ニスを塗った木、ヘアライン加工の金属)。第10章の鏡面ハイライトは光沢のローブです。
- 鏡面反射(完全鏡面):全ての光が丁度1つの方向、入射方向の鏡映の方向に出て行きます(鏡、静かな湖、磨いたクロム)。
現実の材質は其れらの混合です。
例えば、拡散する下地の上に光沢のあるニスが乗っている、と言った具合です。
物理的なBRDFの性質
- 非負:。表面が負の光を反射する事は出来ません。
- 相反性(ヘルムホルツの相反性):。光源と目を入れ替えても値は同じです。レイトレーシングの様に、目から逆向きに光線を辿れるのは此の性質の御陰です。
- エネルギー保存:表面は受け取った以上の光を反射出来ません。全ての入射方向についてです。
入って来た光のうち全体として反射される割合がアルベド(反射率)で、0から1の間の数です。
新雪のアルベドは約0.9、アスファルトは約0.1です。
計算例:ランバート面のBRDF
ランバート面のBRDFは全ての方向で同じ、つまり定数です。
其の定数が幾つでなければならないかは、エネルギー保存が教えてくれます。
反射される割合は(空の時と同じ)で、此れがアルベドに等しくなる筈です:
の白い漆喰の壁なら(1ステラジアンあたり)です。
12.2節の点光源の下( W/m²)で、此の壁が全ての方向に送り出す放射輝度は:
此のが、物理ベースのレンダラーが拡散色をで割る理由であり、フォンのモデルから来た人には其のシーンの光の強さが「倍大き過ぎる」様に見える理由です。
同じ係数はOpenGLシリーズ 第24章でも出てきます。
第10章のフォンのモデルは、一般にはエネルギーを保存しません:が大きいと、届いた以上の光を送り出せてしまいます。
マイクロファセット(簡単に)
粗い表面を顕微鏡で見ると、小さな平らな鏡、マイクロファセットが並んだ地形です。
目に届く光は、法線が丁度光源と目の中間、つまりブリン・フォンのハーフベクトルを向いているファセットが鏡の様に反射した物です。
クック・トランスのモデル(Robert CookとKenneth Torrance、1982年)は、BRDFを3つの因子から組み立てます:を向くファセットがどれだけあるか(分布D)、其のうち他のファセットに影にされたり隠されたりしない物がどれだけか(幾何項G)、1つのファセットが此の角度でどれだけ反射するか(フレネル項F):
滑らかな表面はDが細く(鋭いハイライト)、粗い表面はDが広くなります(ぼやけたハイライト)。
此れが今日の物理ベースレンダリング(PBR)の基礎です。
詳しくは第2部で扱い、OpenGL 第24章で自分で実装します。
表面を通り抜ける光も同じ様にBTDF(双方向透過率分布関数)で表します。
BRDFとBTDFを合わせてBSDF(双方向散乱分布関数)と呼びます。
検定のポイント
- BRDF = 入射する放射照度あたりの出て行く放射輝度。2つの方向に依存し、単位は1/sr。1より大きくなる事もあります(鋭い鏡面のローブ)。
- 相反性:入射と出射を入れ替えられる。エネルギー保存:反射の合計 ≤ 入射。
- ランバート面のBRDF = 。反射される放射輝度はどの方向から見ても同じ(視点に依存しない)。
- マイクロファセットモデル(クック・トランス):D × F × G。
12.4 フレネル効果
窓や湖を見て下さい:正面からは向こう側が見えますが、浅い角度からは鏡になります。
2つの物質の滑らかな境界がどれだけ光を反射するかは角度に依存します。
此れがフレネル効果で、光学のフレネルの式で表されます。
物質は屈折率で特徴付けられます:真空は1(空気は1.0003で、1と見て構いません)、水は約1.33、ガラスは約1.5です。
正面(入射角0°)での、からへの境界の反射率は:
空気からガラスへ:。
空気から水へ:。
つまりガラスは正面から来た光の4%、水は2%を反射します。
残りは物質の中に入ります(屈折、次節)。
厳密な式は光の2つの偏光を別々に扱うので、少し長くなります。
殆ど全てのレンダラーが使うのはシュリックの近似(Christophe Schlick、1994年)です:
は入射光線と法線の成す角です。
0°では、90°(すれすれ)では丁度1になります:どんな表面も、すれすれの角度では完全な鏡になるのです。
計算例:ガラスと水
ではなのでとなり:
近似の良さを見る為に、ガラスの厳密なフレネルの値(偏光していない光)も並べた表です:
| θ | cos θ | ガラス(シュリック) | ガラス(厳密) | 水(シュリック) | |
|---|---|---|---|---|---|
| 0° | 1 | 0 | 0.040 | 0.040 | 0.020 |
| 30° | 0.866 | 0.00004 | 0.040 | 0.042 | 0.020 |
| 45° | 0.707 | 0.0022 | 0.042 | 0.050 | 0.022 |
| 60° | 0.5 | 0.0313 | 0.070 | 0.089 | 0.051 |
| 75° | 0.259 | 0.2237 | 0.255 | 0.253 | 0.239 |
| 85° | 0.087 | 0.6339 | 0.649 | 0.613 | 0.641 |
| 90° | 0 | 1 | 1 | 1 | 1 |
反射率は60°付近まで殆ど変わらず、其処から急に上がります。
シュリックの近似は所々で100分の数ずれますが、実際には見分けられず、引き算1回と掛け算数回で済みます。
実際には
- 水とガラス:湖は向こう岸を映しますが(すれすれの角度)、足元では底が見えます(急な角度)。フレネルが無いと、レンダリングした水はプラスチックの様に見えます。
- 全ての材質にフレネルがある:艶消しの物体でも、すれすれの角度では縁が明るくなります。PBRの材質はを持ち、金属以外では約0.04です。其の為、多くのエンジンは0.04を既定値にしています。
- 金属は正面からでも良く反射し、其のは波長に依存します:金の黄色や銅の橙色は、其のフレネルの色です。
- フレネルの重みが反射と屈折の配分を決めます:光の割合Fが反射され、が透過します。レイトレーサーは正に其の通りに使います(12.8節)。
12.5 屈折
反射されなかった光は物質に入り、向きを変えます:屈折です。
原因は、密な物質の中では光が(倍)遅く進む事です。
スネルの法則は、両側の法線との角度を結び付けます:
密な物質に入る時()光線は法線の方へ曲がり、出る時は法線から離れる方へ曲がります。
計算例:スネルの法則
空気からガラスへ、で:
空気から水へ45°で:なので。
水の屈折率の方が1に近いので、水はガラスより光を曲げません。
全反射
今度は逆向き、ガラス()から空気()へ進みます。
ガラスの中で30°ならで、光線は48.59°で出て行きます。
50°ならです。
正弦が1より大きくなる事は無いので、屈折光は全く存在しません:全ての光がガラスの中へ反射されます。
此れが全反射です。
全反射は、屈折光が丁度表面をかすめる()臨界角から始まります:
全反射は、光が密な物質から疎な物質へ進む時にだけ起こります。
実際には
- 光ファイバーは全反射で光を中に閉じ込めます。カットしたダイヤモンドの輝きは、其の非常に高い屈折率(約2.42、従って臨界角は僅か約24°)から来ます:光は外に出る迄に中で何度も跳ね返るのです。
- スネルの窓:水中から見上げるダイバーには、空全体が半角48.75°(差し渡し97.5°)の円の中に押し込められて見えます。其の外側では水面は鏡です。
- 分散:屈折率は波長に少しだけ依存します(青は赤より強く曲がる)。プリズムが白色光をスペクトルに分けるのも、虹が出来るのも此の為です。レンダラーで再現するには、RGBの代わりに幾つもの波長を扱うスペクトルレンダリングが必要です。
- レイトレーサーでは、屈折の方向をベクトルの形で計算します。入射方向の単位ベクトル、入射光線の側を向いた単位法線、、として:
なら全反射です。
はなので、此れはスネルの法則をベクトルで書いた物です。
GLSL、Slang、HLSLにはrefract(d, n, eta)として組み込まれていて、の時は零ベクトルを返します。
12.6 物質の中と空気の中の光
此処までの事は全て、丁度表面の上で起きていました。
多くの物質は光を中に入れ、内部で散乱させてから外へ出します。
半透明と表面下散乱
懐中電灯を指に当てると、指が赤く光ります。
肌、大理石、蝋、牛乳、翡翠、葉では、光は物質に入り、中で何度も散乱し、別の点から出て行きます。
其の点は数ミリメートルも離れている事があります。
此れが表面下散乱で、此の様な物質は半透明です。
BRDFは光が入った点から出て行くと仮定するので、此れを表せません。
其の一般化がBSSRDF(双方向散乱面反射率分布関数)で、入る点と出る点にも依存します。
表面下散乱が無いと、肌は塗装したプラスチックの様に、蝋人形は石の様に見えます:影の中に滲む柔らかい光や、薄い部分(耳、鼻の穴)の赤みが失われるからです。
映画のレンダラーは此れをシミュレーションし、ゲームは例えば肌の上の照明を画面空間でぼかす事で近似します。
関与媒質
霧、煙、雲、濁った水、そして澄んだ空気さえも関与媒質です:面と面の間の空間自体が光の伝わり方に関わります。
光線に沿って、光は吸収される(熱に変わる)事も、光線から外へ散乱される事も、他所から光線の中へ散乱して入る事もあります(霧の中の街灯の周りが光ったり、光の筋が見えたりするのは此の為です)。
一番簡単な部分はランベルト・ベールの法則です:一様な媒質の中を距離だけ進む光のうち、通り抜ける割合は
で、(1メートルあたり)は媒質の濃さを表します。
計算例:(1メートルあたり)の霧は、10 mでの光を通し、30 mでは僅かしか通しません。
ゲームの古典的な「指数フォグ」は正に此れです:ピクセルの色 。
何故空は青いのか
空気の分子は光の波長よりずっと小さく、此の様な小さな粒子では散乱の強さがに比例します:レイリー散乱です。
従って、450 nmの青い光は700 nmの赤い光の
倍強く散乱されます。
大気を横切る太陽光は四方八方に青を失い、其の散乱された青が空のあらゆる方向からあたし達に届きます。
夕方には光が空気の中をずっと長く進むので、届く前に青の殆どが散乱されてしまい、太陽と雲が橙色や赤になります。
波長と同じ位か其れより大きい粒子(水滴、埃、煙)は全ての波長を殆ど同じ様に、主に前方へ散乱します:ミー散乱です。
雲が白く、霞が灰白色で、霞んだ日に太陽の周りが明るく光るのは此の為です。
ゲームや映画の空のモデルは此の2種類の散乱を基に作られています。
ボリュームレンダリングは第2部で扱います。
コースティクス
コースティクスは、曲がった鏡やレンズが拡散面の上に集めた光です:プールの底の明るい網目模様、水の入ったグラスの下の明るい点、日の当たるコーヒーカップの中のハート形の曲線などです。
経路の表記ではLS+DEです:1回以上の鏡面反射、次に拡散面、そして目。
後で見る様に、コースティクスは最もレンダリングが難しい効果の1つです:光源から光を辿る手法が必要なのです。
12.7 レンダリング方程式
此れら全てが、1つの方程式に収まります。
レンダリング方程式で、1986年にJames Kajiyaが発表しました(同じ年にDavid Immelらも独立に発表しています)。
今日普通に書かれる形は:
左から右へ読みます:
- :点から方向(目の方)へ出て行く放射輝度。ピクセルに映るのは此れです。
- :点自身が放つ放射輝度(光源以外では0)。
- 積分:半球の全ての入射方向について、入って来る放射輝度を、BRDF と法線との角度の余弦(ランバートの余弦則)で重み付けして足し合わせる。
問題はです。
方向からに届く光は、其の方向に見える面の点から出て行く光です:。
未知の量が両辺に現れ、全ての点が他の全ての点に依存します。
1行で書いた大域照明です。
どの手法も近似
| 手法 | 積分をどう扱うか |
|---|---|
| 局所照明(第10章) | 点光源だけを残す:積分は光源についての和になり、残りは全て環境光の定数 |
| ホイッテッドのレイトレーシング | 点光源に加え、鏡なら1方向、屈折なら1方向だけを再帰的に辿る |
| 分散レイトレーシング/パストレーシング | ランダムな標本の方向で積分を推定する(モンテカルロ法) |
| ラジオシティ法 | 全ての面をランバート面と仮定し、小さなパッチの光を解く |
| フォトンマッピング法 | 先ず光源から光を送って蓄え、其の後蓄えたフォトンから積分を推定する |
計算例:何故跳ね返りが大事か
全ての壁のアルベドがの閉じた部屋を考え、光源が直接光で全ての壁に放射輝度を与えるとします。
1回跳ね返った後、各壁は更に其の倍を受け取り、2回跳ね返った後は倍、と続きます。
合計は等比級数です:
の白い壁なら、部屋は直接光だけから想像するより倍明るくなります。
なら2倍です。
白い部屋では、目に見える光の殆どが何回も跳ね返った光です。
当て推量の環境光項を使う局所照明のモデルがのっぺり見えるのは其の為です。
12.8 レイトレーシング法
第6章では三角形を画面に投影して描きました。
レイトレーシング法は其の逆を行きます:ピクセル毎に、目からピクセルを通してシーンへ光線(レイ)を飛ばし、其のレイが何に当たるかを調べます。
光が実際に進む向きとは逆に辿るので、目から辿る事を逆方向の追跡、12.12節のフォトンマッピング法の様に光源から辿る事を順方向の追跡と呼ぶ事が多いです(但し、此の2語を逆の意味で使う本も有ります)。
1本のレイを最初の交点まで辿るだけならレイキャスティング法で、第10章では隠面消去に使いました。
レイトレーシングは、Turner Whittedが1980年に発表した形(論文「An Improved Illumination Model for Shaded Display」)では、交点から再帰的に続けます:
- 一次レイ(視線)は目からピクセルを通り、最初の交点まで進みます。
- 交点から各光源へシャドウレイを飛ばします。何かに遮られたら、其の光源は数えません(第11章)。
- 面が鏡なら、鏡の方向(線型代数 第4章)へ反射レイを辿ります。
- 透明なら、12.5節のスネルの方向へ屈折レイ(透過レイ)を辿ります。
- 反射レイと屈折レイは他の面に当たり、其処から又シャドウレイ、反射レイ、屈折レイが生まれ、と続きます。
1本の一次レイから生まれた全てのレイはレイツリーを作ります。
ピクセルの色は葉から根の方へ集めます:各節点は自分の局所照明と、子の色を重み付けした物を足します。
2枚の鏡の間ではツリーが永遠に育つ事があるので、再帰は最大の深さ(典型的には5から10)か、枝の重みが無視出来る程小さくなった所で止めます。
疑似コードでは:
color trace(ray, depth):
hit = nearest intersection of ray with the scene
if there is no hit: return background color
color = local lighting at hit (one shadow ray per light)
if depth < maxDepth:
if hit is reflective: color += kr * trace(reflection ray, depth + 1)
if hit is transparent: color += kt * trace(refraction ray, depth + 1)
return color
ガラスの場合、とは12.4節のフレネルの重みとです。
ホイッテッドのレイトレーサーは、鋭い反射、屈折、正確なハードシャドウを生み出します。
ラスタライザーでは誤魔化すしかない物です。
出来ない事も同じ位大事です(検定対策として押さえておきたい所です):
- 拡散面の相互反射が無い:艶消しの壁で跳ね返る光は追わないので、カラーブリーディングは無く、環境光項は相変わらず定数です。
- ソフトシャドウが無い:点光源だけで、シャドウレイは1本ずつです。
- 光沢反射が無い:反射レイは丁度1方向に進むので、映り込みは常に完全に鋭くなります。
- コースティクスが無い:シャドウレイは光源へ真っ直ぐ向かうので、ガラスで集められた光は決して届きません(ガラス球の影は真っ黒です)。
レイと球の交差
レイトレーサーの心臓部は交差判定です。
レイはから単位方向へ進み、其の点はについてで、はレイに沿った距離です。
中心、半径の球は、中心からの距離がの点の集まりです:。
として、レイを球の式に代入します:
(は単位ベクトルなので、の項の係数はです。)
2次方程式です。
、と置くと、解の公式は次の様に簡単になります:
判別式の符号が全てを語ります:負ならレイは外れ、0なら接するだけ、正なら小さい方ので入り大きい方ので出ます。
欲しいのは正の値のうち最小のです(負のはレイの出発点の後ろです)。
計算例:ガラス球を通る1本のレイ
レイは目から方向へ進みます。
なので単位ベクトルです。
ガラス球の中心は、半径はです。
交点。
。
どちらも正なので、レイはで入り、で出る筈です。
交点はです。
法線。
球の法線は中心から交点へ向かい、で割れば単位ベクトルになります:
(確認:。)
入射角。
此れは丁度なので、、です:レイはかなり浅い角度で球に当たっています。
フレネル。
シュリックの近似とで:
つまりピクセルの色の12.5%は反射レイから、87.5%は屈折レイから来ます。
反射レイ。
なので:
屈折レイ。
空気からガラスへ、:
スネルの法則で確認します:なので、で、合っています。
レイトレーサーは次にとについてtraceを呼び、結果をと混ぜます。
同じ手順を、線型代数シリーズのlinalg.hhヘッダーを使ったC++で書くと次の通りです(reflectは線型代数 第4章の関数です):
#include <cmath>
#include <cstdio>
#include "linalg.hh"
// Distance t to the nearest hit of the ray o + t d (d normalized) with a sphere, or -1 for a miss.
float hitSphere(Vec3 o, Vec3 d, Vec3 c, float r) {
Vec3 m = o - c;
float b = dot(m, d);
float cc = dot(m, m) - r * r;
float disc = b * b - cc;
if (disc < 0.0f) return -1.0f; // the ray misses the sphere
float s = std::sqrt(disc);
float t = -b - s; // the nearer root first
if (t < 1e-4f) t = -b + s; // we start inside the sphere
return t < 1e-4f ? -1.0f : t; // the whole sphere is behind us
}
Vec3 reflect(Vec3 d, Vec3 n) { return d - 2.0f * dot(d, n) * n; }
// eta = n1 / n2. Returns false on total internal reflection.
bool refract(Vec3 d, Vec3 n, float eta, Vec3 *t) {
float cosI = -dot(d, n);
float k = 1.0f - eta * eta * (1.0f - cosI * cosI);
if (k < 0.0f) return false;
*t = eta * d + (eta * cosI - std::sqrt(k)) * n;
return true;
}
float schlick(float cosTheta, float f0) {
float m = 1.0f - cosTheta;
return f0 + (1.0f - f0) * m * m * m * m * m;
}
int main() {
Vec3 o{0, 0, 0}, d{0, 0.6f, -0.8f}, c{0, 0, -10};
float r = 6.5f;
float t = hitSphere(o, d, c, r);
Vec3 p = o + t * d;
Vec3 n = (p - c) / r;
float cosI = -dot(d, n);
Vec3 refl = reflect(d, n), refr;
refract(d, n, 1.0f / 1.5f, &refr);
printf("t = %.4f, p = (%.4f, %.4f, %.4f)\n", t, p.x, p.y, p.z);
printf("n = (%.4f, %.4f, %.4f), cos = %.4f\n", n.x, n.y, n.z, cosI);
printf("Fresnel (Schlick, glass) = %.4f\n", schlick(cosI, 0.04f));
printf("reflected = (%.4f, %.4f, %.4f)\n", refl.x, refl.y, refl.z);
printf("refracted = (%.4f, %.4f, %.4f)\n", refr.x, refr.y, refr.z);
// inside the glass, 50 degrees from the normal: beyond the critical angle
float a = 50.0f * 3.14159265f / 180.0f;
Vec3 inside{std::sin(a), std::cos(a), 0}; // travelling up towards the glass-air surface
Vec3 facing{0, -1, 0}; // the normal on the side the ray comes from
Vec3 out;
bool ok = refract(inside, facing, 1.5f, &out);
printf("50 degrees inside the glass: %s\n", ok ? "refracts" : "total internal reflection");
return 0;
}
t = 5.5000, p = (0.0000, 3.3000, -4.4000)
n = (0.0000, 0.5077, 0.8615), cos = 0.3846
Fresnel (Schlick, glass) = 0.1247
reflected = (0.0000, 0.9905, -0.1373)
refracted = (0.0000, 0.1300, -0.9915)
50 degrees inside the glass: total internal reflection
平面と三角形(簡単に)
10.5節と同じく、点を通り法線を持つ平面には、次ので当たります:
なら、レイは平面と平行です。
例:床(、)と、原点から方向へのレイなら、です。
三角形は、平面との交差の後に内側判定を行います。
普通は第6章のエッジ関数の様な重心座標を使います。
メラー・トランボアのアルゴリズムは両方を一度に行い、殆どのレイトレーサーが三角形メッシュに使っています。
シェーダーでは:フレネルで重み付けしたガラス
リアルタイムのレンダラーは、第11章の環境マッピングとフレネルの重みを組み合わせると、ガラスの物体らしい見た目を安く得られます。
反射方向と屈折方向で空を引き、で混ぜるのです。
(屈折は1回だけで、物体の裏側は無視します。良く使われる近似です。)
TextureCube<float4> sky;
SamplerState skySampler;
float schlick(float cosTheta, float f0) {
float m = saturate(1.0 - cosTheta);
return f0 + (1.0 - f0) * m * m * m * m * m;
}
// d: unit direction from the eye to the surface, n: unit normal facing the eye
float3 glassColor(float3 d, float3 n) {
const float eta = 1.0 / 1.5; // air -> glass
float f0 = (1.0 - 1.5) / (1.0 + 1.5);
f0 = f0 * f0; // 0.04
float F = schlick(-dot(d, n), f0);
float3 reflected = sky.Sample(skySampler, reflect(d, n)).rgb;
float3 refracted = sky.Sample(skySampler, refract(d, n, eta)).rgb;
return lerp(refracted, reflected, F);
}layout(set = 0, binding = 1) uniform samplerCube sky;
float schlick(float cosTheta, float f0) {
float m = clamp(1.0 - cosTheta, 0.0, 1.0);
return f0 + (1.0 - f0) * m * m * m * m * m;
}
// d: unit direction from the eye to the surface, n: unit normal facing the eye
vec3 glassColor(vec3 d, vec3 n) {
const float eta = 1.0 / 1.5; // air -> glass
float f0 = (1.0 - 1.5) / (1.0 + 1.5);
f0 = f0 * f0; // 0.04
float F = schlick(-dot(d, n), f0);
vec3 reflected = texture(sky, reflect(d, n)).rgb;
vec3 refracted = texture(sky, refract(d, n, eta)).rgb;
return mix(refracted, reflected, F);
}TextureCube<float4> sky;
SamplerState skySampler;
float schlick(float cosTheta, float f0) {
float m = saturate(1.0 - cosTheta);
return f0 + (1.0 - f0) * m * m * m * m * m;
}
// d: unit direction from the eye to the surface, n: unit normal facing the eye
float3 glassColor(float3 d, float3 n) {
const float eta = 1.0 / 1.5; // air -> glass
float f0 = (1.0 - 1.5) / (1.0 + 1.5);
f0 = f0 * f0; // 0.04
float F = schlick(-dot(d, n), f0);
float3 reflected = sky.Sample(skySampler, reflect(d, n)).rgb;
float3 refracted = sky.Sample(skySampler, refract(d, n, eta)).rgb;
return lerp(refracted, reflected, F);
}空のキューブマップと映り込みはOpenGLシリーズ 第18章で、フラグメントシェーダーの中のレイを使ったレンダラーはGLSLシリーズ 第14章で自分で作ります。
12.9 レイトレーシングの高速化
素朴なレイトレーサーは、全てのレイを全ての物体と判定します。
フルHDの画像はピクセルです。
100万個の三角形のシーンなら、シャドウレイや反射レイを1本も飛ばす前に、一次レイだけで約回の三角形の判定になります。
レイはシーンのほんの一部の近くしか通らないので、此れらの判定の殆ど全ては無駄です。
高速化データ構造は、1回の安い判定で物体のグループを丸ごと飛ばします。
バウンディングボリューム
バウンディングボリュームは、複雑な物体を囲む単純な形です:球や、軸に平行な箱(AABB)です。
レイが箱に当たらなければ、中の物にも当たりません。
レイと箱の判定は掛け算数回で済みます(「スラブ判定」:レイのの範囲を3組の平行な平面で切り詰め、範囲が空にならなければ箱に当たっています)。
階層バウンディングボリューム(BVH)
バウンディングボリュームの中にバウンディングボリュームを入れると、木構造、BVH(階層バウンディングボリューム)になります。
根の箱がシーン全体を含み、其の子が其の半分ずつを含み、と続いて、葉には三角形が数個だけ入ります:
図のレイは箱Aに当たらないので、左の部分木全体(A′、a、b、c)が1回の箱の判定で飛ばされます。
Bには当たるので、B′とeを判定し、次にB′の中のdとfを判定します。
個の三角形のバランスの取れた木なら、深さは約です:100万個なら。
レイは100万回の代わりに、数十回の箱の判定と数回の三角形の判定で済みます。
空間分割
物体をまとめる代わりに、空間を分ける事も出来ます:
- 均一格子:シーンの箱を同じ大きさのセルに切り、各セルに其のセルと重なる物体を記録します。レイは自分の通り道に沿ってセルからセルへ進み(第6章の線分を描くアルゴリズムの3次元版の様に)、最初に当たりのあるセルで止まります。単純ですが、物体が偏っていると無駄が多くなります。
- 八分木:物体が多い所だけ、セルを8つの同じ子に切ります。シーンに合わせて細かくなります。
- kd木:セルを1つの軸に垂直な平面で2つに切ります。平面は物体を一番良く分ける位置に置き、軸は交互に、又は節点毎に選びます。
| 構造 | 何を分けるか | 長所 | 短所 |
|---|---|---|---|
| BVH | 物体を入れ子の箱に | 各物体は丁度1つの葉に入る。動く物体の為の作り直しが速い | 箱同士が重なり得る |
| 均一格子 | 空間を同じセルに | とても単純で、作るのが速い | 混んだ所と空いた所があるシーンに弱い |
| 八分木 | 必要な所で空間を8つの子に | 密度に合わせられる | 分割位置が固定 |
| kd木 | 空間を軸に平行な平面で、任意の位置で | 静的なシーンでは走査がとても速い | 物体が幾つものセルに入り得る。作り直しが遅い |
同じ構造は、ゲームや物理の衝突判定も速くします(第14章)。
現代のGPUにはレイトレーシング用のハードウェアがあり(2018年から)、VulkanとDirectX 12のレイトレーシングAPIはBVHの様な高速化構造を作ってくれます:メッシュ毎の下位レベルと、インスタンス全体の上位レベルです。
12.10 分散レイトレーシングとパストレーシング
ホイッテッドのレイはどれも丁度1方向に進むので、全てが完全に鋭くなります。
1984年、Robert Cook、Thomas Porter、Loren Carpenterは論文「Distributed ray tracing」で、レイを或る範囲にばらまいて平均すると、足りなかった効果が現れる事を示しました。
此れが分散レイトレーシングです(確率的レイトレーシングとも言います):
| レイをばらまく範囲 | 効果 |
|---|---|
| ピクセルの面積 | アンチエイリアシング(第2章のスーパーサンプリング) |
| 光源の面積 | 半影のあるソフトシャドウ |
| 鏡の方向の周りの円錐 | 光沢のある(ぼやけた)映り込み |
| レンズの面積 | 被写界深度(第2章の薄レンズ) |
| シャッターが開いている時間 | モーションブラー |
どれも(面積、円錐、時間についての)積分で、ランダムな標本の平均が其れを推定します。
此の考え方には名前があります。
モンテカルロ積分
積分を推定するには、確率密度で個のランダムな点を選んで平均します:
此れがモンテカルロ積分(モンテカルロ法)です。
平均すれば丁度正しい答えになりますが(「不偏」と言います)、1回1回の推定はランダムなノイズの分だけずれます。
そして其のノイズは、標本数の平方根でしか減りません:
計算例。
答えがと分かっているを推定してみます。
半球上で一様に方向を選ぶとなので、各標本の寄与はです。
の4つのランダムな方向なら:
10%大き過ぎます。
ノイズはどれ位でしょうか?
半球上で一様に分布する方向では、は0から1の間で一様に分布し、其の標準偏差はです。
従って標本1つの誤差はで、の半分以上です。
個の標本では:
| N | 誤差の期待値 | πに対する割合 |
|---|---|---|
| 1 | 1.814 | 58% |
| 16 | 0.453 | 14% |
| 256 | 0.113 | 3.6% |
標本を4倍にする毎に誤差は半分に、16倍にする毎に4分の1になります。
10%のノイズを1%にするには、100倍の仕事が必要です。
簡単な実験(各について推定を10,000回)でも、RMS誤差は1.835、0.460、0.113となり、表と合います。
重点的サンプリングは、標本を増やさずにノイズを減らします:をに似た形に選ぶのです。
此処では密度で方向を選ぶ(法線の近くの方向を多くする)と、全ての標本がになります:ノイズ0で正確な答えです。
現実のシーンではに未知の入射光も含まれるのでノイズは消えませんが、BRDFと余弦に比例して標本を取り、更に光源へ向けてレイを追加すれば、其の殆どが取り除けます。
パストレーシング法
パストレーシング法は、1986年にKajiyaがレンダリング方程式と一緒に発表した物で、其の方程式をモンテカルロ法で解きます。
レイのツリーの代わりに、各標本は1本の経路(パス)です:目から面へ、次にランダムに選んだ1つの方向へ次の面へ、と続き、光源に届くか打ち切られる迄進みます。
各ピクセルは、此の様な経路を沢山平均します(1画素あたりのサンプル数、spp)。
color radiance(ray):
result = 0, weight = 1
repeat:
hit = nearest intersection of ray with the scene
if there is no hit: return result
result += weight * (light emitted at hit)
result += weight * (direct light from one random point on a lamp) (shadow ray)
choose a new direction w with probability p(w)
weight *= brdf * cos / p(w)
(Russian roulette) stop with probability 1 - q, otherwise weight /= q
ray = new ray from hit in direction w
拡散面はランダムな方向へ散乱させるので、パストレーサーは全てを得ます:カラーブリーディング、面光源によるソフトシャドウ、光沢のある映り込み、そして(ゆっくりと)コースティクスもです。
代償はノイズです。
次は小さなパストレーサー(約100行のNumPyのスクリプト)で、赤と緑の壁、白い球とガラス球、天井の四角いランプがある箱を、1画素あたり1、16、256サンプルでレンダリングした物です。
誤差は2048サンプルの参照画像と比べて測りました:
測った誤差は、サンプルを16倍にする毎に3.7分の1と4.1分の1になりました。
モンテカルロ法が予言するに近い値です。
一番最後まで残る明るい斑点はガラス球の周りにあります:コースティクスの経路(LSDE)で、目から始まる経路は運が良い時にしか其れを見つけられないのです。
其の隣に、同じシーンをホイッテッドの方法で、ランプの位置に点光源を1つ置いてレンダリングした物を並べます:
ホイッテッドの画像には鋭い黒い影があり、天井は黒く(ランプは天井を照らしません)、白い面に色の付いた光は乗っていません。
パストレーシングの画像には柔らかい影があり、天井は床や壁で跳ね返った光で照らされ、白い面には赤と緑が滲み、ガラス球の下にはコースティクスがあります。
ロシアンルーレットは、偏りを生まずに経路を終わらせます。
何回か跳ね返った後、経路は確率で続き、其れ以外では止まります。
生き残った経路は重みをで割ります。
平均すれば何も変わりません:で寄与0.5の場合、70%の場合にはに、残りでは0になり、です。
しかし暗い経路の殆どは早く止まるので、時間を大きく節約出来ます。
実際には
映画の制作はここ数十年でパストレーシングに移りました。
Arnold、RenderMan、BlenderのCyclesの様なレンダラーはパストレーサーです。
双方向パストレーシングは目からと光源からの両方で経路を作って繋ぎ、コースティクスをずっと速く見つけます。
ゲームは反射、影、一部の大域照明にハードウェアのレイトレーシングを使い、1画素あたり1から2サンプルしか取らず、其の後デノイザー(エッジを保ちながらノイズを均すフィルター。ニューラルネットワークである事も多い)でノイズを取り除きます。
モンテカルロ・レンダリングは第2部で更に深く扱います。
12.11 ラジオシティ法
パストレーシングは1つの視点について、ピクセル毎に光を計算します。
ラジオシティ法は全く違う道を取ります。
熱工学から借りて来た手法で、1984年にコーネル大学のCindy Goral、Kenneth Torrance、Donald Greenberg、Bennett BattaileがCGに持ち込みました(論文「Modeling the interaction of light between diffuse surfaces」)。
其のテストシーンは赤い壁と青い壁のある立方体で、論文の要点は正に、其れまでのどの手法でも出せなかったカラーブリーディングでした。
考え方:
- 全ての面をランバート面(完全拡散面)と仮定する。すると或る点から出て行く光は全ての方向で同じになり、点毎に(色のチャンネル毎に)1つの数で表せる。
- 全ての面を小さなパッチに分け、各パッチの上では光が一定だと仮定する。
- 全てのパッチの間の光の釣り合いを連立1次方程式として書き、其れを解く。
パッチから出て行く面積あたりの光が、其のラジオシティ(放射発散度、W/m²)です。
パッチが放つ光と、他の全てのパッチからの光のうち反射する分の和です:
は放つ光(光源では0以外)、はアルベド、は形態係数(フォームファクタ)です。
ランバート面のパッチでは放射輝度はで、画面に映るのは此れです。
形態係数
は、パッチから出て行く光のうち、パッチに届く割合です。
此れは幾何だけで決まります:2つのパッチの大きさ、距離、向き、そして其の間を何かが遮っているかどうかです。
は2つの点が互いに見える所で1、間に何かがある所で0です。
積分は全ての点の組について平均を取ります。
距離に比べて小さいパッチでは被積分関数は殆ど変わらないので:
計算例:1 m離れて真正面に向き合う()小さなパッチ、 m²(10 cm × 10 cm)なら、です。
両方を60°傾けて2 mに離すと、で、16分の1になります(余弦で4分の1、距離で4分の1)。
押さえておきたい性質:
- 相反性:。大きなパッチが小さなパッチに送る光の割合は、逆向きより小さくなります。
- 総和:閉じたシーンでは。パッチから出た光はどこかに必ず着地します。
- 平らなパッチでは(自分自身は見えない)。又、。
- 形態係数は材質にも光源にも依存しないので、静的なシーンでは1回計算すれば済みます。
計算するのが高く付く部分です。
ヌッセルトの相似則は分かり易い絵を与えてくれます:パッチをパッチの周りの単位半球に投影し、更に其れを底面の円盤に真っ直ぐ投影すると、形態係数は投影された面積を円盤の面積で割った物になります。
ヘミキューブ法(Michael CohenとDonald Greenberg、1985年)は各パッチの周りに半分の立方体を置き、其の面にZバッファでシーンをレンダリングし、各パッチが覆うピクセルの予め計算した重みを足し合わせます。
遮蔽も自然に扱えます。
計算例:3つのパッチとカラーブリーディング
ランプ、白い床、赤い壁で、全て同じ面積です(なので相反性により)。
形態係数は、、で、残りの光はシーンから出て行きます。
ランプは全てのチャンネルでを放ち、何も反射しません。
床は、壁はです。
ランプのラジオシティは只のです。
赤のチャンネルでは、床(W)と壁(R)について:
2つ目を1つ目に代入します:なので:
緑(と青)のチャンネルでは、壁は0.1しか反射しません:
直接光だけなら、床は、無彩色の灰色になる筈でした。
相互反射があるとです:赤のチャンネルが緑や青より9.4%強くなっています。
白い床が赤い壁の為にピンクがかったのです:カラーブリーディングを計算出来ました。
連立方程式を解く:ヤコビ法とガウス・ザイデル法
現実のシーンには何千ものパッチがあり、手で代入するには多過ぎます。
方程式は(はアルベドを並べた対角行列)、つまり連立1次方程式の形をしています。
全てので、のどの行の和も高々1なので、単純な反復で収束します:
- ヤコビ法:から始め、全ての新しい値を古い値から計算します:。回目の反復には、丁度回以下跳ね返った光の経路が含まれます。
- ガウス・ザイデル法:同じですが、新しい値を同じ回の中で次のパッチに直ぐ使います。此処では約半分の回数で済みます。
例の赤のチャンネル(は10のまま):
| 反復 | ヤコビ法 | ヤコビ法 | ガウス・ザイデル法 | ガウス・ザイデル法 |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 1 | 3.2 | 1.6 | 3.2 | 2.112 |
| 2 | 3.456 | 2.112 | 3.5379 | 2.1661 |
| 3 | 3.5379 | 2.1530 | 3.5466 | 2.1675 |
| 4 | 3.5445 | 2.1661 | 3.5468 | 2.1675 |
| 厳密解 | 3.5468 | 2.1675 | 3.5468 | 2.1675 |
ガウス・ザイデル法の1回目では、壁は既に床の新しい値3.2を使っています:。
漸進的改良法(プログレッシブリファインメント。Cohen、Chen、Wallace、Greenberg、1988年)は計算の向きを逆にします:全てのパッチが他の全てから光を集める代わりに、まだ配っていない光を一番多く持つパッチが其れを他の全てに放ち、次に明るいパッチが放ち、と続けます。
最初の数ステップ(光源が光を放った所)で使える画像が出来、其の後も連続的に良くなっていくので、ラジオシティ法を対話的な設計作業で使える様にしました。
結果を描く
ラジオシティが分かれば、其れはカメラではなくシーンに属します。
ラジオシティ法は視点非依存です:シーンの中を歩き回り、各フレームを普通のラスタライズで、パッチの値を頂点の色として描けます。
次は、パストレーシングの例と同じ空の箱を、壁1枚あたり8 × 8パッチ(320パッチ、形態係数は数値計算)で解いた物です:
直接光だけ(ヤコビ法1回)では天井は黒いままです。
完全な解は跳ね返った光で天井を照らし、色の付いた壁の近くの白い面に色を乗せます。
パッチ毎に1色で描くとパッチが四角く見えますが、パッチの中心の間で値を補間すると(第10章のグーローシェーディングの様に)滑らかになります。
限界
- 拡散面だけ:鏡も光沢のハイライトも屈折も無く、従ってコースティクスもありません。ラジオシティ法の長所(視点非依存)は正に此の仮定から来ています。
- メッシュ分割:鋭い影の境界には小さなパッチが必要で、形態係数の数はパッチ数の2乗で増えます。
- 実際には、レイトレーシングと組み合わせた2パス法が良く使われました:拡散光にはラジオシティ法、其の後目からのレイトレーシングで鏡面の効果を足します。
テクスチャに蓄えた事前計算の拡散光(ライトマップ、第11章)は、今日のゲームでの同じ考え方です:跳ね返る光をオフラインで1回計算し、後は引くだけです。
12.12 フォトンマッピング法とリアルタイムの大域照明
フォトンマッピング法
コースティクスは、目から始まるどんな手法にも難しい物です:経路はガラスを通った後で、小さな光源に正確に当たらなければなりません。
フォトンマッピング法はHenrik Wann Jensenが開発した手法で(1995年にNiels Jørgen Christensenとの共著で最初に発表、1996年に完全な2パスの大域照明手法として発表)、逆に光源から始めます。
- フォトントレーシング(1パス目):光源から沢山の「フォトン」を放ちます。各フォトンは光源のパワーの一部を運びます。反射や屈折を通して追い掛け、拡散面に着地した所で、其の位置、方向、パワーをフォトンマップ(近傍を素早く探せるkd木)に蓄えます。先にガラスを通ったり鏡で反射したりしたフォトンは、別の密なコースティクス用フォトンマップに入れます。
- レンダリング(2パス目):普段通り目からレイトレーシングします。拡散面に当たったら、近い方から個のフォトンを探し、其の密度から放射照度を推定し、BRDFを掛けます。
密度の推定:パワーの最も近い個のフォトンが半径の円盤の中にあるなら、
計算例:0.001 Wのフォトンが50個、 mの中に見つかったとします。
W/m²で、のランバート面は W/(m²·sr)を送り出します。
フォトンマッピング法には偏りがありますが(円盤上の平均が細部を少しぼかす)、一致性があります:フォトンを増やせば誤差は0に近付きます。
コースティクス、カラーブリーディング、関与媒質を、純粋なパストレーシングよりずっと効率良くレンダリング出来ます。
古典的な手法の比較
| ホイッテッドのレイトレーシング | ラジオシティ法 | パストレーシング法 | フォトンマッピング法 | |
|---|---|---|---|---|
| 経路(ヘックバート) | LD?S*E |
LD*E |
全ての経路 | 全ての経路、コースティクスLS+DEを効率良く |
| 拡散面の相互反射 | 無し | 有り | 有り | 有り |
| 鏡面反射と屈折 | 有り | 無し | 有り | 有り |
| コースティクス | 無し | 無し | 有り(但しノイズが多い) | 有り |
| ソフトシャドウ | 無し(点光源) | 有り(面光源) | 有り | 有り |
| 視点依存 | する | しない | する | フォトンマップはしない、レンダリングはする |
| 典型的な不具合 | 鋭過ぎる、真っ黒な影 | パッチが四角く見える、光漏れ | ノイズ | まだら模様 |
リアルタイムの大域照明(簡単に)
ゲームには1フレームに数ミリ秒しか無いので、事前計算と近似を組み合わせます:
- アンビエントオクルージョン(第11章):点の上の半球のうち、近くの形状に遮られている割合です。隙間や接地部分を暗くします。スクリーンスペース・アンビエントオクルージョン(SSAO)は深度バッファから其れを推定します。
- ライトマップとライトプローブ:オフラインで焼き込んだ跳ね返りの光を、テクスチャや空間内の標本点に蓄え、実行時に補間します。
- 環境マップによるイメージベーストライティング(次節)。
- 少ないサンプル数のハードウェア・レイトレーシングとデノイズ、そして此れらを幾つか組み合わせた動的なGIシステム。
リアルタイムの影、AO、GIは第2部で深く扱います。
検定のポイント
- ホイッテッドのレイトレーシングは、拡散面の相互反射(カラーブリーディング)、ソフトシャドウ、光沢反射、コースティクスを計算出来ない。
- ラジオシティ法は拡散面の相互反射とカラーブリーディングを扱えるが、鏡面反射は扱えない。視点非依存。
- 形態係数は幾何だけで決まる。相反性。閉じたシーンでは行の和が1。
- パストレーシング法は不偏なモンテカルロ法。ノイズなので、サンプルを4倍にするとノイズは半分。
- フォトンマッピング法:2パス(光源からのフォトントレーシング、其の後密度推定を使ったレンダリング)。コースティクスに強い。
12.13 イメージベーストレンダリング
此処までは全て、形状と材質から始めていました。
イメージベーストレンダリング(IBR)は、形状の代わりに、又は形状と一緒に、写真(又は事前にレンダリングした画像)を主な入力にします。
写真には現実世界の光の伝わり方が既に全て含まれているので、其れを再利用するレンダラーは低いコストで写実的になれます。
イメージベーストライティング
イメージベーストライティング(IBL)は、本物の周囲を撮った写真で合成した物体を照らします。
写真は全ての方向を覆う環境マップ(第11章)で、HDR(高ダイナミックレンジ)でなければなりません:太陽やランプは壁の何千倍も明るく、8ビットの写真では同じ白に潰れてしまうからです。
1点での光を撮った此の様なパノラマをライトプローブと呼びます。
古典的な撮り方は、鏡の様な球を幾つかの露出で撮影する方法です。
Paul Debevecは1998年(論文「Rendering Synthetic Objects into Real Scenes」)に、此の方法でレンダリングした物体を写真に入れ込む方法を示しました。
IBLは今では、視覚効果(撮影現場でHDRのプローブを撮り、CGのクリーチャーを其れで照らす)でもゲーム(空のキューブマップが全てを照らす)でも標準です。
マップを使うには、レンダラーはマップをとしてレンダリング方程式を計算します。
放射輝度の一様な環境の中のランバート面については、12.2節と12.3節から:
の一様な空の中にあるの灰色の球は、形に関係無く、全ての点で同じ放射輝度を見せます。
なら丁度空と同じ放射輝度になり、背景に溶け込んで消えます。
レンダラーは正に此れをテストに使います(「ホワイトファーネステスト」:一様な白い環境の中の白い物体は消えなければならない。消えなければ、レンダラーはエネルギーを増やすか失っている)。
本物のマップでは、積分をマップのぼかした版(拡散用の放射照度マップ、光沢用のプリフィルタードマップ)として事前計算します。
OpenGL 第24章で其れらを作ります。
パノラマ
パノラマ画像は、1点から全ての方向を撮った物です(何枚もの写真を繋ぎ合わせます)。
其の点からなら、見る人は自由に見回せます:レンダラーは今の視線方向に当たるパノラマの部分を投影し直すだけです。
QuickTime VR(Shenchang Eric Chen、1995年)は円筒形のパノラマで此れを広めました。
地図のストリートビューや360°写真も同じ仕組みです。
限界:回転は出来ますが移動は出来ません。
パノラマは1点に届く光しか知らないからです。
視点補間とモーフィング
近い視点から撮った2枚以上の写真(又はレンダリング)と、其のピクセル同士の対応(深度やマッチングから得る)があれば、各ピクセルを対応に沿って動かす事で、其の間の新しい視点の画像を合成出来ます:視点補間(ChenとWilliams、1993年)です。
モーフィングは同じ事を2枚の違う画像(或る顔が別の顔に変わる等)の間で行います。
両方の画像を中間の位置へ変形し、クロスフェードします。
全ての入力画像で隠れていた面の所には穴が開きます。
プレノプティック関数とライトフィールド
画像はどこまでを表せるのでしょうか?
プレノプティック関数(Edward AdelsonとJames Bergen、1991年)は、目が見得る全てです:全ての位置、全ての方向、全ての波長と時刻での放射輝度です:
時刻を固定し(静的なシーン)、波長をRGBに置き換えると、5次元(位置と方向)が残ります。
ここで12.2節の放射輝度の性質を使います:何も無い空間では、放射輝度は光線に沿って一定です。
物体の凸包の外では、光線に沿って動いても放射輝度は変わらないので、5次元のうち1つは余分です:4次元が残ります。
此の4次元の関数「全ての光線の放射輝度」がライトフィールド(日本の研究では光線空間とも呼びます)です。
1996年のSIGGRAPHで、2つの論文が其れをレンダリング手法にしました:Marc LevoyとPat HanrahanのLight Field Renderingと、Steven Gortler、Radek Grzeszczuk、Richard Szeliski、Michael CohenのThe Lumigraph(ルミグラフ)です。
どちらも光線を、2枚の平行な平面と交わる位置、1枚目のと2枚目ので表します。
2平面パラメータ化です:
ライトフィールドは、平面に格子状に並べたカメラ(又は格子の上を動かした1台のカメラ)で撮ります。
各写真が、1つのについて全てのを与えます。
新しい視点の画像には形状が全く要りません:各ピクセルについて其の光線のを計算し、放射輝度を引くだけです(隣の標本の間は補間します)。
ルミグラフは其の補間を良くする為に、大まかな形状を加えます。
代償はメモリです。
計算例:のカメラ位置で、それぞれピクセルのRGBなら
で、控えめな解像度の小さな物体1つでこうなります。
其の為、どちらの論文もデータを強く圧縮しました。
センサーの前にマイクロレンズアレイを置いたライトフィールドカメラは、小さなライトフィールドを1回の撮影で記録し、撮った後でピントを合わせ直せます。
ビルボードとインポスター
IBRの安価な親戚は、全てのゲームで使われています:
- ビルボードは、常にカメラの方を向くテクスチャ付きの四角形です:遠くの木、煙や炎のパーティクル、草など。
- インポスターは、遠くの複雑な物体を、其の場で又は事前にレンダリングした画像で置き換えます。見る角度が変わり過ぎたら更新します。
- 2Dゲームのスプライトは、一番単純なイメージベーストレンダリングです。
写真からモデルへ
IBRは逆向きにも働きます:イメージベーストモデリングは沢山の写真から形状とテクスチャを再構成します。
例えばフォトグラメトリです。
入力装置は第17章で扱います。
ライトフィールドの現代の子孫は、写真からシーンを学習して新しい視点の画像をレンダリングします:NeRF(ニューラル放射輝度場、2020年)は、位置と方向から色と密度を返すニューラルネットワークにシーンを蓄え、3D Gaussian Splatting(2023年)は、ラスタライザーがリアルタイムで描ける何百万個もの小さな色付きのぼんやりした粒でシーンを表します。
第2部のニューラルレンダリングの章で扱います。
検定のポイント
- IBRは形状の代わりに(又は形状と一緒に)画像からレンダリングする。古典的な技法はIBL、パノラマ、視点補間とモーフィング、ライトフィールド、ビルボード。
- 本物の光源は周囲よりずっと明るいので、IBLにはHDRの環境マップ(ライトプローブ)が必要。
- パノラマでは決まった1点から見回せるが、移動は出来ない。
- プレノプティック関数:7次元(位置3、方向2、波長、時刻)。ライトフィールド/ルミグラフ:何も無い空間では放射輝度が光線に沿って一定なので4次元。2平面パラメータ化。
12.14 まとめ
- 局所照明は光源だけを使い、大域照明は他の面を経由する光も追う:相互反射、カラーブリーディング、反射、屈折、コースティクス。
- 放射輝度(W/(m²·sr))は光線に沿った光で、何も無い空間では光線に沿って一定。放射照度(W/m²)は面に届く光。一様な空では。
- BRDFは入射する放射照度あたりの出て行く放射輝度で、相反性とエネルギー保存を満たす。ランバート面は。マイクロファセットモデル(クック・トランス)はD、F、Gを掛け合わせる。
- フレネル:(ガラスで0.04)、シュリックの近似。どの面もすれすれの角度では鏡になる。
- スネル:。臨界角を超えると全反射(ガラスで41.81°、水で48.75°)。
- 表面下散乱(BSSRDF)が肌や大理石を半透明にする。関与媒質は吸収し散乱する(ランベルト・ベール)。レイリー散乱()が空を青く、ミー散乱が雲を白くする。コースティクスは
LS+DEの経路。 - レンダリング方程式:出て行く光 = 放つ光 + BRDF × 入って来る光 × 余弦の積分。再帰的で、どの手法も其れを近似している。
- ホイッテッドのレイトレーシング:一次レイ、シャドウレイ、反射レイ、屈折レイがレイツリーを作る。拡散面の相互反射、ソフトシャドウ、光沢反射、コースティクスは無し。レイと球:。
- 高速化:バウンディングボリューム、BVH、均一格子、八分木、kd木で、何百万回の判定が数十回になる。
- 分散レイトレーシングはレイをばらまいてソフトシャドウ、光沢反射、被写界深度、モーションブラーを得る。パストレーシング法はレンダリング方程式をモンテカルロ法で解き、ノイズは。重点的サンプリングとロシアンルーレットを使う。
- ラジオシティ法:拡散面のパッチについて。形態係数は幾何だけで決まる()。ヤコビ法、ガウス・ザイデル法、漸進的改良法で解く。視点非依存で、鏡面は扱えない。
- フォトンマッピング法:光源からのフォトンをフォトンマップに蓄え、其の後密度推定でレンダリングする。コースティクスに強い。
- イメージベーストレンダリング:HDRのライトプローブによるIBL、パノラマ、視点補間、モーフィング、(7次元のプレノプティック関数から来る)4次元のライトフィールド、ビルボードとインポスター。NeRFとGaussian Splattingは其の現代の子孫。
12.15 用語
| English | 日本語 |
|---|---|
| photorealistic rendering | 写実的表現(フォトリアリスティックレンダリング) |
| local illumination | 局所照明 |
| global illumination | 大域照明 |
| interreflection | 相互反射 |
| color bleeding | カラーブリーディング |
| caustics | コースティクス |
| light path notation | 光路の表記(ヘックバートの表記) |
| solid angle, steradian | 立体角、ステラジアン |
| radiant flux | 放射束 |
| radiant intensity | 放射強度 |
| irradiance | 放射照度 |
| radiance | 放射輝度 |
| BRDF | 双方向反射率分布関数 |
| reciprocity | 相反性 |
| energy conservation | エネルギー保存 |
| albedo | アルベド(反射率) |
| Lambertian surface | 完全拡散反射面(ランバート面) |
| glossy reflection | 光沢反射 |
| microfacet | マイクロファセット |
| Fresnel effect | フレネル効果 |
| Schlick's approximation | シュリックの近似 |
| refractive index | 屈折率 |
| Snell's law | スネルの法則 |
| total internal reflection | 全反射 |
| critical angle | 臨界角 |
| dispersion | 分散 |
| subsurface scattering | 表面下散乱 |
| translucent | 半透明 |
| participating media | 関与媒質 |
| Rayleigh scattering / Mie scattering | レイリー散乱/ミー散乱 |
| rendering equation | レンダリング方程式 |
| ray tracing | レイトレーシング法 |
| ray casting | レイキャスティング法 |
| primary ray / shadow ray | 一次レイ/シャドウレイ |
| reflection ray / refraction ray | 反射レイ/屈折レイ |
| ray tree | レイツリー |
| acceleration structure | 高速化データ構造 |
| bounding volume hierarchy (BVH) | 階層バウンディングボリューム(BVH) |
| uniform grid / octree / kd-tree | 均一格子/八分木/kd木 |
| distributed ray tracing | 分散レイトレーシング |
| Monte Carlo integration | モンテカルロ積分(モンテカルロ法) |
| path tracing | パストレーシング法 |
| importance sampling | 重点的サンプリング |
| Russian roulette | ロシアンルーレット |
| radiosity | ラジオシティ法 |
| patch | パッチ |
| form factor | 形態係数(フォームファクタ) |
| hemicube | ヘミキューブ |
| progressive refinement | 漸進的改良法 |
| view independent | 視点非依存 |
| photon mapping | フォトンマッピング法 |
| ambient occlusion | アンビエントオクルージョン(環境遮蔽) |
| image-based rendering (IBR) | イメージベーストレンダリング |
| image-based lighting (IBL) | イメージベーストライティング |
| high dynamic range (HDR) | 高ダイナミックレンジ(HDR) |
| light probe | ライトプローブ |
| panorama | パノラマ |
| view interpolation | 視点補間 |
| morphing | モーフィング |
| plenoptic function | プレノプティック関数 |
| light field | ライトフィールド(光線空間) |
| lumigraph | ルミグラフ |
| billboard / impostor | ビルボード/インポスター |
12.16 課題
- ★ ダイヤモンド()のと、空気に対する臨界角を求めて下さい。次に、シュリックの近似で水()の80°での反射率を、又、水()からガラス()へ30°で進む光の屈折角を求めて下さい。
- ★ レイがから方向へ進み、球の中心は、半径は3です。2つのの値、交点、単位法線、反射方向を求めて下さい。(確認:法線はの定数倍で、反射方向は単位ベクトルになります。)
- ★★ 或るパストレーサーは1画素あたり64サンプルで8%のノイズを示します。2%にするには、又1%にするには何サンプル必要ですか?重み0.3の経路がのロシアンルーレットに出会います。其の後に取り得る重みを確率と一緒に挙げ、重みの期待値が変わらない事を示して下さい。
- ★★ 2つのパッチが向き合っています:パッチ1は、、の光源、パッチ2は、、で、です。相反性でを求め、ラジオシティの方程式を厳密に解き、から始めてヤコビ法を3回行い、収束する様子を見て下さい。
- ★★★ 次の経路をヘックバートの表記で分類し、ホイッテッドのレイトレーシング、ラジオシティ法、パストレーシング法、フォトンマッピング法のどれがそれぞれをレンダリング出来るかを答えて下さい:窓から艶消しの床に差し込む光を鏡越しに見た物、クロムの球に映る赤い壁、別のガラス越しに見たガラスのコースティクス。次に、「先にラジオシティ法、後でレイトレーシング」の2パスのレンダラーでも何故コースティクスを作れないのかを説明して下さい。
選択問題
問1 ★ 次のうち、大域照明の手法について正しい物はどれか。
| あ | ホイッテッドのレイトレーシングは、シャドウレイを再帰的に辿るので、艶消しの面同士のカラーブリーディングを計算出来る。 |
| い | ラジオシティ法は、形態係数が反射方向を含むので、鏡面反射をレンダリング出来る。 |
| う | ラジオシティ法の結果はカメラの位置に依存するので、カメラが動く度に計算し直さなければならない。 |
| え | ラジオシティ法は拡散面同士の相互反射を計算し、其の結果は視点に依存しない。 |
| お | パストレーシング法は、重点的サンプリングを使う限りノイズを生じない。 |
問2 ★ 次のうち、ラジオシティ法の形態係数について正しい物はどれか。
| あ | パッチのアルベドに依存する。 |
| い | パッチの面積を、とすると、が成り立つ。 |
| う | 2つのパッチの距離に比例して大きくなる。 |
| え | 平らなパッチではである。 |
| お | 光源の色が変わる度に計算し直さなければならない。 |
問3 ★★ 次のうち、ライトフィールドレンダリングについて正しい物はどれか。
| あ | 新しい視点の画像を合成するには、物体の正確な3次元モデルが必要である。 |
| い | 位置、方向、波長、時刻の7次元の関数である。 |
| う | パノラマと同じく、決まった1点から視線の向きを回転させる事しか出来ない。 |
| え | 光線を、2つの同心球との交点で表す。 |
| お | 何も無い空間では放射輝度が光線に沿って一定なので、光線の放射輝度を、例えば2枚の平面との交点による4次元の関数として表す。 |
12.17 実践課題
小さな2次元のシーンで、1本のレイをホイッテッドの方法で手で辿り、其の後ラジオシティ法で跳ね返る光を加えます。
方眼紙(少なくとも26 × 16マス、1マス = 1単位)、定規、分度器、コンパス、鉛筆、色ペン、電卓を用意して下さい。
シーンは断面図です:床は直線、ガラスの円盤(なので)は中心、半径5、点光源はにあって放射強度は W/sr、目はにあり、方向を見ています。
- 描く。 床、円盤、光源、目を描きます。一次レイを描きます。
- 交差。 、、、判別式を計算し、入る点を求めます。其処での単位法線とを計算します。に印を付け、法線を描きます。
- フレネル。 シュリックの近似でを計算します。ピクセルのうち、反射レイから来る割合と屈折レイから来る割合はどれだけですか?
- 反射。 を計算して描きます。床に当たりますか、其れともシーンから出て行きますか?(出て行くなら、黒い背景が見えます。)
- 入る時の屈折。 スネルの法則でを、12.5節のベクトルの式で屈折方向を計算します。図の上で分度器で角度を測ります。が円盤から出る点を求め(ヒント:円の中の弦の長さは)、其処での法線を計算し、もう一度屈折させて外に出します(。全反射が起きない事を確かめます)。
- 床に当てる。 出て行くレイがと交わる点を求めます。から光源へシャドウレイを飛ばし、レイと円の式で円盤との交差を判定します。遮られていなければ、での放射照度と、(ランバート面)の床の放射輝度を計算します。
- 集める。 此のピクセルのレイツリー(目、、反射の枝、屈折の枝、シャドウレイ)を描き、2つ目の面での小さな損失は無視して、ピクセルの放射輝度をとして計算します。
- 跳ね返り。 今度はの周りの照らされた床をパッチ1( = 手順6の床のラジオシティ、)、其れに向き合う壁のパッチをパッチ2(、)とし、面積は等しくとします。ガウス・ザイデル法を3回行い、厳密解と比べます。跳ね返りで床のラジオシティは何%上がりますか?
自分で確かめる方法:、、の長さは全て1です。
はスネルの法則の通り、と角度を成します。
円は対称なので、レイは入った時と同じ角度で法線に対して円盤から出て行きます(出る角度が違ったら、符号の間違いを探して下さい)。
とを足すと1になります。
そしてラジオシティの反復は、厳密解を飛び越さずに、着実に其れへ向かって増えていきます。
コメント(0)
まだコメントはありません。
ログインするとコメント出来ます。