PBRの基礎を学ぶ
久々のブログですが、今日は以下の本を読みつつ、PBRについて調べたので、それをまとめたいと思います。
3DCGにおける質感を表す関数、Bidirectional Scattering Distribution Function(BSDF)について著名なものを取り上げ、レイトレーシングにおける実装法について解説している本です 「Lambert BRDF」「Phong」「Blinn-Phong」「完全鏡面、完全屈折」「Torrance-Sparrow」「Cook-Torrance」「GGX」「Disney BRDF」について取り上げています。
まず、タイトルが難しそうなこの本ですが、2年前くらいに購入しました。
今は電子版しか購入できませんが、私は書籍+電子版を購入しました。 長い間積んであったのですが、突然PBRの用語や歴史を整理したくなったので、この本を読んでみました。
レイトレ用の本ですが、リアルタイム3Dで使われるシェーダーの計算式を学ぶ上でも大変役立つと思います。 ただし、計算式が中心なので、PBRの概念などを学ぶには向いていないですね。
PBRとは何か?
物理法則に基づいたライティング計算ですね。
重要なキーワードとなるのが「エネルギー保存」です。つまり、光源から発せられたエネルギーが物体を照らしており、反射したり透過したり吸収されたりして、すべての明るさを集めると、光源が発したエネルギーに等しくなるという考え方です。PBRなのかPBRではないのかというのは、エネルギー保存を満たしているのか満たしていないのかと等しいと言えます。
ただし、リアルタイムの3Dでは、直接光の反射のみがPBRに則って正確に計算されていて、間接光やSSS(サブサーフェーススキャッタリング)などは簡易的に計算がされていることが多いと思います。また、アーティストが明るさを調整できるようにパラメータを追加したりすると、PBRからは外れてしまうことが多いです。
従来のレンダリングと何が違うの?
以前は、Lambert、Phong、Blinn-Phongという反射モデルが使われていました。このころは、GPUの制限によって、すべてのライティング計算が8~10ビットの整数で 0-255 の数値を 0.0-1.0 に対応させて計算していました。そのため、光源の最大の明るさを 1.0 としたときに、物体表面の明るさを 0.0-1.0 として計算することで、それらしい見た目を表現していました。また、間接光の計算は Ambient というパラメータで固定の明るさを調整していました。
しかし、GPUにプログラマブルシェーダーが導入され、数値の精度が、8 ビット整数から 32 ビットや 16 ビットの浮動小数に変わったことで、PBRで計算するという時代になりました。
ただし、Lambert、Phong、Blinn-Phongが、PBRではないというのも正確ではありません。従来の計算式ではエネルギー保存は満たしていませんが、一定の係数を掛けて正規化することによって、Lambert、Phong、Blinn-PhongでもPBRを満たすことはできます。詳細は書きませんが、上記の本に、この辺の説明がされていました。
PBRを使用するメリット・デメリットは何なの?
メリットとしては、PBRに基づいて光源やマテリアルを設定することで、違和感のないリアルなレンダリングができることです。また、朝、昼、夜と、光源が変化したとしても、マテリアルのパラメータを変えずにレンダリングできます。PBRではないレンダリング方法では、明るいシーンと暗いシーンで、マテリアルやテクスチャを作り直すことが必要になったりします。
デメリットとしては、従来の 8 ビット整数で計算していた頃よりも、計算量やメモリが増えて処理負荷が高くなります。あと、ファンタジーな世界のように、現実世界にない物質を表現したいときなど、物理法則で表現しにくいものには向いていないかもしれません。例えば、発光する宝石のようなものをレンダリングする場合、PBRのマテリアルでは、エミッシブのパラメータに発光のエネルギーを設定する必要があります。この明るさを何ルクスの光源なのか考えるのは結構難しいのではないかと思います。
PBRの代表的な計算式は何ですか?
まず、キーワードとなるのは、「クック・トランスモデル(Cook-Torrance Model)」ですね。 1982 年に発表された論文で、表面のマイクロファセット理論に基づいた反射モデルを提案し、金属やプラスチックの質感をより正確に再現できるようになりました。
「マイクロファセット」とは何かというと、物質の表面が細かい凹凸でできており、それによって光り方が変わるというものです。 代表的なパラメータとしては、「Roughness」と「Metalness」の2つのパラメータです。
つまり、
- 表面がつるつるなのか、ざらざらなのか(Roughness)
- 金属なのか、非金属なのか(Metalness)
という2点で、反射光を計算するというものです。
また、クック・トランスモデルはいくつか改良された計算方法が発表されており、現在、UnityやUE5で主に使われているのは、「GGX」と呼ばれる計算式です。 GGXはマイクロファセットの法線分布関数の1つであり、Trowbridge-Reitz 分布とも呼ばれます。私も正しく理解している自信はないのですが、 2007年にWalterさんによってGGXが発表されて、実験データから求めた式として発表されたそうですが、これと等価な式が、Trowbridge-Reitz から1975年に発表されており、こちらは物理条件から求めたというものらしいです。なので、Walterモデルではなく、GGXと呼ばれているみたいです。
あと、Disney-BRDF というものもあります。Cook-Torrance と GGX をベースにしていますが、追加のパラメータがあったり、拡散光がランバートではなかったりするようです。 UE5 や Unity でも、一部、Disney-BRDF のパラメータを導入したりしているようです。
次に調べたいと思っていること
今回は図も計算式も書いていないので分かりにくかったかもしれませんが、PBRの概要は以上になります。
次は、引き続き、PBRの実装方法に関して調べてみたいと思います。 UnityやUE5のシェーダーで、どのように計算されているのか、ソースを読んでみたい。