"[非公式] Unite Tokyo 2019 Eve2 LT Fes" (2019/9/23) で登壇しました

UniteEve2 で登壇させていただきました。

発表資料

めちゃくちゃ充実した会でとてもよかったです。時間的にはものすごい長いはずだったのですが、あっという間の感じでした。

発表のフォローなど

また発表やらかしてしまったなあと・・・ 結構削ったのですが、これ以上になると章単位で丸ごとになりそうだったのですがそれくらい削ってもよかったかなあと思いました。途中またテンパってしまってしまいましたし。

今回の発表に向けていろいろ検証しましたが、削ったりテンパったりでうまく伝えられていないところも多々あると思いますので、その辺りを書いていきたいと思います。

せっかくなので一部再検証しました。

Unity AOV Recorder

AOV は "Arbitrary Output Variable" の略だそうです。

Deferred Rendering に使用する GBuffer の各レンダリング結果をそのまま出力して、後段の Compositor の素材とするためのものですが、 Unite Tokyo 2019 の映像制作系のセッションではどれもコンポジット含めた最終レンダリングまでを Unity で完結させる話ばかりで「あれー」と思わなくもありませんでしたが技術的には新規性のある話ではないのでまあそれはそうなのかもしれません。

色化け問題 (明るさ)

アルファキャプチャ問題はバグとしか思えないのですが、明るさの件は (Texture Sampling モードを考えると若干一貫性に欠けますが) まあ概ね "仕様" と言い切っても差し支えのない挙動かなとは思います。

発表では時間の兼ね合いもあったので理屈抜きでざっくりとした説明だけになってしまいましたが、検証結果を整理してもう少し詳しく説明したいと思います。

↑ Gamma / Linear についての解説で個人的に一番わかりやすい解説記事だったのでお勧めです。

検証は数値的に Linear に遷移するグラデーションを Shader で記述し、そのレンダリング結果を Unity Recorder で様々な設定の組み合わせでキャプチャしたものを別のアプリで解析したものを見て行いました。

基本的に画像ファイルの Color Space は PNG は Gamma (sRGB) 、 EXR は Linear なので、Project Settings と画像ファイルの Color Space が一致すればグラフは Linear になるはずです (数値的に Linear グラデーションになるようにしているから) 。

Color Space Capture Format グラフ Result
1 Gamma Game View PNG (a) OK
2 EXR (a) NG
3 Render Texture PNG (a) OK
4 EXR (a) NG
5 Texture Sampling PNG (a) OK
6 EXR (a) NG
7 Linear Game View PNG (b) OK
8 EXR (b) NG
9 Render Texture PNG (a) NG
10 EXR (a) OK
11 Texture Sampling PNG (b) OK
12 EXR (a) OK

f:id:tan-y:20191005100007p:plain
(a) Linear
f:id:tan-y:20191005100120p:plain
(b) Gamma Correction
f:id:tan-y:20191005100258p:plain
(c) Display Gamma

  • 1, 3, 5, 10, 12 は入出力の色空間が一致していてグラフが Linear になっているので理解しやすいと思います。
  • 2, 4, 6 は Display Gamma のグラフにならないとおかしいです。
  • 7, 11 は Linear 空間の映像を Gamma 空間の PNG に書き出すので Gamma Correct のグラフになります。 9 は Linear のままなのでおかしい。
  • 8 は入出力の色空間が一致しているので Linear グラフになっていないとおかしいのに Gamma Correct になっています。これは補正が二重がけになるので非常に明るくなってしまっています。

上記から、おそらく次のような理屈に基づいて Unity Recorder では処理がされていると思われます。

  • Game View, Targeted Camera などはディスプレイに表示する映像を想定しているので "Gamma" 空間で出力する
    • Project Settings が Gamma ならそのまま出力し、 Linear ならガンマ補正をして出力する
  • Render Texture Assets は内部処理結果なのでそのまま出力する
  • 出力先ファイルフォーマットの色空間は考慮しない

"Texture Sampling" は問題ないかと思ったら Gamma EXR がダメでしたね (LT 発表時は未確認でした) 。

色化け問題 (色合い)

色空間には本来はいろいろな定義があり、 Gamma / Linear もその一部でしかありません。このうち Unity Recorder の Movie Recorder で発生する色化けは Unity では出て来ない "YUV 色空間" 問題です。

H.264 などのビデオコーデックは一般的には YUV という色空間にしてからエンコードします。その際の RGB - YUV 間の色空間変換の計算式 (変換マトリックス) にいくつか種類があります。エンコードされたビデオストリームにはヘッダーにどの変換マトリックスを用いているのか記録されていますが、ヘッダーに書かれている情報と実際に使われているものが異なっています。

具体的には HD 解像度では BT.709 、 SD 解像度では BT.601 (SMPTE 170M) で計算されていますがヘッダーにはどちらも BT.709 となっています。この挙動は割と想像がつきます (SD 解像度は BT.601 が標準なので、エンコーダーが解像度に応じてマトリックスを変える) 。

f:id:tan-y:20191006234714p:plain
H.264 480p
f:id:tan-y:20191006234717p:plain
H.264 1080p

ちょっとこれだと区別が付きにくいですが、下の 1080p の方は正しいです。グラデーションの右側の部分をスポイトで取得してみると確認できると思います。

元色(R,G,B) 480p 1080p
(1.0, 0.0, 0.0) (255, 25, 0) (255, 1, 0)
(0.0, 1.0, 0.0) (0, 215, 0) (0, 255, 0)
(0.0, 0.0, 1.0) (0, 14, 255) (1, 0, 255)

480p は誤差で済まない値になっています。

試した限りでは 720p 付近が境界っぽいので 1080p にしておけば間違いはないと思いますが、 Unity Recorder の Movie Recorder でのエンコードしながらのキャプチャーはパラメーター設定も細かくできないため画質面から元々あまりお勧めできません。この件に関わらず連番静止画でキャプチャーしてから別途エンコードした方がよいかと思います。