入門この広告は、90日以上更新していないブログに表示しています。Scattering)最近色々忙しくて全然更新できていませんでしたが、ちょうどいいネタを思いついたのと、アドカレが期限超過で1枠空いてたので代わりに投下します。Scattering)とは?人肌や牛乳、ろうそくなど、不透明ですが強い光を当てると透けて見えるような材質があります。表面より深くに潜り込み内部でランダムな反射(散乱)を何度も何度も繰り返し最終的に光が入った場所とは違うとこから出てくる現象のことです。大事な点は拡散反射とは違い、光が"入ったところとは違うところから出てくる"です。人肌がより人肌らしく見える逆光のとき、耳たぶから光が透けて見えるヒスイや大理石などの彫刻がリアルに雪や氷がリアルに特に人肌に有用で、最近のAAAゲームに出てくるリアルな人肌表現は全てSSSによるものです。言われる、不気味の谷を越えるためには絶対に必要な技術になります。地点Aに入射した光が、少し離れた地点Bからも出射するということは、BはAから光を"お裾分けしてもらった"と考えることが出来ます。BはAからだけではなく、周囲のCからもDからもEからFからも受け取ることになります。Bは、自分が光に照らされているかを周りの地点に聞きに回って、照らされていたらその一部を奪っていくことになります。(逆にBの受け取った光は周辺からいくらか奪われます)また、この図ではIとHは遠すぎるので、散乱光は届いていません。まとめると、それぞれの地点で拡散反射光を求める周囲と光の受け渡しをするという二つの手順が必要になります。これまでの実装方法ここから、これまでに提案されてきた代表的なアルゴリズム(リアルタイム系のみ)を紹介します。実装方法:ランバート反射これは入射した光すべてが同じ場所から出射されるので、SSSを考慮していません。解説上必要なので名前だけ載せます。陰のグラデーションをなだらかになるように式を調整したものが、ハーフランバートになります。この手法は周囲のライティング情報を一切考慮しないため、ランバートと同じく局所照明モデルと言われます。周囲の情報を用いないために不正確(非リアル)になります。マイナビニュース実装方法:曲率を考慮したシェーダコーエーテクモで使われているらしいスキンシェーダの実装方法です。こちらは曲率という形で周辺の形状を事前計算で求めておき、それを考慮したライティングを行います。この手法も局所照明モデルなので、高速ではありますが正確さに欠けます。Diffusion:TSD)一旦テクスチャに拡散反射光を計算してから、そのテクスチャにブラーを掛けることで、お隣さんと光を受け渡しする手法です。それぞれ光を受け取る量を確定したうえでお隣さんと分けあっているので、ハーフランバート等より正しい結果となります。問題はテクスチャはオブジェクト(例えば人)単位で貼られているので、その人数分だけ拡散反射光の計算をしなくてはならないことです。2048x2048のテクスチャが貼られた人が10人登場したら、2048x2048x10=約4200万ピクセルだけ計算することになります。ブラー処理も人数分だけ行う必要があるので重い処理となり、キャラクタが多く出てくるゲームのような用途には使えません。Scattering:SSSS)テクスチャ空間でブラーを掛ける代わりに、スクリーン空間でブラーを掛けよう、という手法です。画面から見えない領域は拡散反射光を求めず、結果を保持しておく場所もないので、本来貰えていた裏面から回り込む光を受け取れない4K環境やVRレンダリングでは通常より解像度が増えるため、人肌を近くから見つめるようなシチュエーションの場合、ブラーの負荷が上がる近年のAAAゲームではSSSSが多く使われているようです。耳の裏から入った光が耳の表側から出てくるような表現は出来ません。(TSDでいえば、耳の表のテクスチャと裏のテクスチャは近くに無いからです。SSSSでは、耳の表と裏が同時に見えることがそもそも無いので、情報がありません)これを表現するためには、物体の厚みをリアルタイムで計算して、薄ければ光を透けさせるという感じの処理をします。深度しか考慮してないので、あまり正確な手法とは言えない気がします。他のSSS手法と組み合わせるのだと思います。Scattering)ようやく本題のVSSSについて解説します。鋭い読者なら名前を見ただけでもうお気づきでしょう。テクスチャ空間でもスクリーン空間でもなく、頂点空間(つまり頂点同士)で光の受け渡しを行うのです。ここからQ&AQ1.頂点同士で光を受け渡すってどういうこと?テクスチャ空間もスクリーン空間も、どちらもピクセルに拡散反射光の情報を保存し、近隣のピクセルと光をやり取りしていました。VSSSではピクセルではなく頂点単位で拡散反射光を求め、それから近くの頂点に光を受け渡しします。ピクセルに比べ頂点数は比較的少ないので、より高速になるはずです。Q2.近さの定義テクスチャ空間及びスクリーン空間は二次元なので、二次元上の距離が近さを判断する材料になります。SSSSにおいては奥行き方向の距離を考慮していないため、"画面上では近くても奥行きはすごく離れている"ような場合も近いと判断されてしまいます。画面から深度を拾ってきて、離れていたらブラーに寄与しないようにするなどの考慮が必要になります。TSDにおいてはUV展開する人次第となり、隣接するピクセルは3次元的にも近い位置にあるということを保証する必要があります。テクスチャにはどうしても切れ目が存在するため、そこは別途考慮が必要になります。テクスチャに歪みがあれば、ブラーの方向が縦横一方に伸びてしまったりすることもあるでしょう。これも別途考慮する必要があります。VSSSでは頂点座標を用いるので、直接3次元距離を求めて近いかどうかを決定します。Q3.頂点の座標系は?近接頂点を求めるのはローカル空間で行い、ライティングはワールド空間で行います。ワールド空間では近接頂点を毎フレーム求める必要があるのに対し、ローカル空間では事前計算で近接頂点を決めておくことが出来ます。人体のような変形するモデルで、手を顔に近づけたとします。ローカル空間(初期の姿勢)では手と顔は普通離れているので、手の頂点と顔の頂点で光のやり取りは行われません。近接頂点として扱われてしまいます。Q4.物理的に正確?頂点数が増えるにしたがって探索半径内にサンプリング数が増えるので正確になり、頂点数が減ると高速化する代わりに正確性が下がります。RDPなどちゃんと考慮すれば、それなりに正しくなるとは思います。どっちにしてもかなり大雑把な近似ですが。Q5.利点は?全ての頂点の拡散反射光を求めるので、粒度は粗いがライティングに関する全ての情報使える近接頂点を3次元空間で決定するので、耳たぶなどの薄い物体は自動的に表と裏が近接頂点として扱われる。別途厚みなどを計算する必要が無く、透け表現ができる。SSSオブジェクトの頂点数にもよるが、ピクセル数よりは少ないと思われるので、拡散反射光を毎フレーム求めても高速ピクセル数によらないので、SSSオブジェクトにどれだけカメラを近づけても負荷が変わらない。4KやVRなどの高解像度環境で有用。前フレームにおける頂点単位の拡散反射光をキャッシュしておき、ライティングに変化があった頂点の近接頂点だけ拡散反射光の散乱(受け渡し)を計算しなおせばよいので、毎フレーム全頂点で受け渡し処理をする必要が無い。40MB)にもなるので、1頂点あたり平均208点も近接頂点を持っていることになります。設定次第ではありますが、ちょっと多すぎる気がします。同じメッシュのオブジェクトなら、この値は使いまわせるでしょう。影響のある頂点だけ行えばよく、完全に静的な環境では頂点ライティングも一度だけ行えばいいことになります。(つまりLightmapがベイク出来るような環境では、SSSも頂点にベイク出来るということになります)まとめ今回はベイクも可能な頂点ベースのSSS手法について考えてみました。テクスチャ空間、スクリーン空間があって頂点空間(3次元空間)が無いのは不思議ってくらい、誰かが既に考えていてもよさそうなものですが、ざっと検索した限り見つけられなかったので勝手に名前を付けました。(既にやってる人を見つけたら教えてもらえると助かります)この手法、テクスチャ空間やスクリーン空間のように、サンプリング位置を任意に決められないのが一番の難点かなと思います。探索半径球に触れる|含まれる面から、任意のサンプル頂点を生成するのもアリかもしれません。難しいのでやってませんが。近い頂点から光をもらってくるだけ、という言葉でいえば非常にシンプルなアルゴリズムなわりに、結構それっぽく見えるので満足しています。検索はてなブログをはじめよう!IARIKEさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。