VRコンテンツにおける安定した輪郭線描画手法

こんにちは。エンジニアの原です。

今回はアニメ的な表現では欠かせない輪郭線の描画に関して、VRコンテンツで使用する場合の一つのテクニックをご紹介します。

 

VR+輪郭線描画の問題

VRでは右目用と左目用にそれぞれ別の画面をレンダリングし、その視差によって立体視を実現します。
また、輪郭線描画には背面法、ポストプロセスによる各種フィルタ等の様々な手法がありますが、最終的には現在表示している画面に対して輪郭線を表示するということは同じです。
つまり、この二つの技術を組み合わせた場合、輪郭線描画は右目、左目それぞれの画面に対して行われますが、これにより問題が発生します。

SphericalProjection_11

こちらはポストプロセスによるフィルタ処理によって輪郭線のみを描画した画像です。
右目と左目の絵を比べてみると、輪郭線が出ている位置が大きく違うことがわかるかと思います。
右目と左目の画像を重ねてみるとわかりやすいです。

BeforeImage

これをHMDで見てみると、左右の目で別の輪郭線が表示されるため、輪郭線がブレて見えるという問題が発生します。
遠くに見えるものであれば視差が少ないため問題ないのですが、対象が近付いて視差が大きくなった場合にこの問題は顕著に現れます。

 

カメラに近付いたら視差を無くす

上記の問題は、視差があることによって引き起こされる問題です。
そのため今回は「対象がカメラに近付いたら視差を無くす」という対応を行いました。
これによる効果は以下の画像をご覧下さい。

SphericalProjection_12

AfterImage

最初の画像と比べてキャラクターの輪郭線が出る位置が左右の目で揃っていることがわかるかと思います。
この状態であればHMDで見た場合でも輪郭線がブレず、綺麗に表示されるようになります。
もちろん左右の目に完全に同じ画面を表示するということではなく、近付いた物体以外は視差がある状態で描画されるのでVRの良さも失っていません。
この手法に関して詳しく解説していきます。

 

頂点移動によるカメラから一定距離への投影

「視差を無くす」という事はつまり、「左右の目から見える距離を一定にする」ということです。
しかし単純に対象を平面に投影すると、ただの板ポリに見えてしまい、良い見た目にはなりません。
そのため今回はカメラから一定の距離、つまり球面に投影することで対象を平面化しつつ、カメラから見た形状が変化しないような処理を入れました。

まず、こちらが頂点移動処理を組み込む前の画像です。

SphericalProjection_10

そしてこちらが頂点移動処理を組み込んだ画像です。

SphericalProjection_09

キャラクターが球面に投影されていることがわかるかと思います。
また、右下にあるカメラから見た画像を比べてみると、変形前後でも同じように見えていることが確認できます。

 

上記対応は頂点移動によるものであるため、マテリアルの WorldPositionOffset を使用しています。
また、頂点移動によるファイティングや、頂点密度によって前後関係が入れ替わってしまう問題への対処のために PixelDepthOffset も使用しています。
こちらは処理を共通化するため、マテリアルファンクションとして用意してあります。

 

MF_SphericalProjection

SphericalProjection_15

こちらの各出力を適応したいマテリアルの出力ピンに繋ぐことで使用できます。
処理の内容を簡単に説明すると以下の通りです。

 

  1. カメラから頂点への単位ベクトルを求める。これが頂点を押し出す方向となる。
  2. カメラと頂点との距離からカメラからの投影距離(ProjectionDistance)を差し引くことで、頂点を押し出す距離が求められる。
    また、押し出す距離をそのまま利用するとメッシュが完全に潰れてしまい、ファイティングに繋がるので押し出す距離に対して係数(WorldPositionOffsetRate)をかける。
  3. 変形させるのはカメラからの投影距離(ProjectionDistance)以内にある頂点のみ。
  4. 押し出した距離をPixelDepthOffsetに入れてDepthは押し戻す。ここでも係数(PixelDepthOffsetRate)をかけられるようにする。

 

制限事項

平面化による影響でDefaultLitでの動的影の出方が変わる

標準ライティングを使用する場合、動的影は変形後のメッシュに対して生成されるため、影の出方が変わってしまいます。
まず、こちらが頂点移動前の動的影です。

SphericalProjection_08

SphericalProjection_13

そしてこちらが頂点移動後の動的影です。

SphericalProjection_07

SphericalProjection_14

見た目に大きく影響が出てしまうため、基本的にはUnlitでの運用になるかと思います。
それでも影を表示したい場合は、アニメ的なシェーディングで用いられる、光源の方向と法線の角度から影になる部分を計算して色を落とすという手法が効果的かと思われます。

SphericalProjection_18

ただし、こちらの手法を使ってもCastShadowへの対応はできないため、そちらは丸影等のFakeShadowを使用したりと工夫は必要です。

 

頂点密度が低い場合は綺麗に変形できない

頂点シェーダで処理している都合上、どうしても頂点密度が低い場合は変形後の見た目に影響が出てしまいます。
まず、こちらが頂点移動前のCubeです。

SphericalProjection_16

そしてこちらが頂点移動後のCubeです。

SphericalProjection_17

見た目に影響が出てしまう場合はもう少し分割数を上げてみてください。

 

サンプルプロジェクト

こちらに関するサンプルプロジェクトをGitHubに上げてあります。
ダウンロードして実際にHMD上でお試し下さい。

https://github.com/historia-Inc/Tech_SphericalProjection

 

終わりに

VRコンテンツは注目度も高く、開発事例もどんどん増え続けています。
弊社でもアクエリオンやアーガイルシフト、ネコぱらを始め、多くのVRコンテンツ制作に関わらせて頂いております。
まだまだ増え続けていくと思いますので、より良くするための技術は突き詰めていきたいですね。

 

ヒストリアでは新卒/中途採用を強化中です。
まだまだ若い会社ではありますが、数多くのUE4案件、VR案件に関わらせて頂いております。
もし興味がある方は是非一度会社見学にいらしてください。