シャドウマップ・その戦い。 / 1996年09月21日

前回、「シャドウマップは通常シーン全体を含むように作成される」と書いたが、
これが具体的にどういうことか、ちょっと確認してみよう。
まずは適当な人物フィギュアと基本小道具の平面詳細をロードする。
そしてライトの一つを上方に動かし、視点をそのライトのライトカメラに切り替える。
その状態で、平面詳細を適当に1000%ぐらいに拡大してみよう。
すると次の瞬間、視点が自動的に遠ざかって平面詳細がウィンドウ内に収まるはずだ。

122-1

今度は平面詳細を選択し、特性パレットで「影を作成」のチェックボックスを外してみよう。
すると今度は人物だけがカメラに収まるようにクローズアップする。
画面がすぐに切り換わらない場合は、選択しているオブジェクトなどを変更してみるといい。

122-2

このように、ライトカメラは影を作成するオブジェクト全てを含むように自動調整される。
なぜこのような自動調整機能がついているのだろうか。
それは、今使用しているライトが無限光だからだ。
スポットライトでは、ライトが照射する範囲、イコール影の作成される範囲は決まっている。
したがってシャドウマップもその範囲内で作成すればいい。
ところが無限光ではそうはいかない。無限光は無限の範囲を照射するライトであるため、
そのままではシャドウマップも無限大の範囲を含めなければならない。
そこで「最小の範囲で済むように」、シャドウマップに含める範囲が可変になっているのだ。

ここまで書けばもうおわかりだろう。
以前、ライトカメラにはライトの調整以外の肝心な機能がある、と書いた。
つまりライトカメラは、ユーザーがライトを調整する用途にも使えるものの、
もともとはPoser自身が、シャドウマップを生成し影を描画するために使用するものだったのだ。

(蛇足だが、ポイントライトでシャドウマップが使用できない理由もこのあたりにある。
 ポイントライトは全方向を均等に照らすライトだが、そのシャドウマップを作成するには
 まず全方向を均等に投影するカメラ、というものが実装されなければならない。
 なので今のところポイントライトではレイトレース影しか使用できないのである。)

そしてなにより重要なことは、
ライトカメラを動かすことで、影の作成される範囲をコントロールできるということである。

いや待て、ライトカメラは動かせないんじゃなかったか?

とツッコんでくれたあなたは一連のTips記事を熟読して下さっている方である。ありがたい。
確かにライトカメラはライトに付属するカメラなので、位置も角度も動かせない。
だが実は、写っている範囲を拡大したりずらしたりすることはできるんである。

122-3

ズームは拡大縮小(値が小さくなるほど拡大)、パンXは横方向の移動、パンYは縦方向の移動だ。
これらを使用して、カメラを対象まで近づけてみよう。

122-4

ライトカメラからはみ出す部分で影が途切れているのがわかるだろう。
ちなみに実際にレンダする範囲が正方形でない場合は、横幅を基準にした正方形で計算される。

122-5

この機能を使えば、カメラに写る範囲より大きな背景を使用しているときでも、
必要な範囲だけにシャドウマップの生成範囲を限定することができる。
大きな小道具(笑)を使用していても、影の精度を上げずに鮮明な影を描画できるのである。

122-6

もちろん、この方法では背景でも遠方にあるものの影を落とすことはできない。
その場合はもうさっぱり諦めて、合成に走ることをお勧めする。
つまり遠景の影をレンダしたものと、近景の影をレンダしたものを画像処理ソフトで合成するのだ。

122-7

近景をレンダするときに遠景を表示しておくのは、まあ合成が楽だからだ。
Poserの出力するイマイチなアルファチャンネルでも、フリンジをほぼ気にせずに作業できるので
トータル的な作業時間は短縮できるんではないかと思う。
レンダリングオプションで影のみレンダを使うのもアリ。

まとめると、背景を含むシーンで明確な影を描画するためには
・背景小道具が影を落とす必要がない場合は「影の作成」のチェックを外す。
・背景小道具も影を落としたい場合はライトカメラで影の作成範囲をギリギリまで絞る。
・影を落とす範囲が広い場合は、ライトカメラを調整したものを何パターンか合成する。
・影の精度や影の偏りはその都度適切に調整する。
ということになる。
これらにレイトレースシャドウやAO(環境閉塞)を適宜組み合わせることで、
Poserでもそれなりに説得力のある影の描画が可能になるだろう。

果たして。
長々と説明してきたが、結局のところ結論は
劇的に効果が出たり簡単手軽に解決することはない、ということだ。
つまるところはどれだけ的確に対策を打てるか、そして手間暇をかけられるかが
最終的な品質に繋がっていくのだと思う。


次は……レイトレースシャドウとAO(環境閉塞)をすっ飛ばして、拡散IBLに行こうかな〜。

■頂いたコメント■

›› Read More

シャドウマップ・その宿命。 / 1996年09月17日

なんだかしばらくぶりの更新だなあ(笑)
まあその間何をしていたかというと、自分ちのブログでG2 Jamesのレビューを
書いていたりなんぞしてたわけで、興味のある方はこちらまで(宣伝)。
http://rutenshikai.blog63.fc2.com/blog-entry-148.html

***

前回、シャドウマップとは光源の視点からZ値を取得し、そのグレースケール画像を
レンダリングしたものと、実際の距離を比較した結果から影を求める手法だと説明した。
そのZ値を表すグレースケール画像のことをそもそもシャドウマップと呼ぶわけだが、
端的に表現すればシャドウマップの欠点は、まさにそれが「画像」であるという点に尽きる。

まずは一つ目は、画像の画素数による問題だ。

シャドウマップによる影の描画では、実際のレンダリングの前に一つのライトにつき
「Z値の取得」「Z値をマッピングしたもの」「実際の距離を表したもの」と、
合計3度シーンをレンダリングしていることになる。
この中で、「Z値をマッピングしたもの」と「実際の距離を表したもの」は
カメラからの視点なので、そのレンダリングサイズは最終的なレンダサイズと一致する。
では「Z値の取得」は、一体何ピクセルでレンダリングされているのだろう?
ライトのパラメータパレットにある「影の精度(英語版ではMap Size)」が、その答えだ。

121-1

「影の精度」はデフォルトの状態では256となっている。
これは256×256ピクセルで「Z値の取得」のレンダリングを行うということである。
つまり「影の精度」とは、シャドウマップの1辺のピクセル数のことなのだ。
ちょっと想像してみよう。256×256ピクセルとは、随分と小さくはないだろうか。
このサイズでシーン全体をレンダするのだから、細かい形状まで描画できるはずがない。
描画できないとどうなるのかというと、ようするに影がボケてしまうのである。

これはシーン内のオブジェクトのサイズが大きいと特に顕著になる。
人物のみでテストレンダをした時には描画されていたはずの影が、
背景を追加した途端に薄ぼんやりとしか出なくなった、というようなことはないだろうか。
シャドウマップは通常シーン全体を含むように作成されるので、シーン全体のサイズが
大きくなれば、相対的に人物などは数ドット分の小さい範囲でしか描画されなくなる。
それにさらに影のぼかしがかけられて、ほとんど判別できないほど微かになってしまうのだ。

121-2

もちろん、シャドウマップのサイズを大きくすれば、相対的に影の精度は向上する。
パラメータパレットでは、「影の精度」は最大1024まで上げることができる。
だが、ちょっと想像してみよう。1024×1024ピクセルとは、随分と大きくはないだろうか。
少なくとも自分は普段そんな大きいサイズでレンダリングすることはほとんどない。
1024×1024ピクセルといえばデフォルト(256×256ピクセル)の16倍のサイズである。
単純に影の計算時間も16倍になり、さらにそれでもくっきりとエッジが立つとは限らない。
シャドウマップは影をぼかすのは得意だが、逆にエッジを立てるのは苦手なのだ。

一つ目が画像の画素数による問題なら、二つ目は画像の階調(bit数)の問題だ。

シャドウマップによる影の描画では、最初に取得したZ値をマッピングする都合上、
一度グレースケール画像としてシャドウマップを保存する。
するとシャドウマップは(大抵のレンダラにおいて)、8bit=白黒256階調で保存される。
これはつまり、シーン全体の奥行きを256段階でしか表現できないということだ。
光源から見たシーン全体の奥行きが、例えば2.5メートルなら約1センチずつ、
256メートルなら1メートル単位でしか奥行きを判定できない。
ところが3度目の「実際の距離を表したもの」をレンダリングするときは実数値で計算されるので
シャドウマップと実際の距離に差が出てしまい、階段状のノイズが発生する。

121-3

大きなPropや浅い角度からライトを当てた時に、度々見られる現象の原因がこれである。
この階段状のノイズを回避する為に、シャドウマップではあらかじめZ値の抽出時に
オブジェクトを設定されたオフセット値だけ実際の距離からずらして計算する。
これがライトの特性パレットにある「影の偏り(英語版ではShadow Min Bias)」だ。

121-4

人物の足は接地しているはずなのに、地面の影が浮いてしまって困惑した経験はないだろうか? 
これは、バグでも設定ミスでもない。シャドウマップの影を計算する時だけ、
オブジェクトは実際にその(後方の地面にめり込んだ)位置に存在しているのである。
人の顎や鼻の穴に影が落ちないのも同じ原因だ。
影を落とすオブジェクトと影を受けるオブジェクトの間隔がオフセット値よりも狭い場合、
影はそれを受けるオブジェクトよりも後方で、ようやく発生するのである。

121-5

このオフセット値はもちろん調整できるが、もともと階段状のノイズを軽減する為の
パラメータであるから、オフセット値を小さくするとノイズが発生してしまう。
ノイズができるギリギリのところまで、レンダリングしながら確認するしかない。

このように、シャドウマップは精密な描写を苦手とする。
これは時間やマシンパワーなどのリソース(資源)を費やせば改善できるという問題ではなく、
原理的な限界なのだ。

だが、まったく改善できないかというと、実はそういうわけでもない。
やや誤魔化しに近い限定的な方法で、多少は影の質を向上させることができるのである。

長くなったので次回につづく。

■頂いたコメント■

›› Read More

シャドウマップ・その原理。 / 1996年09月07日

シャドウマップを使用してレンダリングを開始すると、
Poserは画面の描画を始める前にライトごとの影の計算を始める。
この時Poserの中の人が何をしているのか、実際にその計算の手順を追っていこう。
ちなみに今回の図そのものはShadeで疑似的に表現したものなので、
多少の誤差があることをあらかじめお断りしておく。

このような形状がある場合を考える。簡単のために光源は一つであるとする。
さらに(めんどくさいので)透明な物質のことは考えないようにする。

120-1

まず最初に、光源からの視点でシーン全体をレンダリングし、Z値を求める。
するとZバッファの中はこんな風になる。

120-2

次にこのZバッファの値を、光源からの視点ですべてのオブジェクトにマッピングする。
ちょっとわかりにくいが、Zバッファの内容をテクスチャとして、
ライトカメラからのカメラ投影を用いてシーン全体をUVマッピングする……という感じだ。
単純にZバッファのグレースケール画像をそのまま貼り付ける、と考えたらいいかもしれない。

そして今度は実際にレンダリングするときのカメラ視点からシーンをレンダリングする。
レンダリングといっても、ライトによるシェーディング(陰付け)は行わず、
マッピングされた値をそのまま描画するだけだ。

120-3


さらに、もう一度カメラの視点からレンダリングをする。今度描画するのは
マッピングされた画像でも通常の表面材質でもなく、
光源からの距離そのものをグレースケール化したものだ。

120-4

そして求めた二つの画像を比較してその差を求める。するとこんなふうになる。

120-5

白い部分、つまり差が出ている部分は光源から見たZ値と実際の距離が異なるところ、
言い換えれば光源から遮られて影になっている部分だ。
したがってこれを反転すれば影の画像が求められる。
これを最初の影無しレンダ画像に乗算することで、影有りレンダの結果が得られる。
ライトが複数ある場合は、この処理をライトの分だけ繰り返し、
ライトごとに影有りレンダの結果を求めてから最後に加算する。

120-6

ちなみにこちらがShadeで実際にシャドウマップを使ってレンダリングしたもの。
まあちょっとズレているわけだけども(マッピングの精度がね……)。

120-7

このようにシャドウマップとは、光源の視点からの奥行き(Z深度)を求め、
それをマッピングすることで影になっている部分を求める手法である。

これに対しレイトレースシャドウでは、視点から発せられた光線(レイ)がなんらかの
オブジェクトに衝突した時に、その地点から光源を探してその間の障害物の有無を調べる。
障害物があればその地点は影になるというわけだ。

シャドウマップの利点は、なにより処理が高速で簡単なことだ。
1ピクセルずつその部分が影になっているかどうかを調べなくても、
ぱぱっとレンダリングして一括してZバッファを抽出すればいいのだから、手軽である。
また、最初に得た画像にぼかしフィルタをかければ、ソフトシャドウも簡単に実現できる。
レイトレースシャドウで影をぼかそうと思ったら、
サンプリングを増やしたりとにかく時間のかかる処理をしなくてはならない。

このような利点のあるシャドウマップだが、もちろん良いことばかりではない。
というわけで次はシャドウマップの抱える欠点と、それを軽減する方法について。



忘れていたので宣伝。
自サイトでJames/Koji/M3用の下駄を配布しています。
http://www001.upp.so-net.ne.jp/ruten-ryojo/poser/download.html

ついでにおまけネタを自分ちのブログにUP。
http://rutenshikai.blog63.fc2.com/blog-entry-145.html

や、こちらが真面目なTipsに偏ってるのもので……。

120-8


■頂いたコメント■

›› Read More

シャドウマップ・その前置き。 / 1996年09月04日

毎回このTipsを読んで頂いている方には申し訳ないが、今回からの内容は3DCGを
趣味として楽しまれている方には不要の知識であり、ハッキリ言って
理解する必要もないものだと思う。なぜなら自分は一つのアプリケーションにおいて、
個々の機能はブラックボックスであるべきだと考えているからだ。
どのような操作をすればどのような結果が得られるのか、その動作がわかっていれば
使用者が中の挙動まで考慮する必要はない。ただ、その機能が抱える性質と問題について、
「なぜそうであるのか」を説明するには、やはり中身を説明するのが一番手っ取り早い。
その意図でもって今回からシャドウマップによる影の描画の、基本的な原理について説明する。
ナナメ読みののち、Poserの中の人も大変なんだな〜、とでも思ってもらえればありがたい。

Poserでは、影を描画するために「影の奥行きマップ」か「レイトレース影」の2種類の影か、
または「環境閉塞」という特殊なシェーダを使用する。このうちレイトレース影と環境閉塞は
レイトレーシングを使用するため、最もよく使用されるのは影の奥行きマップだろう。
このネーミング、自分的にどうにもアレなので、以下統一してシャドウマップと呼ぶことにする。
ソフトによってはデプスシャドウとか呼ばれたりもしている。
なぜマップでデプス(深度)なのか、そのうち明らかになるだろう。

■陰と影

陰影という言葉がある。陰と影、どちらもカゲと発音するが、それぞれ違うものを指している。
陰は光が当たらない暗い部分、影は光の当たる部分と遮られた部分の境界が作り出すカタチだ。
英語ならば陰はShadeで影はShadow。シェーディングとは陰による明暗をつける作業だ。
Poserなら、影なしレンダで暗くなっている部分が陰、影有りレンダで描画されるのが影。

119-1

CGで影を描画するのは、陰を付けるよりも厄介だ。なぜなら陰は距離や大きさ、
色や角度といった「ライトとオブジェクト自身の情報」だけで描画できるが、
影はシーン内の全てのオブジェクトのどの部分がライトから遮られているのか、
またはその部分からライトが見えるのかどうかを計算しなければいけないからだ。

■Zという値

3DCGでは、しばしばZ値とかZデプスとかいう単語が使われる。Zとは何か。
Poserに慣れてきた方にはもうおわかりだろう。X軸移動と言えば横移動。Y軸回転は縦軸回転。
3DCGでZと言えば、奥行きのことである。特にZ値とかZデプス(深度)とかいう時は、
プレビュー画面(視点)から見た奥行きのことを差す。
プレビュー画面は左から何ピクセル/上から何ピクセルという位置情報の他に、
そこに写っているオブジェクトがどれぐらい後ろにあるのか、という情報を持っているのだ。
表示メニューの「距離感を出す」オプションは、その情報を利用して空気を着色している。

Z値を算出する原理はとても単純だ。
まず、画面サイズと同じ縦横のサイズを持ったZバッファというメモリを用意する。
そしてポリゴンを1枚ずつ計算し、その結果のうちから色の情報を画面に、
奥行き(視点からの距離)の情報をZバッファの同じ位置に書き込む。

119-2

また別のポリゴンを計算し、その奥行きの値をZバッファに保存された同じ位置の値と比較する。
新しいポリゴンがZバッファに保存された値より遠くにあれば破棄し、
近くにあれば画面とZバッファを上書きする。

119-3

そしてこれを全ポリゴンの分繰り返すと、陰面消去された画像とZ値が得られるというわけだ。

119-4

原理がとても単純なので、これは既にハードウェアレベルでサポートされている。
プレビュー描画をハードウェア(OpenGL)/ソフトウェア(SreeD)どちらに切り替えても、
ワイヤーフレーム(陰面消去)以上の表示でカメラやフィギュアをグリグリと動かせるだろう。
これは、上記のような計算がリアルタイムで行われているということを意味する。
Poserの中の人もグラフィックボードの中の人も頑張り屋さんなのである。
そしてシャドウマップによる影の描画は、このZバッファを利用するところから
始まるのである(あー、やっとつながった)。

というわけで続きはまた次回。

■頂いたコメント■

›› Read More

| BLOG TOP |