物理ベースレンダリングについてメモ
はじめに
この記事はシリーズ記事です。目次はこちら。
この記事では物理ベースレンダリングについてメモ書きをして、参考になる記事をメモします。
素人が調べたことまとめているだけなので誤りが含まれているかもしれません。 誤りを見つけた方は連絡をくれると嬉しいです……。 そして、参考資料に挙げている記事のほうがこの記事よりよっぽどわかりやすいので、この記事のことは忘れて参考資料を見たほうが幸せになれるかもしれません……。
物理ベースレンダリングとは
3Dのシェーディングのモデルには感覚的なモデルと物理ベースのモデルというものがあります。
Phongシェーディングによる鏡面反射モデルは、反射ベクトルと視線ベクトルが近いとき明るくなるという性質をもとに感覚的に作られたモデルになります。
一方、物理ベースのモデルというのは物理的な根拠のある式や実際の物理データに基づくマテリアルなどを利用します。 物理的根拠に基づいているというのは、エネルギー保存則をおおよそ満たしていて、BRDF導出元の幾何学モデルが物理的な微細構造を考慮した上で導出していて、パラメータが実際の想定した測定値にうまくフィットしているようなものです。
エネルギー保存則
エネルギー保存則というのは入射する光より射出する光が大きくならないようにできているものです。 前回に書いたような何も考えていないlambertやblinn-phongはエネルギー保存則をじつは満たしていないものです。
微小構造を表現する幾何学モデル
幾何学モデルというのはマイクロファセット理論というのがよく用いられています。 この理論に基づいた導出をされた式は何も考えずに作られた式よりもっともらしい結果になりそうです。
パラメータと測定値
よくある物理ベースモデルでは入力となるデータのalbedoとmetallicとroughnessの値の組み合わせで現実のマテリアルを表現します。 もっとパラメータが増えることもありますが……。 このパラメータで現実の実際の材質を表現できるようになっています。
このパラメータはスキャンされたデータを使うことが多いです? 従来のようにアーティストが感覚的に色を決めるのではなく現実世界を測定したデータをもとに作成するのが物理ベースレンダリングの特徴です。
Behind the Scenes of Substance Source’s Scanned Materials | Substance
物理「ベース」レンダリング
物理ベースレンダリングと言っていて物理レンダリングと言わないのは、物理現象をすべて再現しているわけではないというのがあります。 実測データになるべくフィットするように作られていますが、例えば光の回析現象のような波動としての性質は表せなかったりします。
まあ、現実の大体のいい感じの近似になっているモデルだと思っておけば問題ないです?
光の単位
最初に物理ベースレンダリングをやる上で重要な光の種類と光の単位について見ていきます。
光には「放射量」と「測光量」の2種類があります。
放射量は光を純粋なエネルギーとして捉えた測り方です。 光のエネルギーはW(ワット)などの物理で出てくる単位で表すことができます。
測光量は人間の目が受けて実際に感じる明るさです。 人間の目は光の波長によって感じる光の明るさに差があります。 それも考慮した光の量ということになります。
放射量は物理量ですが、測光量は心理物理量と呼ばれます。
放射量や測光量は幾何学的な分類があり、特にレンダリングで気にするのは放射束、放射輝度、放射照度などがあります。 それぞれを見ていきます。
放射束・光束
放射束はある領域を単位時間あたりに通過する光のエネルギーのことです。 放射束の単位はW(ワット)です。
これに対応する測光量は光束で単位はlm(ルーメン)です。 LED電球とかに書かれている単位ですね。
放射輝度・輝度
放射輝度は単位射影面積あたりかつ単位立体角あたりの放射束です。 方向性を強く意識した光量単位という感じです。
ライティング計算で放射輝度を利用するにはBRDFとコサイン項を乗算し半球面上に積分します。 レイトレーシングなどでモンテカルロ積分を行うことが多いようです? リアルタイムレンダリングというよりレイトレで意識することの多い単位かもしれません。
対応する測光量は輝度で、単位は(カンデラ/平方メートル)、またはnit(ニト)です。
放射照度・照度
放射照度は単位面積あたりの放射束です。 lmの点光源があったときに離れた位置で垂直に光が指す場合の放射照度は、半径の球の表面積がなのでと計算できます。
対応する測光量は照度で、単位はlux(ルクス)です。
物理量と心理物理量のおおよその変換
人間が一番敏感な緑色の光(波長555nm)で1Wの放射束は、およそ683.002lm(ルーメン)だそうです。
同じW数でもスペクトルによって即光量は変わってくるのであれですが、おおよその値で変換をしたいときは683.002をWにかけてやればおおよそのlmになります。
色について
光には色がついています。 これについて軽くメモします。
スペクトルレンダリングとRGBレンダリング
RGBの3次元ベクトルを物理量または心理物理量に掛け合わせて3次元ベクトルで光を表現するようです? これは非常に雑な近似で、例えばナトリウムランプのような黄色の波長しか出ていない光について、反射する材質がその波長を反射するかどうかで見え方が変わるはずのものを、RGBで表現すると黄色を表現するためにRG成分に値を持つ光として表現されるため、RとGを反射する材質ならば何でも反射されてしまいます。
オフラインレンダリングなどではスペクトルレンダリングというものが行われたりもするようです。 ナトリウムランプなどの特定の波長のみが放出されるライトなどが正しく扱われることが期待できます。
コストなどの問題からリアルタイムレンダリングではRGBレンダリングが主流のようです。
RGB空間の種類
RGB空間にもいくつかの種類があります。
sRGB色空間
一番使われるのはsRGB色空間です。 これはLinearとGammaのときのsRGBとはまた別なので注意です。
ほとんどのコンピュータのモニタはsRGBが使われており、出力フラグメントに何も考えずにRGBの値を入れて表示されるのはsRGBです。
ACEScg色空間
映画芸術科学アカデミーによる映画のコンピュータグラフィックスレンダリング用に開発された色空間です。 レンダリング用の作業色空間に使い、その後ディスプレイ用に変換します。
ACESではHDR画像を各種モニタで表示する際のトーンマッピングも定義されています。 ACESによるトーンマッピングはディスプレイによらない中間表現への変換RRTと、各種モニタごとに調整されたODTという変換の組み合わせでなっています。
その他の色空間
Adobe 1998色空間、DCI-P3色空間、Rec. 2020色空間など色々あります。
色空間とレンダリング
レンダリング操作は色空間で得られる結果が異なり、DCI-P3やACEScg色空間でレンダリングを粉うと、線形sRGB空間で行うよりも正確な結果を生み出すことがわかっています。
今回のシリーズではACES色空間でレンダリングを行う予定です。
レンダリング方程式
レンダリングに使う色と光について説明をしてきました。 それでは次にレンダリングの計算についてみていきます。
レンダリングの計算とはカメラのセンサーに届く放射輝度、または輝度を求めることになります。 物理ベースのレンダリングは、何らかのビュー レイのセットに沿ってカメラに入る放射輝度を計算することになります。
ボリュームレンダリングのような媒質で満たされた空間を通過して伝搬する光は吸収や散乱などが起こりますが、とりあえずそれらの媒質が存在しないものとして考えることにします。 その場合、カメラに入る放射輝度は最も近いオブジェクトのサーフェスからカメラの方向への放射輝度に等しくなります。
をカメラの位置、をビュー レイに沿う方向として入射放射輝度はと表記されます。 をビュー レイと最も近いサーフェスの交点、のビューの方向として放射輝度というものを考えたとき、先に述べた等しくなる関係から、
が言えます。
次の目標はを求めることです。 の位置から放出される放射輝度は自己発光により放射される放射輝度と反射される放射輝度の和となります。
ここでは透明なサーフェスやグローバル表面化散乱を考えないこととします。 すると、の点に当たる光を外向きに向け直して戻す、ローカルな反射現象を見ることでを考えられます。 位置のローカルな反射は、入る光の方向と視線方向に依存した関数を利用して次のように書き換えられます。
この式をレンダリング方程式と呼びます。 はの位置の法線方向の半球全体での積分です。
この式について詳しく見ていきましょう。
BRDF
この先ほど導入した関数がかの有名なBRDF(双方向反射率分布関数)です。 ある地点に方向から入射した光のどれだけが方向へ反射するのかという反射分布を示す確率密度関数となっています。
注意が必要なのは入社する放射輝度と反射する放射輝度の比ではないということです。 入射光については放射照度となっています。
これはレンダリング方程式でコサイン項が式の上で分離するからこのように定義されているらしいです。
このBRDFは実は正確にはSVBRDFまたはSBRDFとよんだほうが正しかったりします。 もとの導出のBRDFは一様なサーフェスに定義され、どこでも同じとされていましたが、基本的に一様なサーフェスというのは現実世界には存在しません。 単一の素材であっても、かすり傷やシミなどで反射特性が部分的に変化します。 このように場所によって反射特性が違うサーフェスを意味扱うためには位置に依存した関数として定義されています。 このよう関数はSVBRDF(空間可変BRDF)やSBRDF(空間BRDF)と呼ばれます。 が、実際にはより短いBRDFという言葉がSBRDFを表す用語として使われることが多いようです。
スペクトルレンダリングではなくRGBレンダリングを行う場合、このBRDFはRGBの3次元ベクトルを返すことになります。
放射輝度とBRDFとレンダリング方程式
レンダリング方程式はを積分し求める形になっています。
この式はリアルタイムレンダリングでは直接使わなかったりします。 レイトレではこちらを主に使うかも。 今回扱っているラスタライザ形式でもIBLを実装する際にはこちらの式を意識することになりますが……。
積分計算が入り解析的に解けないのでモンテカルロ法などを使って数値積分することになります。 リアルタイムでは重たい処理になるのでこの式を使わない、あるいはIBLなど事前計算をしておくなどの手法が使われます。
放射照度とBRDFとレンダリング方程式
リアルタイムレンダリングで使うのはこちらの形式です。
積分が消えて放射照度をBRDFに掛けるだけになりました。
ポイントライト、スポットライト、ディレクショナルライトはこの放射照度をBRDFに掛け合わせる形で計算します。 IBLは放射輝度を使うのであれですが……。 リアルタイムではこちらの放射照度を使う計算がメインになります。
各種ライトの強さとレンダリング時の扱い
放射照度で計算できると書きました。 それについて詳しく見てみます。
IBLについてはまた別の機会に。
平行光源
平行光源のライトの強さは放射照度または照度で入力します。 太陽光が100000luxなどというやつですね。 この放射照度は垂直の場合の照度なのでBRDFに掛けるまえにコサイン項をかけることになります。
ポイントライト・スポットライト
一方、ポイントライトやスポットライトは放射照度で定義するのは都合が悪いです。 というのも、距離で減衰するからですね。 距離とは関係ない放射束W、もしくは光束lm(ルーメン)を光源の強さとして利用します。
この放射束をどうやってBRDFに掛ける放射照度に変換するかというと、次のようにします。
これは次のようにして導かれます。
の光源から離れた位置の放射照度はです。 というのは球の表面積で、放射束がこの面積に均等に割り振られることを考えると放射照度はで割った値になります。 また、斜めから入射してくる場合、コサイン項が必要となります。
ポイントライト・スポットライトの距離の減衰
ポイントライトの距離の減衰はそのまま組み込むと問題が生じる場合があります。
一つはが0の場合。 0除算で発散をしてしまいます。 これに対する対処としては例えばFrostbiteというゲームエンジンでは、にへのクランプを行います。
https://seblagarde.files.wordpress.com/2015/07/coursenotesmovingfrostbitetopbrv32.pdf
もう一つは大きな距離でほとんど0になったものについての扱いです。 残念ながらは有限の距離では0にはなりません。 有限の距離で0になってくれればそのライトの計算を省くことができ効率が良くなります。 このために先に上げたFrostbiteというゲームエンジンでは窓関数をかけています。
ここでは値が負ならば2乗の前に0クランプをします。 がライトの最大半径です。
スポットライトの強さ
スポットライトは、その放射束が特定の方向のみに射出されていると考えると、W数が同じならばコーンの角度が小さいほど明るくなるはずです。 Frostbiteではこれがアーティストの作業がしにくくなり、また最適化しにくいという問題からこの挙動は再現しないことにしたそうです。 Frostbiteでは次の式でスポットライトの強さを計算しています。
この記事のシリーズでもそれに習って実装していくことにします。
BRDFの式
ここまでBRDFの式の中身については触れてきませんでした。 これからその中身について眺めていくことにします。
拡散反射と鏡面反射
BRDFは2つの成分に分離できます。 これ入ってしまえば近似の一つですが、反射の仕方が大きく違うため分離しても十分もっともらしい見た目を提供できます。
Wes McDermott「The Comprehensive PBR Guide by Allegorithmic - vol. 1 Light and Matter : The theory of Physically-Based Rendering and Shading」©Allegorithmic から引用
拡散反射というのは光が物体と衝突して、そのうち屈折して物体内に侵入した分が、散乱現象の結果再び物体表面の外へ出ていく現象です。 方向がばらばらになっているのが特徴です。
SSS(表面化散乱)を思い浮かべる人もいるかも知れません。 厳密にはSSSとして扱わなければならないものですが、表面化散乱距離が十分に短くカメラが遠い場合などは、光が入射した点から射出されるものと見なし、単純化されたモデルとして捉えられます。 このような入射と射出が同じ表面化散乱と区別してSSSをグローバル表面化散乱と言ったりもするようです?
鏡面反射は物体表面で入射光を鏡面反射方向に反射するものです。 通常、物体表面にはある程度の粗さがあるため、鏡面反射方向だけでなく若干拡散します。 これもまとめて鏡面反射成分として扱います。
拡散反射BRDF
拡散反射BRDFの式を見てみます。 式にはいくつか種類がありますが、ここでは正規化ランバートを挙げます。 拡散反射(diffuse)成分のBRDFは
です。 はディフューズアルベドです。
以前実装した普通のLambertシェーダはで除算していませんでした。 これは実はエネルギー保存則を満たしていないものとなります。 で除算することで正規化しています。 というのはの半球積分から導出されます。 導出に興味のある方は参考資料の方を見てください。
これ以外にも様々な拡散反射BRDFがありますがそれは参考資料の方を見てください。
鏡面反射BRDF
鏡面反射のBRDFモデルにはCook-Torranceモデルを使うのが定石です。 Cook-Torranceモデルは次のような式で表現されます。
F
Cook-Torranceモデルの式のがフレネル項です。 Schlickの近似式で次のように表現されます。
はハーフベクトルです。
の値は垂直入射におけるフレネル反射係数です。
metallicが1の場合、BaseColorテクスチャ経由でが渡されることになります。
metallicが0の場合は、vec3(0.04)
が使われます。
この4%というのは一般的な不導体を網羅する値だそうです。
マイクロファセット理論
先のCook-Torranceモデルの式は微正面(マイクロファセット)理論をもとに作られた式です。 1px未満に落ち込んでしまう微正面というものを扱います。 マイクロファセットは、次の図のようにガタガタした面として考えられます。
Wes McDermott「The Comprehensive PBR Guide by Allegorithmic - vol. 1 Light and Matter : The theory of Physically-Based Rendering and Shading」©Allegorithmic より引用
マイクロファセットは微小面とは言いますが、波動光学が必要になるものは考えないことにします。 幾何光学の領域で考えることができます。
このマイクロファセット平面にあたったときにどの方向に反射するかというのを考えます。 微正面の向きはややランダムで、その「巨視的なサーフェスの法線」に強いピークがあります。 ランダムさをサーフェスの粗さとして与えると、あらさが大きいほどマイクロファセットの法線は大きく広がります。 すると反射がぼやけるような効果を生み出します。
殆どのサーフェスでは微小サーフェス法線の分布は等方性ですが、ものによっては異方性のものがあります。
マイクロファセット理論では、ただ単にマイクロファセットの法線分布を扱うだけではなく、シャドウイングとマスキングも式に含めます。
マイクロファセット理論を活用した式の中にはさらに相互反射を考えるものもあったりしますが、基本的には法線分布と幾何減衰を考えるのがマイクロファセット理論です。
D
Cook-Torranceモデルの式のが法線分布関数(NDF)です。
式にはいろいろな種類がありますが、ここではGGX(Throwbridge-Reiz)を紹介します。
この式はエネルギー保存が考慮され長いテールを持ちスーパーラフを表現できるモデルです。 はラフネスの値です。
ほかの式については参考資料を参考にしてください。
G
Cook-Torranceモデルの式のが幾何減衰項です。 シャドウイングとマスキングを考慮する項です。
よく使われるのはSmithモデルにSchlickの近似式を使ったものです。
拡散反射と鏡面反射を組み合わせたBRDF
拡散反射と鏡面反射のBRDFについて述べました。 これを組み合わせて一つのBRDFとして扱います。
単純に足し合わせるとエネルギー保存則に違反するのでという拡散反射成分の光の割合を用いて次のようにします。 鏡面反射光にはで鏡面反射成分の割合がすでに入っているので掛ける必要がありません。
このの値を求めるのに必要なはmettalicパラメータをベースに金属の場合BaseColorを、非金属の場合は4%のグレーを入れるようです。 そうして求めたから次のようにしてを求めます。
更に複雑なBRDF
異方性やクリアコートを扱えたり、さらにレイヤーになったマテリアルを扱えたりとバリエーションは色々あります。 興味があれば調べてみると良いでしょう。
露出
カメラにやってくる放射輝度を求めることができました。 これをディスプレイに表示するには露出というものを考える必要があります。
現実のカメラを考えると露出というのはシャッタースピードやセンサー感度、絞りといった要素で決まります。 これらの要素を一緒くたにして露出として特定の定数をかけることで画面に表示する明るさを決めます。
Auto exposure
ゲームなどで使うにはシーンの明るさに応じて露出の値を変更する実装を行う事が多いです。 明順応や暗順応などをエミュレートすることもあります。
物理ベースカメラ
Frostbiteというゲームエンジンでは物理ベースカメラというものが実装されています。 露出をちゃんとシャッタースピードとセンサー感度と絞りから求めます。 これらの値を他のポストエフェクトの被写界深度などに与えることでより正確なポストエフェクトがかけられます。
- Implementing a Physically Based Camera: Understanding Exposure | Placeholder Art
- Implementing a Physically Based Camera: Manual Exposure | Placeholder Art
- Implementing a Physically Based Camera: Manual Exposure | Placeholder Art
トーンマッピングとガンマ補正
HDRレンダリングではLDRなディスプレイ向けにトーンマッピングを施す必要もあるでしょう。
トーンマッピングにもいろいろなものが提案されていて、Reinhardは有名な初期に使われたトーンマッピングオペレータです。
この記事のシリーズではACESの規格のトーンマッピングを利用します。
参考資料
- リアルタイムレンダリング 第4版 (Real Time Rendering Fourth Edition 日本語版) | Tomas Akenine-Moller, Eric Haines, Naty Hoffman, 髙橋 誠史, 今給黎 隆, 加藤 諒, 中本 浩 |本 | 通販 | Amazon
- LearnOpenGL - Theory
- LearnOpenGL - Lighting
- ColorSpace for CGI Artist, Part II : ACES(cg) – VFX Harry's Desk
- レイトレーシングにおける放射輝度って結局何なのか?
- BRDF,Irradiance,Radianceの定義
- 基礎からはじめる物理ベースレンダリング - Qiita
- 基礎からはじめる物理ベースレンダリング(実装編) - Qiita
- 拡散BRDF - Qiita
- 鏡面BRDF - Qiita
- 物理ベースレンダリングを柔らかく説明してみる(1) - Qiita
- 物理ベースレンダリングを柔らかく説明してみる(2) - Qiita
- 物理ベースレンダリングを柔らかく説明してみる(3) - Qiita
- 物理ベースレンダリングを柔らかく説明してみる(4) - Qiita
- 物理ベースレンダリングを柔らかく説明してみる(5) - Qiita
- [Unity] PBR(物理ベースレンダリング)をやってみる - Qiita
- GLSLで物理ベースシェーディング - Qiita
- マイクロファセットの分布関数 D(m) について - OLD hanecci’s blog : 旧 はねっちブログ
- Physics and Math of Shading (4) - graphics.hatenablog.com
- 脱・完全鏡面反射~GGXについて調べてみた~
- CG Education
- Implementing a Physically Based Camera: Understanding Exposure | Placeholder Art
- Implementing a Physically Based Camera: Manual Exposure | Placeholder Art
- Implementing a Physically Based Camera: Manual Exposure | Placeholder Art
おわりに
物理ベースレンダリングの理論などを適当にメモしました。 次回からは実装を行っていきます。