Blenderでレンダリングした3Dの映像データをやりとりするにあたって
深度情報(z,Depth)やマスクデータを受け渡すことがあります。
参照できる記事がなかったので勉強がてらまとめておきます
(認識違い等あれば指摘いただければ幸いです)
画像ファイルのデータ形式
画像データの色を表す方式として、PNGやJPEGでは、黒を(0,0,0)、白を(255,255,255)といった具合に、各色を8ビット(256階調)で表現する方法が一般的に使用されてきました。
この方法で特に問題ないことも多く、サイズや処理の効率を考慮すると、Webやゲームなどでは今後もこの形式が主流ででしょう。
一方で 現実世界の光の強さで考えると 室内の紙の色を"白"と定めても
室外に降り注いでいる光の強さは数百倍だったりと 非常に幅広い範囲の光の強さが存在します
そこで 3DCGでもコンピューターで数字を扱う時に利用する浮動小数点(float) のデータを使って
通常利用する黒を(0.0,0.0,0.0) 白を(1,0,1.0,1.0)といったように色を表現するようになってきています
浮動小数点を使うことにより普通の「色」の範囲をより細かい諧調で扱えるだけでなく
色の範囲を超えたマイナスやとても大きい数値も同じ "データ" としてやりとりできるようになっています
今回話題にするOpenEXRは浮動小数点値で色を扱うファイル形式の一つです
深度データの書き出し
3Dのレンダリングでは各ピクセルから対象までの距離データとして取得できます
ファイルとして書き出す場合にはファイルの形式によって変換が必要になります
PNG等での書き出しの場合
深度をPNGで書き出す場合、指定した範囲内で黒から白までのグレースケールで表現します。
Blenderのミストパスを使用して深度情報を表示してみた例です
「開始」より近い距離を黒 「深度」で指定した奥行を白 中間がグレーの諧調表現になります
それより遠い部分はホワイトアウトしますし、8ビット(256階調)や16ビット(65,536階調)の場合、範囲を指定した場合は諧調が不足することがあります。
また手動で範囲を指定する代わりにコンポジットで「正規化」のノードを使っている例を見かけます
正規化では 画像の中の一番遠い部分を0.0から1.0の範囲に収める計算をしますが
画像1枚1枚単位の処理なので 映り込むものが変化した場合 同じ距離でも値が変化してしまい 動画には不向きです。
EXRでの書き出し
先に触れた通りEXRではコンピュータが計算したままのデータを出力することが可能です。
また、OpenEXRマルチレイヤは複数の画像を名前を付けた上で同一ファイルに記録することもできます
ファイル出力ノードのプロパティ上でファイルフォーマットをOpenEXRマルチレイヤーにして
「入力を追加」を押すことでレイヤを増やして 名前も変更できます
Maya等のArnoldレンダーでは"[Z]"というレイヤ名が使用されるようで 画像でもそのように設定しています。
AfterEffectsでのEXRの読み込み
この設定でシーケンス素材をレンダリングした後 ファイル>読み込みでEXRのシーケンスを読み込むことになります
ファイルを指定して コンポジションを作成 と OpenEXRシーケンス をチェックして読み込みをすると
のような画像が出ます
Inmport as:をComposition でPre Pre-compose layersにチェックを入れた状態でOKすると
このようにEXRのレイヤが1つのコンポジションとなるように読み込まれます
図は階層から「[Z] source」のコンポジションを開いた状態です
「EXtractoR」のエフェクトは自動的に追加されます
(White Pointの数値は分かりやすくするために変更しました)
このエフェクトを使うことで 3Dレンダリングをやり直すことなくAfterEffects上で深度からマスクを作れます
Cryptomatteを使ったマスク
動画のコンポジット作業では オブジェクトやマテリアル毎に切り分けたい場合が出てきます
これまでは オブジェクト毎に色分けしたカラーデータを作成したり マスク用にグレースケールデータを出力することがありました
2019年頃からCryptomatteという方式が使われるようになってきたようで Blenderも対応しています
まずは使用例でどういったデータなのか確認してみます
基本的な使い方
Blenderでは ビューレイヤプロパティのCryptomatteにある項目にチェックを入れることで
レンダーパスとして利用できるようになります
・オブジェクトの項目にチェックを入れるとオブジェクト毎に
・マテリアルにチェックを入れるとマテリアル毎に
・アセットにチェックを入れるとそれぞれのオブジェクトの親毎に
それぞれでマスクをきり分けられる情報が出るようです
レベルの設定は 半透明で重なっているオブジェクトを最大何階層記録するか?という設定のようです。
Blenderのコンポジットノードで使う場合には
マット>Cryptomatte のノードを作成して
情報を取得するシーンやオブジェクトを取得する元(オブジェクトかマテリアルか)を指定して
+ボタンを押した後で画像上の目的の対象がある部分をクリックするか 名前を直接入力することで対象を指定できます
Cryptomatteは規格上は半透明にも対応しています
ただし、BlenderのEeveeのアルファブレンド設定では透明物はうまく扱えないようです
BlenderのCryptomatteデータの出力
OpenEXRマルチレイヤーを使えば CryptomatteデータをAfterEffectsに渡すことが可能です
ファイル出力のプロパティでノードのレイヤを増やして
レンダーレイヤーの「Crypt」で始まる出力名と同じレイヤ名に設定し 同じ名前同士を接続します
このファイルをさっきと同様に AfterEffectでEXR読み込みをすると
Cryptomatteのデータだと認識された状態でコンポジションとエフェクトが作成されます
どうやらCryptで始まる連番のレイヤ名がある場合に1セットのCryptomatteのデータとして扱うようです
エフェクトコントロールで エフェクト選択状態で画像をクリックすると
そのクリック位置にIDが割り振られているオブジェクト全てが選択状態になって
Shift押しながらで追加選択 Alt押しながらで減算選択になるようです
選択していない時の色の表示がBlenderと異なるのは
この表示色は決まった「色」としてのデータではなく各ソフトウエアで設定しているためです。
Cryptomatteは一見すると色分けのマスクと違いがないように見えますが
ソフトウエアの機能で正確にどのデータを選ぶかを指定でき 色分けでは不可能な半透明のマスクも設定できます
ただし、現状ではオブジェクトとマテリアルで分けるデータしか出力できません。
(これはArnoldレンダー等でも同じようです)
任意のマスクを作成するために 仕組みについて調べて次の記事にしてみました