カラースペースについて

7 min read読了の目安(約6700字

はじめに

この記事は主にTouchDesignerを使ってグラフィックス、映像を制作している人達向けの内容ですが、基本的な考え方はその他、openFrameworksやProcessingといったツールを使っている人にも応用できる内容になっていると思います。

手探りで勉強してきた内容のことなので、細かい点や定義などについて嘘が書かれていたらごめんなさい… ということを先に謝っておきます!

サンプルファイル

色について

今も全然得意というわけではないですが、openFrameworksなど、プログラミングと密接にかかわったツールを使って映像を作る時、色を使うのが非常に苦手でした。白黒の映像だったらエイヤッと勢いで作れはするのだけれど、色を使うぞとなると急に色相を回して虹色になってしまう人、多いと思います。

今思うとそれは 変なカラースペースで映像を作ってるから自然とそんな絵になる ような気がしていて、グラフィックデザインや映像制作といったバックグラウンドを持った人が自然にやっている「色を選ぶ」という行為が、プログラミング(というかOpenGLなどのグラフィックAPI)を通すとものすごくコントロールしづらかったためなのではないかと思っています。

この記事ではカラースペースについて理解するといかにもCG、いかにもジェネ系な印象のアウトプットをもっと自然な感じできるかも?といったヒントについて書いていければと思います。

カラースペースを理解すると何が嬉しいのか?

まず、前述のように 「いかにもCG」といったアウトプットからの脱却 ができます。特にグラデーションと合成の部分ではその影響が顕著に出ます。

次に、CGと実写の素材を合成した時の色や光の見た目が非常にリアルになります。これはVFXやAR表現をしたい人には嬉しいのではないでしょうか。

最後に、OpenColorIO TOP を使うことで、外部のルックファイルを拾ってきてそれを適応したり、他のソフトで色を詳細に調整した結果をTouchDesingerで使うことができます。

光と色、物理量と感覚量

色って何だ… と考えていくと、結局の所それは光です。光は物理的な現象で、光が強くなるにつれて(エネルギーが上がるにつれて)線形に明くなっていきます。では色はどうでしょう?

人が光りを感じる時には明さとして知覚されますが、音の大きさ(dB)や音の高さ(オクターブ)などと同様に、明さも光のエネルギーが倍になっても倍明いとは知覚されないようです。参考

色を表す数字として 0~255 や 0~1 の間で表されたRGB値がよく使われますが、この数字は、人間がその色を見たときにどういう色に感じるか という感覚量を、実験による統計をもとにして定義されています。
(というのをどこかで見た気がして色々探したのだけれどソースを失念しました…)


たとえば、↑ の画像の真ん中のグレーはRGB値の中間の50%のグレーですが、その色と同じぐらいグレーなものの物理的な反射率で言うとだいたい18%程度といわれています。ざっくりというと、人の目では暗部が補正されて明く感じられる、その補正後の感覚値を当分してRGBの値などのカラーシステムは定義されている、ということです。

このあたりを語れるほど詳しくもないのと、絵作り自体には直接関わりがないので詳細は割愛させていただきたいのですが、要点としては、光(物理量)と色(感覚量)は分けて考える必要がある、もうちょっとプログラマ向けにいうと 光と色は型が違う ということが重要なポイントです。

LinearとsRGB

これまでカラースペースという単語を詳しい説明なしに使ってきましたが、カラースペースはある数字がどの色に対応するかということを決めたルールです。雑に言えば 数字を色に変換する関数 と言っても問題ないかもしれません。

世の中にはかなり数のカラースペースがあって、それぞれに短所長所があるのですが、TouchDesignerで日常的に使うものと限定すると、

  • sRGB (色、感覚量)
  • Linear (光、物理量)

の2つさえ理解していれば問題ないと思います。

作業をするにあたって、自分が今どのカラースペースにいるかを把握するのはとても大事です。簡単に確認する方法として、手元にある数字を入れると色として出力される環境にRGB全てに50%の値を入れて50%のグレーを表示してみてください。どういう濃さのグレーが表示されるでしょうか?


Constant TOPの場合


GLSL TOPの場合

大抵の環境では↓の図のオレンジの矢印で記されたのと同じようなグレーが表示されると思います。適当なカラーピッカー で表示されているピクセルの値を拾ってみると、オレンジの矢印の所で50%グレーになっているので、よしよしめでたしめでたし… となるような気がしますが、実はこれはそうではありません。

50%の値を入れてオレンジの矢印のグレーが出るということは、TouchDesignerの数字→表示までのカラースペースが sRGB(色) を扱っている ということになります。どういうこと…? という感じになると思いますので、TouchDesignerのネットワークを交えて説明していきたいと思います。

カラースペースごとのAdd


明さ0.5の円を2足すとかさなった所の明さが1になる

まずは簡単な足し算です。明さ0.5の2つの円の重なった所 Add TOP を通すと1になります。(数字には多少の誤差があります)

これだとまあ、そうなんじゃないの?という感じになると思いますが、↓の図だとどうでしょう?


LinearとsRGBのカラースペースでの加算合成の違い

2つを並べてみると、上のほうはバナナの黄色が白トビして左のほうではほとんどシルエットしかわからなくなっている一方、下のほうの結果はグラデーションの階調を保ったまま綺麗に画像とグラデーションが合成されているのがわかると思います。

これが sRGB(色) のまま足し算をした結果と、sRGBからLinear(光) に変換して足し算をした結果の違いです。

sRGBとLinearを相互変換するには Math TOP を使います

Convert Incoming sRGB to Linear で sRGB を Linear に変換、Convert Outgoing Linear to sRGB で Linear を sRGB に変換します。

さきほどの例だと合成したい2つの画像をそれぞれ sRGB→Linear変換した後合成、その後Linear→sRGB変換をしてビューワーで見ても違和感のない色にもどしています。


このセクションの最初に見た50%グレーの丸を重ねたものもLinearカラースペースで合成するとこうなります。下のほうが自然じゃないですか?

レンダリング時のカラースペース

これまでは合成時のカラースペースについて書いてきましたが、Render TOP を使ってレンダリングをする時にもいくつか注意すべき点があります。

TouchDesignerではOpenGLを使ってレンダリングをしますが、OpenGLでは数字を Linear(光) として計算するので、レンダリング後はLinearのカラースペースになっています。なので、Render TOP の後に Math TOP で sRGB(色) に変換してあげないといけません。

逆に、テクスチャとして画像を使う時には sRGB(色) を Linear(光) に変換してマテリアルにアサインします。Movie File In TOP を使うのであれば、Image > Input is sRGB のトグルを入れると読み込み時に自動で Linear に変換してくれるのでそちらでもOKです。

sRGBに変換した結果(上)とLinearの結果(下)を比較するために、ライトで大体同じ明るさになるように調整したものを用意しました。これを見てみると、

A:B → Linearのほうはハイライトの落ち方が急でサチュレーションのようなものが見えてしまう
C:D → Linearのほうはマテリアルの元の色(Diffuse 30%)が見えづらい、青っぽい印象になっている
E:F → こちらも同じく元の色がよくわからない感じになってしまっている

というような点が気になりました。Linearのままだと中間色の表現が微妙で、いかにもOpenGLでレンダリングされたPhongだな~ っていう印象になってしまうので、最終段でsRGBに変換して、ルックの調整をsRGBカラースペース上で行うようにしましょう。 それをするだけでもだいぶいい感じの見た目になります。

ビット深度とエイリアシング

これまで Math TOP を使って Linear/sRGB の変換をしてきましたが、実は Level TOPGamma2.2、又は 1/2.2 をすることで同様のことができます。Gamma の計算はglslで言うと color.rgb = pow(color.rgb, vec3(GAMMA)); となるのですが、pow関数は結構ダイナミックに数字を書き換えてしまうので、入力した画像のビット深度が8bitだと簡単にエイリアスによるバンディング が起きてしまいます。

後処理で解決するのも一つの手ですが、素直に Common > Pixel Format16-bit float(RGBA) に変更して解決するとよいでしょう。

おわりに

TouchDesignerを使う上でのカラースペースの扱い、変換方法について見てきました。

前述のように、カラースペースは言ってしまえば数字をどう色に変換するかの決め事なのでLinearやsRGB以外にも色々なカラースペースがあります。例えば、

  • Log:
    動画撮影時に暗部のグラデーションを8bitの中に効率的につめこむための関数を掛けて記録された形式。カメラメーカーごとに色々な形式がある

  • ACES:
    業務用の映像制作ソフトウェア間でカラースペースこれ一本で統一しようぜ的な目論見として制定された規格っぽい、すごいいいらしい(使ったことない)
    映像制作における色管理と ACES を活用したワークフロー | JAGAT

  • Rec.709 / Rec.2020:
    HD放送、4K放送の時にはこのカラースペースで編集、納品すべし、という仕様らしい(使う機会がない)

などです。

色々あるだけでもややこしいのに、さらにカメラ収録、編集/VFX作業、色の確認など、用途ごとに違ったカラースペースを選択しないといけない事から、そのあたりのカラースペース管理をまとめて行える OpenColorIO というライブラリが登場しており、TouchDesignerでも OpenColorIO TOP でその機能を使えるようになっています。

TouchDesignerでOpenColorIOが使えることで、sobotka/filmic-blender: Film Emulsion-Like Camera Rendering Transforms for Blender のようなフィルムルックなトーンマッパーが流用できます。
まだやったことはないのですが DaVinci Resolve のような映像編集ソフトで作ったOpenColorIOのカラーグレーディング設定ファイルを読み込んだりできるようです。

というように、カラースペースに気をはらうことで最終的なルックを今よりも追い込んで、現在の制作物のクオリティを上げることにつながる可能性が結構広がると思います。

みなさんも、まず最初に Render TOP の後に sRGB 変換を入れる所から始めてはいかがでしょうか


【PR】拙作のShaderBuilderはカラースペース変換を自動でやるようになっているため、何も考えなくてもそれっぽい見た目でレンダリングされるようになっています!
satoruhiga/TouchDesigner-ShaderBuilder: On the fly shader editing tool for TouchDesigner