Skip to content
Go back

Moving Frostbite to Physically based rendering

· Updated:

notes slides web

拙訳は抜粋や意訳を多く含みます。原著を必ず確認してください。

拙訳

1. まえがき(Introduction)

Frostbiteは’映画的ルックcinematic look’を追求してきたことから、物理ベースレンダリングへの移行も自然なことだった。移行作業は[@Drobot2013LightingKillzoneShadow][Karis 2013Karis, B. 2013. Real Shading in Unreal Engine 4. Physically Based Shading in Theory and Practice course. ACM SIGGRAPH. https://blog.selfshadow.com/publications/s2013-shading-course/.][@Lagarde2013ArtRenderingRemember][@Kojima2013PhotorealismEyesFOX]といったゲーム業界の最新技術を基に行い、既存技術の改良と未解決問題open problems取り崩しchip awayを試みた。

研究開発では、測定データかレンダリングデータのいずれか適切な方を正確性の’評価基準ground-truth’として用いた。しかし、真に物理的に正しい処理は負荷が高く、リアルタイム性能という制約の中で今日のゲームエンジンがそれを達成できるとは考えにくい。そこで、まともなdecent近似が可能な所では、品質目標quality targetに近くなるならば、絶対的な正しさよりも 信憑性bilievability を支持することとした。

PBRは業界用語として一般的になっているが、その意味はゲームエンジンごとに大きな差異がある。Frostbiteではマテリアルとライティングの情報を分離することをその原則の中核のひとつとした。これはシーン中のすべてのオブジェクトが一貫性を持ったビジュアルになることを保証するために重要となる。この考えのもとに、特別なハックをせずに同じライティングをすべてのオブジェクト、すべてのマテリアルレイヤに適用する。プロダクションの観点から見ると、アセットやライティング用のリグを異なる環境で再利用しやすくなり、アーティストの操るパラメータ数が減ることでオーサリングがより直観的になる。しかし、本書で後に述べるが、パフォーマンス上の理由によりコード上ではライティングとマテリアルは密に結合している。

PBRを採用するとなると、レンダラやツールを含めたグラフィクスパイプライン全体に手を入れなければならないことはすぐに理解できる。そのことを踏まえて、本書では普通の文献なら省かれる細かいところも含めて、大規模なプロダクションのエンジンに必要な様々なアップグレードのすべてを網羅した。まずはじめに、節2ではground-truthとして利用するリファレンスがPBRの文脈においてどれだけ重要であるかをより詳しく説明する。次に、節3ではマテリアルを提示して、光が物質とどのように相互作用するかを調査reviewする。節4では光の定義や放出emitについて説明する。節5では輝度luminanceを最終ピクセル値に変換する方法に触れながらカメラと出力画像に焦点を当てる。最後に、節6ではPBRへ移行するさいのスケジュールの立て方やこの期間中に検討したことを見直すことで結論を述べる。

v\boldsymbol{v}視線ベクトル
l\boldsymbol{l}入射光ベクトル
n\boldsymbol{n}法線
h\boldsymbol{h}ハーフベクトル
LLライティング関数
ffBRDF
fdf_dBRDFのディフューズ要素
frf_rBRDFのスペキュラ要素
α\alphaマテリアルのラフネス
αlin\alpha_{lin}知覚的に線形なマテリアルのラフネス
\cdotドット積
\langle \cdot \rangleクランプされたドット積
\lvert \cdot \rvertドット積の絶対値
ρ\rhoディフューズ反射率
χ+(a)\chi^+(a)Heaviside関数: a>0a>0のとき1、a<=0a<=0のとき0

: 数学的な表記法mathematical notation

2. リファレンス(Reference)

2.1. モデルと仮説の検証(Validating models and hypothesis)

(図1:現実世界のライティング(左)とインエンジンin-engineライティング(右)の比較。)

ビデオゲーム業界は長年に渡りフォトリアルな画像を得ようと試みを重ねてきたが、フォトリアリズムphotorealism では画像を生成する方法やデータについて言及せずに感覚で(定性的にqualitatively)判断していた。現実世界の振る舞いや特性をシミュレートしようとする 物理ベースレンダリング ではそれと異なり、数値で(定量的にquantitatively)判断する。そのため、きちんとしたモデルや正しい仮説を選び出すためにはground-truthとなる良いリファレンスが必要になる。妥当性の判断や正しい選択をする最善の方法は現実世界と比較観察を行うことである。現実世界を観察することで、図1に見られるようなハイライト形状、濡れた表面の振る舞い、ライト強度の違いによる差異といった様々なビジュアル要素を迅速に把握することができる。現実世界をマテリアルのリファレンスとする場合には、異なるライティングの振る舞いをキャプチャするために複数の縮尺で撮影することが重要になる。

しかし、現実のデータを正確に測定しようにも複雑すぎるか時間がかかりすぎることがよくある。MERLなどのデータベースを利用すれば、モデルの性能評価を迅速に行うことができる。本アプローチでは、ライトの強度やフォールオフ、空の明るさ、カメラのエフェクトなどの実データの測定及び評価を試みたが、これらの工程は時間がかかる上、必ずしも簡単にセットアップできるわけではない。

2.2. インエンジン近似の評価(Validating in-engine approximations)

(図2:実装の妥当性を検証するためのインエンジンの結果とオフラインパストレースの結果との比較ツール。)

MitsubaのようなモダンなPBRパストレーサーは最新のレンダリング技術を実装しており、近似の妥当性を評価する代替手段として十分なほどに現実感のある画像を生成することができる。Frostbiteでは近似の妥当性を迅速に評価できるようにMitsuba用の簡単なエクスポータを作った。このエクスポータはジオメトリ情報、(テクスチャを含まない)定数のマテリアル情報、すべてのライト強度を出力でき、マテリアルモデル、ライトインテグレーション、ライト強度を簡単に確認できる。さらにこのエクスポータはグローバルイルミネーション、アンビエントオクルージョン、反射といったより複雑な現象の正確性を検証することを可能にする。図2はエクスポート後に自動的に起動するウィジェットを示す。このウィジェットでは完全に制御された露出の下で境目をスワイプしてピクセル値を比較することが可能になっている。もうひとつ重要なこととして、出力する強度を広い値範囲で保持するためにレンダラは線形なHDRフォーマットであるOpenEXRに最終画像を出力する。

2.3. インエンジンリファレンスモードの評価(Validating in-engine reference mode)

(図3:(a) インエンジン。)

(図3:(b) インエンジンリファレンス。)

(図3:(c) パストレーサーリファレンス。)

(図3:左:いくつかのタイプのエリアライトからなるインエンジンシーンのレンダリング。中:エリアライトをGPUによる重点サンプリングによってレンダリングした同じインエンジンシーン。右:評価用パストレーサーでレンダリングされたシーン。)

前節で説明したエクスポータは便利だが、シーンをレンダリングするのに毎度数秒から数分かかってしまう。そこでイテレーションを早めるため、GPUでの(IBLとエリアライトの)ブルートフォースサンプリングによるライティングインテグレーションを行うゲーム内リファレンスモードを追加した(図3)。このレンダリング時間は決して短いわけではないが、そのイテレーション間隔はエクスポータを使うよりも格段に短くなる。

: 正しいリファレンスを使うことが重要である。これは明らかなように思えるが、リファレンスが良くない場合、近似もまた良くならない。髪シェーディングモデルを近似するときはリファレンスとして現実世界に一番近いものを使おう。式を近似するときは誤差を計算できるように、Fresnelの式に対するOren-NayarやSchlickの近似式のような、すでにある近似式ではなくオリジナルの式を必ず使おう。唯一完全に信用できるリファレンスは現実世界のみである。

3. マテリアル(Material)

3.1. マテリアルモデル(Material models)

3.1.1. 外観(Appearance)

(図4:光と物質の相互作用の多様性を示す様々な表面の外観。)

表面の外観は入射光と表面のマテリアル特性との相互作用によって生み出され、図4に見られるように、現実世界では一面一辺倒であるような単純なものから層を成したり不均質であったりするような複雑なものまで数多くの外観を観察することができる。

これらの様々な外観は伝導性conductivity平均自由行程mean-free-path吸収absorptionといった固有の物理的特性により分類できる。これらのマテリアル特性に基づき、全波長域の中からある範囲の外観を表現できるとする様々なマテリアルモデルが発表されている。マテリアルモデルの分野は広大であり、用いるトレードオフや求める正確さはモデルにより様々である。BSDFと呼ばれるマテリアルモデルは反射率を示すBRDFと透過率を示すBTDFに分けることができる。この文書では”標準的な”外観を表現できるとするマテリアルモデルにおける反射の部分に焦点を当てようと思う。ここで言う”標準的”とは、とりわけ日常生活の中で遭遇しやすいもののことを指す。故に、これから扱うものは平均自由行程の短い反射的で等方性を持つ誘電体または導体の表面に限定することとする。

3.1.2. マテリアルモデル(Material models)

(図5:(a) 光の相互作用。)

(図5:(b) BSDFのモデル化。)

(図5:“標準的な”物質の厚板slabとの光の相互作用。左:光の相互作用。右:ディフューズ項fdf_dとスペキュラ項frf_rとの相互作用のBSDFモデル。)

(図6:DD項でモデル化される様々なラフネスの表面。上:マイクロファセットとの光の相互作用。中:BRDFfrf_rのローブ。下:球における外観。)

この標準的なマテリアルモデルの文脈では、図5が示すように、表面の応答ffは”ディフューズ”(fdf_d)と呼ばれる低い角周波数の部分と”スペキュラ”(frf_r)と呼ばれる高い各周波数の部分の2つの項に分けられる。界面は空気と物質の2つの媒質で区切られる。平坦な界面からなる表面であれば、誘電体と導体の両方においてFresnelの法則によって簡単に表すことができる。図6が示すような不規則な界面であれば、この種の表面との光の相互作用の特徴にうまく適合するマイクロファセットによるモデル[Cook and Torrance 1982Cook, R. L. and Torrance, K. E. 1982. A reflectance model for computer graphics. ACM Trans. Graph. 1, 1, 7–24. 10.1145/357290.357293. https://graphics.pixar.com/library/ReflectanceModel/paper.pdf.]により表すことができる。マイクロファセットモデルは以下の式により表される。より詳しい導出は[Heitz 2014Heitz, E. 2014. Understanding the masking-shadowing function in microfacet-based brdfs. Journal of Computer Graphics Techniques (JCGT) 3, 2, 48–107. http://jcgt.org/published/0003/02/03/.]を参照のこと。

fd/r(v)=1nvnlΩfm(v,l,m)G(v,l,m)D(m,α)vmlmdm(1)f_{d/r}(\boldsymbol{v}) = \frac{1}{|\boldsymbol{n} \cdot \boldsymbol{v}| |\boldsymbol{n} \cdot \boldsymbol{l}|} \int_{\Omega} f_m(\boldsymbol{v}, \boldsymbol{l}, \boldsymbol{m}) G(\boldsymbol{v}, \boldsymbol{l}, \boldsymbol{m}) D(\boldsymbol{m}, \alpha) \langle \boldsymbol{v} \cdot \boldsymbol{m} \rangle \langle \boldsymbol{l} \cdot \boldsymbol{m} \rangle d\boldsymbol{m} \tag{1}

DD項はマイクロファセット分布(つまり、NDF(法線分布関数Normal Distribution Function))をモデル化し、GG項はマイクロファセットによる遮蔽(マスキング-シャドウイング)をモデル化する。この式はディフューズ項fdf_dとスペキュラ項frf_rの両方に対して対応するマイクロファセットBRDFfmf_mを定めることで用いることができる。スペキュラ項の場合、fmf_m完全鏡面perfect mirrorであり、Fresnelの法則FFによりモデル化される。したがって、以下のよく知られた式を導くことができる。

fr(v)=F(v,h,f0,f90)G(v,l,h)D(h,α)4nvnl(2)f_r(\boldsymbol{v}) = \frac{F(\boldsymbol{v}, \boldsymbol{h}, f_0, f_{90}) G(\boldsymbol{v}, \boldsymbol{l}, \boldsymbol{h}) D(\boldsymbol{h}, \alpha)}{4 \langle \boldsymbol{n} \cdot \boldsymbol{v} \rangle \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle} \tag{2}

DD項は図6が示すように、表面の外観において重要な役割を担っている。[Walter et al. 2007Walter, B., Marschner, S. R., Li, H. and Torrance, K. E. 2007. Microfacet models for refraction through rough surfaces. Proceedings of the 18th eurographics conference on rendering techniques 195–206. 10.2312/EGWR/EGSR07/195-206. https://www.graphics.cornell.edu/~bjw/microfacetbsdf.pdf.; Burley 2012Burley, B. 2012. Physically-Based Shading at Disney. Practical Physically Based Shading in Film and Game Production course. ACM SIGGRAPH. https://disneyanimation.com/publications/physically-based-shading-at-disney/.]はGGX分布のような”ロングテール”のNDFが現実世界の表面をキャプチャするときに良好な結果を示すことを指摘している。GG項もまた高いラフネス値において重要な役割を担っている。 Heitz [2014Heitz, E. 2014. Understanding the masking-shadowing function in microfacet-based brdfs. Journal of Computer Graphics Techniques (JCGT) 3, 2, 48–107. http://jcgt.org/published/0003/02/03/.] はSmithの可視性関数がGG項として正確かつ厳密であることを示している。それに加えて、以下に示すような、マスキングとシャドウイングの間にある相関をモデリングしたマスキング-シャドウイング関数の更に正確な形式があるにもかかわらず、Smithの可視性関数の近似バージョンが使われる傾向があることを指摘している。図7はシンプルなSmithの関数と高さ相関hight-correlatedのSmithの関数との差異を示している。

G(v,l,h,α)=χ+(v.h)χ+(l.h)1+Λ(v)+Λ(l) with Λ(m)=1+1+α2tan2(θm)2=1+1+α2(1cos2(θm))cos2(θm)2(3)G(\boldsymbol{v}, \boldsymbol{l}, \boldsymbol{h}, \alpha) = \frac{\chi^+(\boldsymbol{v} . \boldsymbol{h}) \chi^+(\boldsymbol{l} . \boldsymbol{h})}{1 + \Lambda(\boldsymbol{v}) + \Lambda(\boldsymbol{l})} \text{ with } \Lambda(\boldsymbol{m}) = \frac{-1 + \sqrt{1 + \alpha^2 \tan^2(\theta_m)}}{2} = \frac{-1 + \sqrt{1 + \frac{\alpha^2 (1 - \cos^2(\theta_m))}{\cos^2(\theta_m)}}}{2} \tag{3}

(図7:ラフネスを増加させたときの黒い誘電体の球(上)とクロムの金属的な球(下)におけるSmithの可視性関数の相関なしと相関ありの比較。ラフネス値が大きい場合に注目。)

ディフューズ項の場合、fmf_mはLambertモデルに従い、そのときの式1を簡略化すると以下のようになる。

fd(v)=ρπ1nvnlΩG(v,l,m)D(m,α)vmlmdm(4)f_d(\boldsymbol{v}) = \frac{\rho}{\pi} \frac{1}{|\boldsymbol{n} \cdot \boldsymbol{v}| |\boldsymbol{n} \cdot \boldsymbol{l}|} \int_{\Omega} G(\boldsymbol{v}, \boldsymbol{l}, \boldsymbol{m}) D(\boldsymbol{m}, \alpha) \langle \boldsymbol{v} \cdot \boldsymbol{m} \rangle \langle \boldsymbol{l} \cdot \boldsymbol{m} \rangle d\boldsymbol{m} \tag{4}

これまではこのような単純なLambertモデルでも問題なかったが、図8が示すように、スペキュラ項との一貫性を保つため、ディフューズ項の計算に表面のラフネスを取り入れる必要がある[Burley 2012Burley, B. 2012. Physically-Based Shading at Disney. Practical Physically Based Shading in Film and Game Production course. ACM SIGGRAPH. https://disneyanimation.com/publications/physically-based-shading-at-disney/.] (すなわち、スペキュラ項とディフューズ項で同じラフネスを用いるべきである)。式4は解析的に解くことができないが、 Oren and Nayar [1994Oren, M. and Nayar, S. K. 1994. Generalization of Lambert's reflectance model. Proceedings of the 21st annual conference on computer graphics and interactive techniques 239–246. 10.1145/192161.192213. https://cave.cs.columbia.edu/Statics/publications/pdfs/Oren_SIGGRAPH94.pdf.] はガウス分布のNDFとV型空洞のG項を用いることでOren-Nayarモデルとして知られる式4の経験的近似を発見した。モデルを正しくサポートするためには、[@Gotanda2014DesigningReflectanceModels]で説明されているようにGGXのNDFにも式4に対する同じような近似を作るべきである。付録Bにその詳細を載せるが、さらなる研究が必要である。

(図8:鏡のBRDFfmf_mを持つスペキュラ項frf_r(左)とディフューズBRDFfmf_mを持つディフューズ項fdf_d(右)におけるマイクロスケールでの相互作用。)

Burley [2012Burley, B. 2012. Physically-Based Shading at Disney. Practical Physically Based Shading in Film and Game Production course. ACM SIGGRAPH. https://disneyanimation.com/publications/physically-based-shading-at-disney/.] は現実世界の表面を観察した結果から以下の式で示されるディフューズモデルを発表した。このモデルは経験的だが、MERLデータベースのマテリアルの主な特徴を再現でき、加えて単純であるため、Frostbiteで用いることとした。このディフューズ項はマテリアルのラフネスを計算に取り入れており、グレージング角での自己反射をいくらか生み出すことができる。

fd=ρπ(1+FD90(1nl)5)(1+FD90(1nv)5) where FD90=0.5+cos(θd)2α(5)f_d = \frac{\rho}{\pi} (1 + F_{D90}(1 - \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle)^5) (1 + F_{D90}(1 - \langle \boldsymbol{n} \cdot \boldsymbol{v} \rangle)^5) \text{ where } F_{D90} = 0.5 + \cos(\theta_d)^2 \alpha \tag{5}
3.1.3. エネルギー保存則(Energy conservation)

エネルギー保存則は扱うエネルギー量が受け取ったエネルギー量より多くならないことを考慮する上で重要な概念である。加えて、グレージング角においてディフューズ項よりスペキュラ項のほうが光をより散乱させるという振る舞いを正しく扱うことが可能になる。Frostbiteでは、計算を簡単にするため、半球状の固定照明による与えられた方向に対する反射率の総計である方向性半球反射率hemispherical-directional reflectanceがBRDF全体で1未満であることでエネルギーが保存されているとした。

ρhd(v)=Ωf(v,l)nldl=Ω(fr(v,l)+fd(v,l))nldl1(6)\rho_{hd}(\boldsymbol{v}) = \int_{\Omega} f(\boldsymbol{v}, \boldsymbol{l}) \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle d\boldsymbol{l} = \int_{\Omega} (f_r(\boldsymbol{v}, \boldsymbol{l}) + f_d(\boldsymbol{v}, \boldsymbol{l})) \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle d\boldsymbol{l} \le 1 \tag{6}

スペキュラモデルとディフューズモデルとの関連性が直接的ではないため、適切な導出を作ることは簡単ではない(スペキュラ項とディフューズ項がともにマイクロファセットモデルの基づく場合は付録Cを参照)。Disneyのディフューズモデルはエネルギー保存則を満たしていないことに注意する必要がある1図9aはDisneyのディフューズモデルの方向性半球反射率を表しているが、見るからに値は1を越えており、エネルギー保存則を満たしていないことが分かる。

(図9:(a) オリジナルのfdf_d。)

(図9:(b) 再正規化されたfdf_d。)

(図9:(c) 再正規化されたfd+frf_d+f_r。)

(図9:様々な視野角とラフネスにおけるDisneyのディフューズBRDFの方向性半球反射率のプロット。左:オリジナルの反射率。中:新しい再正規化を施した反射率。右:スペキュラ項とディフューズ項の組み合わせ。)

そこで、我々は自己反射の特性を維持しつつエネルギーのゲインを補正するような修正を追加した。リスト1は再正規化因数を導入したDisneyの評価関数を示している。図9cではスペキュラのマイクロファセットモデルfrf_rとDisneyのディフューズモデルfdf_dを合成したffの方向性半球反射率を表しており、完全に1にはなっていないが十分に近い値になっている。図10ではオリジナルと再正規化バージョンとの比較を示している。

float Fr_DisneyDiffuse(float NdotV, float NdotL, float LdotH, float linearRoughness) {
    float energyBias     = lerp(0, 0.5, linearRoughness);
    float energyFactor   = lerp (1.0, 1.0 / 1.51, linearRoughness);
    float fd90           = energyBias + 2.0 * LdotH*LdotH * linearRoughness;
    float3 f0            = float3(1.0f, 1.0f, 1.0f);
    float lightScatter   = F_Schlick(f0, fd90, NdotL).r;
    float viewScatter    = F_Schlick(f0, fd90, NdotV).r;

    return lightScatter * viewScatter * energyFactor;
}

Listing: エネルギーの再正規化を含むDisneyのディフューズBRDFのコード。linearRoughnessは知覚的に線形なラフネスである(節3.2.1を参照)。

(図10:(a) LambertおよびオリジナルのDisneyのディフューズ項。)

(図10:(b) オリジナルのDisneyのディフューズ項とその再正規化バージョン。)

(図10:上:Disneyのディフューズ項とLambertのディフューズ項との比較。下:オリジナルのDisneyのディフューズ項と再正規化バージョンとの比較。)

3.1.4. 形状の特徴(Shape characteristics)

スペキュラのマイクロファセットによるBRDFはしばしば無視bypassされるが最終的な外観に強い影響を及ぼすある特性を持つ。特に以下の2つの現象が重要である。

  • 半角Half-angleパラメータ化parameterization: このパラメータ化は通常の入射角では等方的になるがグレージング角では異方的になるというBRDF形状の非線形な変換を暗に示している。さらなる洞察は節4.9を参照のこと。
  • オフスペキュラOff-specular: BRDFローブは時折反射した視線方向(反射方向mirror directionとも)を中心とすると仮定されるが、図11に見られるように、ラフネスが大きくなるとnl\langle \boldsymbol{n} \cdot \boldsymbol{l} \rangleとマスキング-シャドウイング項GGによってBRDFローブは法線方向に引っ張られるgets shiftedようになる。これは”オフスペキュラピークOff-specular peak”と呼ばれ、表面の粗い外観を表すのに重要な役割を担っている。

(図11:様々な視野角でのBRDFローブ形状の例。グレージングな視野角では支配的なローブは反射方向RRではなく方向MMの方を向いている。上段:α=0.4\alpha = 0.4。下段:α=0.8\alpha = 0.8。)

ラフネス値が大きいとオフスペキュラピークによる差異が大きくなる可能性がある。この重要な特徴を計算に入れるため、この”支配的な向きdominant direction”のモデル化を試みた。これはエリアライト(節4.7)と画像ベースライト(節4.9)を評価するときに用いた。

3.1.5. Frostbiteの標準モデル(Frostbite standard model)

まとめると、Frostbiteの”標準”マテリアルモデルは他のゲームエンジンで用いられるものと近い[Karis 2013Karis, B. 2013. Real Shading in Unreal Engine 4. Physically Based Shading in Theory and Practice course. ACM SIGGRAPH. https://blog.selfshadow.com/publications/s2013-shading-course/.; @Neubelt2013CraftingNextGenMaterial; Burley 2012Burley, B. 2012. Physically-Based Shading at Disney. Practical Physically Based Shading in Film and Game Production course. ACM SIGGRAPH. https://disneyanimation.com/publications/physically-based-shading-at-disney/.]。これは以下から構成されている。

  • スペキュラ項 frf_r: Smithの相関あり可視性関数とGGXのNDFによるスペキュラのマイクロファセットモデル(式2)。
  • ディフューズ項 fdf_d: エネルギーの再正規化を施したDisneyのディフューズ項。

両パートでは、ライティングを統合するときに支配的向きに対して補正をかける(オフスペキュラピークを制御する)ことができるようになっている(詳しくは次節)。Frostbiteはクリアコートのような異なるタイプのマテリアルや表面下散乱を含むマテリアルもサポートしているが、この文書では標準的マテリアルモデルのみに焦点を当ててゆく。

float3 F_Schlick(in float3 f0, in float f90 , in float u) {
    return f0 + 《f90 - f0》 * pow(1.f - u, 5.f);
}

float V_SmithGGXCorrelated(float NdotL , float NdotV , float alphaG) {
    // 相関あり版G_SmithGGXのオリジナル式
    // lambda_v             = (-1 + sqrt(alphaG2 * 《1 - NdotL2》 / NdotL2 + 1)) * 0.5f;
    // lambda_l             = (-1 + sqrt(alphaG2 * 《1 - NdotV2》 / NdotV2 + 1)) * 0.5f;
    // G_SmithGGXCorrelated = 1 / (1 + lambda_v + lambda_l);
    // V_SmithGGXCorrelated = G_SmithGGXCorrelated / (4.0f * NdotL * NdotV);

    // 最適化バージョン
    float alphaG2 = alphaG * alphaG;
    // 注意:"NdotL *"と"NdotV *"の関係が他と逆なのは間違いではなく意図したもの
    float Lambda_GGXV = NdotL * sqrt((-NdotV * alphaG2 + NdotV) * NdotV + alphaG2);
    float Lambda_GGXL = NdotV * sqrt((-NdotL * alphaG2 + NdotL) * NdotL + alphaG2);
    return 0.5f / (Lambda_GGXV + Lambda_GGXL);
}

float D_GGX(float NdotH, float m) {
    // 1/PIはあとでかける
    float  m2 = m * m;
    float f = (NdotH * m2 - NdotH) * NdotH + 1;
    return  m2 / (f * f);
}

// 以下は上記の関数を呼び出す例
float  NdotV = abs(dot(N, V)) + 1e-5f; // avoid  artifact
float3 H     = normalize(V + L);
float  LdotH = saturate(dot(L, H));
float  NdotH = saturate(dot(N, H));
float  NdotL = saturate(dot(N, L));

// スペキュラBRDF
float3 F     = F_Schlick(f0, f90, LdotH);
float  Vis   = V_SmithGGXCorrelated(NdotV, NdotL, roughness);
float  D     = D_GGX(NdotH, roughness);
float  Fr    = D * F * Vis / PI;

// ディフューズBRDF
float  Fd    = Fr_DisneyDiffuse(NdotV, NdotL, LdotH, linearRoughness) / PI;

Listing: BSDFの評価コード。

3.2. マテリアルシステム(Material system)

3.2.1. マテリアル(Material)

Frostbiteを利用するゲームジャンルはスポーツからレーシング、FPSからオープンワールドに至るまで多岐に渡る。これらのゲームが求めるさまざまな要件を満足するため、エンジンはライティングやマテリアル対応に関する柔軟な制御方法を提供する必要がある。それに加えて、移行を簡潔に行うために以前の非PBRなライティングモデルとの互換性を維持する必要があった。ライティングパスは制御可能であり、ディファード、フォワード、またはそのハイブリッドをサポートしている(詳しくは節4.11)。

Frostbiteでは、“マテリアル”は以下により定義される。

  • ライティングパス: ディファード、フォワード、またはその両方。
  • 入力パラメータの集まり: ディフューズ、滑らかさsmoothness厚さthickness、など。
  • マテリアルモデル: 粗い表面、半透明、肌、髪、など(非PBRな粗い表面も含む)。いわゆるシェーダコード。
  • ディファードパスの場合のGバッファのレイアウト。バッファ数は可変。

ゲーム開発班は指定のライティングパスで利用可能なものの中からマテリアル一式を選ぶことができる。各マテリアルはmaterialID属性によりそのゲームで識別される。最も一般的なケースをカバーするベースマテリアル(“標準”マテリアルと呼んでいるもの)は常に存在し、他のマテリアルと共有するパラメータ(例えば、ラフネス)を定義する。ディファードシェーディングでは、ベースマテリアルは一般に Burley [2012Burley, B. 2012. Physically-Based Shading at Disney. Practical Physically Based Shading in Film and Game Production course. ACM SIGGRAPH. https://disneyanimation.com/publications/physically-based-shading-at-disney/.] が示す”Disney”モデル一式になる。それと、“二色two-color”と”old”の2つのベースマテリアルもサポートする。

Disneyのベースマテリアル: 我々のDisneyマテリアルでは以下のパラメータを用いる。

Normal
: 標準的な法線。

BaseColor
: Burley [2012Burley, B. 2012. Physically-Based Shading at Disney. Practical Physically Based Shading in Film and Game Production course. ACM SIGGRAPH. https://disneyanimation.com/publications/physically-based-shading-at-disney/.] のように、非金属オブジェクトにおけるディフューズのアルベドと金属オブジェクトにおける垂直入射(f0f_0)を定義する。この属性の下位部はマイクロスペキュラオクルージョンmicro-specular occlusionを定義する。

Smoothness
: オブジェクトのラフネスを定義する。値が1のときに滑らかであるとするとアーティストが直観的に扱えるため、また、Frostbiteの非PBRマテリアルモデルがすでにこれを使っているため、ラフネスではなくsmoothnessを選択した。 Burley [2012Burley, B. 2012. Physically-Based Shading at Disney. Practical Physically Based Shading in Film and Game Production course. ACM SIGGRAPH. https://disneyanimation.com/publications/physically-based-shading-at-disney/.] と同様に、視覚的に線形なsmoothnessにリマップされる(1αlin1 - \alpha_{lin})。

MetalMask
: Burley [2012Burley, B. 2012. Physically-Based Shading at Disney. Practical Physically Based Shading in Film and Game Production course. ACM SIGGRAPH. https://disneyanimation.com/publications/physically-based-shading-at-disney/.] のように、“金属らしさ”または表面の導電性(すなわち、誘電体か導体か)を定義する。この変数の二値的な性質をアーティストに示すためこのような名前にした。

Reflectance
: 非金属マテリアル(つまり、MetalMask < 1)のためのアーティスト・フレンドリーな範囲で垂直入射におけるFresnel反射率(f0f_0)を定義する。この属性の下位部は非金属マテリアルにおけるマイクロスペキュラオクルージョンmicro-specular occlusionを定義する。

smoothnessでは、図12に示すような様々なリマッピング関数をアーティストに試してもらいながら分析を行い、 Burley [2012Burley, B. 2012. Physically-Based Shading at Disney. Practical Physically Based Shading in Film and Game Production course. ACM SIGGRAPH. https://disneyanimation.com/publications/physically-based-shading-at-disney/.] と同じように、アーティストが最も満足しそうな”二乗”のリマッピングを選択した。reflectanceでは、以下のリマッピング関数を選択した。

f0=0.16×reflectance2f_0 = 0.16 \times reflectance^2

このリマッピングは、一般的な誘電体の4%の反射率をRGBの128にマッピングしつつ、宝石の高いFrenel値を含むことができる範囲にf0f_0をマップすることを目標としている。宝石のf0f_0はルビーで約8%、ダイヤモンドで約17%になる。我々は近似として関数が16%を上限とするよう制限することにした。図13は一般的な値での比較を示している。実践ではリアルタイムの制限により、1%や2%における変化はほとんど目立たない2ため、この式は4%以上で急激に変化する値によく合っている。

非金属オブジェクト(Reflectance)と金属オブジェクト(BaseColor)の両方における垂直入射でのFresnel反射率(f0f_0)では、マイクロスペキュラを制御するために2%(水の反射率)以下である下位部が使われる(詳細は節4.10を参照)。これは特定のエンコーディングのために非金属オブジェクトで使われるマイクロスペキュラオクルージョンの値が異なる範囲であることを暗に示している。

(図12:Smoothnessのリマッピング比較。(1Smoothness)2(1 - Smoothness)^2の曲線は Burley [2012Burley, B. 2012. Physically-Based Shading at Disney. Practical Physically Based Shading in Film and Game Production course. ACM SIGGRAPH. https://disneyanimation.com/publications/physically-based-shading-at-disney/.] のリマッピングに対応する。暗い青色の曲線はCrytekのRyseが採用したリマッピング(10.7×Smoothness)6(1 - 0.7 \times Smoothness)^6[@Schulz2014MovingNextGeneration]に対応する。これのレンダリング結果は示していないが、その曲線は4乗のものと非常に近い。)

(図13:リマッピング関数の反射率プロットといくつかのリファレンス値。)

Disneyマテリアルは節3.1で示した”標準”マテリアルモデルを用いる。関連するGバッファのレイアウトは表2に示す。このレイアウトは以下の制約からなる。

  • 全ての基本属性(NormalBaseColorSmoothnessMetalMaskReflectance)はディファードデカールをサポートするためにブレンド可能である必要がある。ブレンド不可能な属性はアルファチャンネルに格納する。また、ブレンドの質に影響を与える圧縮やエンコードは避けることとした。
  • MSAAをサポートするとBaseColor属性の彩度サブサンプリングが使えなくなる。[@Mavridis2012CompactYCoCgFrame]
  • 通常使うパラメータは同じバッファに集める必要がある。
  • MaterialIdは全てのマテリアルで同じ場所に格納する必要がある。
  • ベース/標準マテリアルでは4つのバッファのみを使うことがパフォーマンス要件である。(深度バッファは含まない)
RGBA
GB0Normal(10:10)左同SmoothnessMaterialId(2)
GB1BaseColor左同左同MaterialData(5)/Normal(3)
GB2------MetalMaskReflectanceAO
GB3Radiosity/Emissive左同左同左同

: DisneyのディファードのベースマテリアルのGバッファレイアウト。

MaterialDataMateriralIdにより様々な値に解釈される。例えば、ディファードな肌マテリアルではディフュージョンプロファイル指数diffusion profile indexが格納され、異方的なマテリアルでは異方性の強さが格納される。AOは常に存在する(マテリアルタイプに非依存な)アンビエントオクルージョン項である(詳細は節4.10を参照)。RadiosityはGバッファを生成するときに計算された間接ディフューズライティングを格納するライトバッファである。Normalは適用後でも通常のブレンドが可能である非可逆なエンコーディング手法を用いて2つに分割する(このアルゴリズムは後のトークで説明するかもしれない)。

二色のベースマテリアル: Disneyのパラメータ化(単一のベース色、メタルマスク、スカラの反射率)は、例えば金属酸化物のような金属と誘電体の界面では複合マテリアルのスペキュラハイライトを満足に説明できないfall short when expressingため、f0f_0とディフューズ色を持つ”二色”のディファードのベースマテリアルをサポートする。関連するGバッファのレイアウトは表3に示す。f0f_0項はReflectanceと同じような下位範囲でマイクロオクルージョンをサポートする。パラメータ化の間の変換は状況に応じて必要とされる。Disneyのパラメータ化から”二色”のパラメータ化への変換はその定義により自明であり、ライティング計算でGバッファをアンパックするときにすでに行われている。逆の変換は非線形な最適化が必要になりさらに混沌としてくるため、アセットが必要とするときのみ行うこととする。この変換の詳細は付録Dで提供する。

RGBA
GB0Normal(10:10)左同SmoothnessMaterialId(2)
GB1DiffuseColor左同左同MaterialData(5)/Normal(3)
GB2f0 Color左同左同AO
GB3Radiosity/Emissive左同左同左同

: 二色のディファードのベースマテリアルのGバッファレイアウト。

旧ベースマテリアル: これは昔の非PBRエンジンでのベースマテリアルである。詳しくは[Coffin 2011Coffin, C. 2011. SPU-Based Deferred Shading for Battlefield 3 on Playstation 3. Game Developers Conference. https://www.slideshare.net/slideshow/spubased-deferred-shading-in-battlefield-3-for-playstation-3/7192306.]を参照のこと。レガシーなコンテンツをサポートするため、また、移行を簡単にするため、基本的なアート規則に基づいた非PBRマテリアルとPBRマテリアルとの自動変換機能を追加した。この変換は入力パラメータを格納する前にシェーダ内で行われる。ただし、適切に作られたアセットと比べると質は低くなる。質を維持したまま変換する方法は未だ見つかっていない。

図14は異なるマテリアルパラメータの変換を強調して、マテリアルモデルとライティング機能との依存関係を示している。パフォーマンスに関して言えば、エリアライト(節4.7)とIBL(節4.9)はマテリアルモデルに依存した事前インテグレーションに頼っている。これはライティングとマテリアルがエンジン内で結合していることを暗示している。PBRのアプローチにより主張したライティングとマテリアルの分割はアセット制作段階でのみ妥当である。つまり、アーティストはシェーダ内のあらゆるライティング情報にアクセスできない。しかし、その裏under the hoodではこの分割は保たれず、新しいマテリアルを追加するとしばしば暗黙的に新しいライティングコードが追加される。

(図14:Frostbiteにおけるマテリアルの模式図。入力パラメータ(MaterialRootData)のリストはマテリアルモデルのライティング関数を評価するのに使われるライティング評価構造(MaterialData)に変換される。ライティング関数はすべてのライトタイプ(punctual範囲area、IBL)を含む。マテリアルがディファードライティングパスを用いるなら、Gバッファレイアウト にパッキングされて、のちにアンパックして変換される。フォワードライティングパスを用いるなら、直接変換される。同じライティング評価構造(MaterialData)にアンパックできるならば、様々なマテリアルが同じライティングコードを共有することができる。)

3.2.2. レンダループ(Render loop)

前節ではマテリアルの定義を示した。この節ではマテリアルをどのようにレンダリングするかについて説明する。フォワードライティングパスを用いた表面では、マテリアルモデルのシェーダコードをセットアップし、パラメータリストを送り、表面をレンダリングする。ディファードシェーディングパスでは、より込み入ったことをやっている。効率的にマテリアル一式を管理できるようにするため、以下の注意事項considerationsを取り決めた。

  • マテリアルモデルは、細かな調整を動的分岐に頼るなどして、できる限り同じライティングコードを共有してみる。ライティングコードに違いが多すぎるならば、ステンシルバッファを用いて異なるライティングパスを用意しよう。
  • マテリアルは、パラメータを格納するための細かな調整を動的分岐に頼るなどして、ベースマテリアルのレイアウトの一貫性を維持してみる。マテリアルに違いが多すぎるならば、ステンシルバッファを用いて異なるGバッファパスを用意しよう。
  • 調整パスfix-up pass”を行うことで、異なるGバッファレイアウトを持つマテリアルによるライティングパスを共有してみる。

ジオメトリ・ヘビーなパスでは、Gバッファの生成コストを減らしながらライティングパスは同じものを使いたい。典型的なユースケースとしてはベジテーションが挙げられる。ベジテーションでは、ベースとなるGバッファレイアウトの上から2つのバッファのみを埋めて、リスト3に示される”調整”パスにより失ったGバッファパラメータを後から付け足す、ということを行う。調整パスは同じバッファに読み書きできるハードウェア能力に依存した複数パスにより達成することが必要になるかもしれない。

void psMain(
    in float4 pos : SV_Position,
    in float2 texCoord: TEXCOORD0,
    out float4 outGBuffer2 : SV_Target0,
    out float4 outGBuffer3 : SV_Target1)
{
    float4 gbuffer0 = FETCH_TEXTURE(g_gbufferTexture0, texCoord.xy, 0);
    float4 gbuffer1 = FETCH_TEXTURE(g_gbufferTexture1, texCoord.xy, 0);
    float3 worldNormal = normalize(unpackNormal(gbuffer0.rg, gbuffer1.a));

    // グローバルディフューズプロブからラジオシティ用の値を読む。
    float indirectLight = calcShL2Lighting(worldNormal, ...);

    // グローバルな共通値でsmoothness、metalMask、reflectanceを調整する。
    // アンビエントオクルージョンを1にセットする。
    outGBuffer2 = float4(g_smoothness, 0, g_reflectance, 1);
    outGBuffer3 = packLightingRGBA《indirectLight》;
}

Listing: Gバッファ調整サンプル。

レンダリングループの疑似コードは以下のようになる。

// Gバッファ生成
ForEach 異なるステンシルビット do
    Render バッファ数nを持つディファードマテリアルについてGバッファパス
        必要ならば、シェーダ内で分岐する
    Render バッファ数(n + 1)を持つディファードマテリアルについてGバッファパス
        必要ならば、シェーダ内で分岐する

// 調整パス
ForEach ディファードシェーディングパスの共有を必要とするディファードマテリアル
    Render Gバッファの調整パス

// デカール
Render 共通パラメータに影響するディファードデカール

// ディファードシェーディング
ForEach 必要な個別のディファードシェーディングパス do
    Render ディファードシェーディング
        必要ならば、シェーダ内で分岐する

// フォワードなレンダリング及びライティング
ForEach フォワードマテリアルモデル do
    Render フォワードライティング

実践では、マテリアルパラメータとライティング関数が結びついているためにゲームチームがすべてをカスタマイズするのはむしろ困難である。MaterialIdはマテリアルをカスタマイズする簡単な方法を提供する。ただし、ライティングコードの再利用と動的分岐を必須としなければならない制約がある。例としては、ライティングを2回サンプリングする必要があるクリアコートのモデルをゲームチームが追加したことがある。このシステムは非PBRエンジンからの移行とユーザの様々な要求にフィットすることを可能にした。

3.3. PBRとデカール(PBR and decals)

デカールはマテリアル特性を層にしたり、リッチな外観や変化を作れるようにするための動的システムとして理解できる。この文脈の中で、デカールがPBRにおいて”正しい”ことはますます重要になる。ここでの”正しい”とは、デカールのマテリアルパラメータとライティング前の表面を何度重なり合わせても適切に組み合わせることができる能力のことを指す。Frostbiteではこれを目的としてデカールをレンダリングするために主にディファードシェーディングを用いる3が、ハードウェアやパフォーマンスに制約がある中でこれを正しく行うのはほぼ不可能である。我々は様々な物理ベースマテリアルを考慮しつつ正しくデカールをブレンドする良い解答を導き出せないでいるが、完全性のために主要な落とし穴とFrostbiteでの選択をリスト化しておく。

  • 正確性: ブレンド処理の正確性は重要である。すなわち、ブレンド処理後の属性の復元recoveryが正しくなければならない。例えば、normal0.5+0.5normal * 0.5 + 0.5のような標準的なエンコーディングを施したNormalやxy要素のみのNormalにおいて、正しく復元することができるのは置き換え(すなわち、線形補間)のみである。ディテールを付加する[Barré-Brisebois and Hill 2012Barré-Brisebois, C. and Hill, S. 2012. Blending in Detail. Self Shadow. https://blog.selfshadow.com/publications/blending-in-detail/.]ような処理では誤った結果を生み出すだろう。プログラマブルブレンディングが活きる場面だが、対応するプラットホームがほとんどない。我々はこの場合では、いくつかの属性で圧縮することを回避し、単純で線形に補間するアルファブレンディングに頼ることを選択をした。
  • 相互作用: 正しくブレンドするため、デカールと対象の表面は同じマテリアルモデル(同じパラメータリスト)を使うべきである。プロダクションとパフォーマンスの両方の観点から見ると、MaterialIdごとに分けて作ったデカールをそれぞれ個別のパスで描画する必要があるため、これは管理しきれない。我々はデカールパラメータをゲームが選んだマテリアルの中で共通するパラメータ一式に制限することを選択した。これは基本的にNormalBaseColorSmoothnessとなる。MetalMaskReflectance(または、f0 color)といった他のパラメータはDisney(または、二色)のベースマテリアルを選択した場合にのみ検討する4。しかし、これでは十分ではない。デフォルト以外のMaterialIdに影響を与えるデカールはアーティファクトを発生させる。MaterialDataMaterialIdはブレンド可能なデータではなく、置き換えのみ可能である。選択肢のひとつはアルファチャンネルに個別のブレンド因数を用いて中立的な値に強制することである。もうひとつの選択肢はMaterialIDが0以外のマテリアルに影響を与えるデカールを禁止することである。
  • 間接ライティング: デカールが与える影響はライティングを評価する前に処理する必要がある。しかしFrostbiteでは、間接ディフューズをGバッファ生成パスの間に評価するため、ディフューズアルベド以外のマテリアル特性にこれ以上の変更を加えることを妨げてしまう5。解決法のひとつは例えばレベルを網羅するプロブボリュームテクスチャ[Valient 2014Valient, M. 2014. Taking Killzone Shadow Fall Image Quality into the Next Generation. Game Developers Conference. https://www.guerrilla-games.com/media/News/Files/GDC2014_Valient_Killzone_Graphics.pdf.]を用いて、すべての間接ディフューズライティングをディファードパスで評価することである。もうひとつの解決法はUnrealEngine4が提案しているようなGバッファ生成前にバッファにデカール属性を格納するデカール用プリパスを使うことである。これはデカールを貼り付けるオブジェクトを2回レンダリングする必要がある。Frostbiteでは、このような解決法により暗黙的に生まれるオーバーヘッドを危惧しアーティファクトを許容することを選択した。
  • 発光: FrostbiteのGバッファストレージは制限されているため、節4.8に示すように、エミッシブ情報はパフォーマンス上の理由により時折ラジオシティバッファに組み込まれる。ラジオシティバッファはのちにアルベドを組み合わせる。この場合、アルベドを変更するデカールは発光色を変更する。Frostbiteでは、発光とデカールを扱うことによるアーティファクトを許容した。
  • ハイライト形状の保存とスペキュラエイリアシング: いずれかの法線パラメータを変更することはピクセルが占める領域の下にあるNDFを変化させることを暗に示している。これは(ToskvigやLEANマッピングのようなテクニックにより扱われる)形状の保存を偏らせることを意味する。このことは、節5.3に示すように、デカール適用前に処理されていた。解決法はデカール適用後のポストプロセスとして法線フィルタリングパス6を行うことである[@Schulz2014MovingNextGeneration]
  • フォワードレンダリングされた表面: ディファードデカールは透明オブジェクトやフォワードレンダリングされたオブジェクトとの互換性を持たない。この場合の基本的な解決法は表面のライティングを含むライティング結果をブレンドするフォワードデカールを頼ることである。フォワードレンダリングされたオブジェクトにおけるデカールのパラメータブレンディグをサポートすることは可能であるだろうが、アート側に大きな制約が必要になる(ブレンドモードの制限、テクスチャ配列でのテクスチャサイズの制限、など)。この問題はライティングの適用において類似点が存在する。ライティングですでに見つかっている解決策を適用すると、タイルベースのデカールに発展するかもしれない。

4. ライティング(Lighting)

4.1. 一般(General)

ライティングパイプラインはすでに界隈で議論されている基盤技術に敬意を払って、ハイダイナミックレンジをサポートし、線形空間で処理し、(MIPMAP、ブレンド、フィルタリング、などにおいて)入出力をガンマ的に正しく行うべきである。Frostbiteではあらゆるゲームエンジンと同じようにハードウェアがサポートするsRGB変換機能に頼ることを選択した。

信憑性の高いシーンはライティングの一貫性と正確性に基づいている。すなわち、すべてのオブジェクトは周囲の環境からライティングを受け取り、正しい強度の光を反射し、シャドウを持つべきである。ゲームエンジンはそれぞれが関連を持たない様々なライティングツールを提供する。アーティファクトがひとつのライティングツールの操作によって、正しい結果を得るために他のライティング要素を再調整したり、信頼性や空間参照を破壊したりしないというのは困難が伴う。Frostbiteでは、すべてが標準で正しい状態にあり、アーティファクトにより好きなように調整することができる、とするメインのガイドライン用意した。これにより正しい結果を得るよりも正しい結果を逸脱することのほうがアーティストにとって難しくなるはずである。ただし、エンジンの制限の回避やアーティスト的な理由のためアーティストによる制御を忘れてはならない。

Frostbiteは、パンクチュアルライト、エリアライト、エミッシブ表面、IBLといった、いくつかのライトタイプをサポートする。“IBL”という言葉には、(空表現に用いる)遠方のライトプロブ、局所化したライトプロブ、スクリーンスペースリフレクション(SSR)が含まれる。一貫性はすべてのライティング要素が結合し、マテリアル特性と正しく相互作用するとき達成される。以下に例を示す。

  • 一貫性のあるマテリアルライティング: すべてのBSDFはすべてのライトタイプと正しく相互作用すべきである。これは直接光と同じく間接光も含まれる。
  • 一貫性のある間接ディフューズライティング: すべてのライトタイプはラジオシティシステムを考慮しなければならない。太陽や空のライティングは非常に重要な部分であるが、他のライトタイプについてもすべて同様に含まれるべきである。
  • 一貫性のある間接スペキュラライティング: SSR、ローカルライトプロブ、遠方のライトプロブはともに正しく組み合わされなければならない。
  • 一貫性のあるライト単位: すべてのライトは現実的な比率を達成するため同じ単位で表現されるべきである。例えば、HDRキャプチャしたライトプロブを扱うときは注意しないとすぐに解析的ライトとの比率がおかしくなる。
  • 一貫性のあるデカール: デカールは間接光を含むすべてのライトタイプの影響を正しく受けるようにすべきである。

次節ではFrostbiteがサポートするすべてのライトライプとエンジンでライティングの一貫性を保つ方法を説明する。我々はすべてのケースを解決していないため、その落とし穴についても詳しく述べる。デカール由来の問題については節3.3を参照。

4.2. 解析的ライトパラメータ(Analytical light parameters)

アーティストの利便性のため、Frostbiteでは、パンクチュアルライトとエリアライトで同じインターフェースと設定を共有している。これらの設定の一部を図15に示す。我々はライトの強度から色相を分けることを選択する。我々は 強度intensity という言葉をライトが放射するエネルギー量を指すときに使うが、これは厳密な定義ではない。白の色相を差別化するため、人工的な光源は色温度(白熱灯やハロゲンランプ)か相関色温度correlated color temperature(CCT) (ほぼその他)のいずれかを持ってラベル付けされる。色温度は比較可能な色相の光を放出する理想的な黒体放射の温度であり、CCTはそのライトの色に人間の色知覚で最も近いとする色温度を指す。色温度とCCTは通常ケルビン(K)で測定される。この文書では簡単化のために、色温度という言葉にはCCTも含む場合がある。front-facingパラメータのこともcolor temperatureと呼ぶ。表4は様々なライトタイプの対応する温度と知覚する色を示す。

(図15:Frostbiteのライト設定のサンプル。)

スペクトルレンダラ(色の表現にRGBではなくスペクトル値を用いるレンダラ)であれば黒体で定義される放射スペクトルを直に用いることができるだろう7。Frostbiteでは、色温度からは色相のみを参照し8、ライト強度は独立的にアーティストに制御させることとした。色温度から色相を参照することは比較的複雑な処理であり、 @Charity2001WhatColorBlackbody が解説している。アーティストはRGBでも指定できる。

(図16:電球のパッケージに見られる色温度と光量はFrostbiteに直接持ってゆくことができる。)

ケルビン光源の種類
1700-1800マッチの火
1850-1930ロウソクの火
2000-3000日の出や日の入りの太陽
2500-2900家庭用タングステン電球
3000500Wから1kW程度のタングステンランプ
3200-3500水銀灯Quartz lights
3200-7500蛍光灯
32752kWのタングステンランプ
33805kWや10kWのタングステンランプ
5000-5400正午の晴天の太陽Sun direct at noon
5500-6500日光(太陽と空)
5500-6500雲や霞越しの太陽
6000-7500曇り空Sky overcast
6500RGBモニタ(白の点)
7000-8000屋外の日陰
8000-10000部分的な曇り空Sky partly cloudy

: 色温度と知覚する色。2700°Kから3000°Kを暖色、3500°Kから4100°Kを中間色neutral colors、5000°K以上を寒色と呼ぶ。

“ライト強度”は各ライトタイプごとに示される。色温度と強度の両方を用いることで、アーティストはリファレンス値をメーカーのウェブサイトから拾ってきて、Frostbiteに直接突っ込むことができるようになる(図16参照)。ライト設定には通常の減衰範囲が含まれ、ライトの物理サイズ上で制御する。ライトの物理サイズ(例えば、球の半径、ディスクの半径、チューブの長さ、など)はアーティストにそのライトがエリアライトなのかパンクチュアルライトなのかを定義できるようにする。図17はFrostbiteでサポートするライトを示す。点とスポットはパンクチュアルライトのみで、その他はエリアライトと見なされる。パンクチュアルライトとエリアライトを分けているのはパフォーマンス的な理由であり、Frostbiteはライトタイプ間の円滑な移行をサポートする。

(図17:Frostbiteがサポートする4つのライトタイプ。ライトの物理サイズでカテゴライズされる。ポイントライトとスポットライトはパンクチュアルであり、その他はエリアライトと見なされる。)

4.3. ライト単位(Light unit)

一貫性のあるライティングを得るには、ライト強度の比率を尊重する、すなわち、共通の単位システムを持つ必要がある。ライト強度は図18に示されるように広範囲に及ぶ可能性があり、丁重に扱うconserveことが重要である。知覚されるシーンのリッチさはライティングの正しいバランスに起因する。図19は屋内と屋外のライティングをミックスしたものを示す。パイプラインの最後で行う露出処理は広範囲の強度を正規化されたピクセル値に変換する(節5.1参照)。

(図18:上から下まで様々な光量luminous powerを持つ光源。)

(図19:屋内と屋外のライティングが正しい単位により一貫性を持って組み合わせることができる。)

通常はライティングアーティストが太陽のようなリファレンスを任意に定義することによってライト比率をセットアップする。このリファレンスはある強度(通常は5から10の小さな値)を放出するために設定され、他のすべての光源の値はこれをベースに行われる。しかし、大抵の場合でこれらの設定は現在のシーンの状態(地下、屋内、屋外、など)によりバイアスされるため、他のシーンではそのライトリグは使えなくなってしまう。正しいライティング比率を導入するため、Frostbiteではライトに物理単位を採用した。これは以下のことを可能にする。

  • さまざまなライトタイプを一貫性を持って取り扱う。
  • いくつかの場面でライトリグを再利用する。
  • 物理ベースマテリアルからよりよい応答を得る。ハイコントラストなライティングはマテリアルのリッチさを明らかにするのに役立つ。
  • 物理ベースカメラを使うことで、写真家の知識を活用する。節5.1を参照。

ライト単位はライトの測定に関連しており、以下の2つに分けられる。

  • 放射測定Radiometric: “純粋な”物理量を取扱い、光放射測定optical radiation measurementsやスペクトルレンダリングの文脈で使われる9
  • 測光Photometric: 可視スペクトル内の放射の減少radiation fallingのみを考慮する。

放射測定と測光により導かれる量は非常に近い関係にある。測光は本質的に人間の目の感度により重み付けされた放射測定である。これら2つの形式は界隈では広く網羅されてきた。最も一般的に使われる放射測定と測光の量は表5にリスト化されている。放射測定量にはエネルギーの添字eeを用い、測光量にはビジュアルの添字vvを用いる。

放射測定の項単位測光の項単位
エネルギー放射エネルギーQeQ_eJJ(ジュール)光エネルギーQvQ_vlmslm \cdot s(ルーメン・秒)
パワー放射束Φe\Phi_eまたは放射量Js\frac{J}{s}またはWW(ワット)光束Φv\Phi_vまたは光量lmlm(ルーメン)
量毎立体角放射強度IeI_eWsr\frac{W}{sr}光度IvI_vlmsr\frac{lm}{sr}またはcdcd(カンデラ)
量毎面積放射発散度radiant exitanceMeM_eまたは放射照度EeE_eWm2\frac{W}{m^2}光束発散度MvM_vまたは照度EvE_vlmm2\frac{lm}{m^2}またはlxlx(ルクス)
量毎面積毎立体角放射輝度LeL_eWm2sr\frac{W}{m^2 \cdot sr}輝度LvL_vlmm2sr=cdm2\frac{lm}{m^2 \cdot sr} = \frac{cd}{m^2}またはNitNit(ニット)

: 放射測定量と測光量

人間の目の感度はCIEの測光曲線V(λ)V(\lambda)により表される。これは目が特定の光の波長をどれだけ効率的に拾うかを表した釣鐘型の曲線に従う(図20参照)。人間の目の感度は緑として現れる555nmをピークとする。この波長で、感度の関数での値は1単位になり、100%の効率を意味している。測光量は以下の可視光(380nmから780nm)上の積分により放射測定量と関連している。

Xv=Km380780Xe(λ)V(λ)dλ(7)X_v = K_m \int_{380}^{780} X_e(\lambda)V(\lambda)d\lambda \tag{7}

定数KmK_m明所視における放射の最大スペクトル発光効率maximum spectral luminous efficacy of radiation for photoscopic vision と呼ばれ、その値は光度測定におけるSI単位であるカンデラの定義に基づいている。その定義は「1カンデラは、与えられた方向で、周波数540THz(波長にすると555nm)の単色放射を放ち、この方向での放射強度が1683[Wsr]\frac{1}{683} [\frac{W}{sr}]となる、その光度である」であり、Km=683K_m = 683であることを意味する。電球の強度を扱うとき、通常は放射量で説明されるため、上の定義は簡単なフレーズに言い換えることができる。つまり「緑色の555nmの光の1ワットは683ルーメンになる」である。測光曲線からはライトの発光効率を推測することもできる。これは「光源から生み出された光がどれだけ見えているか」と解釈できる。発光効率を計算する式は以下のようになる。

η=683380780Xe(λ)V(λ)dλ380780Xe(λ)dλ(8)\eta = 683 \cdot \frac{\int_{380}^{780} X_e(\lambda)V(\lambda)d\lambda}{\int_{380}^{780} X_e(\lambda)d\lambda} \tag{8}

ここで、η\eta[lmW][\frac{lm}{W}](ルーメン毎ワット)を単位とする。この式は緑(555nm)のライトが683 lm/Wの効率を有することを意味している。これは100%の発光効率と等価である。発光効率はライトタイプごとに異なる可能性がある。つまり、2つの同じワット数を持つライトでも知覚される強度は異なる可能性がある。表6はいくつかの異なるライトの発光効率を示す。

白熱灯2%から5%の間
LEDライト0.66%から8.8%の間
蛍光灯9%から15%の間
太陽15%から19%の間

: いくつかのライトの発光効率(%)。

(図20:人間の目の感度曲線。)

ゲームのような、非スペクトルレンダリングの文脈では、いくつかの簡略化を用いて放射測定単位と測光単位の変換を容易にすることができる。放射量とライトの発光効率の関係から、ワットからルーメンへ変換することが可能になる。

Φv=ηΦe(9)\Phi_v = \eta \cdot \Phi_e \tag{9}

この情報が利用できないときは、ライトはη=683\eta = 683で100%の効率になると仮定するのが一般的である。この式は他の量についてしばしば拡張される。

Xv=683Xe(10)X_v = 683 \cdot X_e \tag{10}

スペクトルレンダラでは、ライトは放射測定単位で表される必要がある。スペクトル加重放射輝度spectral weighted radianceを用いるような後続のsuccessive処理は放射測定の領域でのみ正しくなる。このスペクトル放射輝度をピクセル値に変換する後のステージは測光的な重み付け処理(自動露出やトーンマッピング)をしばしば必要とする。

放射測定か測光か(Radiometry or Photometry?) ほとんどのゲームエンジンのような非スペクトルレンダリングでは、発光効率の情報は放射測定単位と測光単位を行き来するために必要とされる。2つの値(ライト強度と発光効率)を提供することはアーティストに対して複雑さを増加させるため、η=683\eta = 683とする仮定を用いることが好ましい。このような近似により、各量は線形に変換できるようになるため量の表現に関わらず処理が同一のものになる。しかし、現実世界で観察されるものと視覚的に一致させるためにエンジンでは現実世界のライト強度を使うことが望まれる。100%の発光効率を仮定すると、この世界は過度に明るいライティングを生み出すため、放射測定のリファレンス値を使うことを妨げる。幸いなことに、市販のライトは測光量でその特徴を提供している。また、節4.9.1で述べたように、HDRIはしばしば測光単位(輝度)で提供される。

Frostbiteでは、すべてのライトで測光単位を使っている。これは、レンダリングパイプラインがレンダターゲットに輝度値を格納していることを示している。ライティングの強度は相対的な方法(様々なライトタイプの比率)と絶対的な方法(真のライト単位)で表現することもできる。Frostbiteではメーカーのウェブサイトが提供している値やリファレンス値と一致させることができるため、絶対的な方法で扱ったほうが簡単であることを発見した。

備考: あるデバイスでは放射する光を測定することができる。例えば、入射光量計incident light meter(図21)では、表面に届く実際の輝度を測定することができる。輝度は露出計spot meter輝度計luminance meterでも測定できる。これは本質的に入射光を一方向に制限する不透明なシールドを持つ入射光量計である。我々は光度を直接的に測定することはできないので、光源からの距離を把握した状態で輝度を計測し、逆二乗の法則luminousIntensity=luminousdistance2luminousIntensity = luminous \cdot distance^2から等価な光度を計算する必要がある。

(図21:左:白い球の部分で測定する入射光量計。右:望遠鏡型の反射(露出)計。)

EV値Exposure Value: EV値はライト強度を説明するために写真の知識とともにアーティストによりしばしば使われる。もともと、EV値は求められる画のためのカメラの設定(絞りの組み合わせ、シャッタースピード、感度)の集まりである。露出計の助けにより、写真家はカメラフィルムを最大限に使用するように適応したカメラ設定を自動的に決定することができる。詳細は節5.1を参照。こんにちのEV値は写真家による主な使い方から外れてabused from their primary usage、ライトの単位と化している。これは F値f-stop と呼ばれ、底を2とした対数スケールで説明される。このスケールはほぼ知覚的に線形である。EV値はライトの単位として設計されていた訳ではないので、その定義は機器ごとのキャリブレーション定数KKに依存している。

EV=log2(LavgSK)(11)EV = \log_2 \left( \frac{L_{\text{avg}} S}{K} \right) \tag{11}

ここで、LavgL_{avg}はシーンの平均輝度を、SSISOの算術表記ISO arithmeticを、KKは反射光計のキャリブレーション定数を表す。ISO2720:1974ではKKが10.6から13.4の範囲を推奨する。一般用途としてのKKには2つの値がある。すなわち、12.5(キャノン、ニコン、セコニック)と14(ミノルタ、ケンコ、ペンタックス)である。レンダラではK=12.5K = 12.5がもっとも一般的に採用されているように見える10表7はEV値と輝度の対応関係を示す。エリアライトやエミッシブライトとしてlog2のライト単位を用いることは高い値を取り扱う上で好ましいことである。アーティストがEV値を単位とすることに慣れているので、我々はオプションの単位としてK=12.5K = 12.5によるEV値を採用することに決めた。したがって、EV値から輝度への変換は以下のようになる。

L=2EV12.5100=2EV3(12)L = \frac{2^{EV} \cdot 12.5}{100} = 2^{EV - 3} \tag{12}

表8はFrostbiteがサポートすさまざまなライトタイプで使われるライト単位を示す。ライトタイプの各ライト単位が持つそれぞれのアドバンテージは次節で説明する。

EV100EV_{100}-4-3-2-1012345678910111213141516
輝度0.0080.0160.0310.0630.1250.250.512481632641282565121024204840968192

: EV100\text{EV}_{100}(ISO100のときのEV値)とK=12.5K = 12.5のときの対応する輝度(cdm2\frac{cd}{m^2})

タイプ単位
エリア光量(lmlm)、輝度(cdm2\frac{cd}{m^2})、EV値
パンクチュアル光量(lmlm)
測光光度(cdcd)
エミッシブ表面輝度(cdm2\frac{cd}{m^2})、EV値
太陽照度(lxlx)
空や画像ベース輝度(cdm2\frac{cd}{m^2})

: Frostbiteのさまざまなライトタイプに関連するライト単位。

4.4. パンクチュアルライト(Punctual lights)

(図22:逆二乗則の図解。矢印は光源から発散する束を表す。単位面積(オレンジ色の四角形)あたりの矢印の密度、すなわち、束の密度が距離の二乗に比例して減少する。)

Frostbiteはポイントライトとスポットライトの2つのパンクチュアルライトのみをサポートする。パンクチュアルライトを物理的に正しくするためには、いわゆる”逆二乗則inverse square law”に従わなければならない(図22参照)。逆二乗則はポイントライトでのみ有効で、以下には適用しない。

  1. 狭い分布を持つフラッドライトやサーチライト。ライトビームは平行性が強いhighly collimatedため。
  2. エリアライトやフレネルレンズのような特定のライト。

光量: 逆二乗則を式にすると以下のようになる。

E=Idistance2(13)E = \frac{I}{distance^2} \tag{13}

ここで、IIは光度を、EEは照度を表す。この式は距離単位がライティング計算を通して均質である(単位が統一されている)ことを必要とする。この値は距離が0に近づくと無限大に近づくが、ライトは常に大きさを持つため現実世界では起こらない。しかし、リアルタイムグラフィクスでは、数値計算の問題を回避するために小さな補正値を加えることが一般的である。パンクチュアルライトは最小の大きさを持つと考え、オブジェクトを絶対にその中に入り込まpenetrateせないようにすることは経験から言えば良い方法good rule of thumbである。Frostbiteでは、1単位を1mとしてパンクチュアルライトは1cmの大きさを持つと定義する(表記を簡単にするため、この文書で再掲するときは”max”を省略する)。

E=Imax(distance2,0.012)(14)E = \frac{I}{\text{max}(distance^2, 0.01^2)} \tag{14}

Frostbiteでは、アーティストは測光プロファイルにより光量か光度のいずれかを単位としてパンクチュアルのライト強度を制御することができる(節4.5参照)。光量は常にライティング計算において光度に変換される。光量はライトの立体角上で積分することで光度から計算できる。

  • ポイントライト:
ϕ=SIdl=02π0πIdθϕ=4πI(15)\phi = \int_S I d\boldsymbol{l} = \int_0^{2\pi} \int_0^{\pi} I d\theta\phi = 4\pi I \tag{15}
  • スポットライト(開口角opening angle0<θouter<π0 < \theta_{\text{outer}} < \piを持つ):
ϕ=SIdl=02π0θouterIdθϕ=2π(1cosθouter2)I(16)\phi = \int_S I d\boldsymbol{l} = \int_0^{2\pi} \int_0^{\theta_{{\text{outer}}}} I d\theta\phi = 2\pi(1 - \cos\frac{\theta_{\text{outer}}}{2}) I \tag{16}

式16はコーンの正確な立体角である。この式の帰結として、コーンの角度が小さくなるとライティングがそこに集束するためにより明るく見えるということを示している(図23参照)。このような関連性couplingがあることで、アーティストがスポットライトを操作するのが難しくなったり、最適化を行うさいに問題が生じたりする。我々は集束光の関連性を取り除き、反射鏡spot reflectorが光を吸収するかのように振る舞うシンプルなマスキングとすることを選択した。これらの検討と合わせてディスク型のエリアライトへの移行をスムーズに行うため、Frostbiteではスポットライトの光量を以下のように定義した。

ϕ=πI(17)\phi = \pi I \tag{17}

パンクチュアルライトにおける光量から光度への変換は表9にまとめられている。万全を期すために、錐台ライトの変換も付け加えている。錐台ライトと線ライトはFrostbiteではエリアライトとして扱われており、数式を使わない。これらはごくまれに使われる程度であり、ポイントライトやスポットライトの効率的なライティングパスを共有することができない。

ライト計算: これらの光源のライティング計算は以下により求められる。

  • ポイントライト:
Lout=f(v,l)E=f(v,l)Linnl=f(v,l)Idistance2nl=f(v,l)ϕ4πdistance2nl(18)L_{\text{out}} = f(\boldsymbol{v}, \boldsymbol{l}) E = f(\boldsymbol{v}, \boldsymbol{l}) L_{\text{in}} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle = f(\boldsymbol{v}, \boldsymbol{l}) \frac{I}{distance^2} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle = f(\boldsymbol{v}, \boldsymbol{l}) \frac{\phi}{4\pi \cdot distance^2} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle \tag{18}

(図23:光量において、コーンの開口角を小さくするとコーン内の照明レベルが増加する。)

ポイントϕ4π\frac{\phi}{4\pi}
スポットϕ2π(1cosθouter2)\frac{\phi}{2\pi(1 - \cos \frac{\theta_{\text{outer}}}{2})}またはϕπ\frac{\phi}{\pi}
錐台ϕ4arcsin[sin(θa2)sin(θb2)]\frac{\phi}{4 \arcsin \left[\sin(\frac{\theta_a}{2}) \sin(\frac{\theta_b}{2})\right]}

: パンクチュアルライトと錐台ライトにおける光量(lm)から光度(cd)への変換。θouter\theta_{\text{outer}}θa\theta_aθb\theta_bはそれぞれの開口角を表す。

ライト方向に向いている表面の法線を考えると、その照度は逆二乗則に従って以下のようになる。

E=ϕ4πdistance2(19)E_{\perp} = \frac{\phi}{4\pi \cdot distance^2} \tag{19}
  • スポットライト:
Lout=f(v,l)Idistance2nl=f(v,l)ϕπdistance2nlgetAngleAttenuation()(20)L_{\text{out}} = f(\boldsymbol{v}, \boldsymbol{l}) \frac{I}{distance^2} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle = f(\boldsymbol{v}, \boldsymbol{l}) \frac{\phi}{\pi \cdot distance^2} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle \cdot \text{getAngleAttenuation}() \tag{20}

ライト方向に向いている表面の法線を考えると、その照度は逆二乗則(とFrostbiteの慣例)に従って以下のようになる。

E=ϕπdistance2(21)E_{\perp} = \frac{\phi}{\pi \cdot distance^2} \tag{21}

測定: 両者の関係を評価するため、入射光計による一連の測定を行った。そのセットアップは図24で説明されている。光量単位の扱いと電球を表すことができるという点光源についての仮定を評価した結果は表10に示す。ルーメンが2倍になると照度も2倍になることに注目して欲しい。Nearestは得られた中で一番高い値を取り出してきたものであり、電球の大きさに依存する。スポットライトの測定は、セットアップがより複雑になり、我々の定義に合わないため、行わなかった。Frostbiteでのポイントライトはすべての強度キャリブレーションのためのリファレンスライトである。これらは現実世界の測定と合致しており、故に信用に値する。

(図24:ライティング測定のセットアップ。)

電球ブランドワットルーメン1m50cm25cm10cm5.5cm最も近いNearest
Dial6255721394058001700060000
Frostbite62550199796497316441?
Philips70から92120012244018001200033000130000
Frostbiite1200953821528954931568?

: 入射光計による現実世界での電球の測定とインゲーム値の比較。

減衰Attenuation: 逆二乗則が抱える問題のひとつは絶対にゼロに到達しないことである。パフォーマンス的な理由から、レンダラはライトカリングのアルゴリズムをサポートするために有限のライト範囲を実装しなければならない。ある限界点で、照度は滑らかにゼロに達するべきである。これを解決するアプローチのひとつはほとんどの関数に影響を与えないような方法[Karis 2013Karis, B. 2013. Real Shading in Unreal Engine 4. Physically Based Shading in Theory and Practice course. ACM SIGGRAPH. https://blog.selfshadow.com/publications/s2013-shading-course/.]でフォールオフに窓関数を用いることである。これのために、我々は距離基準distance criteriaに基づくゼロへの基本的な線形補間を用いる。

E=lerp(Idistance2,0,distancelightRadius)=Idistance2(1distancelightRadius)(22)E = \text{lerp} \left( \frac{I}{distance^2}, 0, \frac{distance}{lightRadius} \right) = \frac{I}{distance^2} \left(1 - \frac{distance}{lightRadius} \right) \tag{22}

そして、関数を変化しないようにするため、距離基準を微調整すると以下のようになる。

Ewindow2=Idistance2(1distance20lightRadius20)(23)E_{\text{window2}} = \frac{I}{distance^2} \left(1 - \frac{distance^{20}}{lightRadius^{20}} \right) \tag{23}

このシンプルなアプローチはうまくいくが、不自然に見える強めのカットオフを生じる。次のアプローチはしきい値により関数をバイアスして0から1の初期範囲にリマップする[@Madams2011ImprovedLightAttenuation]

threshold=1lightRadius2(24)threshold = \frac{1}{lightRadius^2} \tag{24}
EscaleBias=11threshold(Idistance2threshold)(25)E_{\text{scaleBias}} = \frac{1}{1 - threshold} \left( \frac{I}{distance^2} - threshold \right) \tag{25}

結果は良いが、このアプローチは0地点における勾配が0ではないことでビジュアルに不連続性が生まれてしまうために苦労する。より良いアプローチは窓関数を用いてlightRadiuslightRadius地点における勾配が0になるよう保証することである。図25を参照のこと。

Ewindow1=Idistance2saturate(1xnlightRadiusn)2(26)E_{\text{window1}} = \frac{I}{distance^2} \text{saturate} \left( 1 - \frac{x^n}{lightRadius^n} \right)^2 \tag{26}

(図25:照度: 左のグラフはDistance軸を横切るときの不連続性を強調した様々な窓関数を示す。Window1は[Karis 2013Karis, B. 2013. Real Shading in Unreal Engine 4. Physically Based Shading in Theory and Practice course. ACM SIGGRAPH. https://blog.selfshadow.com/publications/s2013-shading-course/.]で使われているもの。Window2は非連続性の問題を持つ。Window3はなだらか。中と右のグラフは個々のライト半径10と40のフォールオフに適用された窓関数を示す。)

nnは遷移の滑らかさを調整することができる。我々はFrostbiteにおいて Karis [2013Karis, B. 2013. Real Shading in Unreal Engine 4. Physically Based Shading in Theory and Practice course. ACM SIGGRAPH. https://blog.selfshadow.com/publications/s2013-shading-course/.] によって示されたものと同じようなn=4n = 4とした場合のWindow1を採用した。このスムージング関数はすべてのパンクチュアルライトとエリアライトで採用されている。しかし、lerpの基準criteriaは放射状である(x2d2\frac{x^2}{d^2})ので、チューブや矩形ライトのような球でない形ではうまくいかない。我々はパフォーマンス的な理由によりこのトレードオフを許容する。アーティストは正確さが必要とされる場面ではライト半径を拡大することができる。

リスト4はこの節で述べた様々な主題の結果のコードを示す。

float smoothDistanceAtt(float squaredDistance, float invSqrAttRadius) {
    float factor = squaredDistance * invSqrAttRadius;
    float smoothFactor = saturate(1.0f - factor * factor);
    return smoothFactor * smoothFactor;
}

float getDistanceAtt(float3 unnormalizedLightVector, float invSqrAttRadius) {
    float sqrDist = dot(unnormalizedLightVector, unnormalizedLightVector);
    float attenuation = 1.0 / max(sqrtDist, 0.01 * 0.01);
    attenuation *= smoothDistanceAtt(sqrDist, invSqrAttRadius);
    return attenuation;
}

float getAngleAtt(float3 normalizedLightVector, float3 lightDir, float lightAngleScale, float lightAngleOffset) {
    // CPUで以下を計算しておく。
    // float lightAngleScale = 1.0f / max(0.001f, (cosInner - cosOuter));
    // float lightAngleOffset = -cosOuter * angleScale;

    float cd = dot(lightDir, normalizedLightVector);
    float attenuation = saturate(cd * lightAngleScale + lightAngleOffset);

    // 遷移を滑らかにする。
    attenuation *= attenuation;

    return attenuation;
}

// パンクチュアルライトを処理する。
float3 unnormalizedLightVector = lightPos - worldPos;
float3 L = normalize《unnormalizedLightVector》;
float att = 1;
att *= getDistanceAtt(unnormalizedLightVector, lightInvSqrAttRadius);
att *= getAngleAtt(L, lightForward, lightAngleScale, lightAngleOffset);

// lightColorは出射する輝度×ユーザのライト色である。
// つまり、ポイントライトと光量単位だと: lightColor = color * phi / (4 * PI)
float3 luminance o  BSDF(...) * saturate(dot(N, L)) * lightColor * att;

: 減衰。

4.5. 測光ライト(Photometric lights)

測光ライトはそれらの強度分布を説明するために測光プロファイルを使う。これらの分布は測光ファイルに格納されており、ファイルフォーマットとしてIESEULUMDAT2つが一般的に存在する。これらはシンプルなASCIIファイルである。

  • IES: IESはIlluminating Engineering Societyの頭文字で、ウェブ上で測光データを配信するために作られた。北米では最も人気があり、ヨーロッパでも広く使われている。
  • EULUMDAT: EULUMDATはヨーロッパの標準規格であり、ヨーロッパではデファクトスタンダードとなっているが、一般に認められた標準化団体が存在しない。

多くの照明メーカーは自身のウェブサイトで自由に利用可能な測光ファイルを提供している。例えば、Lithonia LightingはIESとEULUMDATのファイルの広大なライブラリを持っている。

(図26:IESのレンダリングとライティング分布の例。)

両フォーマットは様々な角度に対する光度を格納する。これらは研究機関でライトセンサを使って測定され、光源の周りを球状に広がり、球の中心を指し示す。このキャプチャ手法により、すべてのランプは点光源として考えられる(図26を参照)。物理的に正確な結果を得るため、IES/EULUMDATファイルは小さな球の上に適用されるにとどめるべきである。IES/EULUMDATファイルを小さい球でないジオメトリに適用すると、手法やフォーマット定義に固有の不正確さが生じる可能性がある。ライト分布を説明するために使われる球面座標系は”フォトメトリック・ウェブthe photometric web”と言われる。これらは3つの異なるタイプのフォトメトリック・ウェブがあり、タイプA、B、Cと呼ばれる。

  • タイプA: 車のヘッドライトや信号灯用。
  • タイプB: 調整可能な屋外エリアやスポーツの照明器具用。
  • タイプC: 建築や道の明かり用。

実践では、タイプAとBはまれに用いられ、タイプCはコンピュータグラフィクスで最も一般的に用いられる。

IES フォーマットはその構造が理解しにくい形でカンデラとして光度値を格納する。これはこのフォーマットがサポートする絶対的光度と相対的強度の両方に適用される。絶対的光度はLED器具で必要になり、相対的光度はコンピュータグラフィクスや昔ながらのライト(蛍光灯、白熱灯、ハロゲン、など)において最も一般的なケースである。このフォーマットにはIES-LM-63-86からIES-LM-63-2002までの5つの異なる仕様がある。すべてのフォーマットをサポートするIESパーサを書くことは簡単な仕事ではなく、コンピュータグラフィクスで使われるいくつかのファイルは不完全でありフォーマットに反しているように見える。その仕様は自由にアクセスできるわけではなく、いくつか不明な範囲が存在する。具体的には、水平な回転の方向をに伴う測光タイプAとBに関するIESNAの文献にいくつかの混乱がある。IESに関するこんにちの最良の資料はHelios32というウェブサイト[@Ashdown1999Helios32Resources]と彼の関連する文書であるように思われる。IESパーサを書くための良い資料はHelios32を管理している @Ashdown1998ParsingIESNALM63 によって書かれている。IESファイルを可視化するために、最も人気のあるビュアーはIESviewerである[@Legotin2001IESviewer]。一方でEULUMDATフォーマットはライトによって放出される総キロルーメンあたりのカンデラにより光度値を格納するという良く構造化されたフォーマットである。

総キロルーメンあたりのカンデラ(cdklm)=1000光度(cd)総光束(lm)\text{総キロルーメンあたりのカンデラ}(\frac{cd}{klm}) = \frac{1000 \cdot \text{光度}(cd)}{\text{総光束}(lm)}

この特質は重要であり、いくつかの明確化を行うのに必要である。IESファイルは相対的光度と絶対的光度の両方に対してカンデラ値を格納する。絶対的光度と相対的光度の両方に対してEULUMDATファイルからカンデラ値を取り出すには、以下の変換を施す必要がある。

光度(cd)=総キロルーメンあたりのカンデラ(cdklm)総光束(lm)1000\text{光度}(cd) = \frac{\text{総キロルーメンあたりのカンデラ}(\frac{cd}{klm}) \cdot \text{総光束}(lm)}{1000}

EULUMDATフォーマットはより複雑な器具fixtureや色温度のような追加情報を格納することができる。EULUMDATフォーマットをメンテナンスする団体がおらず、その仕様は1990年からほとんど変わらないままである。公式なファイルフォーマットの出版物がなく、唯一の仕様のひとつはHelios32のウェブサイト[@Ashdown1999Helios32Resources]より取得可能である。ビジュアライザや文書を含む良いツールセットがEulumdat Toolsのウェブサイト[@FOLDSystems2003EulumdatTools]にて取得可能である。

Frostbiteでは、開発にかけられる時間が少なかったため、その欠点に関わらずIESフォーマットのみをサポートすることにした。コンピュータグラフィクスで普及していると思われるのも理由のひとつである。IESファイルから生成した測光プロファイルは直接ポイントライトやスポットライトに適用することができる。IESプロファイルはライト強度を記述するのに使うこともでき、乗数multiplierで調整することができる。これは光度でライトを制御する唯一の方法である。もうひとつの選択肢はIESプロファイルをプロファイルの最大光度で正規化されたマスクとして使うことである。光度のポイントライトの数式で両方のケースを扱うため、我々は最大光度でプロファイルを正規化し、以下の式でポイントライトの評価を行う。

L=f(v,l)Id2nlgetIESProfileAttenuation()(27)L = f(\boldsymbol{v}, \boldsymbol{l}) \frac{I}{d^2} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle \text{getIESProfileAttenuation}() \tag{27}

IIはプロファイルの最大光度かマスク用のユーザ定義ライト強度のいずれかを表す。getIESProfileAttenuation\text{getIESProfileAttenuation}関数は正規化されたプロファイル値を返す。スポットライトでは、角度による減衰がこの式の外にかけられる。よりタイトな形はより進んだ最適化を可能にし、単純なプロファイルのために便利である(図27参照)。

(図27:IESライトプロファイルの3Dビュー。左:スポットライトに適した簡単なプロファイル。右:ポイントライトに必要な複雑なライトプロファイル。)

新しいライトプロファイルを作るとき、球面測光関数は球面パラメータ化(θ,cos(ϕ))(\theta, \cos(\phi))により2Dテクスチャを埋めるため再構築されサンプルされる11。我々はマスク的な使い方とそうでない使い方の両方を扱うために最大光度の逆数によりスケールされた正規化済みの値を格納する。シェーダでは、2Dテクスチャが評価され、減衰として適用される(リスト5)。

float getIESProfileAttenuation(float3 L, ShadowLightInfo light) {
    // ライト空間へのサンプル方向
    float3 iesSampleDirection = mul(light.worldToLight, -L);

    // デカルト座標から球面座標へ
    // テクスチャはcos(phi)にエンコードされ、[-1, 1]から[0, 1]へスケールされる。
    float phiCoord = (iesSampleDirection.z * 0.5f) + 0.5f;
    float theta = atan2(iesSampleDirection.y, iesSampleDirection.x);
    float thetaCoord = theta * FB_INV_TWO_PI;
    float3 texCoord = float3(thetaCoord, phiCoord, light.lightIndex);
    float iesProfileScale = iesTexture.SampleLevel(sampler, texCoord, 0).r;

    return iesProfileScale;
}

att *= getAngleAtt(L, lightForward, lightAngleScale, lightAngleOffset);
att *= getIESProfileAttenuation(L, light);
// lightColorは選択に依存する。
// マスクでない: lightColor = color * MaxCandelas
// マスク(光量によるポイントライト用): lightColor = color * phi / (4 * PI);
float3 luminance = BSDF(...) * saturate(dot(N, L)) * lightColor * att;

: IESプロファイルのサンプル。

なぜIESプロファイルを使うのか? IESプロファイルはゲームよりも建築の設計でより役に立つ。しかし、マスクとしてライトプロファイルを使えるようになると、面白い使い方が生まれてくる。例えば、IESプロファイルはあるツールでアーティストが作成することができ、複雑なシャドウをシミュレートするのに使うことができる(図28)。これはcookieテクスチャ12に似ているが、異なるパラメータ化によるものである。

(図28:フェイクシャドウのためにアーティストが作成したIESプロファイルの例。IESプロファイルはIESGen3で作られた。)

4.6. 太陽(Sun)

太陽は、特に屋外環境では重要な光源であり、非常に高い値(表11参照)を持つ一方で、非常に小さな立体角をカバーする。この構成では法線の向きと変化に過敏に反応する。マテリアルのディフューズ部分のためのパンクチュアルライトとしてこのような光源を検討することは許容されるべき近似であるが、スペキュラ部分にこれをすると鏡のような表面で問題を引き起こす。Frostbiteでは、この問題を部分的に緩和するalleviateために、太陽を常に外側の半球に垂直なディスク型エリアライトとして扱う。

アーティストは太陽の方向に垂直な表面に対して太陽の照度(ルクス)を指定する。これは(表11のような)光計を用いなければならない現実世界とは反対に直接的に値を確認できるために便利である。その計算は以下のように単純化される。

Lout=f(v,l)E=f(v,l)Enl(28)L_{\text{out}} = f(\boldsymbol{v}, \boldsymbol{l}) E = f(\boldsymbol{v}, \boldsymbol{l}) E_{\perp} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle \tag{28}

ここで、EE_{\perp}はアーティストにより与えられる照度値である。リスト6は太陽を評価するための関数を示す。ディフューズ部分は太陽がパンクチュアルであるかのように照らされ、スペキュラ部分は太陽の形を計算に入れている。

時間9:0010:0011:0012:0013:0014:3017:0018:30
空+太陽85500880001016001100001136001093007700039800
2570019700201001930019600255002900014000
太陽5980068300815009070094000838004800025800
空+太陽\perp15040014540014250099000
\perp27300290003600020000
太陽\perp12310011640010650079000

: 光計で測定された太陽と空の照度値(ルクス)の例。\perpなしは水平方向での測定を、\perpありは太陽方向での測定を表す。測定場所はストックホルムで、6月に行った。

float3 D = sunDirection;
float r = sin(sunAngularRadius);  // ディスク半径
float d = cos(sunAngularRadius);  // ディスクまでの距離

// ディスクへの最も近い点(半径が小さいため、良い近似となる)
float DdotR = dot(D, R);
float3 S = R - DdotR * D;
float3 L = DdotR < d ? normalize(d * D + normalize(S) * r) : R;

// ディフューズとスペキュラの評価。
float illuminance = sunIlluminanceInLux * saturate(dot(N, D));

// D: ディフューズ方向
// S: スペキュラ法苦
luminance = BSDF(V, D, L, data) * illuminance;

: ディスク型エリアライトとしての太陽の評価。

備考: 現時点では正しいエネルギー保存因数を見つけられていないため、このディスク型エリアライトはエネルギー保存則を満たしていない。空からのライティングは遠方のライトプロブとして扱う(節4.9参照)。

4.7. エリアライト(Area lights)

エリアライトは光源が物理的な形状を持つ現実世界のライティングと一致させるために物理ベースレンダリングにおいて重要である。この形状はアーティストが表面のマテリアル特性、特にラフネスを簡単に把握することができるようにする。以前にパンクチュアルライトを使っていた頃は、アーティストは無限小のスペキュラハイライトを表面のラフネスを調整することで隠す傾向があり、故にライティングとマテリアルが結合していた。パンクチュアルな発生源は光源の良い近似となり得るが、文脈(距離、関与媒質、など)に依存する。後に見ることになるだろうが、エリアライトはIBLと概念的に近いため相互作用を容易に行うことができる。より重要なことは、エリアライトはさらに柔らかいライティングを生み出し、スペキュラエイリアシングを低減する。

(図29:ディスク型エリアライトとして表現された太陽に対して反応する異なるラフネスによるマテリアルの例。)

Frostbiteでは、球、ディスク、チューブ、矩形といった様々なエリアライト形状をサポートする。エリアライトによって照らされているある点の出射する輝度は以下で与えられる。

Lout=Ω+f(v,l)V(l)Linnldl=Ωlightf(v,l)Linnldl(29)L_{\text{out}} = \int_{\Omega^+} f(\boldsymbol{v}, \boldsymbol{l}) V(\boldsymbol{l}) L_{\text{in}} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle d\boldsymbol{l} = \int_{\Omega_{\text{light}}} f(\boldsymbol{v}, \boldsymbol{l}) L_{\text{in}} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle d\boldsymbol{l} \tag{29}

関数VVは陰影が付けられる点からエリアライトが到達可能であれば11、そうでなければ00となる。関数VVはエリアライトの形状とそのシャドウの両方を勘定に入れることができる。この節ではエリアシャドウを考慮しない。これは節4.10.4で述べる。故に、VVはライト形状の可視性のみ表現し、Ωlight\Omega_{\text{light}}はエリアライトに対する立体角を表す。この立体角上の積分は面積上の積分として書き直すことができる[@Pharr2010PhysicallyBasedRendering] (図30を参照)。

(図30:微小面積dAdAに対する微小立体角はdAcosθr2dA\frac{\cos\theta}{r^2}に等しい。ここで、θ\thetadAdAの法線と点ppへのベクトルのなす角を、rrppからdAdAへの距離を表す。)

Lout=Af(v,l)Linnlnaldistance2dA(30)L_{\text{out}} = \int_A f(\boldsymbol{v}, \boldsymbol{l}) L_{\text{in}} \frac{\langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle \langle n_a \cdot -l \rangle}{distance^2} dA \tag{30}

この式は常に解析解を持つわけではないが、Monte Carloと重点サンプリングにより数値積分できる。我々は節2で述べたようにすべてのエリアライトを重点サンプリングするインエンジンリファレンスを実装した。このコードは付録Aで提供される。当然だが、この種の計算はプロダクション用としては高価すぎるので、我々はこれらの近似を開発した。インエンジンリファレンスモードは近似の正確性を確かめるための貴重なツールとなった。

ディフューズライティングとスペキュラライティングの積分はエリアライトのタイプについて別々に記述される。

Lout=Ωlightfd(v,l)Linnldl=Afd(v,l)Linnlnaldistance2dA(31)L_{\text{out}} = \int_{\Omega_{\text{light}}} f_d(\boldsymbol{v}, \boldsymbol{l}) L_{\text{in}} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle d\boldsymbol{l} = \int_A f_d(\boldsymbol{v}, \boldsymbol{l}) L_{\text{in}} \frac{\langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle \langle n_a \cdot -\boldsymbol{l} \rangle}{distance^2} dA \tag{31}
Lout=Ωlightfr(v,l)Linnldl=Afr(v,l)Linnlnaldistance2dA(32)L_{\text{out}} = \int_{\Omega_{\text{light}}} f_r(\boldsymbol{v}, \boldsymbol{l}) L_{\text{in}} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle d\boldsymbol{l} = \int_A f_r(\boldsymbol{v}, \boldsymbol{l}) L_{\text{in}} \frac{\langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle \langle n_a \cdot -\boldsymbol{l} \rangle}{distance^2} dA \tag{32}

備考: この文書で表されるエリアライトは執筆時点ではプロダクションで使われていない。これらはシネマティクスのような30FPSのゲームを対象とすることを目標としており、非最適化バージョンを提供するのみとなっている。

4.7.1. エリアライトの単位(Area light unit)

物理的なライト単位に伴い、エリアライトの大きさとその強度はお互いに繋がっている。アーティストは2つの強度単位から選択することができる。

  • 光量: ルーメン(lm)で表される光量は、ライトによってすべての方向に放たれる可視光の総量を記述する。この量はライトの大きさに対して独立である。ライトのサイズが大きくなってもシーンの照明レベルは変化しないが、その面積が大きくなると同じ光量でより広い範囲に広がるため、ライトが生み出すハイライトは暗くなる(図31の上段を参照)。
  • 輝度: ニット(cd/m2\text{cd}/\text{m}^2)またはEV値で表される輝度は可視光の表面光量を記述する。この単位が使われるとき、ライトにより放たれるエネルギー総量はそのサイズに依存する。シーンの照明レベルはその面積が増加するごとに上昇するが、そのようなライトが生み出すハイライトは強度を保存する(図31の下段を参照)。

(図31:上: 左から右に球の半径が増加する。シーンの照明レベルは据え置きであるが、スペキュラハイライトは大きく暗くなっている。下: 左から右に球の半径が増加する。同様に全体のディフューズ強度も増加しているが、スペキュラハイライトはその強度を維持しつつ大きくなっている。)

実践では、アーティストはエリアライトのセッティングとして輝度をめったに使用しない。ディスプレイのような、表面全体に均等に光を放出する平坦なディフューズ表面においてほぼ適切である。

利便性のため、我々はライティング計算において強度を輝度に対象的に変換する。任意の方向に放たれる、ランバートエミッタ13上の点における輝度はエミッタの面積AAと射影した立体角で割ったその総光量ϕ\phiに等しい。

L=ϕAΩ+lndl=ϕAπ(33)L = \frac{\phi}{A \int_{\Omega^+} \langle \boldsymbol{l} \cdot \boldsymbol{n} \rangle d\boldsymbol{l}} = \frac{\phi}{A \pi} \tag{33}

光量から輝度への変換式は表12に示す。EV値から輝度への変換は節4.3で詳しく述べている。

ϕ4r2π2\frac{\phi}{4 r^2 \pi^2}
ディスクϕr2π2\frac{\phi}{r^2 \pi^2}
チューブϕ(2πrl+4πr2)π\frac{\phi}{(2\pi rl + 4 \pi r^2) \pi}
矩形ϕπwh\frac{\phi}{\pi wh}

: Frostbiteのライトのための光量(lm)から輝度(cd/m^2)への変換式。ここで、rrは半径を、llはチューブの長さを、wwhhは矩形の幅と高さを表す。

では、パンクチュアルライトが輝度単位を用いない理由をより明らかにする。エリアライトでライティングを計算するとき、我々はライト面積上の積分を効率的に計算して輝度を扱う。ただし、パンクチュアルライトは面積を持たないので、光度に頼ることになる。しかし、Frostbiteでは、パンクチュアルライトとエリアライトは同じインターフェースを共有する。この共通のインターフェースをサポートするため、我々は、アーティストがその強度を制御するために輝度単位を指定した場合、パンクチュアルライトを1cmのエリアライトへ自動的に格上げするpromoteことにした。輝度単位はほとんど使われないため、このハックはパフォーマンスを傷つけない。パンクチュアルライトとすべきラインライトや錐台ライトもその複雑さのためにエリアライトとして考え、それぞれチューブライトと矩形ライトとの差異は存在しない。

4.7.2. ディフューズエリアライト(Diffuse area lights)
4.7.2.1. 一般(General)

当初、我々はDisneyのディフューズBRDFのケースを見つける前だと、ランバートディフューズBRDFρπ\frac{\rho}{\pi}でエリアライトの積分を解こうと考えていた。エリアライトが均一な定数の強度LinL_{\text{in}}を持つと仮定することも考えられた。つまり、式31のディフューズライティング積分は以下のように書き換えられる。

Lout=ρπΩlightLinnl=ρπE(n)(34)L_{\text{out}} = \frac{\rho}{\pi} \int_{\Omega_{\text{light}}} L_{\text{in}} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle = \frac{\rho}{\pi} E(n) \tag{34}

ここで、放射照度EEは以下で定義される。

E(n)=ΩlightLinnldl=ALinnlnaldistance2dA(35)E(n) = \int_{\Omega_{\text{light}}} L_{\text{in}} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle d\boldsymbol{l} = \int_A L_{\text{in}} \frac{\boldsymbol{n} \cdot \boldsymbol{l} \rangle \boldsymbol{n_a} \cdot \boldsymbol{-l} \rangle}{distance^2} dA \tag{35}

節4.4式13に見られるように、放射照度計算における逆二乗則は、このエリアライトがレシーバーである表面から十分に遠く離れている場合を除き、エリアライトにおいて正しくない(節4.7.3参照)。故に、エリアライトの放射照度を計算するため、我々は式35を解決する必要がある。

(図32:ライト構成2つ。左:ライトがパッチdAdAから全体的に見えている。右:ライトがパッチdAdAから部分的に見えている。ここではライトの半分が表面の地平線の下にある。)

エリアライトは大きな立体角にまたがったり、一部が陰影付けされる点の地平線の下に行くことさえあり得る。この場合、エリアライトのライティングはオブジェクトを回り込むwrap aroundため、柔らかい見た目になる。この”地平線の場合”を正しく扱わないと、その回り込むライティングwapped lightingの強度は不正確になり、エリアライトで照らされているようには見えなくなる(図32図33を参照)。式35を解くための手法がいくつか存在する。あるものは陰影付けされる点から小さい立体角に対するエリアライトでのみ正しい。これは地平線と交差しない。もうひとつは地平線の場合を扱うが、強度が不正確になる。次節では、正しい強度を持った大きいエリアライトの場合を解決するかどうかの”地平線を正確に扱うcorrectly handling the horizon”手法を述べる。

(図33:大きな矩形ライトのライティング。左上:リファレンス。右上:地平線ハンドリングをしない手法。ライティングはエリアライトの中心へ向かう小さな円錐の中では正しい。ライティングはライト一や陰影付けされる点により定義される半球の中に制限される。左下:地平線ハンドリングをする手法だが、回り込むライティングが誤った強度を持つ。右下:正確な地平線ハンドリングをする手法。見た目が柔らかく、滑らな遷移を伴う回り込むライティングが存在する。)

解析的積分: 積分は複雑であるが、ある制約の下では、解析解が存在する。幸いにも、その他の構成やライトタイプの解は 光輸送light transport伝熱heat transfer の二分野で利用可能である。光輸送では、ラジオシティの体系で使われる、2つの差分領域PiP_iPjP_jの間のよく知られた フォームファクタform factor が以下のような形で定義される。

FormFactor=xPiyPjcosθcosθπr2V(x,y)dxdy(36)\text{FormFactor} = \int_{x \in P_i} \int_{y \in P_j} \frac{\cos\theta \cos \theta'}{\pi r^2} V(x, y) dx dy \tag{36}

この式は式35の一般形式である。これは他の表面により陰影付けされる表面を扱う一方で、式35は表面により陰影付けされる点を扱う。ラジオシティの体系では表面により陰影付けされる点に対する様々な解法が提供される。式中の1π\frac{1}{\pi}はLambertのBRDFに由来することに注意したい。これは、これを打ち消すためのπ\piによるフォームファクタに基づいた解析解をかける必要があろうことを意味するため、重要である。そのため、我々の場合では、放射照度の定義は1π\frac{1}{\pi}を含まない。

E(n)=Ωlight=LinnlπFormFactor(37)E(n) = \int_{\Omega_{\text{light}}} = L_{\text{in}} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle \pi \text{FormFactor} \tag{37}

放射輸送radiative transferでは、形態係数view factor と呼ばれる等価な数式が存在する。FabF_{a \to b}で示される形態係数は表面Aを離れて表面Bに当たる放射の割合である。伝熱の分野は様々な表面形状から放射を受け取る点に対するいろいろな解析解を提供する[@Howell2010CatalogRadiationHeat]。単純化のため、意味論的に異なっていたとしてもこれらは同じ式を共有するので、フォームファクタ形態係数の両方をフォームファクタと述べることにする。フォームファクタの式は正確な地平線ハンドリングを持つことも持たないこともできる。我々は球とディスクのエリアライトのためにフォームファクタの手法を採用することを選択した。万全を期すために、我々は付録Eに矩形ライトのものも提供するが、これは採用しなかった。ほとんどのフォームファクタの式は複雑である。我々はここの式を再現せず、対応するコードリストのみを提供するのみとした。詳細は参考文献を参照のこと。

4.7.2.2. 球型エリアライト(Sphere area lights)
  • @Quilez2006SphereAmbientOcclusion は地平線の場合を扱わない解を提供している。これは [@Martinez2014RadiantiveViewFactors]て提供される”正面の球へのパッチPatch to a sphere frontal”の構成と似ている。Quilezのバージョンは球型エリアライトの中心が表面の法線に平行でない場合の扱いができるようにするための追加のnl\langle \boldsymbol{n} \cdot \boldsymbol{l} \rangleを持つ。しかし、地平線の上だけでは十分ではなく、数式は地平線より上の対応する小さな立体角でのみ働く(図36参照)。
  • [@Martinez2014RadiantiveViewFactors]でもたらされる”傾いた球へのパッチPatch to a sphere tilted”の構成は地平線の場合を正しく扱う。その他では @Snyder1996AreaLightSources による式がある。

“正面の球へのパッチ”と”傾いた球へのパッチ”は図34に表される。Quilezの式と”傾いた球へのパッチ”はリスト7に報告され、結果は図35に示される。

(図34:球型エリアライト。左:“正面の球へのパッチ”、すなわち、光源が地平線のより上にあり、パッチdAdAの表面法線と平行である場合。右:“傾いた球へのパッチ”、すなわち、光源がパッチdAdAの地平線より下にある可能性がある一般的な場合。)

(図35:左:正確な地平線ハンドリングを伴う球型エリアライトの結果。右:リファレンス。完全に一致している。)

float3 Lunormalized = lightPos - worldPos;
float3 L = normalize(Lunormalized);
float sqrDist = dot(Lunormalized, Lunormalized);

#if WITHOUT_CORRECT_HORIZON  // 地平線より上での解析解

// "正面の球へのパッチ"の式(Quilezのバージョン)
float sqrLightRadius = light.radius * light.radius;
// オブジェクトをライトに入り込ませない(max)
// "FB_PI *"はフォームファクタの式に含まれる(1/FB_PI)を打ち消す
float illuminance = FB_PI * (sqrLightRadius / (max(sqrLightRadius, sqrDist))) * saturate(dot(worldNormal, L));

#else  // 地平線ありの解析解

// "傾いた球へのパッチ"の式
float Beta = acos(dot(worldNormal, L));
float H = sqrt(sqrDist);
float h = H / radius;
float x = sqrt(h * h - 1);
float y = -x * (1 / tan(Beta));

float illuminance = 0;
if (h * cos(Beta) > 1) {
    illuminance = cos(Beta) / (h * h);
} else {
    illuminance = (1 / (FB_PI * h * h)) * (cos(Beta) * acos(y) - x * sin(Beta) * sqrt(1 - y * y)) + (1 / FB_PI) * atan(sin(Beta) + sqrt(1 - y * y) / x);
}

illuminance *= FB_PI;

#endif

: 球型エリアライトの放射照度。

(図36:球型エリアライティング。緑色のハイライトは、一般に地平線ハンドリングなしの式radius2distance2nl\frac{radius^2}{distance^2}\langle \boldsymbol{n} \cdot \boldsymbol{l} \rangleを使っている所なので、正確である。左:小さなエリアライトでは、ライティングのほとんどが正しい。右:大きなエリアライトでは、正確な結果を表す範囲が減少している。故に、正しい値はライトが地平線と交差していないか対応する立体角が小さい所の陰影付けされる点に限られることが分かる。)

備考: 節4.7.1は光量単位を使うと照明レベルをライト面積から独立させるということに言及している。(一般性を失わずに)地平線ハンドリングをしない式を使うことで、光量ϕ\phiを伴う球型エリアライトの照度は以下で求められる。

E=LinπFormFactor=ϕ4π2r2πr2d2nl=ϕ4πd2nl(38)E = L_{\text{in}} \pi \text{FormFactor} = \frac{\phi}{4 \pi^2 r^2} \pi \frac{r^2}{d^2} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle = \frac{\phi}{4\pi d^2} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle \tag{38}

この式は(nl=1\langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle = 1としたときの)ポイントライトの照度(式19)と一致し、球表面の面積と独立している。これは節4.4の現実世界の測定結果とも一致する。

4.7.2.3. ディスク型エリアライト(Disk area lights)

(図37:ディスク型エリアライト。左:傾いたパッチdAdAと向きを持たない(向き合った)ディスクの単純なケース。中と右:ディスクとパッチdAdAが無作為に向きを持ち、地平線より下にある可能性がある一般的なケース。)

  • @Coombe2005GlobalIlluminationUsing は向きを持ったディスクに対する正確な地平線ハンドリングを持たない解法を提案する。球のときと同じように、地平線の上だけでは十分ではなく、数式は地平線より上にある小さななす立体角と制約方向constraint orientationでのみ働く。
  • 放射輸送の一覧表catalogueの構成[@Howell2010CatalogRadiationHeat]は地平線の場合を正しく扱うが、傾いた平面と方向を持たないディスクに限られる(図37参照)。ディスクの方向を計算に入れるため、我々は数式にライト平面の法線nlight\boldsymbol{n}_{\text{light}}を持つ追加のnlightl\langle \boldsymbol{n}_{\text{light}} \cdot -\boldsymbol{l} \rangleをかける。この追加は制限された方向の中での地平線の上と小さななす立体角でリファレンスと一致させることができるが、その他の場合では小さな不一致discrepancyがある。我々の目的では十分に良い結果を出している。

これら2つのケースの式はリスト8に報告され、結果は図38に示される。

(図38:左:正しい水平線ハンドリングを持つディスク型エリアライトの結果。右:リファレンス。)

float cot(float x) { return cos(x) / sin(x); }
float acot(float x) { return atan(1 / x); }

#if WITHOUT_CORRECT_HORIZON  // 水平線より上の解析解

// フォームファクタの式は打ち消される必要がある(1 / FB_PI)を持つ。
// そのためilluminanceは"FB_PI *"を持つ。
float illuminance = FB_PI * saturate(dot(planeNormal, -L)) * saturate(dot(worldNormal, L)) / (sqrDist / (radius * radius) + 1);

#else  // 水平線ありの解析解

// ほぼ厳密解
float h = length(lightPos - worldPos);
float r = lightRadius;
float theta = acos(dot(worldNormal, L));
float H = h / r;
float H2 = H * H;
float X = pow((1 - H2 * cot(theta) * cot(theta)), 0.5);

float illuminance = 0;
if (theta < acot(1 / H)) {
    illuminance = (1 / (1 + H2)) * cos(theta);
} else {
    illuminance = -H * X * sin(theta) / (FB_PI * (1 + H2)) + (1 / FB_PI) * atan(X * sin(theta) / H) + cos(theta) * (FB_PI - acos(H * cot(theta))) / (FB_PI * (1 + H2));
}

// saturate(dot(planeNormal, -L))をかけたほうがground truthと良く一致する。式の第一の部分と良くマッチするが、第2の部分とは不一致が起こる。まだ改良途中だが、十分良好な結果を示している。
illuminance *= FB_PI * saturate(dot(planeNormal, -L));
#endif

: ディスク型エリアライトの照度。

備考: 球ライトとポイントライトの比較と同じく、ディスクを一定の光量を持つFrostbiteのスポットライトの照度の式と比較する。(一般性を失わずに)地平線ハンドリングを持たない数式を使うことで、光量ϕ\phiを持つディスク型エリアライトの照度は以下で求められる。

E=LπFormFactor=ϕπ2radius2πradius2distance2+radius2nl=ϕπdistance2+πradius2nl(39)E = L \pi \text{FormFactor} = \frac{\phi}{\pi^2 radius^2} \pi \frac{radius^2}{distance^2 + radius^2} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle = \frac{\phi}{\pi distance^2 + \pi radius^2} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle \tag{39}

Frostbiteでスポットライトの光量のために選ばれた変換は光量単位の特性を模倣することを目標としている。この式と式21は(nl=1\langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle = 1のときに)近く、(半径が減少すると追加の項が消えるので、)一方から他方へ滑らかにフェードすることができる(図39参照)。つまり、照明レベルが光量を伴う面積とは無関係であるという言明statementは我々の光量の近似では完全に正しいわけではないが、それが十分に機能することを発見した。

(図39:スポットライト(左)と大きな半径を持つディスクライト(右)の照度の比較。全体の照明レベルは一定のままであり、(球のような)ディスク近くのオブジェクトの小さな領域はディスクの方ではく若干暗くなっていることに注目。)

ディスク型エリアライトはFrostbiteではスポットライトに似ており、角減衰angular attenuationをサポートする。この角減衰はスポットライトの遷移を滑らかにするために現実的なこと考えずに照度に対して単純に適用される。角減衰はエリアライトでシャドウを計算する方法と同じようにライトの位置を偽ることによってスポットライトのときと同じ式で得られる。リスト9節4.10.4を参照。

// CPUで
float3 virtualPoint = lightPos + lightForward * (discRadius / tan(halfOuterAngle));

// GPUで
// ライトの位置を外側の角度に基づいた量だけライトの反対方向にシフトした仮想的な位置で減衰する
illuminance *= getAngleAtt(normalize(virtualPos - worldPos), lightForward, lightAngleScale, lightAngleOffset);

: 角減衰を含むディスク型エリアライトの照度。

4.7.2.4. 球型とディスク型のエリアライトのマージ(Sphere and disk area light merging)

三角関数の恒等式trigonometric identitiesを使うと、正しい地平線ハンドリングを伴う球型とディスク型のエリアライトの数式が似ていることを示すことができる。これらはなす角によってのみ異なるため、評価コードを共有することができる。リスト10にその詳細を示す。高価な逆三角関数はAMDのGCNアーキテクチャにおいて効率的に近似することができる[@Drobot2014ShaderFastLibs]

// right diskは常に照らす表面の方を向く円盤である。
// 球とright diskの立体角は2 * PI * (1 - cos(なす角))である。
// なす角sigmaは、球だとarcsin(r / d)であり、right diskだとatan(r / d)である。
// sinSigmaSqr = sin(なす角)^2は、球だと(r^2 / d^2)であり、円盤だと(r^2 / (r^2 + d^2))である。
// cosThetaはクランプされていない。
float illuminanceSphereOrDisk(float cosTheta, float sinSigmaSqr) {
    float sinTheta = sqrt(1.0f - cosTheta * cosTheta);

    float illuminance = 0.0f;
    // メモ: 以下のテストはオリジナルの式と等価である。
    // 曲線には以下の3つのフェーズが存在する。
    //     cosTheta > sqrt(sinSigmaSqr)のとき、
    //     cosTheta > -sqrt(sinSigmaSqr)のとき、
    //     0のとき。
    // 上2つはcosTheta * cosTheta > sinSigmaSqrとすることで1つにでき、
    // 代わりにsaturate(cosTheta)を用いる。
    if (cosTheta * cosTheta > sinSigmaSqr) {
        illuminance = FB_PI * sinSigmaSqr * saturate(cosTheta);
    } else {
        float x = sqrt(1.0f / sinSigmaSqr - 1.0f);  // 円盤ではx = d / rに単純化する
        float y = -x * (cosTheta / sinTheta);
        float sinThetaSqrtY = sinTheta * sqrt(1.0f - y * y);
        illuminance = (cosTheta * acos《y》 - x * sinThetaSqrtY) * sinSigmaSqr + atan(sinThetaSqrtY / x);
    }
    return max(illuminance, 0.0f);
}

// 球の評価
float cosTheta = clamp(dot(worldNormal, L), -0.999, 0.999);  // エッジケースを避けるためにクランプする
// オブジェクトが表面を貫通するのを防ぐ必要がある
// なので、0で割るのを避けなければならず、0.9999fとする
float sqrLightRadius = lightRadius * lightRadius;
float sinSigmaSqr = min(sqrLightRadius / sqrDist, 0.9999f);
float illuminance = illuminanceSphereOrDisk(cosTheta, sinSigmaSqr);

// 円盤の評価
float cosTheta = dot(worldNormal, L);
float sqrLightRadius = lightRadius * lightRadius;
// ライトを表面に貫通させない
float sinSigmaSqr = sqrLightRadius / (sqrLightRadius + max(sqrLightRadius, sqrDist));
// ground truthとのさらなる一致のために、saturate(dot(planeNormal, -L))をかける
float illuminance = illuminanceSphereOrDisk(cosTheta, sinSigmaSqr) * saturate(dot(planeNormal, -L));

: 球型と円盤型のエリアライトの照度。

4.7.2.5. 矩形型エリアライト(Rectangular area lights)

(図40:矩形型エリアライト。左:矩形の法線がパッチdAdAを指している単純なケース。中と右:矩形の法線が無作為に向きを持ち、地平線より下にある可能性がある一般的なケース。)

我々は矩形ライトに対する正しい地平線ハンドリングを持つ手頃なaffordableフォームファクタの解を見つけられなかった。図40は様々な構成を強調している。そこで、代替となる解を探した。万全を期すため、我々は地平線ハンドリングを持たない矩形ライトのフォームファクタを付録Eで提供する。

最も代表的な点Most representative point: Drobot [2014Drobot, M. 2014. Physically Based Area Lights. GPU Pro 5 34. https://www.taylorfrancis.com/chapters/edit/10.1201/b16721-10/physically-based-area-lights-michal-drobot?context=ubx&refId=7eb353ba-e8dd-4524-9e5c-467c8fcd7230.]ライトの立体角で重み付けされた単一の代表的なディフューズポイントライトで照度の積分を近似することを提案している。

E(n)=ΩlightLinnldlΩlightLinnl(40)E(n) = \int_{\Omega_{\text{light}}} L_{\text{in}} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle d \boldsymbol{l} \approx \Omega_{\text{light}} L_{\text{in}} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle \tag{40}

この近似は小さな立体角において妥当である。これはl\boldsymbol{l}を上手に選ぶことで改善し、より大きな立体角に拡張することができる。l\boldsymbol{l}は陰影付けされる点から 最も代表的な点(MRP) と呼ばれるエリアライトの点へ向かう方向を指す。MRPはディフューズライティングの積分を計算したときに最も大きな値となる点である。この手法は、ライトの位置がMRPに移動するため、地平線の場合を正しく扱う。これは地平線を計算に入れることで立体角を正しく計算すること、立体角の中にMRPが存在することを暗に示している。残念ながら、これはコストのかかる処理である。立体角は以下の積分により計算できる。

Ωlight=Ω+V(l)dl=Ωlightdl(41)\Omega_{\text{light}} = \int_{\Omega^+} V(\boldsymbol{l}) d\boldsymbol{l} = \int_{\Omega_{\text{light}}} d\boldsymbol{l} \tag{41}

この数式はLLln\langle \boldsymbol{l} \cdot \boldsymbol{n} \rangleのない照度の積分と似ているように見える。フォームファクタと同じような流れで数値的か解析的かのいずれかで解くことができる。向きを持つ矩形の立体角の解析的な数式は[@Urena2013AreapreservingParametrizationSpherical]で提供されるが、地平線ハンドリングを持たない。パフォーマンス的な理由で、Drobotは向きを持つ矩形の代わりに地平線ハンドリングを持たない直角錐right pyramid型立体角[@pahio2013SolidAngleRectangular]を使うことを提案する。これらの立体角の式はリスト11に集めてある。 @Mathar2014SolidAngleRectangular は地平線ハンドリングを持つ常に正面を向く矩形に対する立体角の式化を提供するが、複雑すぎるし、向きを持つ矩形を扱えない。

float rightPyramidSolidAngle(float dist, float halfWidth, float halfHeight) {
    float a = halfWidth;
    float b = halfHeight;
    float h = dist;

    return 4 * asin(a * b / sqrt((a * a + h * h) * (b * b + h * h)));
}

float rectangleSolidAngle(float3 worldPos, float3 p0, float3 p1, float3 p2, floatp3) {
    float3 v0 = p0 - worldPos;
    float3 v1 = p1 - worldPos;
    float3 v2 = p2 - worldPos;
    float3 v3 = p3 - worldPos;

    float3 n0 = normalize(cross(v0, v1));
    float3 n1 = normalize(cross(v1, v2));
    float3 n2 = normalize(cross(v2, v3));
    float3 n3 = normalize(cross(v3, v0));

    float3 g0 = acos(dot(-n0, n1));
    float3 g1 = acos(dot(-n1, n2));
    float3 g2 = acos(dot(-n2, n3));
    float3 g3 = acos(dot(-n3, n0));

    return g0 + g1 + g2 + g3 - 2 * FB_PI;
}

: 直角錐と向きを持つ矩形の地平線ハンドリングを持たない立体角。

MRPアプローチの質は立体角の計算の正確性に依存する。残念なことに、立体角の地平線を扱うコストはリアルタイム制約では手頃ではない。なので、代替となる解決法を探した。改善を取り込んだDrobotのMRPアプローチとスクリーンショット比較を付録Eに提供する。

ライト形状の構造化されたサンプリング: 我々はいかなる関数でも以下のように記述できることを知っている。

Ωf(x)dl=ΩAverage[f(x)](42)\int_{\Omega} f(x) d\boldsymbol{l} = \Omega \text{Average}[f(x)] \tag{42}

故に、定数LinL_{\text{in}}の仮定をもって、以下と書くことができる。

E(n)=ΩlightLinnldl=ΩlightLinAverage[nl](43)E(n) = \int_{\Omega_{\text{light}}} L_{\text{in}} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle d\boldsymbol{l} = \Omega_{\text{light}} L_{\text{in}} \text{Average}[\langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle] \tag{43}

立体角上でnl\langle \boldsymbol{n} \cdot \boldsymbol{l} \rangleの平均を見つけることは簡単ではないが、上手に選んだライトポイントで近似することが可能かもしれない。リアルタイム制約を考慮して、ライト表面のカバレッジを最大化するようなライトポイントをN個選ぶことで前述のコサインを平均することにした。矩形ライトの場合では、4つの角と中心を取る。

E(n)=ΩlightLinnldlΩlightLin1Ni=1Nmax(nli,0)(44)E(n) = \int_{\Omega_{\text{light}}} L_{\text{in}} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle d\boldsymbol{l} \approx \Omega_{\text{light}} L_{\text{in}} \frac{1}{N} \sum_{i = 1}^{N} \max(\langle \boldsymbol{n} \cdot \boldsymbol{l}_i \rangle, 0) \tag{44}

このアプローチの利点は、コサインをクランプすることにより、表面の法線によって定義される正の半球に位置するようにその点を制限することである。これにより、暗黙的に立体角の地平線を扱うことが可能になる。MRPアプローチは1つのサンプルを持つ重点サプリング積分に基づいており、最も重要なことである。このことはライト形状の知識に依存する構造化されたサンプリング積分に基づいている。これは、積分が少数のサンプルに限定されているとき、より正確であることが証明されている[Dupuy et al. 2013Dupuy, J., Heitz, E., Iehl, J.-C., Poulin, P., Neyret, F. and Ostromoukhov, V. 2013. Linear efficient antialiased displacement and reflectance mapping. ACM Trans. Graph. 32, 6. 10.1145/2508363.2508422. https://inria.hal.science/hal-00858220v1/file/LEADRmapping.pdf.]

我々は矩形型エリアライトにこの手法を採用した。これにより、地平線での立体角を計算しなくても回り込むライティングで正しい強度を持つことができる。しかし、5つのサンプルしか用いていないことに起因するアンダーサンプリングによって目立ったバンディングアーティファクトが僅かに現れる。それを図41に示す。このコードはリスト12に提供する。

(図41:左上:正しい地平線ハンドリングを持つ矩形型エリアライトの結果。右上:リファレンス。左下:左上の近接ショット。回り込むライティングが正しい強度を持つが、バンディングが僅かに示しているのが見れる。右下:右上の近接ショット。)

if (dot(worldPos - lightPos, lightPlaneNormal) > 0) {
    float halfWidth = lightWidth * 0.5;
    float halfHeight = lightHeight * 0.5;
    float3 p0 = lightPos + lightLeft * -halfWidth + lightUp *  halfHeight;
    float3 p1 = lightPos + lightLeft * -halfWidth + lightUp * -halfHeight;
    float3 p2 = lightPos + lightLeft *  halfWidth + lightUp * -halfHeight;
    float3 p3 = lightPos + lightLeft *  halfWidth + lightUp *  halfHeight;
    float solidAngle = rectangleSolidAngle(worldPos, p0, p1, p2, p3);

    float illuminance = solidAngle * 0.2 * (
        saturate(dot(normalize(p0 - worldPos), worldNormal)) +
        saturate(dot(normalize(p1 - worldPos), worldNormal)) +
        saturate(dot(normalize(p2 - worldPos), worldNormal)) +
        saturate(dot(normalize(p3 - worldPos), worldNormal)) +
        saturate(dot(normalize(lightPos - worldPos), worldNormal))
    );
}

: クランプされたコサイン平均の手法による矩形ライトの照度。

備考: エリアライトの近似を開発するため、我々はMathematicaでフレームワークを作った(この文書の付属ファイルとして提供されている)。このフレームワークはここや付録Eで述べられているいくつかの手法によるさまざまな誤差推定を含んでいる。我々の経験から、MRPアプローチは、(ブルートフォースで定められる)真のMRPや真の立体角を用いたとしても、ディフューズエリアライトにおいて構造化されたサンプリングアプローチより正確性に劣る。

チューブ型エリアライト(Tube area lights)

Frostbiteにおいて、チューブ型エリアライトはカプセル、すなわち、両方の終端が半球となった円柱として表される(図42参照)。カプセルに対するフォームファクタか立体角を見つけるのは、リアルタイム制約に合わないため、難しい問題である。我々は円柱と2つの半球に分けることで、以前の結果を用いて、カプセルを近似することとした。

(図42:チューブ型エリアライト。左:チューブの法線がパッチdAdAを指し示す単純なケース。中と右:チューブの法線が無作為に向いており、地平線の下に潜り込む可能性がある一般的なケース。)

  • 円柱からの照度は円柱の大きさから生成される正面を向いた矩形ライトとして近似される。
  • 半球からの照度は陰影付けされる点から円柱の軸への最も近い点に位置する球のフォームファクタによって近似される。
  • 両方の照度は足し合わされて最終的な照度になる(リスト13図43参照)。

この分割と近似にも関わらず、結果はground truthに十分に近くなる。

// 線の最も近い点を返す(制限なし)
float3 closestPointOnLine(float3 a, float3 b, float3 c) {
    float3 ab = b - a;
    float t = dot(c - a, ab) / dot(ab, ab);
    return a + t * ab;
}

// 線分の最も近い点を返す(制限あり)
float3 closestPointOnSegment(float3 a, float3 b, float3 c) {
    float3 ab = b - a;
    float t = dot(c - a, ab) / dot(ab, ab);
    return a + saturate(t) * ab;
}

// 球は線分の最近傍点に配置される。
// 矩形平面は以下の正規直交枠《orthonormal frame》で定義される。
float3 forward = normalize(closestPointOnLine(P0 , P1, worldPos) - worldPos);
float3 left = lightLeft;
float3 up = cross(lightLeft , forward);

float3 p0 = lightPos - left * (0.5 * lightWidth) + lightRadius * up;
float3 p1 = lightPos - left * (0.5 * lightWidth) - lightRadius * up;
float3 p2 = lightPos + left * (0.5 * lightWidth) - lightRadius * up;
float3 p3 = lightPos + left * (0.5 * lightWidth) + lightRadius * up;

float solidAngle = rectangleSolidAngle(worldPos, p0, p1, p2, p3);

float illuminance = solidAngle * 0.2 * (
    saturate(dot(normalize(p0 - worldPos), worldNormal)) +
    saturate(dot(normalize(p1 - worldPos), worldNormal)) +
    saturate(dot(normalize(p2 - worldPos), worldNormal)) +
    saturate(dot(normalize(p3 - worldPos), worldNormal)) +
    saturate(dot(normalize(lightPos  - worldPos), worldNormal)));

// そして、球の寄与を加える。
float3 spherePosition = closestPointOnSegment(P0, P1, worldPos);
float3 sphereUnormL = spherePosition - worldPos;
float3 sphereL = normalize(sphereUnormL);
float sqrSphereDistance = dot(sphereUnormL, sphereUnormL);

float illuminanceSphere = FB_PI * saturate(dot(sphereL, data.worldNormal)) * ((lightRadius * lightRadius) / sqrSphereDistance);

illuminance += illuminanceSphere;

: チューブの照度。

(図43:左:正しい地平線ハンドリングを持つチューブ型エリアライトの結果。右:リファレンス。)

4.7.3. 5倍ルール(Five times rule)

エリアライトがレシーバーの点から遠くにあるとき、逆二乗則によって照度を近似できる。照度に対する一般的な経験則として、逆二乗則を適用するために”光源への距離は光源の最大の大きさの5倍より大きくあるべきである”という 5倍ルールthe five times rule [@Ryer1997LightMeasurementHandbook]がある(図44参照)。我々は複雑な照度計算をディフューズエリアライトの特性やレシーバーへの距離に基づいたより単純な逆二乗則へと最適化するためにこのルールを使うことができる。リスト14はFrostbiteでの球とディスクのエリアライトのサンプルコードを提供する。このコードは、これらのケースが単純でオリジナルのコードのなす角テストによってすでに扱われているので、実践で使われていない。矩形とチューブのライトの扱いはよりトリッキーであり、さらなる研究が必要である。

(図44:逆二乗則に従うポイントライトと(フォームファクタに正面を向いた構成を使った)ディスク型エリアライトの比較例。グラフは対数スケールである。DistanceRadius>10\frac{Distance}{Radius} > 10のとき、逆二乗則の誤差は1%、すなわち、直径の5倍より小さくなる。)

float3 unnormalizedLightVector = P - worldPos;
float sqrDist = dot(unnormalizedLightVector, unnormalizedLightVector);
float3 L = normalize(unnormalizedLightVector);

// 球の5倍ルールの例。
// パンクチュアルライトを取り戻すためにこのルールを使うとき、
// Frostbiteではライト単位を補う必要がある。
// 故に、球の場合では、その"最適化"は使い物にならない。
float irradiance = FB_PI * sqrlightRadius * saturate(cosTheta) / sqrDist;

if (sqrDist < 100.0f * sqrlightRadius) {
    irradiance = irradianceSphereOrDisk(cosTheta, sinSigmaSqr);
}

// ディスクの5倍ルールの例。
// 我々はディスクの向きを計算に入れる必要があり、
// 球のように、ライト単位を補う必要がある。
// 今回は、多少のALUを節約するが、これは未だに使い物にならない最適化である。
float irradiance = FB_PI * sqrLightRadius * saturate(cosTheta) * saturate(dot(planeNormal , -L)) / sqrDist;

if (sqrDist < 100.0f * sqrLightRadius) {
    irradiance = irradianceSphereOrDisk(cosTheta, sinSigmaSqr) * saturate(dot(planeNormal , -L));
}

: 球とディスクのライトに対する5倍ルール。

Disneyのディフューズによるディフューズエリアライト(Diffuse area light with Disney’s diffuse)

以前の導出のすべてはランバートBRDFに対して行われていた。しかし、マテリアルモデルの節で言及されるように、我々の標準マテリアルはDisneyのディフューズ項を用いる。これは解析的手法に対応しておらず、構造化されたサンプリングのアプローチで各サンプルのモデルに対する評価を呼び出すのが高価になる可能性があった。これを扱うために、我々はランバートエリアライトの照度へ単一のライト方向に対するDisneyのディフューズ評価を適用することとした。

Lout=fd(v,l)E(n)(45)L_{\text{out}} = f_d(\boldsymbol{v}, \boldsymbol{l}) E(n) \tag{45}

l\boldsymbol{l}に対する最も単純な選択はライト位置を使うことである。いくつかのライトタイプでは、この近似は十分に良好である(図45参照)。しかし、より良い選択はDrobotのアプローチのように最も代表的な点の方向を取ることである(図46参照)。Frostbiteでは、パフォーマンス的な理由によりDisneyのディフューズ項に対して入力としてライト位置を使う。

(図45:球は左から右にラフネスが増加する。左:Disneyのディフューズ項への入力としてライト位置を与えるディスク型エリアライティング。右:リファレンス。結果は類似している。)

(図46:球は左から右にラフネスが増加する。左上:Disneyのディフューズ項への入力としてライト位置を与える矩形型エリアライティング。右上:入力としてMRP方向を使う場合。下:リファレンス。MRP近似がよりリファレンスに近い。)

BRDFローブの支配的な方向を計算に入れることでこの近似を改善することが可能である。この支配的な方向の処理は節4.9.3にてその詳細を述べる。我々は表面の法線のシフトによりこれを取り戻す(リスト15参照)。しかし、その差異はとても微妙であるので、シェーダコストを減らすためにこのシフトを適用しないことにした。

float3 getDiffuseDominantDir(float3 N, float NdotV, float roughness) {
    float a = 1.02341f * roughness - 1.51174f;
    float b = -0.511705f * roughness + 0.755868f;
    float lerpFactor = saturate((NdotV * a + b) * roughness);

    return normalize(lerp(N, V, lerpFactor));

: エリアライトを評価するとき、Disneyのディフューズ項のローブの支配的な方向を計算するための関数。

4.7.5. スペキュラエリアライト(Specular area lights)

スペキュラエリアライトはリアルタイム制約下では本当に複雑な問題である。BRDFの入力(視線ベクトル、f0、ラフネス)の数と矩形のような標準ライトの形状のそれ(幅、高さ、向き、定数でない強度)はライトプロブと同様に事前計算アプローチを困難にする。文献で利用可能な現在の解決法はGGXスペキュラモデルのリファレンスとの比較に耐えうるものではない。 Drobot [2014Drobot, M. 2014. Physically Based Area Lights. GPU Pro 5 34. https://www.taylorfrancis.com/chapters/edit/10.1201/b16721-10/physically-based-area-lights-michal-drobot?context=ubx&refId=7eb353ba-e8dd-4524-9e5c-467c8fcd7230.] のMRPアプローチはPhongモデルに限りうまく行き、 Karis [2013Karis, B. 2013. Real Shading in Unreal Engine 4. Physically Based Shading in Theory and Practice course. ACM SIGGRAPH. https://blog.selfshadow.com/publications/s2013-shading-course/.] の反射レイからの最短距離は良い具合のエネルギー保存の項が失われていおり、グレージング角でうまく動作しない。他の数学ヘビーな解決法と同じくエリアライトのためのフィルタされた重点サンプリング[@Colbert2010ImportanceSamplingProduction]に触発された他の解決法を試したが、シェーダコストは法外である。我々はground truthと一致させず、単純に最適なビジュアルを持つより安価な解決法を採用することに決めた。我々のライトはKarisのアプローチを用いているが、ディスクと矩形については、良い具合の粗いエネルギー保存の項をいずれも見つけられなかった(図47参照)。

(図47:スペキュラのみのライティングを持つシーン。左:スペキュラにKarisのアプローチを用いたさまざまなエリアライトタイプ。右:リファレンス。)

粗い表面に対するスペキュラエリアライトの積分を多少改善するため、我々はBRDFローブの支配的な方向を計算に入れた。支配的な方向の処理は節4.9.3でその詳細を述べている。鏡面方向のシフトによりそれを取り戻す(リスト16)。エリアライトのバージョンはライトプロブで使われるそれよりも単純である。我々の場合ではそれで十分であることが判明した。図48には鏡面と支配的な方向を使った比較を示す。これは相関ありと相関なしの両方のSmishのG項でうまく機能する。

float3 getSpecularDominantDirArea(float3 N, float3 R, float NdotV, float roughness) {
    // 単純な線形近似
    float lerpFactor = (1 - roughness);

    return normalize(lerp(N, R, lerpFactor));
}

: エリアライトを評価するとき、マイクロファセットGGXベースのスペキュラ項に対するローブの支配的な方向を計算する関数。

(図48:左:ミラー方向の積分における様々なサイズの球型エリアライティングの近似。右:支配的方向の場合。大きい球と粗い表面で改善が見られる。)

備考: ライトと表面の特性に依存すると、ディフューズエリアライトで計算される照度はスペキュラエリアライトには適切でないことがある(Lambertのコサインが常にディフューズとスペキュラの両方の項に適用されるパンクチュアルライトの場合とは異なる)。確かに、ライトの形状とBRDFの重点コーンの交差に対する立体角は異なる可能性があり、Lambertのコサインに関する積分結果が異なるはずである。

4.8. エミッシブな表面(Emissive surfaces)

現実世界では、エミッシブな表面はエリアライトと同等である。これらは光源のように近くの表面を照らす光を放射する。ゲームでは、パフォーマンス制約により伝統的なライトとして表面のエミッシブな部分を扱うことはできない。Frostbite内では、1)元となる表面に表示されるエミッシブライト、2)光を放つエリアライト、の2つの区別を設けた。エミッシブライトは他のライトと同様にエミッシブ色とエミッシブ強度値を与えることによりシェーダ内でピクセル精度で生成される。強度は輝度(cdm2\frac{cd}{m^2})かEV値で渡される。これらのエミッシブライトはライティングを生み出さず、見えている色のみを生み出す。しかし、その強度がカメラセンサーを飽和させたとき、これらはブルームを生み出す(節5.1参照)。我々は3つのエミッシブな表面のケースを大まかに示すことができる(図49を参照)。

  • A. エミッシブマテリアルが非エミッシブマテリアルの下にある。
  • B. エミッシブマテリアルが非エミッシブマテリアルの上にある。
  • C. マテリアル全体がエミッシブである。

(図49:エミッシブマテリアルの3つのケース。A)エミッシブマテリアルが非エミッシブマテリアルの下にある。B)エミッシブマテリアルが非エミッシブマテリアルの上にある。C)マテリアル全体がエミッシブである。)

ケースBとCは、Bでエミッシブ層の下のマテリアルが覗けること以外、ほぼ同じである。Frostbiteでは、暗黙的にケースCをサポートするケースBのみを扱う。エミッシブな表面を効率的にレンダリングするのは簡単ではない。ディファードなやり方でエミッシブな不透明オブジェクトを適切にレンダリングして、(Gバッファ生成パスの後にレンダリングされる)ディファードデカールとの互換性を保つためには、エミッシブ情報をGバッファに格納する必要がある。これはコストの高い追加のバッファを必要とする。Frostbiteでは様々なパスを持つ。

透明オブジェクトエミッシブは表面のレンダリング中に適用される
フォワード不透明オブジェクトエミッシブは表面のレンダリング中に適用される
完全なエミッシブを持つディファード不透明オブジェクトエミッシブは表面の追加のレンダリングパスで適用される、つまり、表面は2回レンダリングされる
安価なエミッシブを持つディファード不透明オブジェクトエミッシブはラジオシティバッファに格納され、間接ライティングとして同時に適用される

間接ディフューズライティングはGバッファ生成時のディフューズアルベドで構成されていないが、これは後にディフューズアルベドを調整することをデカールで可能にするためである。アーティストがパフォーマンスを正確性とトレードしたいときに備えて、エミッシブ値をラジオシティバッファに格納できるようにしてある。このアプローチで問題になるのはエミッシブ色がディフューズアルベドと結合してしまうことである。ラジオシティバッファが適用されるとき、ディフューズアルベドをラジオシティバッファに乗算する。エミッシブでも同様である。ディフューズアルベドを調整するデカールはこの場合エミッシブも調整する。これが”安価”なエミッシブと呼ぶ所以である(リスト17)。もうひとつの制約はこのテクニックがディフューズを持たないような金属質のオブジェクトで動作しないことである。

// Gバッファ生成中に
float3 radiosity = ...;
// エミッシブをラジオシティにパックする(同じ単位(輝度)で)
radiosity += emissive * emissiveIntensity;
gBufferRadiosity = packLightingRGBA(gbufferRadiosity);

// ラジオシティアプリケーション中に
float3 unpackedRadiosity = unpackLightingRGBA(gbufferRadiosity);
indirectDiffuse = unpackedRadiosity * data.diffuseAlbedo;

: ディファードのケースで管理される安価なエミッシブ。

(図50:フォワード(上)とディファード(下)でレンダリングされたエミッシブな表面の例。すべての球はエミッシブなオブジェクトであり、球型エリアライトがエミッシブ球として同じ位置に追加された。)

備考: エリアライトの場所に正確な強度を持つエミッシブ球を自動的に生成するツールを開発した。例を図51に示す。これは実際に説得力のあるビジュアルシーンを生み出し、アーティストがこれらのライトをデバッグするのに役立つ。

(図51:エミッシブな表面としてライトを可視化するデバッグモード。)

4.9. 画像ベースライト(Image based lights)

画像ベースライト(IBL)は点を取り囲む入射するライティングを表すことができる。この取り囲むライティングはオブジェクトをその環境に”フィット”させるために重要である。アーティストから”反射”と呼ばれることが時折あるため、この入射ライティングはBRDFの式ff、つまり、標準マテリアルに対するスペキュラfrf_rの部分だけでなくfdf_dの部分も含めて、すべての部分に矛盾なく適用される必要がある。レイヤードマテリアルのようなさらに進化したマテリアルでは、すべてのレイヤがこのライティングによって影響を受ける必要がある。シェーダで反射テクスチャを直接追加することでこのライティングを”見せかけることfaking”はライティングとマテリアルの情報の間の 大事な分離key separation を破壊してしまい、異なる環境でアセットの再利用を難しくする。IBLのLLとBRDFのffとの間の相互作用の計算は以下の積分を評価する必要があるコストの高い処理である。

L(v)=Ωf(l,v,Θ)L(l)dl(46)L(\boldsymbol{v}) = \int_{\Omega} f(\boldsymbol{l}, \boldsymbol{v}, \Theta) L(\boldsymbol{l}) d\boldsymbol{l} \tag{46}

視線方向v\boldsymbol{v}、マテリアルモデルff、パラメータΘ\Theta(Fresnel、ラフネス、アルベドなど)を持つ。連続的にオブジェクトを環境に合わせつつ、依然として良い反射の近似を提供するためには、すべての状況で反射を提供できるようにする必要がある。このため、 @Drobot2013LightingKillzoneShadow に触発された4つのタイプのIBLに頼る。こららのタイプのそれぞれは入射ライティングの特定のタイプか範囲を表現することを可能にする。

  • ディスタントライトプロブ: 取り囲む遠く離れたライティングをキャプチャする。これはいかなる視差parallaxも含まない(空、遠方の建物、背景の水滴など)。これは最も正確でない反射タイプであるが、いつでも利用できる。
  • ローカルライトプロブ: ビューの単一の点からあるエリアに含まれるすべてのオブジェクトをキャプチャする(キューブマップ)。これらのキャプチャは、取り囲むジオメトリを一致させるためにアーティストにより慎重に調整された、単純なプロキシジオメトリに再投影される(例えば、球か箱)。この反射タイプはディスタントライトプロブより正確であるが、オブジェクトライティングと視差は完璧にキャプチャされない。
  • スクリーンスペース反射: 深度バッファに対するレイマーチングによりライトバッファに基づく反射をキャプチャする。これは小から中の範囲の反射を捕らえ、良好なcontact hardening14反射を保証する。これは最も正確な反射源のひとつである。
  • 平面反射Planar Reflections: エンジンによる自動かアーティストによる手動いずれかでセットアップされた平面に反射したシーンをレンダリングすることで反射をキャプチャする。この反射タイプは反射が道路、建物、水面といったほぼ平坦な表面でうまく働く平面に横たわると仮定する。

静的vs動的: ディスタントライトプロブとローカルライトプロブは、ある瞬間における周辺のライティングをキャプチャした、通常”静的”なライティング情報を含む。これらのコンテンツは、要件や割り当てられたパフォーマンス予算に従い、要求に応じて又は毎フレームにリフレッシュさせることができる。SSRや平面反射は、それらの視点に依存するという特徴により毎フレーム更新されるため、“動的”なライティング情報を含む。これらの計算はそのコストを減らすためにいくつかのフレームに分散させることもできる。

簡単にSSRや平面反射を述べるが、この節は主にローカルライトプロブとディスタントライトプロブに焦点を当てる。まず、ライトプロブの取得とそのライティング単位を説明する。そして、それらのフィルタリング、評価、さまざまなIBLの合成を説明する。

4.9.1. ライトプロブの取得と単位(Light probes acquisition and unit)

Frostbiteでは、IBLは画像データに関連して定義されるものである。それらすべては、ライティングパイプラインの出力であるので、輝度単位を使う。

4.9.1.1. ディスタントライトプロブ(Distant light probe)

ディスタントライトプロブはキューブマップとして表される周囲の環境をキャプチャする。アーティストにはディスタントライトプロブを取得するための2つの方法がある。

  • 任意に背景に合成される物理ベーススカイを通してライティングを取得する。
  • 現実世界のカメラから取得したハイダイナミックレンジ画像(HDRI)を使う。

Frostbiteはディスタントライトプロブをキャプチャするのに使える物理ベーススカイを使う。ディスタントライトプロブは状況の変化(時刻サイクル、天候の変化など)に対処するときに必要に応じてリフレッシュさせることができる。スカイライティングはその他のライトのように輝度に変換される。キャプチャする時は、ライティングパイプラインのみを考慮する。我々はいかなる色管理処理(トーンマッピング、カラーグレーディング…)を含むポストプロセスを取り除き、HDRテクスチャフォーマットRGBA16Fに結果の輝度を格納する。

現実世界のディスタントライトプロブをうまく使うには何が取得されていたかを理解する必要がある。取得したHDR画像はその静的な特徴によりインゲームで最終的なライティングに使われるのは稀である。これらはむしろ、アセットを設計したり、マテリアル特性が自然なライティングで正しく反応することを検証したりするために、入射ライティングとして使われる。しかし、取得したHDRIをインゲームライティングと混ぜ合わせる必要があるとき、注意して行う必要がある。HDRIのテクセルに格納されているものは明確ではない。カメラが輝度値を出力すると考えられるかもしれないが、カメラの応答とポストプロセスステップは最高と最低の輝度値をカットする。出力されたピクセルはもはや輝度値を表しておらず、むしろそれはもとのシーン輝度に関係するデバイス依存の値である。輝度からピクセル値への変換を詳しく述べる実際のプロセスは節5.1にその詳細を述べる。

HDRI生成: LDRカメラでは、以下の複雑なキャプチャプロセスと再構築が 絶対輝度範囲absolute luminance range [Debevec and Malik 1997Debevec, P. E. and Malik, J. 1997. Recovering high dynamic range radiance maps from photographs. Proceedings of the 24th annual conference on computer graphics and interactive techniques 369–378. 10.1145/258734.258884. https://www.pauldebevec.com/Research/HDR/debevec-siggraph97.pdf.]でHDR画像を得ることを可能にする。このプロセスは、複数の露出でシーン受け取り、(Luminance HDR[@Anastasia2019LuminanceHDR]のような)ソフトウェアで後にそれらを組み合わせるということを暗に示す。ソフトウェアはデバイス依存の応答曲線により元のシーン輝度を再構成する。良い画像15を取得することと、カメラ応答曲線を識別できることという二重の困難は、アーティストによって生み出されたほとんどのHDR画像が 相対的輝度 か露出前の輝度を表現するだけになっている、ということを暗に示している(図52参照)。他のライトタイプとそのようなディスタントライトプロブを混ぜ合わせるために、我々は相対的輝度値を調整するためのマルチプライヤをアーティストに提供する。Mac-Bethチャート、カメラ設定、よく知られた輝度値に基づく手動のキャリブレーションにより、アーティストは絶対輝度を取り戻すために良い因数を見つけることができる16。正しく再構築された画像では、晴れた空は約8000[cdm2]8000[\frac{cd}{m^2}]の輝度を持ち、曇り空では約2000[cdm2]2000[\frac{cd}{m^2}]の輝度を持つ。夜のシーンでは、3000[cdm2]3000[\frac{cd}{m^2}]から5000[cdm2]5000[\frac{cd}{m^2}]の値はストリートのライト照明では珍しくない。月の輝度は約2500[cdm2]2500[\frac{cd}{m^2}]で、他のオブジェクトは、環境光でのみ照らされるときは、1[cdm2]1[\frac{cd}{m^2}]以下になるためかなり暗くなる[@McNeel2015WorkingHDRis]

(図52:ディスタントライティングのために用いられるHDRIテクスチャの例。HDRIは相対的輝度値を格納する。)

強い光源: 取得したHDRIでは、事前インテグレーション中のノイズを避け(次節を参照)、それらの可視性を扱うためにライトプロブから強い光源を取り除くことが必要である。例えば、ライトプロブにベイクする代わりに太陽をディレクショナルライトとすると、適切に太陽のシャドウイングを扱うことができる。HDRIから太陽を取り除くことは太陽に周囲の空の小さな部分を単純にコピペする必要がある。

4.9.1.2. ローカルライトプロブ(Local light probes)

ローカルライトプロブはそれらのボリュームの周りの限られたエリアにある周囲のオブジェクトをキャプチャする。その目標はローカルな環境を一致させることである。この取得は常にエンジン内で処理され、オフラインで”ベイク”又は一度だけキャプチャされるか、要求に応じてリフレッシュされるか、実行時に毎フレームリフレッシュさせるか、のいずれかを行うことができる。その選択は予算や必要条件(動くオブジェクト、ライティング状況の変化、など)に依存する。ローカルライトプロブをキャプチャすると、レンダリングの問題が生じる。

  • 順序依存性Order-dependency: ローカルライトプロブをキャプチャし終わるまで、シーンはローカルライトプロブで照らすことができない。この鶏と卵17の問題は、ローカルライトプロブがあるものの後に別のものをキャプチャする場合にキャプチャの順序依存性を生じさせる。
  • メタリックな表面: メタリックな表面はキャプチャ時にディフューズの寄与もスペキュラの寄与も持たないために問題となり、結果として真っ黒な見た目になる。光のバウンスをシミュレートするために何回かローカルライトプロブをキャプチャすることがあり得るが、メタリックな部屋のケースでは大きなバウンス数を必要とするだろう。もうひとつの可能性として、ディスタントライトプロブのライティングに頼ることが挙げられるが、屋内の環境で明らかなライトリークが現れる可能性がある。
  • ビュー依存の効果: ローカルライトプロブは単一の点(つまり、キューブマップの中心)でキャプチャされる。そして、光沢のある鏡のような表面から入射するこのライティングは、ビュー依存性のために、キャプチャされた点以外の視点では誤りである。

これらの問題を解決するため、我々はライトプロブの取得中にマテリアルのスペキュラ要素を無効化する。スペキュラ項のみを含むメタリックな表面はディフューズアルベドとしてFresnelf0f_0を用いることでディフューズ表面として近似される。キャプチャ中に、アルファチャンネルに周囲のオブジェクトの可視性も格納する。これはローカルライトプロブの寄与をフェードするためにIBL合成さいに後で使われる。図53はキャプチャされたローカルライトプロブの例を示す。

(図53:上:いくつかのオブジェクト周りのローカルプロブのアプリケーション。地面に配置されたオブジェクトに当たっている、壁から来る赤色の反射に注目。左下:ローカルライトプロブに取得した色。金色のメタリックなオブジェクトが黄色に発光していることに注目。左下:ローカルライトプロブに格納されたアルファチャンネル情報。)

関与媒質: 例えば霧がかった環境では、ローカルライトプロブの寄与を評価するときに、理想としては媒質の透過率を計算に入れるべきである。フォグをローカルライトプロブに直接的に取得するのは、それが3D(θ\thetaϕ\phi、深度)ではなく2D(θ\thetaϕ\phi)の関数をモデル化するので、正しく動作しない。なので、この単純な2D関数では、陰影付けされる点とローカルライトプロブのプロキシジオメトリとの間の実際の透過率を計算することはできない。

(図54:様々な角度から見た(GGXのNDFによる)マイクロファセットBRDFの形状。見る角度でローブの異方性がどのように増加するかに注目。)

4.9.2. ライトプロブのフィルタリング(Light probe filtering)

式46の積分は視線方向v\boldsymbol{v}、マテリアルモデルff、そのパラメータΘ\Thetaに依存する。通常はそのような積分は解析解を持たず、一般的にはMonte-Carloのような確率的な積分のテクニックによる、数値的な評価を必要とする。そのような積分を直接評価するには毎フレームに各ピクセルごとに大量のサンプルを必要になると思われる。これは可能であるが、ゲームのようなハイパフォーマンスアプリケーションの文脈では現実的ではない。重点サンプリングはサンプル数を減らすことができるが、複数重点サンプリングmultiple-importance sampling(MIS)でさえ各フレームで各ピクセルを評価するために必要とするサンプル数は多すぎる。

スペキュラの事前統合: この評価を単純化するため、いくつかの近似を作ることで積分を事前統合することができる。すべてのv\boldsymbol{v}Θ\Thetaに対してこの式を事前に統合することは巨大なメモリフットプリントを必要とするだろう。そのため、初めの近似はビュー依存を取り除くことである。これはBRDFの粗い近似を引き起こすが、マイクロファセットフレームワーク及び/又は半角パラメータ化に基づくBRDFの形状は図54に示されるように見る角度に強く依存するため、許容できるトレードオフである。法線入射方向では、BRDF形状は等方的である。グレージング角では、BRDF形状は異方的である。式46を事前統合することでビュー依存を取り除くことはBRDF形状がすべての角度から見て等方的であるという仮定を行う。これは、引き伸ばされた反射stretched refrectionsを妨げるような、重要なkeyビジュアルの差異を引き起こす。この近似は図55に示されるように平坦な表面でかなり目立つ可能性があるが、曲がった表面では多少目立ちにくくなる18

(図55:(GGXのNDFによる)マイクロファセットBRDFにおけるグレージング角での引き伸ばされた反射。左:近似。右:正しい挙動。)

事前統合の次元性をさらに減らすため、ラフネスα\alphaと0°の入射角でのFresnel値f0f_0によるΘ=(f0,α)\Theta = (f_0, \alpha)へパラメータ数を減らす必要がある。先に述べたように、式46は数値積分する必要がある。“事前にベイク”されたローカルライトプロブにおいて、この積分は、すべての計算がオフラインで行われるため、あらゆるパフォーマンスに関する懸念を持たずに行うことができる。しかし、オンデマンドなライトプロブ、連続的にリフレッシュされるローカルライトプロブ、アーティストによる高速な操作(ローカルライトプロブの配置、ディスタントライトプロブの回転)では、パフォーマンスが重要criticalであり、良好な質/速度の比率を達成する必要がある。重点サンプリング19は被積分関数の重要な部分での計算に注力することで集束を早めるために使うことができる。

L(v)=1NiNfr(li,v,Θ)L(li)pr(li,v,Θ)nli(47)L(v) = \frac{1}{N} \sum_i^N \frac{f_r(\boldsymbol{l}_i, \boldsymbol{v}, \Theta) L(\boldsymbol{l}_i)}{p_r(\boldsymbol{l}_i, \boldsymbol{v}, \Theta)} \langle \boldsymbol{n} \cdot \boldsymbol{l}_i \rangle \tag{47}

prp_rはBRDFのPDFを表す。li\boldsymbol{l}_iprp_rから生成されたサンプルである。 Karis [2013Karis, B. 2013. Real Shading in Unreal Engine 4. Physically Based Shading in Theory and Practice course. ACM SIGGRAPH. https://blog.selfshadow.com/publications/s2013-shading-course/.] はマイクロファセットBRDFの場合には、式47の積分はLDとDFGの2つの項の積に分けることで近似することができることを示した。pr=D(h,α)nhJ(h)p_r = D(\boldsymbol{h}, \alpha) \langle \boldsymbol{n} \cdot \boldsymbol{h} \rangle J(\boldsymbol{h})とハーフベクトルからライティングベクトルへの変換のヤコビアンJ(h)=14vhJ(\boldsymbol{h}) = \frac{1}{4 \langle \boldsymbol{v} \cdot \boldsymbol{h} \rangle}により、以下を得る。

L(v)=1NiNfr(l,v,Θ)L(li)pr(l,v,Θ)nl(48)L(v) = \frac{1}{N} \sum_i^N \frac{f_r(\boldsymbol{l}, \boldsymbol{v}, \Theta) L(\boldsymbol{l}_i)}{p_r(\boldsymbol{l}, \boldsymbol{v}, \Theta)} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle \tag{48}
=1NiND(h,α)F(v,h,f0,f90)G(l,v,h,α)4nlnv1pr(l,v,Θ)L(l)nl(49)= \frac{1}{N} \sum_i^N \frac{D(\boldsymbol{h}, \alpha) F(\boldsymbol{v}, \boldsymbol{h}, f_0, f_{90}) G(\boldsymbol{l}, \boldsymbol{v}, \boldsymbol{h}, \alpha)}{4 \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle \langle \boldsymbol{n} \cdot \boldsymbol{v} \rangle} \frac{1}{p_r(\boldsymbol{l}, \boldsymbol{v}, \Theta)} L(\boldsymbol{l}) \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle \tag{49}
=1NiND(h,α)F(v,h,f0,f90)G(l,v,h,α)4nv1pr(l,v,Θ)L(l)(50)= \frac{1}{N} \sum_i^N \frac{D(\boldsymbol{h}, \alpha) F(\boldsymbol{v}, \boldsymbol{h}, f_0, f_{90}) G(\boldsymbol{l}, \boldsymbol{v}, \boldsymbol{h}, \alpha)}{4 \langle \boldsymbol{n} \cdot \boldsymbol{v} \rangle} \frac{1}{p_r(\boldsymbol{l}, \boldsymbol{v}, \Theta)} L(\boldsymbol{l}) \tag{50}
=1NiND(h,α)F(v,h,f0,f90)G(l,v,h,α)4nv4vhD(h,α)nhL(l)(51)= \frac{1}{N} \sum_i^N \frac{D(\boldsymbol{h}, \alpha) F(\boldsymbol{v}, \boldsymbol{h}, f_0, f_{90}) G(\boldsymbol{l}, \boldsymbol{v}, \boldsymbol{h}, \alpha)}{4 \langle \boldsymbol{n} \cdot \boldsymbol{v} \rangle} \frac{4 \langle \boldsymbol{v} \cdot \boldsymbol{h} \rangle}{D(\boldsymbol{h}, \alpha) \langle \boldsymbol{n} \cdot \boldsymbol{h} \rangle} L(\boldsymbol{l}) \tag{51}
=1NiNF(v,h,f0,f90)G(l,v,h,α)nvnhvhL(l)(52)= \frac{1}{N} \sum_i^N \frac{F(\boldsymbol{v}, \boldsymbol{h}, f_0, f_{90}) G(\boldsymbol{l}, \boldsymbol{v}, \boldsymbol{h}, \alpha)}{\langle \boldsymbol{n} \cdot \boldsymbol{v} \rangle \langle \boldsymbol{n} \cdot \boldsymbol{h} \rangle} \langle \boldsymbol{v} \cdot \boldsymbol{h} \rangle L(\boldsymbol{l}) \tag{52}
1NiNF(v,h,f0,f90)G(l,v,h,α)nvnhvh1iNnliNL(l)nl(53)\approx \frac{1}{N} \sum_i^N \frac{F(\boldsymbol{v}, \boldsymbol{h}, f_0, f_{90}) G(\boldsymbol{l}, \boldsymbol{v}, \boldsymbol{h}, \alpha)}{\langle \boldsymbol{n} \cdot \boldsymbol{v} \rangle \langle \boldsymbol{n} \cdot \boldsymbol{h} \rangle} \langle \boldsymbol{v} \cdot \boldsymbol{h} \rangle \frac{1}{\sum_i^N \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle} \sum_i^N L(\boldsymbol{l}) \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle \tag{53}

この分離はDFGとLDの2つの独立した項を導く。これらは個別に事前計算することができる。LD項は各ライトプロブごとに計算する必要があるが、DFGは一度だけ計算してすべてのライトプロブで再利用できる。リスト18はDFG項を示す。ここでは、異なる重み付け1iNnl\frac{1}{\sum_i^N \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle}と同様にLD項の追加のnl\langle \boldsymbol{n} \cdot \boldsymbol{l} \rangleに注意したい。これらの経験的な項は、この積分の分割可能性の粗い仮定に悩まされている再構築されたライティング積分を改善できるようにKarisにより導入された。これらの項には数学的な導出が存在せず、定数L(l)L(\boldsymbol{l})に完全一致することが目標であった20[Karis 2013Karis, B. 2013. Real Shading in Unreal Engine 4. Physically Based Shading in Theory and Practice course. ACM SIGGRAPH. https://blog.selfshadow.com/publications/s2013-shading-course/.]で示されるように、Fresnel項のSchlickの式を用いることで、

F(v,h,f0,f90)=f0+(f90f0)(1vh)5(54)F(\boldsymbol{v}, \boldsymbol{h}, f_0, f_{90}) = f_0 + (f_{90} - f_0)(1 - \langle \boldsymbol{v} \cdot \boldsymbol{h} \rangle)^5 \tag{54}

DFG項は見る角度vvとラフネスα\alphaにのみ依存する2D関数で表すことができる。f0f_0f90f_{90}は事前計算の外に出す。この2D関数はDFG1DFG_1DFG2DFG_2の2つの項を格納する。

DFG(v,l,f0,f90,α)=1NiN(f0+(f90f0)(1vh)5)G(l,v,h,α)nvnhvh(55)DFG(\boldsymbol{v}, \boldsymbol{l}, f_0, f_{90}, \alpha) = \frac{1}{N} \sum_i^N \frac{(f_0 + (f_{90} - f_0)(1 - \langle \boldsymbol{v} \cdot \boldsymbol{h} \rangle)^5) G(\boldsymbol{l}, \boldsymbol{v}, \boldsymbol{h}, \alpha)}{\langle \boldsymbol{n} \cdot \boldsymbol{v} \rangle \langle \boldsymbol{n} \cdot \boldsymbol{h} \rangle} \langle \boldsymbol{v} \cdot \boldsymbol{h} \rangle \tag{55}
=1NiN(f0+(f90f0)FC)GVis with GVis=G(l,v,h,α)nvnhvh,FC=(1vh)5(56)= \frac{1}{N} \sum_i^N (f_0 + (f_{90} - f_0) F_C) G_{\text{Vis}} \text{ with } G_{\text{Vis}} = \frac{G(\boldsymbol{l}, \boldsymbol{v}, \boldsymbol{h}, \alpha)}{\langle \boldsymbol{n} \cdot \boldsymbol{v} \rangle \langle \boldsymbol{n} \cdot \boldsymbol{h} \rangle} \langle \boldsymbol{v} \cdot \boldsymbol{h} \rangle, F_C = (1 - \langle \boldsymbol{v} \cdot \boldsymbol{h} \rangle)^5 \tag{56}
=1NiNf0GVis+f90FCGVisf0FCGVis(57)= \frac{1}{N} \sum_i^N f_0 G_{\text{Vis}} + f_{90} F_C G_{\text{Vis}} - f_0 F_C G_{\text{Vis}} \tag{57}
=f01NiN(1FC)GVis+1NiNf90FCGVis(58)= f_0 \frac{1}{N} \sum_i^N (1 - F_C) G_{\text{Vis}} + \frac{1}{N} \sum_i^N f_{90} F_C G_{\text{Vis}} \tag{58}
void importanceSampleCosDir(in float2 u, in float3 N, out float3 L, out float NdotL, out float pdf) {
    // ローカルなreferencial
    float3 upVector = abs(N.z) < 0.999 ? float3(0, 0, 1) : float3 (1, 0, 0);
    float3 tangentX = normalize(cross(upVector, N));
    float3 tangentY = cross(N, tangentX);

    float u1 = u.x;
    float u2 = u.y;

    float r = sqrt(u1);
    float phi = u2 * FB_PI * 2;

    L = float3(r * cos(phi), r * sin(phi), sqrt(max (0.0f, 1.0f - u1)));
    L = normalize(tangentX * L.y + tangentY * L.x + N * L.z);

    NdotL = dot(L, N);
    pdf = NdotL * FB_INV_PI;
}

float4 integrateDFGOnly(in float3 V, in float3 N, in float roughness) {
    float NdotV = saturate(dot(N, V));
    float4 acc = 0;
    float accWeight = 0;

    // 事前統合を計算する
    Referential referential = createReferential(N);
    for (uint i = 0; i < sampleCount; ++i) {
        float2 u = getSample(i, sampleCount);
        float3 L = 0;
        float NdotH = 0;
        float LdotH = 0;
        float G = 0;

        // 実装は[Karis13]を参照
        importanceSampleGGX_G(u, V, N, referential, roughness, NdotH, LdotH, L, G);

        // スペキュラGGXのDFG事前統合
        float NdotL = saturate(dot(N, L));
        if (NdotL > 0 && G > 0.0) {
            float GVis = G * LdotH / (NdotH * NdotV);
            float Fc = pow(1 - LdotH , 5.f);
            acc.x += (1-Fc) * GVis;
            acc.y += Fc * GVis;
        }

        // ディフューズDisneyの事前統合
        u = frac(u + 0.5);
        float pdf;
        // pdfは他の項で打ち消されるため使われない
        // (ディフューズBRDFから1/PIとLambertの法則からNdotL)
        importanceSampleCosDir(u, N, L, NdotL, pdf);
        if (NdotL > 0) {
            float LdotH = saturate(dot(L, normalize(V + L));
            float NdotV = saturate(dot(N, V));
            acc.z += Fr_DisneyDiffuse(NdotV, NdotL, LdotH, sqrt(roughness));
        }

        accWeight += 1.0;
    }

    return acc * (1.0f / accWeight);
}

: スペキュラGGXとディフューズDisneyBRDFの両方についての事前統合されたDFG関数。

LD項は時刻変化のように入射ライティングが変化するたびに再計算される必要がある。これはLDが実行時に計算される必要があること、つまり、高速でロバストである必要があることを意味している。重点サンプリングを使うと収束が改善されるが、かなりのサンプルが必要になる。 @Krivanek2008RealtimeShadingFiltered によって導入された事前にフィルタした重点サンプリングは低確率のサンプルのための事前にフィルタされた値に頼ることでサンプル数を削減できる。これは収束を著しく改善する(小さなバイアスを導入するコストについては図56を参照)21リスト19はLD項を示す。ハイコントラストな環境において、特に中または高ラフネスα\alphaの値で、依然としてノイズが観測される可能性がある。これは、ハイコントラストなライトプロブ(本当に高い強度を持ついくつかのピクセル)を伴う(特にGGXのようなロングテールのNDFで)半球上のBRDFローブの幅広いサポートに主に起因する。このノイズを取り除くには、サンプル数を増やすか、ピクセルごとにサンプルパターンを回転/ジッタリングしないことにより、相関のあるバイアスとこのノイズをトレードするか、のいずれかを行う。これはゴーストアーティファクトを引き起こすが、通常はノイズより目立たない。

(図56:重点サンプリングを用いた事前畳み込み結果と事前フィルタされた重点サンプリングとの比較。両方の画像は同じサンプル数を使っている(テクセルあたり64サンプル)。)

float3 integrateCubeLDOnly(in float3 V, in float3 N, in float roughness) {
    float3 accBrdf = 0;
    float accBrdfWeight = 0;
    for (uint i = 0; i < sampleCount; ++i) {
        float2 eta = getSample(i, sampleCount);
        float3 L;
        float3 H;
        importanceSampleGGXDir(eta, V, N, roughness, H, L);
        float NdotL = dot(N, L);
        if (NdotL > 0) {
            // 事前フィルタされた重点サンプリングを使う(つまり、分散を減らすために低確率のサンプルをフェッチするために低いMIPMAPレベルを使う)。
            // (参考: GPU Gem3)
            //
            // 法線方向で結果を事前統合するため、N == Vであり、NdotH == LdotHである。これがBRDFのpdfを単純化できる理由である。
            // pdf = D_GGX_Divide_Pi(NdotH, roughness) * NdotH / (4 * LdotH);
            //     = D_GGX_Divide_Pi(NdotH, roughness) / 4;
            //
            // MIPMAPレベルはキューブマップフィルタリングの問題を避けるために8x8より低い何かへクランプされる。
            //
            //   - OmegaS: サンプルに関する立体角。
            //   - OmegaP: キューブマップのピクセルに関する立体角。
            float NdotH = saturate(dot(N, H));
            float LdotH = saturate(dot(L, H));
            float pdf = D_GGX_Divide_Pi(NdotH, roughness) * NdotH / (4 * LdotH);
            float omegaS = 1.0 / (sampleCount * pdf);
            float omegaP = 4.0 * FB_PI / (6.0 * width * width);
            float mipLevel = clamp (0.5 * log2(omegaS / omegaP), 0, mipCount);
            float4 Li = IBLCube.SampleLevel(IBLSampler, L, mipLevel);

            accBrdf += Li.rgb * NdotL;
            accBrdfWeight += NdotL;
        }
    }
    return accBrdf * (1.0f / accBrdfWeight);
}

: 事前フィルタされた重点サンプリング関数。

ディフューズ事前統合: いままでは、スペキュラfrf_rの部分の入射ライティングの積分のみを考えてきた。以前に言及したように、すべてのマテリアルの部分が同じ入射ライティングを受け取ることが重要crucialである。故にライティングはディフューズ部分fdf_dに対しても統合される必要がある。fdf_dはDisneyのディフューズBRDFを使うために見る角度v\boldsymbol{v}とラフネスα\alphaに依存するので、DFGとLDの2つの項に分離することで、スペキュラ部分と同じような事前統合に頼る。LD項では、入射ライティングはnl\langle \boldsymbol{n} \cdot \boldsymbol{l} \rangleで重み付けされた定数のランバートローブと統合される。これは @Ramamoorthi2001EfficientRepresentationIrradiance によって示されるような球面調和基底や重点サンプリングで効率的に行うことができる。我々は、(Disneyのローブ分布に従う代わりに)コサイン分布に従うサンプル分布を伴う重点サンプリングを、この低角周波ローブを採用するために、用いる22

pr=nlπp_r = \frac{\langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle}{\pi}とすると、

L(v)=1NiNfd(l,v,Θ)L(l)pr(l,v,Θ)nl(59)L(v) = \frac{1}{N} \sum_i^N \frac{f_d(\boldsymbol{l}, \boldsymbol{v}, \Theta) L(\boldsymbol{l})}{p_r(\boldsymbol{l}, \boldsymbol{v}, \Theta)} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle \tag{59}
=1NiNπfd(l,v,Θ)L(l)nlnl(60)= \frac{1}{N} \sum_i^N \frac{\pi f_d(\boldsymbol{l}, \boldsymbol{v}, \Theta) L(\boldsymbol{l})}{\langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle} \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle \tag{60}
=1NiNπfd(l,v,Θ)L(l)(61)= \frac{1}{N} \sum_i^N \pi f_d(\boldsymbol{l}, \boldsymbol{v}, \Theta) L(\boldsymbol{l}) \tag{61}
=πNiNfd(l,v,Θ)1NiNL(l)(62)= \frac{\pi}{N} \sum_i^N f_d(\boldsymbol{l}, \boldsymbol{v}, \Theta) \frac{1}{N} \sum_i^N L(\boldsymbol{l}) \tag{62}

LD項の計算はリスト20で確認できる。DFG項は様々なビュー角度v\boldsymbol{v}とラフネスα\alphaでDisneyのディフューズBRDFを統合することで計算される(リスト18参照)。

float4 integrateDiffuseCube(in float3 N) {
    float3 accBrdf = 0;
    for (uint i = 0; i < sampleCount; ++i) {
        float2 eta = getSample(i, sampleCount);
        float3 L;
        float NdotL;
        float pdf;
        // 付録の参考コードを参照のこと。
        importanceSampleCosDir(eta, N, L, NdotL, pdf);
        if (NdotL > 0)
            accBrdf += IBLCube.Sample(incomingLightSampler, L).rgb;
    }
    return float4(accBrdf * (1.0f / sampleCount), 1.0f);
}

: ディフューズ重点サンプリング関数。

ストレージ: これらの事前統合の結果を格納することは文献ではしばしば無視されるが、重要な詳細である。DFG項は128x128の解像度を持つ2Dテクスチャに簡単に格納できる。LD項は16ビット浮動小数点キューブマップのセットに格納できる3D関数である(Frostbiteでは、望ましいクオリティに依存して128x128から512x512までを解像度に使うが、滑らかな/鏡のような表面を良質に表現するとこができる最小限度は256x256であることを発見した)。事前統合されたライティングの周波数はα\alphaが増加するたびにだんだんと小さくなるので、事前統合された結果をMIPレベルに格納することができる[^43]。このストレージはαlin\alpha_{\text{lin}}(知覚的に線形なラフネス)からmipLevelmipLevelへの関数マッピングで定義される。図57図58で示されるように、αlin\alpha_{\text{lin}}のexponent-2マッピングが良い結果をもたらす。線形マッピングは全体的により良い分布をもたらし、中範囲のラフネスを維持するが、低ラフネスで若干のブラーをもたらす。我々はexponent-2で行くことに決めた。

mipLevel=αlin(63)mipLevel = \sqrt{\alpha_{\text{lin}}} \tag{63}

(図57:ラフネスとMIPレベルの間の様々なマッピング関数。exponent-2マッピングはすべてのMIPレベルでより良いプロファイルの分布を得ることができる。)

(図58:ラフネスをMIPレベルに格納する2つのマッピング関数のリファレンスに対する比較。差異は微妙だが、SquaredマッピングはすべてのMIPレベルでわずかにより良いプロファイル分布をもたらす。)

4.9.3. ライトプロブの評価(Light probe evaluation)

ランタイムでは、ローカルとディスタントの両方のライトプロブは環境から来る光を計算に入れるために評価される。ディフューズとスペキュラの両方の事前統合がビューに依存しない方法で行われるが、実際のディフューズfdf_dとスペキュラfrf_r項はビュー依存である。これはそれらのローブ方向がビューベクトルv\boldsymbol{v}に依存していることを意味する。スペキュラのfrf_r項では、事前統合された値をフェッチするためにミラー反射を使う代わりに、我々は主要方向(つまり、節3.1に見られる”オフスペキュラピーク”)でBRDFを評価する。

このズレをモデル化するため、我々は見る角度とマテリアルのラフネスに依存する最高の偏差値を調査した。完全な解析はこの文書の付属のMathematicaファイルとして利用できる。我々の提案したモデルは見る角度が小さいと誘電体マテリアルに対して正しい振る舞いをキャプチャするには不十分である。これは実際のローブがある角度でのみ”出現”するためである。幸いにも、Fresnel値は見る角度によって緩やかに増加するため、この誤差はほとんど目立たず、この近似は十分なままである(リスト21参照)。いくつかの実験ののちに、スペキュラローブの支配的な方向のより単純な近似がオリジナルのベストフィットする近似より良い結果をもたらすかについても調査した(リスト22参照)。手法の評価と比較の結果は図59に示される。我々は相関ありのSmithのG項と相関なしのG項に対して支配的な方向の近似を行った。我々の単純な数式は両方でうまく動作しているように見える。

// これはスペキュラピークの正確なフィッティングであるが、
// 分離処理中の他の近似によりうまく動作しない。
float3 getSpecularDominantDir(float3 N, float3 R, float  NdotV, float  roughness) {
###if GSMITH_CORRELATED
    float lerpFactor = pow(1 - NdotV, 10.8649) * (1 - 0.298475 * log(39.4115 - 39.0029 * roughness)) + 0.298475 * log(39.4115 - 39.0029 * roughness);
###else
    float lerpFactor = 0.298475f * NdotV * log (39.4115f - 39.0029f * roughness) + (0.385503f - 0.385503f * NdotV) * log(13.1567f - 12.2848f * roughness);
###endif

    // 結果はキューブマップでフェッチするので正規化されていない。
    return lerp(N, R, lerpFactor);
}

: ライトプロブを伴うスペキュラマイクロファセットのGGXベースのスペキュラ項の支配的な方向を計算する関数。

// オフスペキュラピークの近似としてはもっと良い方法があるが、
// 他の近似との兼ね合いでこれがベターであることを発見した。
// Nは法線方向。
// Rは鏡面反射方向。
// この近似はSmithのGが相関をあってもなくてもうまく動作する。
float3 getSpecularDominantDir(float3 N, float3 R, float roughness) {
    float smoothness = saturate(1 - roughness);
    float lerpFactor = smoothness * (sqrt(smoothness) + roughness);
    // 結果はキューブマップでフェッチするので正規化されていない。
    return lerp(N, R, lerpFactor);
}

: ライトプロブを伴うスペキュラマイクロファセットのGGXベースのスペキュラ項の支配的な方向を計算する単純な関数。

(図59:上:リファレンスとローブの支配的な方向との比較。その差異は高ラフネス(αlin0.6\alpha_{\text{lin}} \ge 0.6)で目立つ。下:正確さで並べた様々な手法での粗い表面の接写。リファレンス以外のすべての手法は事前統合のスキームを用いている。)

純粋なランバート表面では、BRDFがビューに依存しないので方向のズレは起こらない。しかし、Disneyの自己反射ディフューズ項では、ローブの支配的な方向はビュー方向に依存する。支配的な方向は非線形なやり方でズレてしまう。スペキュラ項のときと同じ解析を適用すると、単純な線形モデルがこの挙動を比較的正確にキャプチャすることができることが判明した(リスト23参照)。Frostbiteでは、間接ディフューズライティングはGバッファ生成中に適用される。なので、支配的な方向を正確に扱うためにこのステップでこれを適用することが必要である。正確な支配的な方向を扱うことで得られる差異は微妙であり、我々はこれを採用しないことを決めた。更に、節3.3で示すように、デカールは正しくサポートされない。

// Nは法線方向。
// Vはビュー方向。
// NdotVはビューベクトルと法線とのなす角のコサイン。
float3 getDiffuseDominantDir(float3 N, float3 V, float NdotV , float roughness) {
    float a = 1.02341f * roughness - 1.51174f;
    float b = -0.511705f * roughness + 0.755868f;
    lerpFactor = saturate ((NdotV * a + b) * roughness);
    // 結果はキューブマップでフェッチするので正規化されていない。
    return lerp(N, V, lerpFactor);
}

: ライトプロブを伴うDisneyの自己反射ディフューズ項の支配的な方向を計算する関数。

スペキュラとディフューズの両方の項におけるディスタントライトプロブでのライティングを評価するためのコードをリスト24に示す。

float3 evaluateIBLDiffuse(...) {
    float3 dominantN = getDiffuseDominantDir(N, V, NdotV, roughness);
    float3 diffuseLighting = diffuseLD.Sample(sampler, dominantN);

    float diffF = DFG.SampleLevel(sampler, float2(NdotV, roughness), 0).z;

    return diffuseLighting * diffF;
}

float3 evaluateIBLSpecular(...) {
    float3  dominantR = getSpecularDominantDir(N, R, NdotV , roughness);

    // 関数を再構築する。
    // L.D.(f0.Gv.(1 - Fc) + Gv.Fc).cosTheta / (4.NdotL.NdotV)
    NdotV = max(NdotV, 0.5f / DFG_TEXTURE_SIZE);
    float mipLevel = linearRoughnessToMipLevel(linearRoughness, mipCount);
    float3 preLD = specularLD.SampleLevel(sampler, dominantR, mipLevel).rgb;

    // 事前統合されたDFGをサンプルする。
    //   Fc = (1 - H.L)^5
    //   PreIntegratedDFG.r = Gv.(1 - Fc)
    //   PreIntegratedDFG.g = Gv.Fc
    float2 preDFG = DFG.SampleLevel(sampler, float2(NdotV, roughness), 0).xy;

    //   LD.(f0.Gv.(1 - Fc) + Gv.Fc.f90)
    return preLD * (f0 * preDFG.x + f90 * preDFG.y);
}

: スペキュラとディフューズの両部分に対するディスタントライトプロブの評価コード。

エネルギー保存: 先に述べたように、ライトプロブは一貫したライティングのためにマテリアルのスペキュラとディフューズの両方の部分で評価される。この場合なら、特に両方の積分が半球上で行われる粗い表面の場合には、ライティングを2回適用しようかと考えることもできるかもしれない。しかし、DisneyディフューズBRDFに対する我々の修正のおかげで、マテリアルモデルのエネルギー保存則が保証されているので、入射エネルギーはエネルギーの追加なしにスペキュラとディフューズの項に正しい割合で影響を与える。

再投影: 周辺環境の視差を計算に入れるために、ローカルライトプロブは取得したライティング情報を再投影するためにプロキシジオメトリを使う。Frostbiteでは、球と向きを持つ箱oriented box2つの再投影ボリュームタイプをサポートする。これらのボリュームは周囲のジオメトリにできるだけ近くなるよう近似するためにアーティストにより手動で配置されてセットアップされる。実行時に、ローカルライトプロブ内のオブジェクトはサンプリング方向とプロキシジオメトリとの交差を計算し、この交差に基づく補正された方向でローカルライトプロブを評価する[@Lagarde2012LocalImagebasedLighting]。ライトプロブはボリュームの中心から事前畳み込みされている。アーティファクト(鋭い不連続性)を制限するため、我々はラフネスに基づいて補正された方向をもとの方向へ滑らかに補間する。さらに、キューブマップのキャプチャ中心に移動するためのオフセットベクトルを提供する。これはアーティストに重要な箇所で解像度をあげることができるようになり、ボリュームの中心の望ましくないオブジェクト場所を迂回することができる。

我々のローカルライトプロブはマテリアルのスペキュラ部分でのみ使われる。スペキュラ部分のローカルライトプロブに対するライティングを評価するコードは付録Fに提供される。ディフューズ要素では、ライティング情報はラジオシティシステムに由来する。これは、ライトマップかプロブボリュームを通した入射ライティングを問い合わせることができる。このディフューズライティングは自己反射ローブの支配的な方向で評価される。

距離ベースラフネス: BRDFローブは入射ライティングが半球上でどのように積分されるかを説明する。この角度の説明はBRDFフットプリントを距離依存にする。与えられた陰影付けされる点に対して、オブジェクトの反射はこのオブジェクトが陰影付けされる点に近ければシャープになり、離れるごとにぼやけてゆく(図60図61参照)。ローカルライトプロブのプロキシジオメトリは陰影付けされる点と入射ライティングの間の距離を計算できるようになる。この情報をもって、我々は環境にキャストされるBRDFフットプリントを粗く近似できる。評価中では、似たようなフットプリントに一致させるためにBRDFラフネスを修正して、この”距離ベースラフネス”を近似する(リスト25参照)。

(図60:距離ベースラフネスの概念の図解。左:壁に近い点におけるBRDFローブの射影は小さなフットプリントを生み出す。右:同じBRDFローブの射影だが大きく離れると、大きなフットプリントを生み出す。)

(図61:テクスチャ付きの壁と光沢のある金属の平面がある距離ベースラフネスの例。距離により、BRDFフットプリントが広くなるほど反射がぼやける。)

float computeDistanceBaseRoughness(float distInteresectionToShadedPoint, float distInteresectionToProbeCenter, float linearRoughness) {
    // アーティファクトを回避するため、もとのlinearRoughnessへクランプする。
    // これは、許容可能なバイアスを引き起こし、滑らかな表面において鏡面反射の振る舞いの維持を可能にする。
    float newLinearRoughness = clamp(distInteresectionToShadedPoint / distInteresectionToProbeCenter * linearRoughness, 0, linearRoughness);
    return lerp(newLinearRoughness, linearRoughness, linearRoughness);
}

: 距離ベースラフネスの計算。

このラフネス補正を計算するため、NDFを境界として支配的なBRDF方向に平行な円錐を計算する。境界円錐の角度θlim\theta_{\text{lim}}θlim=atan(Eα21E)\theta_{\text{lim}} = \text{atan}(\frac{E \alpha^2}{1 - E})によりラフネスα\alphaと関係する。ここで、EEは保存されたエネルギーのパーセンテージであり、E=75%E = 75\%であれば、円錐は75%のNDFボリュームを含んでいるということになる(詳細なプロットは付属のMathematicaファイルで利用可能)。この半径RRから、ライトプロブの中心から始まる円錐を計算できる。そこから、対応するラフネスを推論する。この完全に連鎖的な操作は項のほとんどを排除することができ、“距離ベースラフネス”はこの単純な式α=distanceInteresectionToShadedPointdistanceInteresectionToProbeCenterα\alpha' = \frac{distanceInteresectionToShadedPoint}{distanceInteresectionToProbeCenter} \alphaによるラフネスと関連させることができる。これは粗い近似であることに注目することが重要である。近似された交差に加えて、スケールされたフットプリントとして事前に畳み込まれた輝度を使ってみる。これは低ラフネス値ではまともに動作するが、高ラフネスでは不正確になる。この問題を回避するため、また、この効果が低ラフネス値でより鮮明になるようにするため、我々はラフネス値に基づいて”距離ベースラフネス”をもとのラフネスと線形に補間する。我々はlinearRoughnessを用いた処理がより良い結果をもたらすことも発見した。

後の節4.9.5で説明されるように、SSRパスが与えられたピクセルに対して反射情報を提供できないときにSSRはローカルライトプロブにフォールバックする。異なるライティングインテグレーション(SSRはBRDFを適切に統合して完全な視差を処理してくれるが、ローカルライトプロブは単一点から事前統合されて視差は近似される)により、この距離ベースラフネスを計算に入れることはSSRとローカルライトプロブとの間を合わせることができ、結果としてより良い遷移が現れる。

4.9.4. スクリーンスペースリフレクション(Screen space reflections)

スクリーンスペースリフレクション(SSR)は近から中範囲の反射をキャプチャすることができ、小さなオブジェクト/ディテールではこれが正確な遮蔽をもたらすために非常に重要である。我々のテクニックはシーンの深度バッファの頂点で構築されるHierarchical-Z構造に頼っている。これは長いレイを素早くトレースして、利用可能なシーン情報をできるだけ多く使うことができる。入射ライティングはマテリアルBRDFに対して統合される。我々のアプローチは @Uludag2014HiZScreenSpaceConeTraced の”Hi-Z Screen-Space Cone-Traced Reflections”により説明される。

SSRとエミッシブ: 節4.8に見られるように、エリアライトは2つの部分で構成する必要がある。

  • 放射emission特性を説明したり、BRDFで統合されたりする解析的ライト
  • 放射する光emitting lightの実際の形状を説明するエミッシブ表面

1つ目は解析的ライティング評価パス中に評価される。純粋に視覚的なことである2つ目はSSRパスかローカルライトプロブパスでキャプチャされることができる。ここではエミッシブ形状のキャプチャは入射ライティングとして取り扱われるため、この場合の光は、解析的評価中に1回、画像ベース評価中に1回、の2回分寄与することになる。残念ながら、この問題に対処するための簡単な解法は存在しない。

4.9.5. 画像ベースライト合成(Image based lights composition)

各IBLタイプは異なる入射ライティングを表し、それら自身の制限を持つ。環境に継続的に合わせるオブジェクトを持つことを可能にするため、これらすべてのIBLを階層的な方法で組み合わせる。

SSRは正しい反射を得る良いテクニックであるが、スクリーンスペース制限によりかなり頻繁に失敗する(現在の錐台に制限された情報、単一の深度レイヤ情報)。様々なヒューリスティクスを用いることで主な失敗ケースを特定することができる(スクリーンボーダー付近、レイの向き、交差タイプ、などなど)。SSRが失敗するとき、ローカルライトプロブ情報にフォールバックする。単一の視点からキャプチャされるが、ライトプロブはSSRパスで欠けている情報を滑らかに埋めるためにそれらのプロキシジオメトリへキャプチャされた情報を再投影することができる。ローカルライトプロブはレベルのすべてでアーティストにより手動で配置される。ローカルライトプロブは小さいボリュームから大きなボリュームまで反射情報が完全に復元されるまで階層的に評価される。そのため、アーティストはこれらをネストして、ある位置で反射を局所的に洗練することができる。反射情報が依然として欠けている場合、ディスタントライトプロブが評価される。

図62はこの合成の概要を示し、様々なステップの疑似コードを以下に示す。

// 短距離反射
SSRを評価する
RGB = SSR.rgb
Alpha = SSR.a

// 中距離反射
While ローカルライトプロブ And Alpha < 1 do
    ローカルライトプロブを評価する
    a = saturate(localLightProbe.a - Alpha)
    RGB += localLightProbe.rgb * a
    Alpha = saturate(a + Alpha)

// 長距離反射
If Alpha < 1 Then
    ディスタントライトプロブを評価する
    RGB += distantLightProbe.rgb * (1-Alpha)

(図62:2つのローカルライトプロブ(AとB)と1つのディスタントライトプロブの合成。ローカルライトプロブAとBの両方はプロキシジオメトリを持ち、それらのアルファチャンネルにシーンの一部(緑と赤)を取得する。レイがローカルライトプロブと交差するとき、そのアルファが1なら、レイはライトプロブの値(1)を評価する。そうでなければ、レイは他のプロキシ(2)か、ディスタントライトプロブ(3)に到達するまで進み続ける。)

ローカルライトプロブのアルファチャンネルは与えられたピクセルが近い周囲の環境に属しているかを示している。このタグ付けは空のピクセルをリジェクトし、ディスタントライトプロブをフェッチすることを強制できる。これにはいくつかのアドバンテージがあり、ディスタントライトプロブが(動く雲23のような)動的な要素を低コストで含められたり、ディスタントライトプロブが通常ローカルライトプロブより高解像度で、詳細がより鮮明になったりする。欠点としては入射ライティングの統合結果がこの方法で組み合わせたときに完全に正しくならないことである。

中くらいの範囲の反射の重みの計算について。各ローカルライトプロブの重複部分が同じ可視性情報を含み、厳密に同じ方法でBRDFローブを遮蔽すると仮定する。可視性0.1を持つオーバーラップしたローカルライトプロブを10個追加した場合、0.1を得るようにすべきである。このスキームは、階層のライトプロブの可視性が1にならない場合に、ディスタントライトプロブの寄与を常に持つことを可能にする。このアルゴリズムはローカルライトプロブの順に依存することに注意する。

平面反射: 加えて、平面反射情報が利用可能であるとき、フォワードでオブジェクト毎の基準によってか、ディファードでオブジェクトが受け取るタグによってかのいずれかを適用できる。平面反射は通常、単一の深度レイヤ制約や錐台制限の両方を緩和するため、平坦な表面でのSSRの良好な代替となり、さらにロバストにする。

4.10. 影と遮蔽(Shadow and occlusion)

4.10.1. ディフューズ遮蔽(Diffuse occlusion)

@McGuire2010AmbientOcclusionVolumes はアンビエントオクルージョンを定式化し、物理的基礎を与える。可視性関数は表面からl\boldsymbol{l}方向に視線を遮るものがない場合V(v)=1V(\boldsymbol{v}) = 1、そうでなければ00として定義される。レンダリング式のアンビエント項は以下となる。

L(v)=Ωf(l,v)La(l)V(l)nldl(64)L(\boldsymbol{v}) = \int_{\Omega} f(\boldsymbol{l}, \boldsymbol{v}) L_a(\boldsymbol{l}) V(\boldsymbol{l}) \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle d\boldsymbol{l} \tag{64}

ここで、LaL_aはアンビエントライティングである。粗く近似するには可視性の項をBRDFと入射ライティングから分割することである。

L(v)=[πΩf(l,v)La(l)dl][1πΩV(l)nldl](65)L(\boldsymbol{v}) = \left[ \pi \int_{\Omega} f(\boldsymbol{l}, \boldsymbol{v}) L_a(\boldsymbol{l}) d\boldsymbol{l} \right] \left[ \frac{1}{\pi} \int_{\Omega} V(\boldsymbol{l}) \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle d\boldsymbol{l} \right] \tag{65}

この分割はfr(l,v)f_r(\boldsymbol{l}, \boldsymbol{v})La(l)L_a(\boldsymbol{l})が定数である場合にのみ正しい。これはランバートな表面は一定のディスタントライトによって照らされることを意味する。この近似は両方の関数が球の周りで滑らかである場合に理に適っている。右の項は0から1の間のスカラの因数であり、点の到達率fractional accessibilityを示している。アンビエントオクルージョンこの到達率の反数oppositeとして定義される。

AO=11πΩV(l)nldl(66)AO = 1 - \frac{1}{\pi} \int_{\Omega} V(\boldsymbol{l}) \langle \boldsymbol{n} \cdot \boldsymbol{l} \rangle d\boldsymbol{l} \tag{66}

ゲームでは、パフォーマンス的な理由により、アンビエントライティングLa(l)L_a(\boldsymbol{l})を様々な位置で何回もキャプチャして、ライトマップ、キューブマップ、球面調和関数のいずれかにベイクするのが一般的である。しかし、このベイクはシーンでの動的オブジェクトの知識が失われる。実行時に、この情報は陰影付けされる点でベイクされた情報を補間することでシーンをシェーディングするために使われる。これは陰影付けされる点がベイク時よりも異なる到達率を持つことができることを暗に示している(例:静的オブジェクトと動的オブジェクトの合成)。これを補うため、一般的には入射ライティングを再構築することでアンビエントオクルージョン項を適用する24。可視性と入射ライティングの間を分割できるとする仮定は正確ではないが、パフォーマンス的な理由のためにトレードオフされる。

4.10.2. スペキュラ遮蔽(Specular occlusion)

アンビエントオクルージョンの導出はランバートな表面を仮定する。つまり、間接ディフューズライティングでのみ”正しいvalid”。光沢のある、または、スペキュラな表面、つまり間接スペキュラライティングではどうだろう?間接スペキュラライティングを再構築するときに到達率の知識を持たないと、間接ディフューズのときよりはるかに酷い。高いライティング強度や物理ベースBRDFは大量の可視ライトのリークを引き起こす(図63参照)。さらに、高周波の間接スペキュラライティングは大容量のストレージを必要とするため、キャプチャポイントの数が制限され、到達率のばらつきがより大きくなる。

(図63:スペキュラライトリークのアーティファクト例。タイヤの上やホイールの中のスペキュラ反射に注目する。)

これを解決するために光沢のある、または、スペキュラな遮蔽に対してアンビエントオクルージョン項を直接使うことは理想的ではない。アンビエントオクルージョンはコサインローブ形状、つまり、半球上の広いローブの到達率の反数を表す。対して、光沢のある表面はラフネスが減少するたびに狭くなるBRDFローブ形状を示す。図64は様々なラフネス値でのローブのBRDFに関連する到達率の円錐25を図示している。これはスペキュラライティングでキューブマップを事前統合する方法に密接に関係している。

(図64:様々なラフネス値でのBRDF形状に基づく様々な到達率の円錐(灰色の円錐で示される)。)

しかし、そのような到達率の円錐が使える状況でも、期待される結果をもたらさない。例えば、クロムの球のような完璧に滑らかな表面では、到達率は単一の方向でテストされ、0か1の二値で結果を得る。その結果、この到達率の情報を用いるクロム球は遮蔽された所が黒色になる。この小さな例はアンビエントライティングの積分で可視性を分割することが光沢のある及びスペキュラな表面では間違いであることを単純に強調している。

しかし、@Kozlowski2007AccurateOcclusionGlossy は光沢のあるシーンの大多数がある程度まで近似でき、球面調和関数を用いるディレクショナルアンビエントオクルージョンの近似が最も効果的な手法であることを示した。

@Gotanda2013RealtimePhysicallyBased はアンビエントオクルージョン項から導出されたスペキュラ遮蔽の項を提案した。彼は高い強度でのアンビエントオクルージョンが正しいスケールを持たないことに気付き、BRDFローブ形状を計算に入れるべきであるとしている。Frostbiteでは、GGXのラフネスに経験的に適合させた、似たアプローチを現時点では採用した(リスト26参照)。この結果は物理的なアプローチと相関がなくてもビジュアル的に良いものにであった。これはそのクオリティを改善するためのさらなる研究から恩恵を受けると思われる。図65は0.5のアンビエントオクルージョンでのこの関数の振る舞いを示している。表面が完全に粗いとき、関数は未修正のアンビエントオクルージョン項を返す。滑らかな表面では、垂直入射ではアンビエントオクルージョンの影響は減少するが、グレージング角では増加する。

float computeSpecOcclusion(float NdotV, float AO, float roughness) {
    return saturate(pow(NdotV + AO, exp2(-16.0f * roughness - 1.0f)) - 1.0f + AO);
}

: 与えられたラフネスでスペキュラ遮蔽を計算する関数。

(図65:0.5のアンビエントオクルージョンでのスペキュラ遮蔽の3Dプロット。)

備考: ご覧の通り、スペキュラ遮蔽は物理ベースではない。しかし、我々のスクリーンスペースリフレクションでもたらされる値は物理ベースである(節4.9.4参照)。これはアンビエントレンダリングの式の積分を可視性を分割せずに評価する。なので、我々のSSR項は理論上のスペキュラ遮蔽より良い項である。それにも関わらず、スペキュラ遮蔽を考慮しない場合、SSRは一般的なスクリーンスペースのアーティファクトに加えて、間接キューブマップによって引き起こされるライトリークのアーティファクトに悩まされることになるだろう。故に、スペキュラ遮蔽を適用することは未だに役に立つ。

4.10.3. 複数解像度のアンビエントオクルージョン(Multi resolution ambient occlusion)

前の節では、ディフューズ遮蔽とスペキュラ遮蔽が入射ライティングを再構築し、ベイクしたライトの制限を迂回し、ライトリークを減らすために、暗くするファクタであることを見てきた。これらのファクタは物理ベースではないが、画像のクオリティのためには望ましいものである。ディフューズ遮蔽のファクタを生み出すためにこんにち用いられるテクニックには2つのタイプがある。

  • オフライン事前計算: 中〜遠距離から遮蔽情報をキャプチャする。
  • スクリーンスペーステクニック: 中距離から遮蔽をキャプチャする。これは、HBAO、SSAO、ボリューメトリックAO、ambient obscurance、など、といった大量の様々なテクニックをカバーする。

これらのテクニックは中から大の遮蔽スケールを管理することが可能になるが、これらのいずれも小スケールの遮蔽を扱うことはできない。折り目creases空洞cavities、小さな穴はエンジンよってもこれらの中〜長距離の遮蔽のテクニックによっても自動的に扱うことができない。この観察結果は”複数解像度の遮蔽”[@Quilez2012MultiresolutionAmbientOcclusion]の必要性を示している。我々はスペキュラとディフューズ両方に対する遮蔽を、小、中、大の3つの範囲に分類できる。

小スケール遮蔽: Frostbiteでは、アーティストにテクスチャ内に直接マイクロ遮蔽をベイクさせることで小さな遮蔽を扱う。空洞、折り目、ひび割れもシャドウマップで扱うには小さすぎる。そのため、マイクロ遮蔽は直接ライティングと間接ライティングの両方で適用される。我々はマイクロ遮蔽をディフューズとスペキュラの2つの部分に分けることにした。これらは両方共同じマイクロ遮蔽情報から導かれる26

  • ディフューズマイクロ遮蔽: ディフューズマイクロ遮蔽は視点非依存であり、命令数を節約するためにディフューズアルベドテクスチャに事前に掛け合わせられている(図67参照)。
  • スペキュラマイクロ遮蔽: スペキュラマイクロ遮蔽は視点依存であり、ShaderX7の @Schuler2009EfficientPhysicallyPlausible で提供される解法に頼っている。その目標は、特定のしきい値の下でいずれの値でもFresnel反射率を徐々に小さくするように、Schlickの近似を修正することである。我々は現実世界のマテリアルが0.02より小さいf0f_0の値を持つことがないことを知っているので、これより小さい反射率のいずれかの値は事前にベイクされた遮蔽の結果であると仮定することができ、Fresnel反射率の寄与を滑らかに減らす(リスト27参照)。故に、スペキュラマイクロ遮蔽は反射率テクスチャ内に事前にベイクされる。

(図67:左:伝統的なベイクされたアンビエントオクルージョンテクスチャ。中:ディフューズマイクロ遮蔽。右:アルベドに事前乗算されたディフューズマイクロ遮蔽テクスチャ。)

f90 = saturate(50.0 * dot(fresnel0, 0.33));

float3 F_Schlick(in float3 f0, in float f90, in float u) {
    return f0 + (f90 - f0) * pow(1.f - u, 5.f);
}

: スペキュラマイクロ遮蔽に対する @Schuler2009EfficientPhysicallyPlausible の解法。

備考: この解法は、f0f_0の値を変更せずに反射の遮蔽情報を事前にベイクすることは本当はできないので、f0f_0f90f_90の値の両方のFresnel反射率曲線が修正されていることを暗に示している。f0f_0を修正することはマテリアルを特徴付ける屈折率を修正することを意味する27。故に、到達率によりライティングのみに影響を与えると想定されていたものは現実にはマテリアルの特性に影響を与えており、時折グレージング角でFrenelが変化しないことさえある。我々は別個の専用のスペキュラマイクロ遮蔽テクスチャを使うことを調査した。これは、Gバッファに格納される追加のパラメータであることも意味する。この項はマテリアル特性でではなく我々のスペキュラ遮蔽に似た数式を用いるライティング計算に適用された。しかし、我々は知覚される結果がコストに見合わないことを発見した。

中及び大スケール遮蔽: 中から大スケール遮蔽は間接ライティングでのみ適用される。我々はHBAOをサポートする。これは、中範囲のアンビエントオクルージョンをもたらすが、より重要なこととして、動的オブジェクト同士のシャドウコンタクト28を提供する。我々は、古典的なオフラインベイクか、ラジオシティシステムで提供される動的にベイクされた項の2つの選択肢を持つベイクされた中から大のアンビエントオクルージョンもサポートする29。ベイクされたアンビエントオクルージョンはGバッファに格納される必要がある。ゲームチームはこれらの選択肢を選ぶことができるが、我々は過剰に暗くなることを防ぎたかった。これを行うため、中から大のアンビエントオクルージョンの適用される項のすべてを最小限に抑える。これはコンタクトに対する動的なアンビエントオクルージョンを加えたベイク済みアンビエントオクルージョンをうまく扱う。マイクロ遮蔽は全く異なるスケールでの話であり、その影響を維持するほうが良い30。スペキュラ間接ライティングでは、以前の節で提供した式を通して結果のアンビエントオクルージョン項を変換する。

まとめると、様々な遮蔽の形式は以下になる。

直接ディフューズディフューズマイクロ遮蔽
間接ディフューズディフューズマイクロ遮蔽、min(ベイク済みAO, HBAO)
直接スペキュラスペキュラマイクロ遮蔽を通したFresnel反射率修正
間接スペキュラスペキュラマイクロ遮蔽を通したFresnel反射率修正、その後、computeSpecOcclusion(NdotV, min(ベイク済みAO, HBAO), ラフネス)
4.10.4. シャドウ(Shadows)

シャドウはPBRに対する重要な見た目の手がかりcueである。その分野はこのトピックについて極めて広範囲に渡るため、ここでは議論しない。理想的には、すべてのライトがシャドウを持つべきであるが、パフォーマンス負荷的に難しいことがある(パフォーマンスコストはそれらをすべてのライトでしばしば手に入らなくする)。通常、ゲームチームはこの情報の欠落を隠すためにアーティストを頼る。ソフトシャドウは柔らかいルックを提供したり回り込むライティングをサポートしたりするためにエリアライトにおいて重要である。エリアライトで通常の”パンクチュアル”シャドウマップを用いると、回り込むライティングが取り除かれるだろう(図63参照)。エリアシャドウハンドリングの良い解法は @Kasyan2013PlayingRealTimeShadows によって説明されるボクセル化テクニックである。限定された結果を伴うより安価なテクニックはシャドウマップ計算中にジオメトリのサイズを若干小さくすることで達成することができる[@Bredow2000FurStuartLittle]

(図68:左:シャドウなしエリアライト。中:非エリアシャドウ付きエリアライト。徐々に変化する回り込むライティングが失われる。右:エリアシャドウ付きエリアライト。)

Frostbiteでは、現時点ではポイントライトとスポットライトのシャドウマップをサポートしている。これらの種のシャドウマップはすべてのライトタイプを網羅するために使われる。エリアシャドウを偽装するため、射影の中心を前方と逆の方向に移動する。これは錐台がエリアライト形状全体をカバーする/に及ぶことができるようになる。そして、強いブラーと低いシャドウ解像度が柔らかいルックを得るために使われる(図69参照)。これらはクオリティを改善するためのさらなる研究から利益を得られるだろう。

(図69:エリアライトの形状を含む仮想的な位置に射影の中心を移動することでエリアシャドウを偽装し、シャドウマップを強くぼやけさせる。)

備考: 達成されるべき真のビジョンを得るため、ライティングのリファレンスとしてすべてのライトでシャドウを用いることは重要である。

4.11. ディファード/フォワードレンダリング(Deferred / Forward rendering)

Frostbiteはフォワードとディファード両方のタイルレンダラを持つハイブリッドエンジンをサポートする[@Andersson2009ParallelGraphicsFrostbite]。その分野はこれらのトピックについて極めて広範囲に渡るため、ここでは議論しない。影付けされるライトを含めたすべてのライトタイプはTiledパスの使用をサポートする。このようなアーキテクチャの選択はパフォーマンスによって動機付けされる。ライトカリングは無駄なピクセル評価を避けるためにライト形状を尊重するタイトな境界ボリュームを用いる。我々はGバッファの読み込みで帯域幅を消費するのを避けたり計算精度を向上させたりするためにすべてのライトをひとつの大きなループの中で評価する。

5. 画像(Image)

5.1. 物理ベースカメラ(A Physically Based Camera)

以前の部のすべてはライトがシーンにおいて物理ベースな方法でどのように相互作用するかに焦点を当てていた。信頼できる結果を達成するためのもうひとつの重要な検討事項はシーン輝度から最終的なピクセル値までの変換チェーン全体を考えることである。

5.1.1. カメラ設定(Camera settings)

我々はFrostbiteにおけるレンダリングパイプラインのすべてに渡り測光単位を扱うので、カメラに到達するライトのエネルギーは輝度で表現される。入射光は通常暗いシーンでの数cdm2\frac{cd}{m^2}から太陽を見るときの数十億cdm2\frac{cd}{m^2}まで大きな値範囲をカバーする(図71参照)。これらの値はディスプレイに映せる最終的な画像を生成するために正規化されたピクセル値に再マップされる必要がある。ディジタルカメラでは、この処理がある時間だけディジタルセンサーを”露出exporsing”して後処理を適用することで行われる。この露出の目的は現在の光の範囲が白と黒の中間(ミドルグレー)を中心となるようにしたり、画像範囲の中間に興味のあるオブジェクトをセットアップしたりすることでセンサーのラティチュード31を最大化することにある。入射光から最終ピクセル値への変換の完全なパイプラインは図70で説明される。

(図70:光の様々な変換工程を示すカメラパイプライン。)

(図71:入射光の範囲が世界の範囲からカメラの範囲へ、また、画像の範囲へどのようにリマップされるかを示す。斜線の領域は入射ライティングの低い値と比較されたカメラセンサーの有限の精度のために切り捨てられたカメラ範囲である。)

以下の3つの主なパラメータは露出を設定するためにアーティストによって制御可能となっている。

  • 相対的絞りRelative aperture (F値NN): 絞りの開く大きさを制御する。被写界深度に影響を与える。
  • シャッタースピードShutter time (tt秒): 絞りの開く時間の長さを制御する。モーションブラーに影響を与える。
  • センサー感度Sensor sensitivity/ゲインgain (ISO感度SS): ディジタルセンサーでどれだけのフォトンが数え上げられる/量子化されるかを制御する。

与えられたこれらのパラメータの組み合わせは EV値Exposure Value (EVEV)にまとめることができる。EVEV慣例に従ってper conventionISO100で定義され、EV100EV_{100}と記される。故に、以下の関係が成り立つ。

EV100=log2(N2t)log2(S100)(67)EV_{100} = \log_2 \left( \frac{N^2}{t} \right) - \log_2 \left( \frac{S}{100} \right) \tag{67}

様々な設定の組み合わせで同じEVEVを得ることができるので、図72に示されるように、アーティストがモーションブラー、被写界深度、ノイズ又はざらつきgrainの間の様々なトレードオフを作ることを可能にする。

(図72:様々な露出設定の構成。絞り、シャッタースピード、感度の間の様々なEV値に対する同等な設定を示す。)

EV100EV_{100}節4.3で説明したようにライト強度を説明または測定するためにアーティストにより使われもする32。絞り、シャッタースピード、感度に加えて、アーティストは画像を露出過多(つまり、明るくする)または露出不足(つまり、暗くする)にするために露出補正(F値ECEC)を適用することができる。このECECはEV値への単なるオフセットである。

EV100=EV100EC(68)EV'_{100} = EV_{100} - EC \tag{68}

負の符号はECECがF値であるという事実に由来し、値が増加すると絞りサイズが増加することを意味している。これは、値が増加すると絞りサイズが減少するEVEVから見ると逆方向になる。手動の露出設定はアーティストが求める厳密なルックを得るために便利であるが、セットアップするのが面倒tediousになる可能性がある。ディジタルカメラはそれらの操作を簡単にするために自動露出モードを提供する。与えられたシーンに対して正しいカメラ設定(すなわち、EVEV)を見つけるには、シーン輝度についての知識が必要になる。露出計に似たあるカメラは平均入射輝度を測定して、それをEV値に変換することができる。これは節4.3式11でその詳細を述べたが、可読性のためにここに再掲する。ここで、KKは反射光計のキャリブレーション定数である(12.512.5に等しい)。

(図73:手動モードでの設定の比較。上:絞りサイズのみ変更して、ISO感度は一定のままにする。このにより、EV100EV_{100}の値は増加し、強度は減少している。下:同じEV100EV_{100}を達成するために絞りサイズの減少を補正するためにISO感度を変更する。)

EV100=log2(LavgSK)(69)EV_{100} = \log_2 \left( \frac{L_{\text{avg}} S}{K} \right) \tag{69}

ゲームでは、LavgL_{avg}を得る通常の方法はすべての画像ピクセルの平均対数輝度を取ることである。これは高い強度のちらつくライトやハイライトで若干不安定であることを証明する。より良い方法は時間上で値を平滑化する、または、極端な値を取り除くために輝度のヒストグラムを使うことである[@Vlachos2008PostProcessingOrange]。しかし、これらの手法はアルベドを乗算したピクセル輝度に基づく露出に悩まされる。これは、シーンが完全に10%グレーか完全に90%グレーである場合、結果として同じ色になることを意味している。代替案としてはアルベドで乗算する前に輝度に基づいて露出制御することが挙げられる[@Kojima2013PhotorealismEyesFOX]。しかし実践では、白のみの輝度を持つ別のライティングバッファを維持するのは高価である。Frostbiteでは、ヒストグラムの手法を採用した。

5.1.2. 露出(Exposure)

EVEVの量はセンサーに到達するシーン輝度を説明するluminous exposure又はphotometric exposure H[lxs]H[lx \cdot s]と混同してはいけない。HHは以下で定義される。

H=qtN2L(70)H = \frac{qt}{N^2}L \tag{70}
=tE(71) = tE \tag{71}

ここで、LLは入射輝度を、qqはレンズと口径食の減衰(一般値はq=0.65q = 0.65)を表す。センサーによって記録される実際の値は感度/ゲインに依存する。ISO標準[^52]はphotometric exposureや感度に関する3つの異なる方法を定義している。

  • SOS: Standard Output Sensitivity
  • SBS: Saturation Based sensitivity
  • NSB: Noise Based Sensitivity

最も理解しやすいもののひとつであるSBSはカメラの出力がクリップやブルームを起こさないできるだけ最大の露出として定義され、以下として両方の項が関係する。

Hsbs=78Ssbs(72)H_{sbs} = \frac{78}{S_{sbs}} \tag{72}

因数7878は、標準照度計に基づく露出設定や18%の反射面が結果として飽和の18%/2=12.7%18\%/\sqrt{2} = 12.7\%のグレーレベルを持つ画像になるように選ばれる。因数2\sqrt{2}は、100%反射の白色の表面より明るく見えるスペキュラ反射を扱うために半分程度の余白half a stop of headroomがあることを示している33式72式71を組み合わせることで、センサーが飽和したときの最大輝度LmaxL_{max}を決定することができる。

Hsbs=78S(73)H_{sbs} = \frac{78}{S} \tag{73}
qtN2Lmax=78S(74)\frac{qt}{N^2} L_{max} = \frac{78}{S} \tag{74}
Lmax=78SN2qt(75)L_{max} = \frac{78}{S} \frac{N^2}{qt} \tag{75}

最終的なピクセル値ppリスト28で示されるように最大輝度LmaxL_{max}で入射輝度LLを正規化することで計算することができる。

float computeEV100(float aperture, float shutterTime, float ISO) {
    // EV値は以下のように定義される。
    //   2^EV_s = N^2 / t
    //   EV_s = EV_100 + log2(S / 100)
    // これで以下が求まる。
    //   EV_s = log2(N^2 / t)
    //   EV_100 + log2(S / 100) = log2(N^2 / t)
    //   EV_100 = log2(N^2 / t) - log2(S / 100)
    //   EV_100 = log2(N^2 / t . 100 / S)
    return log2(sqrt(aperture) / shutterTime * 100 / ISO);
}

float computeEV100FromAvgLuminance(float avgLuminance) {
    // 我々はスペキュラハイライトのための√2空間を持つ18%のミドルグレーを持つために後に12.7%のミドルグレーを用いるが、ここで我々はミドルグレーを計測する露出計を扱う。これは標準のカメラ構築設定に合わせた12.5に固定される(つまり、キャリブレーション定数K=12.5となる)。
    // 参考: https://en.wikipedia.org/wiki/Film_speed
    return log2(avgLuminance * 100.0f / 12.5f);
}

float convertEV100ToExposure(float EV100) {
    // H_sbsの感度を持つできる限りの最大輝度を計算する。
    // maxLum = 78 / (S * q) * N^2 / t
    //        = 78 / (S * q) * 2^EV_100
    //        = 78 / (100 * 0.65) * 2^EV_100
    //        = 1.2 * 2^EV
    // 参考: https://en.wikipedia.org/wiki/Film_speed
    float maxLuminance = 1.2f * pow(2.0f, EV100);
    return 1.0f / maxLuminance;
}

// 手動設定による使い方。
float EV100 = computeEV100(aperture, shutterTime, ISO);
// 自動設定による使い方。
float AutoEV100 = computeEV100FromAvgLuminance(Lavg);

float currentEV = useAutoExposure ? AutoEV100 : EV100;
float exposure = convertEV100toExposure(currentEV);

// 露出は色がXYZに分解される場合に輝度をスケールするためにシェーダで後の使うことができる。
...
float exposedLuminance = luminance * exposure;
...
// または、色に直接適用することができる。
...
finalColor = color * exposure
...

: 入射ライティングLLを現在のカメラ設定、絞りNN、シャッタースピードtt、感度SS、でのカメララティチュードにリマップするためにEV値を計算するためのヘルパー関数。

この値はセンサーやアナログtoディジタル変換器によってディジタル値に変換される。センサーの物理特性(CCD技術、ビット解像度、など)はライトが量子化され、格納される方法にわずかながら影響を与える。このステップはディジタルカメラでRAWファイルに直接格納される線形な値を出力する。そして、この線形データを人間が見やすい形に変換するためにいくつかの変換が適用される。

  • ホワイトバランス調整。
  • カラーグレーディング。
  • トーンマッピング。
  • ガンマ補正。

これらすべての変換は入力として露出した光HHを取り、最終的なピクセル値を出力する単一のLUTにベイクすることができる34。各カメラメーカー固有で時々”フィルムストックfilm stock”と呼ばれるこのLUTは、カメラからJPEG画像を出力するとき、すなわち、RAWに出力するときではないとき、に各画像で自動的に適用される。露出した光は依然として、露出後でも、広範囲(“ラティチュードlatitude”と呼ばれる)に渡る可能性があるので、LUTは高精度であり、正規化範囲[0,1][0, 1]の外側の値、つまり、“HDR”の値をサポートする必要がある。この単一の変換はアーティストにさらなるコントロールを提供するために異なるステップに分解することもできる。

備考: 完全な光の変換やセンサーの大きさを計算に入れるため、絞り形状上でLLを積分することで像平面image planeの照度EEを計算することができる。HHは露出時間全体の間に受け取る光密度を説明することを思い出してほしい。故に、photometric exposure HHとすると、センサーセルによって記録される実際のエネルギー量Q[lms]Q[lm \cdot s]を計算できる。

Q=HA(76)Q = HA \tag{76}

ここで、AAはセンサーセルの大きさ(m2m^2)である。これはトータルのセンサーサイズ(例えば、36mm x 24mm)やセンサーの解像度(例えば、5760x3240)に依存する。

5.1.3. エミッシブおよびブルーム効果(Emissive and bloom effects)

ゲームエンジンが再現しようとする様々なカメラアーティファクト(被写界深度、モーションブラー、ノイズやグレイン、レンズフレア)の中でも、ブルームbloomは興味深いものである。ブルームは高強度情報を伝達する人間の目とディジタルカメラの両方を通して確認できる重要なエフェクトである。このアーティファクトの原因は幾重にも折り重なっている。

  • センサーセルが飽和したり近傍のセンサーセルに漏れたりする高強度値
  • 鏡筒内の相互反射
  • レンズの中及び表面の不完全性やホコリ。

ピクセルの最終的な明るさはカメラ設定に依存する。EV値に依存して、エミッシブ値がブルームするピクセルを生み出すかどうかを決める。つまり、入射輝度LLがセンサーの最大輝度LmaxL_{max}を上回るかどうかである。これはVFXアーティストが昼でも夜でもこれらの効果のために一貫性のあるブルームの強さを求める所である時刻変化time of dayで特に問題である[@Vainio2014VisualEffectsInFAMOUS]。エミッシブな表面では、エミッシブな表面がブルームする時しない時を制御できるようにするためにアーティストへツールを提供することが役に立つ。そうするために、エミッシブな表面はそれらの現在の強度を調整したり強度飽和点以上であることを保証したりするために露出補正の観点で表現させることができ、これにより、ピクセルを強制的にブルームさせる35

float3 computeBloomLuminance(float3 bloomColor, float bloomEC, float currentEV) {
    // currentEVは前フレームで計算された値である。
    float bloomEV = currentEV + bloomEC;
    // 輝度に変換する。
    // EV値から輝度への変換についての説明は式12を参照のこと。
    return bloomColor * pow(2, bloomEV - 2);
}

: すべての露出でブルームすることを保証するためにエミッシブ表面の輝度を計算する関数。

5.1.4. サニー16(Sunny 16)

計算を評価するため、“Sunny 16”ルールを用いてきた。Sunny16ルールはライティング条件に適したカメラ設定を素早くみつけるために写真家によりしばしば用いられる。このルール曰く、“晴れの日では、直射日光の当たる対象物に対して、絞りをf/16に、シャッタースピードをISO設定スピードに設定する”。これは、晴れの日に、ISO100設定では、絞りをf/16に、シャッタースピードを1100\frac{1}{100}1125\frac{1}{125}に設定することを意味する。このルールは表13が示すように他のライティング環境に拡張されている。Sunny16ルールでは、ISOとシャッター時間は同じ値である。図74は晴れ日のライティング条件に対するこのようなルールの例を示す。

(図74:絞りをf/16、ISOを100、シャッタースピードを1/125秒に設定したときのSunny 16テストの例。)

絞りライティング条件影のディテール
f/22雪や砂鋭い輪郭を伴う暗い
f/16晴れ明瞭
f/11若干の曇り輪郭周りが柔らかい
f/8曇りほとんど見えない
f/5.6かなりの曇り影なし
f/4Open shade36又は日没影なし

: 他のライティング条件に拡張されたSunny16ルールの例。これらの値はISO100とシャッタースピード1/125で使うことができる。

5.1.5. 色空間(Color space)

我々のパイプラインは最終結果をsRGB空間、Rec709空間37、その他の空間のいずれかで出力することができる。節5.1を参照。

ゲームエンジンでの一般的な落とし穴はsRGB変換をガンマ2.2の曲線として(しばしばパフォーマンス的な理由により)近似することである。このガンマ2.2は避けて、リスト30で提供される正確なsRGB変換式に置き換えられるべきである。これらの2つの関数をグラフ化したもの(図75)は暗い値で近似の不正確さを強調する。これは目が低値の範囲での変化に非常に敏感であるため重大である。例えば、図76はsRGBへの近似が真っ黒を生成できないことを示している。

float3 approximationSRgbToLinear(in float3 sRGBCol) {
    return pow(sRGBCol, 2.2);
}

float3 approximationLinearToSRGB(in float3 linearCol) {
    return pow(linearCol, 1 / 2.2);
}

float3 accurateSRGBToLinear(in float3 sRGBCol) {
    float3 linearRGBLo = sRGBCol / 12.92;
    float3 linearRGBHi = pow(( sRGBCol + 0.055) / 1.055,  2.4);
    float3 linearRGB = (sRGBCol  <= 0.04045) ? linearRGBLo : linearRGBHi;
    return linearRGB;
}

float3  accurateLinearToSRGB(in  float3  linearCol) {
    float3 sRGBLo = linearCol * 12.92;
    float3 sRGBHi = (pow(abs(linearCol), 1.0 / 2.4) * 1.055) - 0.055;
    float3 sRGB = (linearCol  <= 0.0031308) ? sRGBLo : sRGBHi;
    return sRGB;
}

: sRGBから/への変換。

(図75:線形からsRGB曲線への変換の比較。青:正確な線形からsRGBへの変換。赤:(1/2.2)近似。右では、一般的な暗いアルベド値に対する近似の不正確さを強調するためにグラフが拡大されている。)

(図76:左:正確な変換でsRGBに変換された線形RGB0.02の値。右:近似曲線で変換した値。)

5.2. 大きい値の操作(Manipulation of high values)

節5.1に見られるように、現実世界の輝度のダイナミックレンジは広大である。単純なシーンでは100000:1のダイナミックレンジを持つのが一般的である。我々はスクリーン上に出力する値としてこのような大きな値を扱う方法を探していたが、その以前にこれらの値を操作し格納するにはどうすればいいのだろう?精度の問題に特別な注意を払わないと、バンディング、無限数、非数NaNを生じるだろう。

ライティングバッファのストレージでは、MDRからHDR程度の浮動小数点フォーマットがいくつか利用可能である。最も一般的なのは、Float32、Float16、R11F_G11F_B10F、RGB9_E5である。後者2つのフォーマットは符号ビットを持たず、RGB9_E5フォーマットはRGB要素ごとに個別の仮数部ビットを持つが、これらすべては単一の指数部を共有する(14ビットfloat)。数値的な精度やこれらフォーマットの限界は表14に提供される。

ビット深度ビット 符号/仮数/指数最大値最小値*精度の十進数
32ビットFloat1/23/83.4028237×10383.4028237 \times 10^381.175494×10381.175494 \times 10^{-38}7.22
16ビットFloat1/10/5655046.10×1056.10 \times 10^{-5}3.31
14ビットFloat0/9/565408**6.10×1056.10 \times 10^{-5}3.16
11ビットFloat0/6/5650246.10×1056.10 \times 10^{-5}2.5
10ビットFloat0/5/5645126.10×1056.10 \times 10^{-5}2.32

: 小さな浮動小数点フォーマットの数値的な限界と精度[@OpenGLWiki2023SmallFloatFormats]。* この場合の最小は0に最も近く非正規化を無視した場合を意味する。 ** このフォーマットは再構築で(1+仮数)ではなく(仮数)を使う。

浮動小数点フォーマット: これらは知覚的な光の明るさと同様に非線形であるため、ライティング情報を格納するのに適している。従って、大きな値で精度が足りなくても、思っていたより問題は少なくなる。すべての小さな浮動小数点フォーマットのダイナミックレンジは約30stops38であり、これは人間の目の20stopsの範囲をカバーする(ただし、同時には6.5stopsしか使えない)。10ビットfloatsは11ビットfloatsより精度が低く、丸め方が異なるので、R11F_G11F_B10Fフォーマットでは小さな色相シフトが起こる可能性があることに注意したい。

整数フォーマット: これらはRGBM、RGBD、RGBE、LogLUV、LUV39 [@Guertault2013GammaCorrectHDR]、10_10_10_2といったフォーマットも利用可能であるが、よりバンディングに悩まされる。カスタムフォーマットは追加のALUが必要になり、良好なハードウェアフィルタリングを妨げる。

Frostbiteでは、ライティングストレージとして以下のフォーマットを使う。

ライトマップRGB9_B5。我々は様々なクオリティオプションを提案するが、RGB9_E5は間接ライティングを格納するだけのライトマップとして十分良いことを発見した。
HDRIFloat16。エンジン内でHDRフォーマット(OpenEXR(Float16かFloat32)またはHDR(RGBE))をインポートして、Float16へ変換する。Float16への変換が65504より大きな値を無限値とするようなフォーマットとしてインポートするときは注意しなければならない。
ライトバッファFloat16。露出は事前に適用される。

ライトバッファはさらなる注意が必要である。Float16の大きなダイナミックレンジにも関わらず、極端な値がしばしば現れる。最大値はとても低すぎる(65504)し、最小値は小さすぎる(6.101056.10 \cdot 10^{-5})。加えて、いくつかのパスでライティングを累加すると、バッファが簡単に飽和し、無限値を生成する可能性がある。Float16パラメータによってもたらされる30stopsはカメラの露出範囲として解釈できる。この範囲から本当の利益を得るため、カメラがフィルムを最大限活用しようとするのと同様の方法で露出を使うことができるかもしれない。シーンに対して使われる望ましい露出は結果として焦点の当たっているオブジェクトが黒と白の大体中間の値(ミドルグレー18%)を持つことになる。ただし、ライティングパイプラインの終わりではなく始めにこの概念を適用することを除く。結果はこれらの焦点の当たっているオブジェクトのライティングを中和neutralizingすることと同様であり、故に、多かれ少なかれ、ディフューズアルベド40を復元することや数値的な問題を制限することに対応する。

我々はすべてのライティングをそれを格納する前に事前に露出するために節5.1で述べた露出情報を用いる。固定の露出か前フレームの自動露出により計算される露出かのいずれかを用いる。最初にレンダリングされるフレームと同様に素早い又は大きなカメラ動作(テレポートを含む)を伴う前フレームの露出を用いることの一般的な落とし穴が存在する。しかし、これは目の順応時間として知覚させることができ、故に許容できる。事前露出はすべてのライティングシェーダに存在する最後段epilogueで処理される(リスト31参照)。

float epilogueLighting(float3 color, float exposureMultiplier) {
    return color * exposureMultiplier;
}

// ライティング付きシェーダ。
...
outColor0 = epilogueLighting(outColor0, g_exposureMultiplier);

: 最後段に事前露出されるライトバッファ。

事前露出に伴い、パイプラインの最後で露出を適用する必要はなくなる。もし必要とするならば、事前露出は絶対輝度値を取り戻すために復元することができる。事前露出に加えて、シェーダ内でFloat32精度から利益を得るためにひとつのパスですべてのライトを処理することを選択した。そのため、低精度バッファから読み書きするために情報が失われることを回避することができる。

5.3. アンチエイリアシング(Antialiasing)

エイリアシングはリアルタイムレンダリングでは一般的で知られた問題である。新しくはないが、PBRは(低いラフネスで大きな値が生成される)正規化されたNDFの使用、入射ライティングの大きな強度、すべてに”反射”があること(すなわち、入射ライティングに囲まれている)での、によりエイリアシング量が増加する可能性がある。この節では、これらの問題の原因とこれらに対処するための主な解決法を読者へ改めて簡潔に説明briefly remindしようと思う。

観察できるエイリアシングの大多数は式77で推定されるピクセルの表面上のサンプルが不足していることに起因する。通常ゲームは主にパフォーマンス的な理由において与えられたピクセルに到達する入射ライティングを推定するためにピクセル当たりひとつのサンプルを取る。

I(v)=pixelL(v)dA(77)I(\boldsymbol{v}) = \int_{\text{pixel}} L(\boldsymbol{v}) dA \tag{77}

この疎なサンプリングはライティング評価をカメラ位置と表面の向きに強く依存させる。近スペキュラnear-specular表面では、法線はハイライトを生成するための入射光と視線のベクトルに完璧に並行している可能性がある。視点位置の若干の変化はこの平行関係を妨げ、唐突にハイライトを取り除いてしまう。この明滅flickeringは自然(例えば、水面を動く太陽光)において観測されるが、ほとんどの場合に不自然で、明らかに目立ち、ユーザーの気を散らしてしまう。これに対処するため、この分野ではテクニックの主なカテゴリが2つ挙げられる。

スーパーサンプリング: MSAA(MultiSample Anti-Aliasing)、SSAA(SuperSample Anti-Aliasing)、TAA(Temporal Anti-Aliasing)のようなテクニックはピクセルについて複数点で入射ライティングを評価することで、小さな変化を捕捉して可視エイリアシングを低減する。これらのテクニックの間の差異はこれらのサンプルが生成され蓄積される方法に依存する。MSAAは可視性サンプル数を増やす一方で、シェーディングサンプルはひとつのままになる。これは幾何的な不連続性に役立つが、シェーディング問題の役には立たない。SSAAはピクセル上で空間的にサンプル数を増やすことで、式77の積分をより良く推定することができる。理論的には理想的である一方で、そのコストがSSAAを実践で使用されることを妨げている。あるいは、TAAのテクニックは時間上でピクセル当たりのサンプル数を増やす。これは複数フレーム上にコストを分散させる一方で、依然としてピクセル当たりのサンプル数は高いままである。TAAテクニックの時間的な特徴により、以前のサンプルはカメラかオブジェクトが移動するときに以前のフレームから現在のフレームに再投影される必要がある。ライティング変化を含むサンプルを排除したり、再投影できない半透明の表面を扱ったりするためにいくつかのヒューリスティクスが通常使われる。TTAテクニックのさらなる詳細については[Sousa 2013Sousa, T. 2013. Graphics Gems from CryENGINE 3. Advances in Real-Time Rendering in Games course. ACM SIGGRAPH. https://advances.realtimerendering.com/s2013/index.html.; Karis 2014Karis, B. 2014. High Quality Temporal Supersampling. Advances in Real-Time Rendering in Games course. ACM SIGGRAPH. https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf.]を参照のこと。

事前フィルタリング: Toksvig[Toksvig 2004Toksvig, M. 2004. Mipmapping Normal Maps. https://developer.download.nvidia.com/whitepapers/2006/Mipmapping_Normal_Maps.pdf.; @Han2007FrequencyDomainNormal]、LEAN[Olano and Baker 2010Olano, M. and Baker, D. 2010. LEAN mapping. Proceedings of the 2010 ACM SIGGRAPH symposium on interactive 3D graphics and games 181–188. 10.1145/1730804.1730834. https://userpages.cs.umbc.edu/olano/papers/lean/.]、LEADR[Dupuy et al. 2013Dupuy, J., Heitz, E., Iehl, J.-C., Poulin, P., Neyret, F. and Ostromoukhov, V. 2013. Linear efficient antialiased displacement and reflectance mapping. ACM Trans. Graph. 32, 6. 10.1145/2508363.2508422. https://inria.hal.science/hal-00858220v1/file/LEADRmapping.pdf.]のようなテクニックはマクロ幾何的な変化(曲率)やメゾ幾何的な変化(ノーマルマップ、ディスプレースメントマップ)を、ピクセルフットプリントに包含して、マテリアル特性(すなわち、統計的なマイクロ幾何的変化)に変換することでサンプル数を少ないままにしようとする。この移し替えはピクセルフットプリント内で起こる相互作用のすべてをより簡単により高速に評価できるようになる。ToksvigやLEANのようなテクニックはノーマルマップのフィルタリングに焦点を当てている[@Bruneton2012SurveyNonlinearPrefiltering]一方で、LEADRはディスプレースメントマップのフィルタリングを対処する。その他は曲率をマテリアル特性に転送することで近似的なマクロ幾何的フィルタリングを処理する。ディファードレンダリングを使うとき、このマクロ幾何的フィルタリングは、 Hill [2012Hill, S. 2012. Rock-Solid Shading: Image Stability Without Sacrificing Detail. Advances in Real-Time Rendering in Games course. ACM SIGGRAPH. https://advances.realtimerendering.com/s2012/index.html.] が提案するようにGバッファパス中に、または、 Mittring [2012Mittring, M. 2012. The Technology Behind the "Unreal Engine 4 Elemental demo". Advances in Real-Time Rendering in Games course. ACM SIGGRAPH. https://advances.realtimerendering.com/s2012/index.html.]@Schulz2014MovingNextGeneration が提案するようにポストプロセスとして処理することができる。

これら両方のテクニックのカテゴリはいくつかの制限があり、これらを組み合わて良い解決策とする。例えば、事前フィルタリングのテクニックは輪郭のようなマクロ幾何的な不連続性を計算に入れていない。スーパーサンプリングのテクニックはこのタイプの問題を解決できる。技術的には、スーパーサンプリングテクニックはスタンドアローンとすることができるが、これらは安定したピクセル値に収束するために大量のサンプルが必要になる可能性がある。両方のアプローチを組み合わせるとほとんどのケースを効率的に扱うことができる。加えて、エイリアシング起こっているエッジを減らすことで画像を改良しようとする、多数のポストプロセステクニック[Jimenez et al. 2011Jimenez, J., Gutierrez, D., Yang, J., Reshetov, A., Demoreuille, P., Berghoff, T., Perthuis, C., Yu, H., McGuire, M., Lottes, T., Malan, H., Persson, E., Andreev, D. and Sousa, T. 2011. Filtering approaches for real-time anti-aliasing. ACM SIGGRAPH 2011 courses. 10.1145/2037636.2037642. https://www.iryoku.com/aacourse/.]が存在する。これらはよりきれいな画像を提供できるが、実際の問題を解決するわけではなく、単に最小化しようとするだけである。

Frostbiteでは、FXAA、SMAAT1x、SMAAT2x[Jimenez et al. 2012Jimenez, J., Echevarria, J. I., Sousa, T. and Gutierrez, D. 2012. SMAA: Enhanced subpixel morphological antialiasing. Computer Graphics Forum 31, 2pt1, 355–364. 10.1111/j.1467-8659.2012.03014.x. https://www.iryoku.com/smaa/downloads/SMAA-Enhanced-Subpixel-Morphological-Antialiasing.pdf.]、MSAAといった様々なアンチエイリアシングテクニックのタイプをサポートする。ノーマルマップの事前フィルタリングでは、 @Neubelt2013CraftingNextGenMaterial によって述べられる手法を採用した。我々はテクセル毎法線に基づくNDFを計算して、新しい”効果的な”なラフネスを生み出すために現在のラフネスと組み合わせる。ラフネスマップの様々なレベルに新しいラフネスを格納する @Neubelt2013CraftingNextGenMaterial に加えて、我々はライティングが起こる前にシェーダ内でその場でこの処理を適用する可能性も提供することにした(ディファードマテリアルモデルでは、これはGバッファレイアウトにラフネスを格納する前に適用される)。我々の動機付けはシェーダ内で起こる法線合成のフィルタリング(例えば、ノーマルマップ、ディティールマップ、プロシージャル法線)を正しく扱うことができることである(リスト22)。更に、これはノーマルマップとラフネスマップを分離することができるようになるので、異なる解像度にしたりテクスチャを再利用したりできるようになる。この処理を助けるため、テクスチャをオフラインで処理するときにノーマルマップと合わせて追加の平均法線長を格納する41。NDFの操作や計算はアーティストに対して透過的に取り扱われる。

float adjustRoughness(float inputRoughness, float avgNormalLength) {
    // The Order: 1886のSIGRAPHコースノートの実装に基づく
    if (avgNormalLength < 1.0f) {
        float avgNormLen2 = avgNormalLength * avgNormalLength;
        float kappa = (3 * avgNormalLength  - avgNormLength * avgNormLen2) / (1 - avgNormLen2);
        float variance = 1.0f / (2.0 * kappa);
        return sqrt(inputRoughness * inputRoughness + variance);
    }
    return (inputRoughness);
}

void packGbufferData(PBRMaterialRootData data, out GBufferData gbData, in float opacity) {
    data.roughness = adjustRoughness(data.roughness, data.normalLength);
    gbData.GBuffer0 = float4(data.worldNormal, data.roughness);
    (...)
}

: Gバッファに保管する前の平均法線長に基づいたラフネス調整。

備考: 明滅するスペキュラハイライトを取り除くことに加えて、これらすべてのアンチエイリアシングテクニックはピクセルフットプリントの下地となるジオメトリのマイクロ/メゾ/マクロな変化のために正しいハイライト形状を復元するのに役立つ。事前フィルタリングされたテクニックはこれを行うのに本当に効率的である42。しかし、ノーマルマップフィルタリングテクニックのほとんどはピクセルフットプリントの元になる法線の(異方的な)ガウス分布を仮定する。同時にこれらのテクニックはガウス的なNDFを持つマテリアルを仮定するため、(2つの球面ガウス分布の畳み込みは1つの球面ガウス分布になるので、)解析的なやり方で両方の正規分布を組み合わせることを可能にする。しかし、GGXのNDFを持つマテリアルでは、この仮説が正しくなくなってしまう。GGX分布と球面ガウス分布との畳み込みは解析的ではないが、その結果は事前計算されたテーブルを持つGGX分布により合理的に近似できる。

6. PBRへの移行(Transition to PBR)

エンジンをPBRへ移すことを考えるとき、技術面と芸術面の両方を計算に入れる必要がある。その開始から、技術開発と並行していくつかのゲームチームのテクニカルアーティストを訓練していた。

複数のタイトルに対してプロダクションですでに使われていたエンジンをPBRに移すことは単純な仕事ではなかった。数多くのアセットがすでに作成されており、アーティストの知識は時代遅れのプラクティスに頼っている。PBRエンジンの早期バージョンはプロダクションから分かれたブランチで開発されていた。第一段階はテクニカルアーティストを訓練することができるツールを開発することだった。このため、単一のディスタントライトプロブを持つオブジェクトをライティングできる単純なエンジン内オブジェクトビュアーを作った43。ディスタントライトプロブに加えて、このビュアーはπ\piにキャリブレーションされた太陽光を含んでいたので、太陽に照らされたオブジェクトはディフューズアルベドを返していた44。このツールの助けにより、他のPBR機能を開発しつつ、訓練とアセットの生成を始めることができた。

第二段階は節3.2で述べたマテリアルシステムの助けを持つ同じエンジン内で動作するレンダラのPBRと非PBRバージョンを維持することであった。これはプロダクションブランチにPBRエンジンを移せるようにするために重要であった。すでに生成されたまともなビジュアルを持つレベルをローンチできるようにするため、我々は自動変換を開発した。

  • マテリアルパラメータでは: 幸いにも、非PBRなFrostbiteエンジンはすでにsmoothnessを使ったり固有のmetalIdを持つメタリックな表面を分けたりしていた。近似したPBRテクスチャを得るためにその場でシェーダ内でパラメータを変換することができた。アーティストは変換の質を改善するために手動でテクスチャを変換しようともした。これらの変換手法による経験は、アーティストは良い結果を得ることができるが各テクスチャは固有の扱いを必要とする、ということである。残念ながら、すべてのテクスチャを良品質で変換する自動的な方法は存在しない。
  • ライトでは: ライトを任意の単位から物理ベース単位に変換するのは極めて難しいことを発見した。非PBRライトのほとんどは固有のライティング条件で調整され、相対的な割合を持つ。故に、すでに存在するレベルのいくつかの部分は正しく照らされなかった。

第三段階はPBRをゲームチームに説くevangelizeことであった。訓練したテクニカルアーティストがこの受け入れの際に重要であった。すべてのFrostbiteのレンダリングチームはPBRバージョンへ徐々に切り替えていき、非PBRレンダラのサポートを取りやめていった。我々は移行を楽にするためにMari、Substance、Marmosetのようなゲームチームで使われる外部ツール内のベースマテリアルモデルのためのサポートも開発した。

最後に、移行期間中にアーティストを助けるため、範囲マテリアルテクスチャやライティング照度を確認するための検証ビューモードを開発した(図77参照)。

(図77:入射照度の強度を示す照明のデバッグビューモード。このモードはライティングリグを検証するためにライティングアーティストによって使われる。)

謝辞(Acknowledgements)

バージョン(Version)

参考文献(Bibliography)

A. リファレンスモードのコード(Listing for reference mode)

リストA.1は予期される結果を素早く確認するためにスペキュラGGXマイクロファセットモデルでライトプロブを積分する単純なカーネルを示す。

float3 evaluateSpecularIBLReference(
    in float3 N,
    in float3 V,
    in float roughness,
    in float3 f0,
    in float f90)
{
    // local referentialを作る
    float3 upVector = abs(N.z) < 0.999 ? float3(0, 0, 1) : float3(1, 0, 0);
    float3 tangentX = normalize(cross(upVector, N));
    float3 tangentY = cross(N, tangentX);

    float3 accLight = 0;
    for (uint i = 0; i < g_sampleCount; ++i)
    {
        float2 u = getSample(i, g_sampleCount);

        // GGX NDFのサンプリング
        float cosThetaH = sqrt((1 - u.x) / (1 + (roughness * roughness - 1) * u.x));
        float sinThetaH = sqrt(1 - min(1.0, cosThetaH * cosThetaH));
        float phiH = u.y * FB_PI * 2;

        // 半角から入射角へサンプルを変換する
        float3 H;
        H = float3(sinThetaH * cos(phiH), sinThetaH * sin(phiH), cosThetaH);
        H = normalize(tangentX * H.y + tangentY * H.x + N * H.z);
        L = normalize(2.0 f * dot(V, H) * H - V);

        float LdotH = saturate(dot(H, L));
        float NdotH = saturate(dot(H, N));
        float NdotV = saturate(dot(V, N));
        float NdotL = saturate(dot(L, N));

        // サンプルごとの重点サンプリング重み
        //
        // weight = fr . (N . L)
        //
        // ここで:
        // fr = D(H) . F(H) . G(V, L) / ( 4 (N.L) (N.O) )
        //
        // マイクロファセット空間で積分するので、変換のヤコビアンを含める
        //
        // pdf = D(H) . (N.H) / ( 4 (L.H) )
        float D = D_GGX(NdotH, roughness);
        float pdfH = D * NdotH;
        pdf = pdfH / (4.0 f * LdotH );

        // 暗黙的な重み (N.Lは打ち消される)
        float3 F = F_Schlick(f0, f90, LdotH);
        float G = G_SmithGGX(NdotL, NdotV, roughness);
        weight = F * G * D / (4.0 * NdotV);
        if (dot(L, N) > 0 && pdf > 0) {
            accLight += g_IBL.SampleLevel(sampler, L, 0).rgb * weight / pdf;
        }
    }
    return accLight / g_sampleCount;
}

: ディスタントライトプロブでスペキュラGGXマイクロファセットBRDFを積分するためのランタイムのリファレンスコード。

リストA.2は予期される結果を素早く確認するためにディフューズDisneyBRDFモデルでライトプロブを積分する単純なカーネルを示す。

void importanceSampleCosDir(
    in float2 u,
    in float3 N,
    out float3 L,
    out float NdotL,
    out float pdf)
{
    // Local referencial
    float3 upVector = abs(N.z) < 0.999 ? float3(0, 0, 1) : float3(1, 0, 0);
    float3 tangentX = normalize(cross(upVector, N));
    float3 tangentY = cross(N, tangentX);

    float u1 = u.x;
    float u2 = u.y;

    float r = sqrt(u1);
    float phi = u2 * FB_PI * 2;

    L = float3(r * cos(phi), r * sin(phi), sqrt(max(0.0 f, 1.0 f - u1)));
    L = normalize(tangentX * L.y + tangentY * L.x + N * L.z);

    NdotL = dot(L, N);
    pdf = NdotL * FB_INV_PI;
}

float3 evaluateIBLDiffuseCubeReference(
    in TextureCube<float4> incomingLight,
    in SamplerState incomingLightSampler,
    in float3 V,
    in MaterialData data,
    in float3 brdfWeight = float3(0, 0, 0),
    in uint sampleCount = 1024)
{
    float3 accLight = 0;
    for (uint i = 0; i < sampleCount; ++i)
    {
        float2 eta = getSample(i, sampleCount);
        float3 L;
        float NdotL;
        float pdf;
        importanceSampleCosDir(eta, data.worldNormal, L, NdotL, pdf);
        if (NdotL > 0)
        {
            // 各サンプルをL * weight / pdfで重み付けする必要がある
            // ここで:
            // - weight = NdotL
            // - pdf = NdoL / Pi
            // しかし、(weightとpdfにある)NdoLとPiは打ち消される
            // そのため、ここではすべての項がなくなっている
            float f = 1.0 f;
        #if FB_DIFFUSE_MODEL == FB_DIFFUSE_DISNEY
            // 半角の公式:
            // cos(2 theta) = 2cos^2(theta) - 1
            float cosD = sqrt((dot(V, L) + 1.0 f) * 0.5);
            float NdotV = saturate(dot(data.worldNormal, V));
            float NdotL_sat = saturate(NdotL);
            // DisneyのディフューズBRDFは線形ラフネスで計算する
            // これは、GGXのalphaラフネス項の平方根である
            float fd90 = 0.5 + 2 * cosD * cosD * sqrt(data.roughness);
            float lightScatter = 1 + (fd90 - 1) * pow(1 - NdotL_sat, 5);
            float viewScatter = 1 + (fd90 - 1) * pow(1 - NdotV, 5);
            f = lightScatter * viewScatter;
        #endif
            accLight += incomingLight.SampleLevel(incomingLightSampler, L, 0).rgb * f;
        }
    }
    return accLight * (1.0 f / sampleCount);
}

: ディスタントライトプロブでディフューズDisney BRDFを積分するランタイムのリファレンスコード。

リストA.3は予期される結果を素早く確認するためにエリアライトでマイクロファセットBRDFを積分する様々なライトの重点サンプリング手法を示す。

...

B. Oren-NayarとGGXのディフューズ項の導出(Oren-Nayar and GGX’s diffuse term derivation)

C. エネルギー保存則(Energy conservation)

D. Disneyのパラメータ化に変換するための最適化アルゴリズム(Optimization algorithm for converting Disney’s parametrization)

E. 長方形エリアライティング(Rectangular area lighting)

F. ローカルライトプロブの計算(Local light probe evaluation)

Footnotes

  1. 脚注4: Burley [2012Burley, B. 2012. Physically-Based Shading at Disney. Practical Physically Based Shading in Film and Game Production course. ACM SIGGRAPH. https://disneyanimation.com/publications/physically-based-shading-at-disney/.] が説明するように、これはアーティストがあらゆるラフネス値を通して同じディフューズ色を得られるようにすることを目的とした仕様によるものである。

  2. 脚注5:誘電体におけるf0f_0の小さな変化はほとんどのリアルタイムエンジンがサポートしていない屈折光の方向に関係している。

  3. 脚注7:ここでのディファードデカールはボリュームデカールとクラシックなデカールの両方を含む。

  4. 脚注8:フォワードでは発光デカールもサポートする。

  5. 脚注9:Frostbiteではラジオシティバッファはライティングパス後にアルベドとともに圧縮される。

  6. 脚注10:法線フィルタリングパスはラフネスを変更することを暗に示している。

  7. 脚注13:スペクトルは色相と強度を同時に扱うことができる。

  8. 脚注14:黒体放射の色温度は現実世界のライトの色全体を網羅しているわけではない。

  9. 脚注15:光放射はおおよそ紫外線、可視光、赤外線の放射を含む波長範囲を持つ光学の原則に従う放射である。

  10. 脚注19:12.5はおおよそとしてヘッドルーム(ひずみが生じないギリギリの上限)を提供するためのミドルグレーより0.5ストップだけ小さい値である。

  11. 脚注27:三次スプライン曲線を使って水平な角度を補間することを推奨する(水平な角度の360°の全範囲が指定されているか否かによって開けたり閉めたりする) [Ash14]。

  12. 脚注30:ランバートエミッタLambertian emitterはコサイン分布に従う放射輝度分布を持つ光源である。

  13. 訳注:投影先への距離が近いほど像が正確になるような特徴。

  14. 脚注36: 自然な密度フィルタを使うと、特に太陽をキャプチャしようとする[@Reinhard2005HighDynamicRange]ときに、適切な輝度を再構築するのに役立つ。

  15. 脚注37: MaxwellやVRayはHDRIを輝度単位ではなく放射輝度単位として考えていることを確認した。我々の結果と合わせるためにこのソフトウェアのHDRIを683で除算する必要がある。CañadaはMaxwellにおいて、これが下手に取得された古いHDRIに関する歴史的な理由によるものであることを確認していた。

  16. 「(生命の起源として)鶏と卵のどちらが先に現れたのか」という循環する因果関係のジレンマのこと。

  17. 脚注38:積分を正しく評価し、引き伸ばされた反射を復元するために事前にフィルタした重点サンプリング[@Krivanek2008RealtimeShadingFiltered]を使うか、事前統合と @Green2007EfficientReflectanceVisibility に示されるような等方的なローブの分解を使うかのいずれかが可能である。

  18. 脚注39:我々は事前統合でMISを使おうとしたが、確率テーブルの構築コストと各サンプルごとのバイナリサーチコストは収束の利得と比べて大きすぎた。

  19. 脚注40:我々は分離を若干の改良を加えて数学的に定義してみた。しかし、理論がよくなったとしても、ビジュアル結果はKarisの分離で得たものより常に悪くなった。

  20. 脚注41:Frostbiteでは、インテグレーションに32個のサンプルを使う。

  21. 脚注42: Ashikhmin and Shirley [2000Ashikhmin, M. and Shirley, P. 2000. An anisotropic phong BRDF model. Journal of Graphics Tools 5, 2, 25–32. 10.1080/10867651.2000.10487522.] は我々のものと類似性を持つ彼のディフューズモデルで同じ調査を行っている。

  22. 脚注44:フローマップのテクニックにより、HDRIで動く雲っぽさthe impression of moving cloudsを与えることができる。[@Guerrette2014MovingHeavensArtistic]

  23. 脚注45:アンビエントオクルージョン項はベイクされたライティングを暗くするのみを可能とし、光を生み出さない。ベイクされたライティングはしばしば遮蔽物なしに処理されるので、到達率が高いときに、ゲーム中では到達率を減らす文脈で暗くするのが理に適っている。

  24. 脚注46:BRDFローブは半球全体で定義されるが、ピークから外れるいくつかの値は破棄しても良いくらいとても小さい。これはラフネスを円錐の角度に変換できるようになる。節4.9を参照。

  25. 脚注47:このマイクロ遮蔽情報は伝統的なアンビエントオクルージョンテクスチャのようにオフラインプロセスで生成される可能性があるが、その場合レイ範囲がより短くなる。

  26. 脚注48:我々が用いる場合のf0f_0は空気とマテリアルからの屈折率を持つ空気-マテリアル間の界面から計算される。

  27. 訳注:面同士が接触する(ほど近い)ところに影付けを行うことで与えられる接地感のこと。

  28. 脚注49:我々のラジオシティシステムは静的データに基づいたアンビエントオクルージョン項を提供するため、動的オブジェクトを伴わない単純化されたシーンであることを意味する。しかし、この項はライティングデータにすでに含まれているので、間接ディフューズで再び適用される必要はない。

  29. 脚注50:Frostbiteでは、マイクロ遮蔽は他のテクスチャの中にベイクされるので、どの方法でもアクセス可能とはならない。

  30. 訳注:写真の分野における「ダイナミックレンジ」の意味。

  31. 脚注51:しかしながら、それは、デバイス依存であるので、正確な測定ではない。

  32. 脚注53:これは式71に示されるEVEVと輝度LLの関係に似ている。

  33. 脚注54:このLUTはハードウェアがこの最終ステップをサポートしているかどうかに依存してガンマ補正を任意に含めることができる。

  34. 脚注55:露出がピクセルを明るくしたり暗くしたりするためにシーンに注入されるので、このアプローチはフィードバックループを生成する可能性があるが、実践ではこれは起こらない。

  35. 訳注:(撮影場所としての)明るい日陰。そこそこの光量が指向性をそれほど持たずに届くため、そこにある対象物は陰影が付きづらい。

  36. 脚注56:sRGBとRec709は基本的に同じものhave same primariesだが、これらの指数の近似ガンマ曲線が異なる。sRGBは2.2、Rec709は2.4である。

  37. 脚注58:log2(6.55×1046.10×105)\log_2 \left( \frac{6.55 \times 10^4}{6.10 \times 10^{-5}} \right)

  38. 脚注59:輝度=16ビット、赤=8ビット、緑=8ビット。

  39. 脚注60:[@Reed2014ArtistFriendlyHDRExposure]のコメントでは、Hoffmanが似たような概念を説明している。

  40. 脚注61:LEANでは、法線の分散を線形に再構築するために平均法線長の二乗と平均二乗法線長を理想的には格納すべきである。しかし、これは1つではなく2つのチャンネルを必要とすると思われる。これは、導入された誤差が2つのMIPレベル間の補間に含まれているので、小さな正確性のトレードオフである。圧縮フォーマットでもいくつかの量子化アーティファクトを生成する可能性があるため重要である。

  41. 脚注62:これがないと、鏡のようなでこぼこした表面は、粗い表面の外観を持つのではなく、すべての法線が平均化されるために遠距離で平坦な鏡のように見える。

  42. 脚注63:この時、パブリックツール(Marmoset、SUbstance、…)やエンジン(UE4、Unity、…)は使えなかった。

  43. 脚注64:この時、ライティングの単位と良いHDRIの取得についての知識が不足していた。