リニアワークフロー入門 簡単な説明とその意義

リニアワークフローの基本的な説明とそれを使う意義についてまとめました。

はじめに

本記事ではリニアワークフローの説明とそれを使う意義についてまとめます。

内容に関してはゲームエンジンを用いてシェーダで色を取り扱う上で必要な知識を簡潔に得ることを目的としています。
そのため、不要な知識については敢えて説明を省略していますのでご承知ください。

あなたが見ているグレーはグレーじゃない

さて下図は左端に黒、右端に白を置いたPhotoshopのグラデーション編集ツールをキャプチャしたものです。
黒の明るさを0、白の明るさを1とすると、中央は0.5のグレーに見えます。

f:id:halya_11:20200210231541p:plain:w450

この「中央が0.5のグレーに見える」というのは感覚としては正しいです。
しかし実は、光学的なエネルギー量(輝度)としてはこのグレーは白の約22%の強さの光しか発していません。
つまりエネルギー量としては中央は約0.22のグレーということになります。

f:id:halya_11:20200210232617p:plain:w450

ではなぜ0.22のエネルギーしか持たないグレーを人間は0.5のグレーと感じるのでしょうか?
これは人間の目が実際のエネルギー量よりもより明るく知覚する性質を持つためです。

f:id:halya_11:20200212185427p:plain:w450
※この図は厳密には不正確です(補足参照)

上図を見ると、0.22のエネルギーを持つ色を人間は0.5のグレーとして知覚しています。
このように、人間が知覚している50%グレーは実はエネルギー量としては50%ではありません。

ガンマワークフローは色を見た目のまま取り扱う

さて前節の通り、人の目に見える中間グレーはエネルギー量としては約0.22しかありません。
それではシェーダで中間グレーを取り扱う際には0.22として扱うべきでしょうか?
それとも0.5として扱うべきでしょうか?

実はこれがリニアワークフローを使う理由となります。

まず、リニアじゃないワークフロー(本記事ではUnityマニュアルに従いガンマワークフローと呼びます)では、
中間グレーを0.5として、つまり見た目のまま取り扱います。
この場合、中間グレーは0.5として取り扱われるので、グレーとグレーを加算すれば1、つまり白になります。

f:id:halya_11:20200212190420p:plain

このようにガンマワークフローは見た目のまま色を取り扱う直感的なワークフローであるといえます。

リニアワークフローは色を物理的なエネルギー量として取り扱う

一方、リニアワークフローでは中間グレーを0.22として取り扱います。
この場合、グレーを足し合わせても白にはならず、0.44の明るいグレーにしかなりません。

f:id:halya_11:20200212190509p:plain

これは直感的ではないように感じますが、中間グレーの持つエネルギー量は0.22なので、物理的にはこちらの方が正しいです。
そしてこの正しさは、物理ベースレンダリング(PBR)を行うときに重要になります。

PBRでは色を物理的なエネルギー量として取り扱い、物理的な根拠に基づいた色計算を行います。
入出力される値は以下の記事にまとめているような物理的な単位を持つ値です。

light11.hatenadiary.com

したがって、中間グレーはエネルギーを表す値である0.22として取り扱わなければ正確な計算結果は得られません。
そのためリニアワークフローでは、入力値をシェーダに渡す際に、0.5の中間グレーを0.22に変換する処理を行います。

このようにして色を物理的に正確な値として扱うワークフローがリニアワークフローです。

用語の説明

さてここまでなるべく難しい用語を使わずに解説しましたのでここで用語をまとめておきます。

用語 説明
sRGB色空間 人間の知覚する明るさに基づいた色空間。
中間グレーを0.5として取り扱う。
※厳密な説明ではないです
リニア色空間 物理的なエネルギー量に基づいた色空間。
中間グレーを0.22として取り扱う。
ガンマ補正 リニア色空間の値をsRGB色空間の値に変換すること。
つまり中間グレーを0.22 -> 0.5に変換すること。
デガンマ
リニアライズ
sRGB色空間の値をリニア色空間の値に変換すること。
つまり中間グレーを0.5 -> 0.22に変換すること。

Unityにおける設定

UnityではPlayer SettingsのOther SettingsからColor Spaceを選択できます。
デフォルトはGammaになっており、これをLinearに変えることでリニアワークフローの設定になります。

f:id:halya_11:20200212170507p:plain

Linaer設定にするとシェーダに渡される色は自動的にリニアライズされます。
つまり0.5のグレーを設定するとシェーダ内では約0.22として取り扱われます。
この挙動については以下の記事で実際に検証していますので参考にしてください。

light11.hatenadiary.com

補足: ディスプレイガンマについて

理解がややこしくなるので本記事では補足という扱いにしますが、ディスプレイにはディスプレイガンマという性質が存在します。
これは「ディスプレイに表示する際には受け取った値を約2.2乗した値が出力される」という性質です。

この性質により、ガンマのワークフローではシェーダで0.5のグレーとして出力した結果がディスプレイ表示時に0.22となり、
さらにこれが前述の人間の目の性質により50%グレーとして知覚されます。

一方リニアワークフローではディスプレイ出力前にガンマ補正を掛ける必要があります。
ただしこれはゲームエンジン側でやってくれるので、シェーダを書く上では意識する必要がありません。
このような理由から本記事では解説を省略しています。

補足: 人間の知覚する中間グレーについて

本記事では人間は22%のエネルギーを持つグレーを中間グレーと知覚すると説明しました。
しかしこの値は説明の簡易化のための、ディスプレイガンマに合わせた値です。

厳密には人間が中間グレーとして知覚する値は22%グレーではありません。
以下の記事よると、18%の反射率を中間グレーと感じるようです。

technorgb.blogspot.com

ただしこれもシェーダを書く上では特に意識する必要はないことなので、簡単な説明に留めています。

関連する記事

最後に本ブログにおいてリニアワークフローに関連する記事をまとめておきます。

light11.hatenadiary.com

light11.hatenadiary.com

light11.hatenadiary.com

light11.hatenadiary.com

参考

docs.unity3d.com