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の明るさ倍率の関係


2016年5月9日月曜日

UEカメラ露光量

久しぶりにUE4を調査。
UEライト関連調査の続き。 ライト関連を調査 UEライト関連調査

今回はカメラ露出について。
カメラの露出調整ができるのかと、できた場合のカメラEV値をどのように調整すればよいかを調べた

目的

pbrは本来、ライトの入力やカメラの光量の設定までを一貫して正しい値にするべき、
そのほうが作りやすいし、破綻も起きづらい。(特に室内と日中の屋外が共存するようなシーン等)

ゲーム業界ではそこまで考慮しているケースは少ないと思う。
メンタルレイやVray等のレンダラーではこの辺は問題ないがunityやUE4ではあまり考慮されていない感じなので調べたい

結果

下記の4点を守ればライトの単位を正しく設定できそうなことがわかった
  • ポイントライトのIntensityはルーメンそのもの。600ルーメンのライトならIntensityに600と入れる
  • 平行光源はルクス換算で1/50の値を入れる。Intensityは1/50の値を入れる。10万ルクスならIntensityに2000と入れる
  • 自己発光のエミッシブカラーは輝度換算で1/50の値を入れる。200[cd/㎡]ならエミッシブカラーは4.0と入れる
  • 実際のカメラと6EVのずれがあり、値もプラスマイナスが逆。14EVで撮影しようとするとUE4では-8EVと入れる。ue4EV = -(EV-6)

調査方法

単位は光束(lumen)で定義することになっているのでこれをベースにして調査する

ポイントライトについては前回調べたときに距離減衰が正しく行われていたことがわかったため、
例えば12.56ルーメンの場合1m先の板に1ルクス当たっているとみなすことができる

前回調べたときは約2000ルーメンのポイントライトにして、1m先の真っ白な板を真上から見たときの中心が1.0となった。
正確には1950ルーメン位だったが2000ルーメンとして取り扱うことにする。

このような設定で調べた
  • このときポストフィルタは全部無効にしたつもり。
  • マテリアルのカラーは単純なランバートがわからなかったのでなるべくランバートに近い状態にした
  • カメラ露出は0で固定
       


この状況で2000ルーメンを照度に置きかえると約160ルクス。2000ルーメン/(4π) より。

本来はカメラのEV0は「シャッター速度1.0秒」「絞りF1.0」の露光量に相当する。
またこの露光量は2.5ルクスを撮影する条件としている。

一方UE4のデフォルトのカメラ露出とでは64倍のずれがあることになる。160/2.5 より
ということはEV換算で6EVずれているということ。log(64,2)より

露出表
 ここがわかりやすい → 写真の明るさの概念 (1) : 因画応報

平行光源
 ちなみに真上からの平行光源の強度は3.14で1.0になったためそのままルクスとしてよい。(輝度[cd/㎡] = 照度[lux]/π= 3.14/π = 1.0)
ただしこの1.0は160ルクス相当なので実際のずれは約50倍となる。160/3.14

なので日中の平行光源を10万ルクスとするとらいとのIntensityは2000の値を入れることになる
emissive
 自己発光のエミッシブカラーは1.0を入れると1.0となる。これは正面から160ルクスのライトが当たった真っ白な板と同じ輝度であることから、
約50[cd/㎡]となる 160/πより

例えば200[cd/㎡]のTVの画面の輝度を設定する場合はエミッシブカラーに4.0と入れればよいことになる
カメラ露出
 カメラの露出調整はマニュアルで設定する方法が良くわからないがとりあえずできそうな方法があった。
ただしトーンマップを有効にするためフィルミック調なカーブがかかってしまう(ほかに良い方法があるのかもしれないが...)
下の画像は太陽光10万ルクスにして、14EVで撮影したものと同等

100000Lux = Intensity: 2000          14EV = ExposureBias:-8



 


2016年1月27日水曜日

RGB色空間の色域の比較

物体色の色域が判ったので幾つかのRGB空間で物体色をどれだけカバーできているかを比較する

RGB色空間はどの色を3色選ぶかで色域が決まる。
ディスプレイで表示できる規格とそうでないものが在る。
sRGB、AdobeRGB、rec2020 等は物理的に表示が可能な色空間。
ProphotoRGB、ACES(ap0,ap1)、XYZ等は現実には存在しない架空の色を扱っているので主にデータを扱うためのもの。

色域比較

xyY座標とL*a*b*座標での比較。
色域の広さに関して見る場合はL*a*b*のほうが良い
物体色の限界は点線で表し、着色はrec.2020で統一した

sRGB vs rec.2020

ディスプレイの色空間で色域が狭いsRGBと広いrec.2020(UHDTVの規格)の比較。
左がxyY座標、右がL*a*b*座標

sRGBとrec2020では大きさの違いからも差が大きいことがわかるが、彩度の違いも見た目で分かる

他の色空間

クリックでgifアニメ

xyYL*a*b*
sRGB
adobeRGB
cieRGB
rec.2020
ACES ap1
ACES ap0
XYZ



2016年1月24日日曜日

MacAdam limits 物体色の色域


  • 物体色の色域は最適化色立体(Macadam Limits)で定義されている。
  • 理解を深めるために最適化色立体を自分で作成する。
  • 最適化色立体を均等色空間の一つであるL*a*b*空間で表示し、ディスプレイカラーの色空間と比較することで、実際の物体色に対してのカバー率を視覚的に見たい

物体色と光源色

光源色は 光源そのものの色のこと。
光源色は光源の分光分布と目の感度を掛けることで色が求まる
  • XYZ = 光源の分光分布 * XYZ等色関数
物体色は光源に照らされた物体の色のことでライトの色が変われば物の色も変わる。
物体色は光源の分光分布と物体の分光反射率と目の感度を掛けることで色が求まる
  • XYZ = 光源の分光分布 * 物体の分光反射率 * XYZ等色関数
但し人には色の恒常性があり、光源色を打ち消した物体本来の色を感じられる。そのためさらにホワイトバランスを適用して光源色を打ち消した色を求めることが多い
物体色は光源色と違い、明るさに制限があり明るくなるほど彩度が無くなり白になっていく。

最適化色立体(Macadam Limits)の作成

一番鮮やかになるであろう分光反射率のパターンに光源の分光分布を掛け合わせたものをプロットするという手法。
鮮やかになる理想な分光反射率は凸型と凹型となる。
その凹凸位置と幅を変えたものを全パターン用意してプロットする。(現実にそんな切り立った分光反射があるかどうかは怪しいけれども..)
380~780nmまでの分光反射のパターンを1nm間隔で用意して光源の分光分布と掛け合わせxyY座標の値を求め、さらに明るさYを分割して、その明るさに近いものを選んでプロットする

参考資料
Estimation of the Device Gamut of a Digital Camera in Raw Performance Using Optimal Color-Stimuli 

プロット結果
  • xyY座標でプロット
  • 380-780nmまでの波長を扱う
  • 5nmの8分の1の単位でポイントを打った(総ポイント数は約20万)
  • D65光源を使用(分光分布の元データは5nmステップのものなので線形で8倍にした)
  • Yの分割は0.1~0.9までを0.1ステップ。ほかに0.01と0.98を選んだ
  • 0.002~0.003位の高さを許容してポイントを選びYの値を同じにした
  • ポイントの色はrec.2020(D65)の色空間で着色
  • Yに対してほぼ等間隔にスライスしているが人の感じる等間隔の明るさとは違うことに注意

  • L*a*b*座標でプロット
  • 明度指数L*に対して10~90までを10ステップの他に4と98を選んだ
  • 明度指数L*は人の明るさの感じ方に近い
  • a*b* の色相環みたいな部分の見た目もxy座標よりも人の感覚に近い

Macadam Limitsの作成過程をわかり易く説明

分光反射のパターンの作成からxyY座標にプロットするまでの流れを理解しやすいようにアニメーションを作成
  • 上図は分光分布のパターンをすべてをプロットしていく様子(5nm単位で粗くしている)
  • 下記はわかり易くするために光源の分光分布は掛け合わせていないがE光源(全波長がフラットな光源)で照明したと考えても良い。
  • 凸型のほうは青から赤に変化していくが徐々に彩度がなくなる
  • 凹型のほうは赤と青を繋ぐ紫色が強くなっていく
これをもっと細かいステップ(今回は0.625nmステップ)でプロットし、その後Yが一定となるものを選べばプロット結果となる。

単色のスペクトルが白になっていく軌跡

こちらは青から赤までの単色光スペクトルの幅を増やして白に近づいていく軌跡を表したもの(光源はD65を使用)

白に向かって直線的に遷移するわけでもないみたい。
黄緑と青の付近はかなり直線的に白に向かっているが赤紫はとても歪んでいる。
黄色は彩度が高いが白とほぼ同じ明るさを直前までキープできている


光源を変えた時の変化の様子

 ポイントの着色はrec.2020(D65)固定

D光源は昼光で青空と太陽光を含んだスペクトル
A光源は白熱灯で赤味が強いが連続したスペクトル
E光源はすべてフラットで反射の色がそのまま返ってくる
F光源は蛍光灯で特定の波長が強い、その為色の再現性は他と比べると低くなる。
それにしてもF11光源の結果が歪みすぎている。本当にあっているのかな?

ディスプレイカラースペースとの比較

後日調査