2016年7月3日日曜日

unity リニアワークフロー

前に少しだけunity触ったときになんとなくリニアワークフローが正しくないとおもいつつスルーしてたが、
今日改めて調べたらやはり注意すべき問題があることがわかった。バグかもしれないが運用で回避することが可能

通常のリニアワークフローではカラーテクスチャ等の見た目で作ったテクスチャはシェーダー内でデガンマされたリニア値で取り扱われる。
RGB等の数値の場合はもともとリニア値として使われるのが普通だが、Uniytyの場合はその数値もデガンマしている。
また1.0以上の値を持つことができるインテンシティも含めてデガンマされていることはかなり特殊な仕様だと思う
物理ベースの入力値を使う場合は注意が必要。

このあたりはマニュアルにも書いていなさそう。
というかUE4も含めて一般的なゲームエンジンでは入力値に関して物理ベースで正しく扱う気が無いように感じる。
UE4はテクスチャ以外の入力値はリニアとして処理されているがライト入力に関しては物理的な単位についてあまり明確な設定方法が記載されていない

リニアワークフローの設定方法


リニアワークフローの比較

ディフューズは0.5にし、ライトの強度を変えたものの比較
light_Intensity0.250.5124
unityのLWF
通常のLWF
unityのマテリアルは今回はLegacyShadersのDiffuseを使ったがStandardでも同じ傾向になる

unityでは0.25では暗すぎ4.0では明るすぎるため、一見するとLWFができていないように感じるが、
そうではなくシェーディングに注目するとLWFはできていることがわかる。
こうなってしまうのはテクスチャ以外の入力値もデガンマされているからで、リニアワークフローに設定したら入力値が2.2乗されると考えてよい。
なのでライトのintensityが4.0の場合、実際は21.1のライトが当たっているということ
また、ライトのintensityが0.25の場合、実際は0.047のライトが当たっているということ

実際のライト強度 = pow(unityIntensity , 2.2)

例えばライトの明るさを16にしたい場合はunityでは
unityIntensity = pow(16 , 1/2.2) となり、3.53を入れればよいということになる

またマテリアルの数値にも同じことがいえる
上記のマテリアルのカラー値 128/255 で約0.5だが、実際の値は0.22となっている
この処理はsRGBテクスチャの場合にはデガンマ処理で行われるが数値に対しても行われているということ

実際のカラー値 = pow(rgb , 2.2)

例えば反射率0.18のグレーを入力したい場合はテクスチャと同様に0.46を入れればよいということ

デフォルトでテクスチャ以外の入力値に対してもデガンマされる処理は自分が知る限りUnityが初めて。(ほかにもあるかもしれないけど)

unity内部のデガンマ処理がガンマ2.2なのかsRGBなのかはまだ調べていない。

調整例比較

ディフューズ0.1。平行光源の強度4.0の見え方が同じになるように調節した例。
理論値としては一番明るい部分は0.4となりガンマ2.2の補正が入るとしたらモニタ上では0.66 (168/255) となる

mayaはカラーマネジメントを有効にしてガンマ2.2を基準としたリニアワークフローに設定したもの。
また、もう一つのmayaの例は値の設定をディスプレイスペースにすることでunityと同じ感覚できることを検証したもの。

画像 ランバート設定 ライト設定RGB
unityのLWF
RGB = (1,1,1)
mayaのLWF
RGB = (1,1,1)
mayaのLWF
別タイプ

(unityと同じ値)

↓rgb側に含める強度はunitiyと同じ強度

このようにmayaのカラー入力でdisplaySpaceを使えば同じことができるがdisplaySpaceのカラー値でインテンシティの領域まで扱う方法はあまり一般的ではないと思う

物理的な明るさの倍率とunityiの明るさ倍率の関係


0 件のコメント:

コメントを投稿