« HyperNURBSのこまかい話 | メイン | 王の帰還 Special Extended Edition »
2005年03月21日
屈折率 [ CINEMA 4D R9 ]
屈折率の件をMOMOで冨士俊雄さんに教えてもらった後、自分でもいろいろとテストなどしてみたので、まとめてサイトにアップしようと思ってたのがずるずるとやらずじまいでもう一年近くになってしまった。なんでさっさと手をつけなかったかというと、3DCGの屈折率について論じる場合、いろいろとややこしいことになるんで腰が引けてた。
・屈折率についてあまり理解していない人が多い
・ソフトによって設定の仕方も再現の正確さもまちまち
・多少間違った設定をしていても絵ヅラでは意外とばれない
こういった事情があるので、ともすると「屈折率とは何か」「正しく屈折を表現することの意義は」なんていうところから始めないとスジが通らないような気分になってしまう。
でも今回はそういうのはなるべく無しの方向で。CINEMA 4Dで間違った設定をしたときの画像とか、他のソフトのレンダリング結果と突き合わせて検証した画像もあるんだけど、今回は出さないことにする。興味を持った人は、ソフトがどう機能してるかについては自分で実験してみればいい。屈折率そのものについての説明が不足であれば、Googleで探すなりなんなりしてくれたまえ(理数系の知識についてはWEBにいくらでもある)。
◆水の入ったグラス
以下は「ガラス容器に水を入れた状態」の設定。オブジェクトはこんな具合。左が空のグラス、右が水(色ついてるけど)の入ったグラス。

どちらも回転NURBSだが、水が入ってるほうは3個に分けている。わかりやすいように断面のスプラインだけを表示したのが下の図。

オブジェクトは、サーフェスが境界になっている物質の組み合わせごとに分割する。この場合だと、「空気と水」「水とガラス」「空気とガラス」の3個になる。
片側が空気であればマニュアルにあるとおりに絶対屈折率をそのまま設定すればいい(厳密にいうと空気との相対屈折率だが値の差は無視できる)。問題になるのは「水とガラス」の境界になるオブジェクトだ。大抵のソフト(maxとか)では、面の両側にある2種類の物質の絶対屈折率から算出した相対屈折率(この場合1.6/1.33=1.20)を持つ単一のマテリアルを設定し、裏表は面の法線の向きで決定する。ところがCINEMA 4Dの場合は、表と裏にそれぞれ別のマテリアルで、両側の物質の絶対屈折率を設定することになる(マニュアルにはそんなことひとことも書いてない)。

わかりにくいのがどっちの面にどっちの屈折率を使うかだけど、「その面の向こうにある物質の屈折率」を使うことになる。奥の部屋の表札がついたドアをイメージするとわかりやすいかもしれない。この面の向こうがガラスならガラスの屈折率を貼る、という具合。
しかしここでひとつ疑問が生じる。「空気と水」と「空気とガラス」の境界のオブジェクトでも、内側の面は向こうが空気だから、その面には空気の屈折率「1.0」をを設定する必要があるんではないのか?

さらに考えてみると、最も一般的な屈折オブジェクト、一種類の物質だけでできているもの(中身の入っていないグラス等)の場合、裏表で屈折率を変えなくても何の問題もないが、どうなっているのか?
実はそのケースでは、「例外的な処理」がされている。

上図の「ガラスに入ってガラスを出る」「水に入って水を出る」のように、同じ物質を出入りして「空気」(カメラがある空間と同じ物質)に戻る場合に限り、「出る」ほうの面が「入る」ほうの面と同じマテリアル=同じ屈折率のままでも正しい屈折になるよう処理されている。透明オブジェクトは単一の物質だけで閉じているケースが大半なので、大半がこの「例外」に該当することになる。「裏面」の屈折のためにマテリアルを貼り分ける手間が省けるということを考えれば合理的かもしれない。
では、この「例外的な処理」をあてにせず、空気に向かって出て行く面に頑固に屈折率「1.0」を設定してみるとどうなるか。

結果は、水−ガラス面のみ裏表を貼り分けたものと全く同じになる。


単一の物質だけでできたオブジェクトで両面貼り分けをしなくて済むのはたしかにラクチンだが、こういう「違う設定なのに同じ結果」という仕組みに弊害はないのだろうか?
◆水に沈んだ透明シート
板ガラスやビニールシートのようにごく薄い透明オブジェクトの場合、面は一枚だけで体積を持たせず、屈折率は「1.0」のままにするのが普通だ。屈折しなければレンダリングが速いし、屈折による透過像のズレは無視できる程度でしかない。モデリングのほうでは(板ガラスならまだしも)くちゃくちゃのビニールシートに数分の一ミリの厚みを持たせるような作業は煩雑このうえない。
しかし、この「屈折率1.0の一枚板」が存在する場所が「空気中」でなかった場合、ちょっとややこしいことになる。


上図は、鉢に水を満たして薄いシート(赤い正方形)を沈めたものだ。シートは平面オブジェクトで厚みはない。
まず試しに、アルファで切り抜いてみる。

アルファは問題ない。アルファがあっても透過がなければ屈折率もないので当然といえば当然。
次はシートを透明にしてみる。
大抵のソフトではこういうときは単に屈折率を「1.0」にしておくだけでいい。屈折率「1.0」の面で屈折は起こらない。ためしにこのシートの屈折率を「1.0」にしてみる。

ところがこの場合、透過像が屈折してしまう。なぜかというと、「面の向こうの物質の屈折率を設定する」というルールによって、屈折率「1.0」の面の向こうは「空気」ということになり、このシートは「水と空気の境界」とみなされるからだ。
そこで「向こう」ルールに従い、屈折率は水と同じ「1.33」にしてみる。

やっぱり同じように屈折してしまう。
シートの屈折率がすぐ手前にある水面の屈折率と同じなので、「同じ物質に入って出る」ことになり、前述の「例外的な処理」が行われるからだ。シートの向こうは「空気」とみなされ、「1.0」のときと同じ屈折像になる。「違う設定で同じ結果」が悪い方向に転んでしまった。
で、この場合どうやって解決するか。
シートが単純な平面なら厚みを持たせて通過する面を2枚にするのもいいかもしれない。厚み数分の一ミリでビニールの屈折率、杓子定規な正攻法だ。
透過はやめて、表示タグの「可視性」で見え具合を薄くすることもできる。しかし、背後との合成が乗算でなく加算になり、影に色がつかなくなるのでイマイチだ(クラゲみたいなものにはいいかもしれない)。
マテリアルで解決する場合は、少々ウラワザ気味な方法になる。

同じ屈折率の面が連続したときの「例外的な処理」を回避するため、シートの屈折率を0.01だけ下げて「1.329」とする(「1.331」でも「1.3299」でもいいが)。
これでシートの透過像は屈折しなくなる(厳密にはほんのわずかに屈折しているはずだが)。もちろんアルファと併用しても問題なし。
サンプルファイル(要R8.5以上)
◆
透明オブジェクト関係ではほかに、アルファチャンネルに鏡面反射やスペキュラーの明度、後ろに見えてる背景オブジェクトや空オブジェクトの明度が影響するとか、解せない仕様がある。単純に合成できなくなるようなアルファを出して何の役に立つのかわからないが、何か合理性があるのだろうか。もしかしたら「単に誰もつっこまないから放置されてる」類いのことなのかもしれない。たとえば、「選択されているオブジェクトのワイヤーフレームを白くハイライトする」というようなごくあたりまえの機能が実現したのがこないだのR9だったりするぐらいなので、ユーザーからのフィードバックが量的に少ないとか質的に偏ってるとかで、すごく「抜けてる」ところがあったりするのかも。
投稿者 ヒロツ : 2005年03月21日 18:27
トラックバック
このエントリーのトラックバックURL:
http://kowloo.net/hirotsu/mt/mt-tb.cgi/109
コメント
>正しく屈折を表現することの意義は
ああ、これありますね。
そういう人って、ちょっと難しい話になってくると
頭が真っ白になってしまって、
それ以上考える事を拒否するように出来てるんじゃないか?
とか、思ってしまいます。
特に屈折率に関しては、水オブジェクトを
わずかに小さくするっていう、
かなりいいかげんな方法が有名ですからねー。
かくいうぼくも、ちょっと前まではそんなもんだろうと
思っていました。
ちゃんと比較しないと分かりにくいんですよね。
C4Dというば、ちょっと関係ないかもしれないけど、
SLA-Banji(ガラス)を使うっていうのはどうなんでしょうね。
一応、ソリッドに計算するとかそれっぽい項目があるみたいですが。
もし、そっちも何か実験していたら教えてください。
投稿者 kurosawa : 2005年03月21日 19:33
>水オブジェクトをわずかに小さくするっていう
僕が知ってるだけでもそう書いてる書籍が2冊あります。
まあ相対屈折率についてマニュアルに書いてないソフトのほうも
問題大アリなんですけども。
Banjiもテストしたんだけど屈折率については同じでしたね。
オプションが色々あって可能性は感じるんだけど、
リアルっていうことでいえば普通に標準マテリアルで
フレネルONにしたほうが簡単というか(笑)
あと、照明タブでシェーダーをブリンにすると
法線が裏の面にスペキュラーが出なくなります。
こうするのが正しいっていうのを海外のサイトで見たんですが、
本当のところどうなのかよくわかりません。
そもそもスペキュラー自体がフェイクなので、
光源位置に発光体を置いてフレネル反射させるのが正しいということかも。
投稿者 ヒロツ : 2005年03月21日 20:31
カメラが水中にあると屈折率ぜんぶ設定しなおしだよなあ〜
とか考えてたらちょっと説明不足に気がついたので加筆しました。
投稿者 ヒロツ : 2005年03月22日 00:05