フォトリアルCGの為に、実物のカメラについて調べてみた

近年、リアルタイムCGでは物理ベースマテリアル”が普及してきましたが、これだけでは所謂フォトリアルな表現を作る事は難しく、質感と同様にカメラ、ライトにも物理的な挙動が加わり、はじめてフォトリアルになるのではと考えました。
そこで今回はまず、現実のカメラの挙動をCGに落とし込む方法を調べてみました。


#カメラと写真とCGの関係
私はプロのカメラマンではなく、写真を撮る際に表現(コントロール）したいと思う事もそれほど多くはありません。自分が写真を撮る時には以下のような項目を意識しています。多くの方もこんな感じではないでしょうか？
**・ピントがどこにあっているか
・どのぐらいの画角で撮るか
・被写界深度の深さ(ボケが強いか弱いか)
・手ブレ、被写体ブレの強さ
・画質(ノイズ、解像度)
・写真全体の明るさ**

これらはCGの技術に置き換えるとこんな感じだと思います。

**・Angle of View**　(どのぐらいの画角で撮るか)
**・Depth of Field**　(ピントがどこにあっているか＆被写界深度の深さ)
**・Motion Blur**　　(手ブレ、被写体ブレの強さ)
**・Tone Mapping**　(写真全体の明るさ)
・Render Quality　(画質)　※今回はテーマから除外



そして実際に写真を撮る際カメラでは以下のような項目を調整します。これはカメラのボディやレンズの物理的な交換または、それらに付属する調整箇所(ボタンやダイヤル)を操作します。

|調整箇所|効果|
|:---:|:--------:|
|**レンズ**|レンズの**焦点距離**によって**画角**が変わる。**開放F値**によって**絞りの上限**が決まる。|
|**ボディ**|使われている画像素子の大きさによって**画角**が変わる**※**|
|**ISO感度**|同じ光量の場合、感度が高いほど**明るく写る**が、その分ノイズが増える。|
|**フォーカス**|ピントの合う距離。距離が短い程**被写界深度**が浅くなる。|
|**絞り**|レンズに光を取り入れる穴の大きさ。大きい程**明るく写り**、**被写界深度**が浅くなる。|
|**シャッター速度**|シャッターが開いて閉じる時間。長いほど**明るく写る**が**被写体ブレ**や**手ブレ**が強く出る。|

このように多くの調整箇所は、特定の項目に作用すると同時にカメラに光が入ってくる量**(入光量)**にも影響を与えます。写真としてちょうどよく現像する光の量**(適正露出)**は決まっており、これを越えると真っ白、下回ると真っ黒な写真になってしまうので、一つの項目で入光量が増えた場合には他の項目で量を減らす調整をします。また、そもそも夜のように外の光量が少ない場合は、いろいろな項目で最大限に光を取り込むように調整して適正露出に近づくようにしますが、その結果自由に表現できる幅はぐっと狭くなります。
この**差し引きのバランス、不自由さ**をCGで再現する事がリアリティに繋がるのでは、というのが今回の動機です。

続いて各項目が、実物のカメラの設定でどのように変化するかを調べてみます。

#Angle of View
Angle of Viewは、実際のカメラと同じく画角という考え方でCGでも馴染みの深いパラメータです。
しかしCGでは**角度(°)**で扱っている画角は、実物のカメラでは**レンズの焦点距離(mm)**で表現されますので変換が必要になります。加えてボディの**画像素子の大きさ(センサーサイズ)**によって補正も掛かるので、それも考慮する必要がありそうです。さらに面倒な事に、画像素子は縦横の長さが違う事が普通なので、**縦・横・対角**のどの長さを基準にするかも決める(CGツールの挙動から探る)事が必要となります。
まず一般的なセンサーの水平、垂直、対角のサイズは規格があるので参照できます。

|センサー|水平サイズ|垂直サイズ|対角サイズ|
|:---:|:---:|:---:|:---:|
|**35mmフルサイズ**|36mm|24mm|43.27mm|
|**APS-C**|23.4mm|16.7mm|28.75mm|
|**フォーサーズ**|17.3mm|13mm|21.64mm|

次にレンズの**焦点距離(㎜)**と**センサーサイズ(㎜)**から、下の式で**画角(°)**を求める事ができます。
　
　**画角° = 2×atan(センサーサイズ / (2 × 焦点距離))**
#Motion Blur
Motion Blurは、多くの場合ポストプロセスによって実装され、CGでの調整項目はあまり多くない印象です。
実際のカメラでは**シャッター速度(秒)**によって調整をします。これはシャッターボタンを押した後、シャッターが開いて閉じるまでの時間の長さであり、この時間内に動いた量が手ブレ、被写体ブレになります。
CGでもパラメータにはそのままシャッター速度が使われる事が多く、その場合は同じ数値が渡せますが、稀にフレームレート換算の場合もあるのでその際は、**シャッター速度 × フレームレート**　とする必要がありそうです。
またビデオカメラを想定した場合、パラメータはシャッター速度ではなく**シャッター角度**になります。
シャッター速度とシャッター角度は以下の式で変換可能です。

**シャッター角度 ＝ シャッター速度 * 360 * フレームレート**

#Depth of Field
Depth of Fieldはいわゆる被写界深度として、ポストプロセスで実装されることが多いです。
扱われるパラメータはまちまちですが、ほぼ必ず存在するのは**カメラからピントが合う場所までの距離**と**ボケの強さ**の指定です。ただDoFは他と比べて考え方がやや複雑で、実装が現実に即していない場合もあるのでより理解が難しく感じました。まずは段階的に、実物のカメラでのボケの量を考える際に用いる**合焦距離**と**F値**、**許容錯乱円**について調べてみます。
###合焦距離
合焦距離は最初に書いたとおり**カメラからピントが合う場所までの距離**です。
CGでは**注視点とカメラとの距離**を測定する事で得られますが、DoFの計算では単位を㎜に揃えるので、ツール内の単位スケールから㎜への換算が必要になります。

###F値
F値は**レンズを通る光量を表す単位**です。
実物のカメラでは、レンズによって最大でどのぐらいの光量が通れるかを示す**開放F値**が決まっており、その最大値から**絞り**を使って光量を減らす方向に調整する事ができます。ボケの大きさはこの光量に比例するため、絞りを強くする(F値を上げる)事によって被写界深度を深く(ボケを少なく)することができます。

###許容錯乱円
許容錯乱円はあまり耳慣れない用語です。これを理解するにはまず**錯乱円**について知る事が必要でした。
本来、実物のカメラにおいて完全にピントが合っている距離というのは1点のみであり、それ以外の場所では多少はあっても絵はボケています。このボケの大きさを示す数値が**錯乱円(㎜)**です。錯乱円はフォーカス位置で1点であるものが別の距離でどのぐらい大きな円(ボケ)になるか、という値になります。
その上で、感覚的にこのぐらい小さな錯乱円であれば実質ボケてないと言えるだろうという値が**許容錯乱円**であり、通常は固定値で**0.02～0.03ｍｍ**が設定されています。

###そして被写界深度を理解する
上記を前提に改めて考えてみると、被写界深度とは**"合掌距離前後の、錯乱円が許容錯乱円に収まっている範囲"**の事だという事がわかります。よってこの範囲を求める事でボケの強さがわかるのですが、計算するためにはもう一つ、**過焦点距離**という値が必要です。過焦点距離とは**計算上無限遠が許容錯乱円に収まる合焦距離**の事で、以下の式で求められます。

　**過焦点距離 = レンズの焦点距離^2 / 許容錯乱円 / F値**

そして過焦点距離がわかれば、そこからフォーカス位置前後の被写界深度を求める事ができます。
　**前側深度 = 過焦点距離 × 合焦距離 / (過焦点距離 + 合焦距離)
　後側深度 = 過焦点距離 × 合焦距離 / (過焦点距離 - 合焦距離)** 

ここまでで一通り、被写界深度について数値的な理解をしたつもりですが、結局のところはCGツールが何をパラメータにしているかによって入力する値は異なるので、ここまで人力で計算する必要はないと思います。

#Tone Mapping
DoFで息切れしそうですが、やっとTone Mappingです。
Tone Mappingもやはりポストプロセスですが、他の要素よりももう一段本質的なものだと感じます。意味合いとしてはHDRでレンダリングされた結果を表示出来る輝度レンジに収める為の処理となりますが、これは実物のカメラで光量を適正露出に収める行為に近いです。なのでこのTone Mappingの結果が、今まで他プロセスで扱ってきた値の影響によって決定する事で物理的な挙動を持つカメラになるのではないかと思います。
入光量に関わるものは**F値**と**シャッター速度**なので、まずはこの2つの値を明るさに変換して入光量を求め、その後**ISO感度**の設定によって入光量に対する発色の補正を行います。

###シャッター速度とF値から入光量を求める
シャッター速度と入光量の関係は、1秒間の入光量を基準(0)とし、**”段”**で表現されます。
シャッター速度が1段上がると、入光量はその前段の半分の量となり、逆に1段下がると入光量は倍になります。この段数を**TV(Time Value)**と呼び、シャッター速度(秒)と以下のように対応します。

|段(TV)|-3|-2|-1|0|1|2|3|4|5|6|7|
|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
|秒|8|4|2|1|1/2|1/4|1/8|1/16|1/32|1/64|1/128|

またこのTVは以下の計算でシャッター速度から求める事ができます。
**　TV = log2 (1/シャッター速度)**


F値もシャッター速度と同じく、下の表のようにF1.0を基準とした段で表現されます。
1段変わると入光量がその前段の半分/倍の量となる点もシャッター速度と同様です。
F値の段数は**AV(Aperture Value)**と呼びます。

|段(AV)|-1|0|1|2|3|4|5|6|7|8|9|10
|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
|F値|0.7|1.0|1.4|2|2.8|4|5.6|8|11|16|22|32|

F値の1段ごとの数値は平方根の値を丸めたもので、以下の式でF値からAVを求める事ができます。
**　AV = log2 (F値^2)**

そして、このTVとAVを足したものを、入光量を指す**LV(Light Value)**と呼びます。

**　LV = TV + AV**

###ISO感度による補正

ISO感度も写真の明るさに寄与するパラメータですが、TVやAVと違い、入ってきた光によってどのぐらい画像素子が強く反応するか、という値です。ISO感度もAVやTVと同様段数に換算して明るさの計算に加えますが、光量が増えるわけではない点には注意が必要です。
**ISO感度**は100を基準(0段)として数値が倍になる事で明るさも倍になります。実物のデジタルカメラの場合、もっとも一般的な領域ISO100～200あたりがもっとも画質が良く、感度が上がると比例してノイズが増えていきます。また感度を低くし過ぎても結果がピーキーになり過ぎて、画質としては劣化ととられる事が多いそうです。段数は以下で求めます。

**　ISO段数 = log2 (ISO感度 / 100)**


LVにISO段数を加味したものを**EV(Expose Value)**と呼びます。
LVは数が大きくなるほど写真が暗くなりますが、ISO段数は値が大きいほど明るくなるので、以下の式となります。

**　EV = LV - ISO段数**

EVは写真撮影のいろいろな場面で使われる数値ですが、本来は**撮影環境の明るさ(露出)**を指す値です。
まず**環境の明るさ(EV)**があり、これに**カメラの設定(EV)**を合わせる事で、**EV0(適正露出)**の写真が撮れる、という考え方になります。

**　撮影環境のEV　ー　カメラのEV　＝　適正露出(EV0)**

またカメラの自動露出を用いた際になどに使われる**露出補正**も単位はEVですが、これは加減させる事で目指すべき適正露出の値を**EV0**から可変させる効果があります。

# まとめ
ここまでで、複数のポストプロセスに対して実物のカメラのパラメータがどのように影響するかを一旦調べ終わりました。
今回除外した画質については、ISO感度に応じて意図的にノイズを加えるなどの処理で実現できそうですが、あえて画質を下げる処理を作る事は稀だと感じ省略しています。
今後はこの調査をもとにして、~~実際にUnity上で動作するカメラリグを作ってみたいと思います。~~
いろいろ事情がありまして、Unityでのテストは別の形になりそうです汗

*※2019/01/17：EVとLVの記述に間違いがあったので加筆修正しました。*