カテゴリー別アーカイブ: 技術情報

ゲーム進捗報告 UE4編 (2019年5月前半)

CAVYHOUSEは現在、新作・ダンジョン農地化ローグライク「くちなしアンプル」を製作中です。
使用しているエンジンのUE4に関する進捗を書いていこうと思います。
また、ゲーム全体の進捗はpixivFanboxで公開中です(有料記事になります)。

■グラフィックの改良

「くちなしアンプル」はローグライクなのですが、ダンジョンをレベルアップして農地にすることができます。
今月ようやく、ゲームの肝になる農地を実装できたので、この機会に見た目を改良しようと、いろいろ新しいことを試してみました!

● 「水面の表現」アセットを追加
前作「マヨナカ・ガラン」では、平面的な画作りを目指していたのでリアルなアセットは使っていないのですが、
今回はフォトリアルとノンフォトリアルの中間くらいを目指しているので試してみました。
水面を簡単に表現できてとってもいい感じ。別のアセットもいろいろ試したくなっちゃう。

● Planar Reflectionを配置
後回しになっていた反射に手を入れました。かなりきれい。
(右がPlanar Reflection)

● パーティクルにLightを追加
安全なのが見た目でわかりやすいように、キラキラした光が降ってくるようにしました。
白くて小さい粒が発行しています。

■パフォーマンスの改善

まずはパフォーマンスのことは考えずに作って、重くなったら改善するようにしているのですが、
ここ数ヶ月、システムや描画を追加して、ちょっと重たくなってきたのでプロファイルを覗いてみました。
気になったのは2点。

● Generate Overlap Eventsをoffに
今回のゲームはマス目型のローグライクなので、衝突判定は使わずに実装しています。
組み込みのPlaneやCubeのコリジョンがそのまま残ってしまっていたので、Overlap Eventをoffにしました。

● arrayのget
想定よりも呼び出し回数が多かったので調べてみたところ、
ブループリントのANDノードは、falseの入力を見つけても止まらずに、全部の入力を評価するようです(ORも同様)。
※リンク先参照

画像のような条件チェックができないので、ブランチを明示的に増やして、必要ない呼び出しを回避しました。

まだ余裕がありそうなので、パフォーマンスの許す限り描画をリッチにしていく予定です!

■最後に…ScreenshotSaturdayまとめ

Unreal EngineのマテリアルエディタでVR表示時にもScreenAlignedUVs的な効果を実装する

まだ当サークルではUnreal EngineもVR(Oculus)も使い始めたところなので、
間違っていることもあるかもしれませんが、備忘録的に技術的なことを書いてみようと思います。

次回作の「マヨナカ・ガラン」は画面演出手段の一つとして、
一部の物体や人物に三次元空間上の位置ではなく二次元スクリーン中の位置に対して座標を固定するテクスチャ表現を使っています。
以下の映像では、煙のパーティクルや聖堂中の村人たちのテクスチャがそれにあたります。

Unreal Engineの場合、マテリアルのテクスチャ座標の決定にScreenAlignedUVsノードを使うことで
上記のようなスクリーン中の位置に対して座標を固定することができるようです。
(UEオンラインマニュアルのScreenAlignedUVsの解説

しかし、体験版をVRに移植しようとしたところテクスチャ座標の計算で問題が発生しました。
VR表示時にScreenAlignedUVsノードを利用すると、視差の問題で元のオブジェクト中のある点を
スクリーンに投影する位置が右目側と左目側で異なるため、テクスチャによる模様が両眼で矛盾を起こしてしまいます。
before
(テクスチャの矛盾の例)

そこで、矛盾を起こさないように両スクリーンとは異なる擬似的なスクリーンを想定して、そこに投影することにします。
具体的には、両眼の真ん中(単眼時と同じ位置)にあるカメラに紐付いたスクリーンを取得し、
その投影行列をテクスチャ座標の計算に利用します。
これにより、両眼での視野上で一定したテクスチャ座標への投影が可能になります。
after
(整合性のあるテクスチャの例)

両眼の真ん中にあるカメラに紐付いたスクリーンの投影行列は、レベルエディタ上のコードで取得することができます。
これは、もともとUEでは通常の描画とVRでは途中まで処理を共有しているため、
レベルエディタ上では通常の描画(単眼)用のカメラを保持していると考えられるためです。
具体的には、ULocalPlayer::GetProjectionData()で投影行列を取得することができます。

取得した行列は、マテリアルエディタのBlueprintに渡したいのですが、
行列をそのままの形を受け渡す方法が見つからなかったので以下の方法を利用しました。
マテリアルエディタはMaterial Parameter Collection というベクトルの集合を大域変数的に利用でき、レベルエディタからもアクセスできるため、
4×4のViewProjection行列を4×1のベクトル4つに分解し、Material Parameter Collections にそれぞれのベクトルをセットします。
(UEオンラインマニュアル中のMaterial Parameter Collectionsの解説)

(C++ソースコード例)
FMatrix ProjMat;
ULocalPlayer *lP = GWorld->GetFirstLocalPlayerFromController();
FSceneViewProjectionData ProjData;
lP->GetProjectionData(GEngine->GameViewport->Viewport, EStereoscopicPass::eSSP_FULL, ProjData);
ProjMat = ProjData.ComputeViewProjectionMatrix();

後は、マテリアルエディタ側で投影行列を受け取り、WorldPositionを掛けあわせます。
(実際はベクトルで受け取っているので、それぞれの行ベクトルとの内積をとっています)
あとはスケールを調整すると、スクリーン上の座標に従うテクスチャが表示できます。
BluePrintは以下のようになります。
material-2
(マテリアルBluePrint例)

また、UEのanswerhubで同様の試みをしている記事を見つけました。
これも投影行列をレベルエディタ上のコードで取得し、Material Parameter Collectionsで行列を受渡しています。
マテリアルエディタ側では、Custom UVでHLSLを書いて投影行列の掛け算を実行しているようです。

これで目的を達成することができたのですが、もっと簡単な方法があるかもしれませんので、
その場合はコメント欄などで教えていただけると嬉しいです。