Slide 1

Slide 1 text

SH,MonoSH対応 シェーダーの書き方

Slide 2

Slide 2 text

SH、MonoSHとは • BakeryにあるLightmapの形式 • 通常のLightmapとは異なり光の方向も保存している L0 L1x L1y L1z L1 L0 SH MonoSH

Slide 3

Slide 3 text

SH、MonoSHとは • 通常のLightmapではできなかったNormal Mapに対応した正確な シェーディングが可能 • ある程度方向の情報が記録されているのでSpecularの計算も疑似的に可能

Slide 4

Slide 4 text

Lightmapが記録する情報 • Lambert(Diffuse)反射は理論的に以下の値として表される • 意味的には「いろんな方向からの光の足し上げ」 න Ω 𝑏𝑎𝑠𝑒𝑐𝑜𝑙𝑜𝑟 𝜋 𝑛 ⋅ 𝜔 𝐿𝑖 𝜔 𝑑𝜔 𝐿𝑖 (𝜔) 𝑛

Slide 5

Slide 5 text

Lightmapが記録する情報 • 定数を抜けば、積分の部分は事前計算可能 • この値をLightmapは持っている 𝑏𝑎𝑠𝑒𝑐𝑜𝑙𝑜𝑟 න Ω 1 𝜋 𝑛 ⋅ 𝜔 𝐿𝑖 𝜔 𝑑𝜔 (厳密ではないけど)放射照度 Irradiance 𝐿𝑖 (𝜔) 𝑛

Slide 6

Slide 6 text

Lightmapの問題点 • 事前計算できるのは法線𝑛を固定しているおかげ • NormalMapなどにより法線𝑛が変わるとLightmapの値は使えなくなる • 指向性が強いライティングとかだと値も大きく変わる 𝐿𝑖 (𝜔) 𝑛′ 𝐿𝑖 (𝜔) 𝑛 ≠

Slide 7

Slide 7 text

Lightmapの問題点 • なのでLightmapあたりの処理ではNormalMapは(多分)対応されない

Slide 8

Slide 8 text

やりたいこと • 法線𝑛が変化しても値がとれる事前計算の形式が欲しい 𝐸 𝜃, 𝜙 = න Ω 1 𝜋 𝑛(𝜃, 𝜙) ⋅ 𝜔 𝐿𝑖 𝜔 𝑑𝜔 𝐿𝑖 (𝜔) 𝑛(𝜃, 𝜙) • テクスチャで保存するとなるとLightmap 1pixelの情報量がすごいことになる • 32*32で保存したとしても32*32*3倍のライトマップが必要になる

Slide 9

Slide 9 text

Spherical Hermonics • 球面調和関数 • 方向を変数とする関数たち

Slide 10

Slide 10 text

Spherical Hermonics • 番号𝑙に対して𝑚 = −𝑙, … , −1,0,1, … , 𝑙の個の 関数がある • 𝑌𝑙 𝑚と表記される 𝑌0 0 𝑌1 1 𝑌1 −1 𝑌2 2 𝑌2 1 𝑌1 0 𝑌2 0 𝑌2 −1 𝑌2 −2 𝑌0 0 𝜃, 𝜙 = 1 4 𝜋 𝑌1 −1 𝜃, 𝜙 = 3 4 𝜋 𝑥 𝑌1 0 𝜃, 𝜙 = 3 4 𝜋 𝑦 𝑌1 1 𝜃, 𝜙 = 3 4 𝜋 𝑧

Slide 11

Slide 11 text

SHの良いところ • 各SHは正規直交している 𝑌𝑙 𝑚, 𝑌 𝑙′ 𝑚′ = 𝛿𝑚𝑚′,𝑙𝑙′ • 方向を引数とする関数𝑓(𝜃, 𝜙)はSHの級数として表現することが出来る • フーリエ級数展開みたいなもの 𝑓 𝜃, 𝜙 = ෍ 𝑙=0 ∞ ෍ 𝑚=−𝑙 𝑙 𝑓𝑙 𝑚𝑌𝑙 𝑚(𝜃, 𝜙)

Slide 12

Slide 12 text

SHの良いところ • この形式は各係数を知っていれば置けば関数を近似できる 𝑓 𝜃, 𝜙 = ෍ 𝑙=0 ∞ ෍ 𝑚=−𝑙 𝑙 𝑓𝑙 𝑚𝑌𝑙 𝑚(𝜃, 𝜙) ≈ 𝑓0 0 𝑌0 0 𝜃, 𝜙 + 𝑓1 −1𝑌1 −1 𝜃, 𝜙 + 𝑓1 0𝑌1 0 𝜃, 𝜙 + ⋯

Slide 13

Slide 13 text

SHの良いところ • この形式は各係数を知っていれば置けば関数を近似できる 𝑓 𝜃, 𝜙 = ෍ 𝑙=0 ∞ ෍ 𝑚=−𝑙 𝑙 𝑓𝑙 𝑚𝑌𝑙 𝑚(𝜃, 𝜙) ≈ 𝑓0 0 𝑌0 0 𝜃, 𝜙 + 𝑓1 −1𝑌1 −1 𝜃, 𝜙 + 𝑓1 0𝑌1 0 𝜃, 𝜙 + ⋯ これらを覚えておけば元の関数を近似できる

Slide 14

Slide 14 text

SH Lightmap • 先ほどの放射照度の関数をSHで近似する手法 𝐸 𝜃, 𝜙 = 𝑓0 0 𝑌0 0 + 𝑓1 −1 𝑌1 −1 + 𝑓1 0𝑌1 0 + 𝑓1 1𝑌1 1 + …

Slide 15

Slide 15 text

SH Lightmap • 先ほどの放射照度の関数をSHで近似する手法 • 実用的には𝑙 = 1までで殆ど近似できる 𝐸 𝜃, 𝜙 ≈ 𝑓0 0 𝑌0 0 + 𝑓1 −1 𝑌1 −1 + 𝑓1 0𝑌1 0 + 𝑓1 1𝑌1 1

Slide 16

Slide 16 text

SH Lightmap • SHの𝑌を展開するとこんな感じ 𝐸 𝜃, 𝜙 ≈ 𝑓0 0 1 4 𝜋 + 𝑓1 −1 3 4 𝜋 𝑥 + 𝑓1 0 3 4 𝜋 𝑦 + 𝑓1 1 3 4 𝜋 𝑧

Slide 17

Slide 17 text

SH Lightmap • SHの𝑌を展開するとこんな感じ • 各定数部分をまとめてL0,L1x,L1y,L1zとする • こうすると僅か4つのパラメーターだけを持って置けばよい 𝐸 𝜃, 𝜙 ≈ 𝐿0 + 𝐿1𝑥 𝑥 + 𝐿1𝑦 𝑦 + 𝐿1𝑧 𝑧

Slide 18

Slide 18 text

SH Lightmap • RGBでそれぞれ必要なので全体としては以下のようになっている 𝐸𝑅 𝜃, 𝜙 ≈ 𝐿0𝑅 + 𝐿1𝑥𝑅 𝑥 + 𝐿1𝑦𝑅 𝑦 + 𝐿1𝑧𝑅 𝑧 𝐸𝐺 𝜃, 𝜙 ≈ 𝐿0𝐺 + 𝐿1𝑥𝐺 𝑥 + 𝐿1𝑦𝐺 𝑦 + 𝐿1𝑧𝐺 𝑧 𝐸𝐵 𝜃, 𝜙 ≈ 𝐿0𝐵 + 𝐿1𝑥𝐵 𝑥 + 𝐿1𝑦𝐵 𝑦 + 𝐿1𝑧𝐵 𝑧

Slide 19

Slide 19 text

SH Lightmap • RGBでそれぞれ必要なので全体としては以下のようになっている • Lightmap 1pixelあたり12パラメーターを持つ必要がある 𝐸𝑅 𝜃, 𝜙 ≈ 𝐿0𝑅 + 𝐿1𝑥𝑅 𝑥 + 𝐿1𝑦𝑅 𝑦 + 𝐿1𝑧𝑅 𝑧 𝐸𝐺 𝜃, 𝜙 ≈ 𝐿0𝐺 + 𝐿1𝑥𝐺 𝑥 + 𝐿1𝑦𝐺 𝑦 + 𝐿1𝑧𝐺 𝑧 𝐸𝐵 𝜃, 𝜙 ≈ 𝐿0𝐵 + 𝐿1𝑥𝐵 𝑥 + 𝐿1𝑦𝐵 𝑦 + 𝐿1𝑧𝐵 𝑧

Slide 20

Slide 20 text

SH Lightmap • Bakeryでは4つのLightmapTextureを用意して各パラメーターを持っている 𝐸𝑅 𝜃, 𝜙 ≈ 𝐿0𝑅 + 𝐿1𝑥𝑅 𝑥 + 𝐿1𝑦𝑅 𝑦 + 𝐿1𝑧𝑅 𝑧 𝐸𝐺 𝜃, 𝜙 ≈ 𝐿0𝐺 + 𝐿1𝑥𝐺 𝑥 + 𝐿1𝑦𝐺 𝑦 + 𝐿1𝑧𝐺 𝑧 𝐸𝐵 𝜃, 𝜙 ≈ 𝐿0𝐵 + 𝐿1𝑥𝐵 𝑥 + 𝐿1𝑦𝐵 𝑦 + 𝐿1𝑧𝐵 𝑧 L0 L1x L1y L1z

Slide 21

Slide 21 text

SH Lightmap • 高々4倍の容量で実現できる 𝐸𝑅 𝜃, 𝜙 ≈ 𝐿0𝑅 + 𝐿1𝑥𝑅 𝑥 + 𝐿1𝑦𝑅 𝑦 + 𝐿1𝑧𝑅 𝑧 𝐸𝐺 𝜃, 𝜙 ≈ 𝐿0𝐺 + 𝐿1𝑥𝐺 𝑥 + 𝐿1𝑦𝐺 𝑦 + 𝐿1𝑧𝐺 𝑧 𝐸𝐵 𝜃, 𝜙 ≈ 𝐿0𝐵 + 𝐿1𝑥𝐵 𝑥 + 𝐿1𝑦𝐵 𝑦 + 𝐿1𝑧𝐵 𝑧 L0 L1x L1y L1z

Slide 22

Slide 22 text

SHありなし比較

Slide 23

Slide 23 text

MonoSH • SH Lightmapは4倍の容量で済むと言っても重い • 容量を減らすため、L1についてRGBで同じ値を使ったも • Bakery独自の形式? L1 L0

Slide 24

Slide 24 text

MonoSH • 式的にはこんな感じ L1 L0 𝐸𝑅 𝜃, 𝜙 ≈ 𝐿0𝑅 𝐸𝐺 𝜃, 𝜙 ≈ 𝐿0𝐺 𝐸𝐵 𝜃, 𝜙 ≈ 𝐿0𝐵 +𝐿1𝑥 𝑥 + 𝐿1𝑦 𝑦 + 𝐿1𝑧 𝑧

Slide 25

Slide 25 text

SHとMonoSHの差異 • SHはRGBでL1を記録している • MonoSHはGrayScaleでL1を記録している • SHはMonoSHの上位互換としての立ち位置 L0 L1x L1y L1z L1 L0 SH MonoSH

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

SHとMonoSHの差異 • MonoSHだと色の変化が激しいとちょっと鮮やかさが失われる • 煌びやかなワールドとかだとちょっと気になるかも? • 遠目だと正直よくわからない

Slide 29

Slide 29 text

SH Lightmapの実装 • BakeryのDirectional modeをSHに • ~_L0,~L1x,~L1y,~L1zの4つのライトマップが生成される ~_L0 ~L1x ~L1y ~L1z

Slide 30

Slide 30 text

SH Lightmapの実装 • BakeryのSH Lightmapは Frostbiteの実装を基に制作

Slide 31

Slide 31 text

SH Lightmapの実装 • SH Lightmapの値を計算する処理は右図

Slide 32

Slide 32 text

SH Lightmapの実装 • SH Lightmapの値を計算する処理は右図 • L0はunity_Lightmapとして送られる ~_L0 unity_Lightmap

Slide 33

Slide 33 text

SH Lightmapの実装 • L1は_RNMという名前でBakeryから送ら れる ~L1x ~L1y ~L1z _RNM1 _RNM0 _RNM2

Slide 34

Slide 34 text

SH Lightmapの実装 • 各LightmapからL0,L1x,L1y,L1zを取得 する • 正規化されてたりするので復元する処理 が書かれている • この辺の式はBakeryのテクスチャ仕様だ と思われる

Slide 35

Slide 35 text

SH Lightmapの実装 • Normalの(x,y,z)座標を使って対応するSH を計算 • それをDiffuseの値として扱う

Slide 36

Slide 36 text

Non Liner SH • L1だとやっぱり精度がちょっと悪い • 指向性が極端なライティングだとおかしくなる場合がある • (LightProbeでも同様の現象がある)

Slide 37

Slide 37 text

Non Liner SH • その影響を防ぐ補正をGeometricsがCEDEC2015で発表(資料はもう消えていて、 webアーカイブでしか残ってないので注意) • 結構いい感じにしてくれる

Slide 38

Slide 38 text

Non Liner SH • 実装ではここに相当 • shEvaluateDiffuseL1Geometricsという 関数を使う

Slide 39

Slide 39 text

Non Liner SH

Slide 40

Slide 40 text

Non Liner SH

Slide 41

Slide 41 text

Non Liner SH • 陰影が分かりやすくなり、かなりいい感じになる • 基本的に入れた方がいいと思う

Slide 42

Slide 42 text

MonoSHの実装 • SHの計算は同様 • L1のライトマップはunity_LightmapIndに 渡されている • RGBがL1x,L1y,L1zに相当する L1 Unity_LightmapInd

Slide 43

Slide 43 text

Diffuseの計算 • SHの値が計算できたらbasecolorをかければ、Diffuse反射の値になる 𝐷𝑖𝑓𝑓𝑢𝑠𝑒 = 𝑏𝑎𝑠𝑒𝑐𝑜𝑙𝑜𝑟 ∗ 𝑆𝐻

Slide 44

Slide 44 text

Approximate Specular • ある程度は光の方向を記録しているのでSHから疑似的にSpecular反射も計算 できる • ちょっと時間が足りなかったので割愛

Slide 45

Slide 45 text

参考、引用文献 • Bakery Wiki • https://geom.io/bakery/wiki/index.php?title=Manual#Render_mode • Global Illumination in Frostbite • https://media.contentapi.ea.com/content/dam/eacom/frostbite/files/gdc2018- precomputedgiobalilluminationinfrostbite.pdf