Syoyo Fujita's Blog

raytracing monte carlo

Month: December, 2008

Gamma correction

gamma06_400.png
(image from Wikipedia)

レンダラコンサル(のようなもの)を引き続き続けています.

いくつかいただいた質問などの中から今回は、数人の方から同時に話題に上がったガンマ補正について調べたので書いてみます.
自分でも今までガンマ補正には, 存在には気づきつつも考慮していなかったため、よい勉強となりました.

ガンマ補正の実制作現場における問題については、すでに masuo さんが取り上げられています [2].
非常に参考になりますので、こちらも参考にしてください.

問題

CRT や液晶などの表示デバイスは、その特性状、入力の色の強度に線形比例して応答して発光せず、色の強度に対して曲線状に応答します(上図の下側の曲線).
この曲線は、 gamma(γ, ガンマ) という値を用いて表現することができます.
入力の強度が I であったとき, 実際に発光される色 I’ は、

I’ = I^gamma

という関係があります. I は通常 0.0(真っ黒) – 1.0(真っ白. 最大輝度) の範囲で定義されるので、gamma が高いほど曲線は下側に向きます.

入力で 0.5 の値を与えても、ちょうど中間のグレーが表示はされず、それよりも小さな値(より暗い色)が見えることになります.
(人間の知覚反応が強度に対して線形に反応するかという考慮はここでは割愛)

たとえば gamma = 2.2 のケースですと、入力のグレー値 0.5 は、0.5^2.2 = 0.21 の色強度として表示されます. なんと, 表示させたいと思っている値の半分以下です! 0-255 の階調で考えると、127(グレー)が実は 54 で見えているということになります. ガンマ、おそるべし.

この gamma 値は、OS によっても異なり、Windows では標準ですと 2.2, Mac は 1.8 となっています.

gamma が大きいほうが応答曲線はより大きく曲がり、暗い部分はより暗くなります. Windows だと色が引き締まってみえたり、Mac だと白っぽくなって見えたりするのはガンマがその原因のひとつと言えます.

ちなみに、Mac は今は gamma = 1.8 ですが、時期 OS である SnowLeopard からは Windows と同じ gamma = 2.2 になります. これで Windows と Mac でガンマの違いで見え方が異なる、という問題は無くなりますね.

ガンマ補正

表示デバイスを介すると、入力の強度に応じて線形に出力の強度が応答しないという問題がありました. この問題を解決して、線形に応答させるようにするのがガンマ補正です.

やり方は至って簡単です、「歪むのが分かっているのなら、逆方向に歪んだ入力を与えればいいじゃない]

つまり線形の入力(上図の y=x の線)を一旦上図の上側の曲線に変換したものをディスプレイに入力すれば, 目的とする線形に比例する応答が実現できるわけです.この変換は gamma の逆数を入力の強度にかけてあげれば OK です.

とはいえ、ディスプレイデバイスもそんな単純ではなくなってきているようです.

[3] のようにディスプレイによっては必ずしもガンマ乗に比例して階調が変化しないものがあったり、ディスプレイ側でガンマ補正が調整できるロジックの入った表示デバイスも出てきています(この場合、ディスプレイに画素を送るまえにガンマ補正を行うと逆におかしな結果になる).

昔の CRT ディスプレイのころとは違い, ガンマ補正を取り巻く問題はより複雑になったと言えるかもしれません.

テクスチャペインターの視点

というわけで、テクスチャペインターが描いたテクスチャなどのコンテンツは, テクスチャペインターがディスプレイを介して見ながら生成したものであるのでガンマがすでに付いている素材になります.
これをレンダラ側で使う場合にも、やはり適切にガンマ補正を行いガンマの歪みを取り除く必要があります.

ただし、masuo さんが述べているように、色でない要素、バンプテクスチャやディスプレースメントテクスチャでは、ガンマ補正の必要がない機会もあります.

ディスプレイが発達して、gamma=1 を再現できるのなら、そのキャリブレーション環境でテクスチャを作ってもらうのも一案ですが、デザイナーとしては「色味が変わるからやだ、自分に適した環境でなきゃいやだ」という声が上がりそうです.

よって、各デザイナごとの製作環境におけるガンマ値を適切に記録しておき, キャリブレーションして線形データにテクスチャを変換するというのが現実的な解でしょうか.

しかしそもそも、元々の精度が十分でないのも問題では?

しかし、ガンマ補正に関するより大きな問題は、現状のコンテンツ作成環境では入力が 8bit という時点で、ガンマ補正などを正しく考慮して各種変換を行う場合には, これはもはや十分な精度ではないということではないでしょうか.

そのため、各種変換操作を施しても精度が十分保てるように、16bit HDRI などより精度の高い環境でオリジナルのデータを作成するのが理想です.
最近は OpenEXR に代表される 16bit 画像フォーマットや Photoshop 16bit 化, Cinepaint などにより, 16bit HDR のコンテンツ作成環境が整備されてきていますので、だんだんと入力側の精度の問題は解決されていくと思います.

そうなってくれば、あとは純粋にデバイス間のキャリブレーションの問題(ディスプレイのガンマや色温度などを正しく知り、適切な変換を適用する)に落ち着きそうです.

PC からモニタへ表示データを送るときも、今だったら 8bit ではなくて 16bit で送るようなパスがありそうです. OS の API で存在したりしないのかな.
あと、GPU 経由であれば 16bit half で表示データをテクスチャとして持っておいて、矩形にテクスチャマッピングさせて表示させるという手もありますね.

共通のまとめ

ガンマ補正を適切に考慮しておきましょう.
コンテンツにはガンマ補正のプロファイルを保持しておきましょう.
入力データ(オリジナル)が 8bit というのは精度が問題である. 16bit 等高精度なフォーマットで持っておくのが望ましい. そうすれば、オリジナルがどのガンマで作られたとしても、各種変換で精度をあまり落とさず目的のガンマ画像に復元できるだろう.

レンダラ野郎向けのまとめ

色計算はすべて線形で(gamma=1). テクスチャや HDR 環境マップは使う前に gamma=1 に変換する. よってテクスチャにはどの gamma で作られたかの gamma 値の情報があることが望ましい.

レンダリング結果表示時にガンマ補正を行う.
(ただしファイル保存の場合は 16bit HDR のリニア(gamma=1)が望ましい)

色に関係しないコンポーネント(デプス、バンプ)はそのままで.

未解決の問題

さて、ガンマ補正、どうすればいいか解決したように見えて実はまだ問題がありそうです.

– アルファチャンネルはガンマ補正すべきか?(アルファがテクスチャペインターによって描かれた場合)
– また、アルファがある場合、カラーチャンネルのガンマ補正はいつ行うか?(アルファ適用後? 適用前?)
– ちょっとレンダラとは外れるけど、PNG に gamma 値を導入したことにより生じた不都合 [4]

Refernces

[1] Gamma correction(Wikipedia)
http://en.wikipedia.org/wiki/Gamma_correction

[2] color space
http://www.ousam.com/blog/category/computer-graphics/page/5

[3] ガンマ:滑らかな階調表現のために
http://eclub.eizo.co.jp/lcdtopics/2006/03/post_6.html
ディスプレイにも「くせ」があり、必ずしもγ乗で階調が比例するわけではない.

[4] The Sad Story of PNG Gamma “Correction”
http://hsivonen.iki.fi/png-gamma/
Web における, PNG がガンマ値を持ったことによる不都合.

Advertisements

Suicidator City Engine

cityengine_lucille.png
(The city model is generated by Suicidator City Engine. Rendered by lucille)

Suicidator City Engine
http://blenderartists.org/forum/showthread.php?t=140415

[Ja]

Blender スクリプト(python)で実現した都市ジェネレータ.
SIGGRAPH 論文で発表された cityengine のようなものを実装したものといえば分かるひとは分かるでしょうか.

デフォルトの設定で generate するだけでも, ポリゴンに落とすと大体 100 万ポリゴンになります.
ちょっとしたレンダリングパフォーマンステストにいいかも.
(細かい窓の間隔などは、アンチエイリアシングのテストにも適していると思います)

Out-of-core Data Management for Path Tracing on Hybrid Resources

outofcoredatamanagementforpathtracingonhybridresources_fig7.png
(from Out-of-core Data Management for Path Tracing on Hybrid Resources)

Out-of-core Data Management for Path Tracing on Hybrid Resources
Brian C. Budge, Tony Bernardin, Shubhabrata Sengupta, Kenneth I. Joy, John D. Owens
Eurographics 2009
http://graphics.idav.ucdavis.edu/publications/print_pub?pub_id=957

[Ja]

大規模シーン向けのスケーラブルなパストレアーキティクチャの提案.

Out-of-core と呼ばれる、必要なときだけメモリにデータをロードして有限なメモリ量でも効率良く大規模なデータを処理する手法をパストレにも応用して、スケーラブルなパストレにしてみました, という感じ.

また、GPU も使わなければもったいない(スケーラブルでない!)ということで、
GPU でもレイトレカーネルを CUDA で実装してより異種混合プロセッサの構成でもスケールするようにしています.

GPU でのレイトレですが、レイトレコアは CPU の 6-12 倍とありますが、
システム全体でみるとレンダリング時間は CPU と CPU + GPU との構成比較で 2-3 倍程度しか違いがないように見えます.
もちろんレイトレ処理だけがレンダリングのすべてではないのもありますが、
CPU が GPU での処理結果をサバき切れてないだけなのかもしれません.

GPU で処理を行う場合は、データをあらかじめ明示的に GPU 側に転送しなくてはいけないのですが、
そのような処理もスケーラブルパストレのフレームワークの中で実現しています.

なぜパストレをアルゴリズムとして選んだかというと、パストレが基本的に incoherent なアルゴリズムだから,
これがスケーラブルにできるのであれば意義があるからだそう.

論文からの上記の図は, なにも考えていないパストレ(standard)だとすぐに破綻してレンダリング時間がシーンサイズに指数関数的に比例するのが、
スケーラビリティを考慮したパストレならレンダリング時間がほぼシーンサイズに線形に比例していることを示しています.
(standard(無限大)はいまいち何なのか不明)

RenderMan だと数日、スケーラブルパストレなら 2 時間だぜ

スケーラブルであることの比較として、
240 M 三角形(2 億三角形)相当のシーンを RenderMan と提案されているパストレとでレンダリングし、
RenderMan だと 2 CPUs で数日かかるのが、提案するスケーラブルなパストレだと 1 CPU + 1 GPU の構成で
2 時間で終わったと報告しています.

RenderMan 野郎なら、「いや、RenderMan(reyes) も最適化すればもっと早くレンダリングできる!」
と言うかもしれませんが、しかしやはり RenderMan の古典的アーキティクチャ(reyes)がそろそろ
シーンの複雑性に追いつけなくなってきているということを示しているような気がしています.
そして逆に、シーンが複雑になるほど、スケールしやすいレイトレがだんだんと適合してくると.

やはりゲームもオフラインレンダラも、将来はレイトレが基礎のレンダリング技法になることは間違いないように思えます.

lucille on iPhone

lucille_on_iphone1.png

I’ve ported lucille into iPhone 🙂
RenderMan-like + global illumination renderer on iPhone!

This demo shows the extreme portability of lucille renderer.
Since lucille code base is written in very portable manner, porting was done within half of a day:
What I did is just fixing few compilation errors and adding iPhone specific display driver.

The rendering speed is reasonably slow on iPhone because there’s no iPhone specific optimizations(e.g. VFP optimization).
It’s about 1/10 ~ 1/15 of the speed of Core2 2GHz.

[Ja]

lucille を iPhone に移植しました.
ほんとは最初は OoO 5th 向けにリアルタイムレイトレを移植しようとしたのだけれど、
x86 SSE 依存部分の排除が思う以上に面倒だったので lucille を移植することにしました.

移植自体は半日ほどの時間で完了.
プロジェクトファイルの作成と、ちょっとした 3,4 個の trivial なコンパイルエラーの fix と, iPhone 用の表示ルーチンの追加くらいで完成.
lucille ソースコードの非常に高いポータビリティと iPhone 開発環境の容易さを示す好例と言えるでしょう.
これで RenderMan(疑似) + 大域照明レンダラが iPhone で動くということになりますね 🙂

処理はやっぱりそれなりに遅いです. Core2 2GHz の 1/10 ~ 1/15 くらい.
VFP をバリバリ使うように最適化したらもう少し差は縮まるかもしれませんが、それはまた今後時間があればということで.

OoO 5th に来ていただければ、今回の実機デモをお見せできます.
(上記スクリーンショットは、はめ込み合成ではないということを示すため 🙂 )

OoO 第5回 レンダラ忘年会

(追記)

bee さんがスペシャルゲストで参加していただけることになりました.
Progressive Photon Mapping の講演が(日本語で)聞けるのは OoO 第五回だけ!?

ーーー

ニュースヘッダではすでに告知していますが、
以下のように OoO 第5回を開催します.
(OoO =オフラインレンダラ野郎のためのオフラインレンダラについて議論するオフライン会)

日時: 12 月20日(土) 13:00-19:00

場所 : 恵比寿ガーデンプレイス SGI 株式会社様(31F)
集合: 13:00 B1F ホール(マックの隣)
http://www.sgi.co.jp/company_info/map1.html

集合時間に間に合わない方には、当日 B1F の入り口に連絡先が書かれた張り紙をしておきます。

参加費: 0 円
懇親会(任意参加): 有料

今回はレンダラ忘年会 08 です. 今年のレンダラ界隈の話題をまったりと振り返ります.

話題の予定

– Progressive Photon Mapping 講演(SIGGRAPH ASIA 採択論文) by bee
– SIGGRAPH ASIA の DVD を鑑賞する.
– iPhone レイトレ by syoyo
– CUDA レイトレ by kioku
– GI 本進展状況 by syoyo
– 今年のレンダラ界隈を振り返ってみる.
– その他ボーナスステージ. OoO 参加者だけの特典!?

レンダラ初心者も歓迎です.
ぜひお時間があればご参加ください.

yukio andoh さんから SIGGRAPH ASIA 2008 の Proceedings DVD を
レンダラ財団に寄付(?)していただけることになりました! ありがとうございます.
なので当日は SIGGRAPH ASIA の DVD 鑑賞会も行いたいと思います.

Mantra vs lucille, first round.

3102877052_ae91a4b911.jpg

The scene from houdini tutorial,

http://www.sidefx.com/index.php?option=com_content&task=view&id=992&Itemid=132

is rendered by Mantra and lucille(through htol exporter).

I’ve compared the image rendered by mantra and the one by lucille.

Mantra: raytracing, environment light(64 sampels)
lucille: raytracing(absolutely!), AO(64 samples), 2×2 subsample.

You’ll see notable artifacts in mantra(corners of the geometry, low frequency blurring),
beside of small differences in lucille(aspect ratio, non smoothed vertex normal).

I use default settings for mantra, what is the source of artifact in the image rendered by mantra?

[Ja]

ちょうど AO なシーンをレンダリングするチュートリアルが houdini のサイトにあったので、
mantra(houdini 標準レンダラ)と lucille で比較をしてみました.

なるべく比較環境を合わせるために、mantra はレイトレ, environment light のサンプル数は 64 samples にしています.

んん…? なんか mantra おかしくね?
角部分の輝度変化のおかしさや、ボケた感じのシェーディング変化が mantra では見て取れます.
(シェーディング結果の一部白飛びも気になりますが、これはトーンマップで直りそう)

lucille のほうは、それに比べれば小さな違いで, アスペクト比が違うとか、頂点法線でスムージングしていないからくらいです.

mantra は基本的にレンダリングエンジンをレイトレに変えているだけで、
他のパラメータはいじっていないのですが、
なにか他に設定すべきところでもあるのでしょうか?
(デフォルトだと計算をはしょっているので、まともに計算させるようにパラメータを設定すると直るとか)
我こそは mantra 使い、という方はアドバイスいただけると幸いです.

追記

masuo さんのアドバイスを参考にして、頂点アトリビュートを分離させる(共有させない)ようにしたら mantra でも
期待する画像になりました. ありがとうございます.

mantra_fixed.png

あと、元の mantra 画像でエッジ部分が変に明るかったのは environment light で
Use full sphere for environment というのにチェックが入っていたからでした.
正しい画像のほうではチェックを外しています(もともとのデフォルト).
なぜチェックが入っていたのかとか、このパラメータは何?というのは不明です 🙂

おまけ

毛も出始めてきました.

3099965259_3e47aae63d.jpg

まだ適当なポリゴンで毛のカーブデータを復元しているので、有刺鉄線みたいですが.

世界同時ゼロ金利に突入か!?

世界の金利にルカナンがかけられているような感じです.

BOE は金利を下げた!

http://jp.reuters.com/article/topNews/idJPJAPAN-35260820081204

ちょっと前までは高金利通貨として知られていたポンドですが、
いつのまにか政策金利はたったの 2.0% に!.
1951年以来の低水準だそう.

ECB も金利を下げた!

ECB、主要政策金利を75bp引き下げ2.50%に
http://jp.reuters.com/article/topNews/idJPJAPAN-35261320081204

FED もさらに金利を下げる… かもしれない.

政策金利は現在 1.0%, 次回 FOMC では予想では 0.5% 下げるとも 0.75% 下げるとも言われている.
円とドルの金利差が逆転するなんてことも?…
すでに FX の世界ではドル円のスワップ金利はマイナスになっている(円を売ってドルを買う場合)
普通はドル金利 > 円金利なのでプラスの金利差になります.
それがなんとマイナスに… こんなこといままであり得なかった!

そしてついにスイスフランはゼロ金利に突入!

スイスがゼロ金利政策、0.5%利下げ 金融危機下、主要国で初
http://www.nikkei.co.jp/news/kaigai/20081211AT2M1103011122008.html

スイスが一番乗りです 🙂

ゼロ金利世代

私の場合は物心ついたときから、金利ってなに? 預金金利 0.25 % とかなにそれ?無いも等しくね?
っていう環境で育ったのであまりゼロ金利には抵抗(?)が無いのですが、
それでも主要先進国がすべてゼロ金利に突入しようとしているというのはなかなか壮絶なものがあります.

参考

主要各国政策金利表
http://www.gaitame.com/market/seisakukinri.html

Ambient Occlusion demo for NativeClient

nacl_ao.png

NativeClient (NaCl) と呼ばれる x86 バイナリをほぼそのままブラウザで実行できるフレームワークが出たので、AO bench を NaCl に移植してみました.

http://lucille.atso-net.jp/nacl/ao.html
(NativeClient プラグインがインストールされている x86 マシンである必要があります.
処理速度が早いので、せっかくですからマウスでいじれるようにインタラクティブにしてみました)

source
http://lucille.svn.sourceforge.net/viewvc/lucille/angelina/nacl/ao/

速度ですが、処理時間をブラウザに戻す仕組みがよくわからなかったので目視レベルで確認しました.
ブラウザで動かしても速度がネイティブとちがうということはないです.
速度低下がほとんど無い事は、これは NaCl のドキュメントなどでも示されていますね.
ってか基本サンドボクシングが必要な部分に施された x86 コードまんまを実行しているので、
ブラウザで実行で速度低下がないというのも納得がいきます.

ネイティブとほとんど同じ速度で、というのはすごい特徴なのだろうけど
(ブラウザでレンダラとかレイトレを走らせるのも現実的になる)、
しかし実現の仕方がとても直接的というか、プラグインが結局は必要になるし、バイナリも x86 などのアーキ依存というのがちょっと気持ち悪いですね.
ユーザは多様なクライアントをサポートするとなると、
x86 や ARM それぞれにバイナリを作らなければならなくなるのでしょうか.

ところで、最初は NaCl は x86 コードをダイレクトに解釈して JIT したりサンドボクシングを施して、
Chrome の高速 JS エンジンで実行するという仕組みだと思ってました.
x86toLLVM でやろうとしたことを google に先を越された!みたいな.

おまけ

nacl って、どうしてもナッ○ルって読んでしまいますね.
また次に読めるのは何週後になるのだろう…

[htol] Rendering fur: work in progress

3095918258_4492584dc9.jpg

This is an work in progress image of fur rendering using htol, houdini to lucille exporter.

You’ll find rendered image is definitely not a fur.
I know why, and I know how to fix it, but needs more time to do it.

[Ja]

houdini と htol を引き続きいじってます. 毛もだんだんと出始めてきました.

houdini の fur ノードについて、さわりくらいですが発見したことを書いてみます.

* 適当にジオメトリを作って選択する -> シェルフの [fur] -> [Add fur] とやると勝手に毛が選択したジオメトリに生えてくれます 🙂
* houdini の fur ノードはなんか一回作ったらいじれない(ノードがロックされている)みたいです. op でつなげられない?
* fur のデータはカーブ(毛)を構成する頂点と毛の幅だけみたい. なのでカーブ頂点から fur ジオメトリをシリンダとかで復元する必要があります.

本来であればカーブデータからのジオメトリなどはレンダラ側で復元するのがいいのでしょうが、
とりあえずは Python スクリプト側でカーブ頂点に沿って円柱ジオメトリを生成して RIB に吐く方法を取り、もう少しまともな毛画像をレンダリングできるようにしてみます.

Lsystem exported by htol, Houdini to lucille exporter.

3093142574_d108b03da7.jpg

Lsystem! But to do this, you’ll need to connect Convert SOP to Lsystem to convert Lsystem into polygonal geometry.

[Ja]

htol(Houdini to lucille exporter)で、 Lsystem でました. というか直接 Lsystem データを RIB に吐いてレンダリングはできないので、Houdini 側で Convert SOP 使ってポリゴンに変換しています.

法線のエクスポートがおかしいのか、レンダリング結果にアーティファクトが見られます.
まあおいおい改善されるでしょう.

fur ももうすぐ吐き出せそうです.