はじめに
DeathStrandingはCGのクオリティがとても高くて感動しますね!
VFXアーティストとして自分は、中でも色々出てくるホログラム表現が好きです。今回はその内、カイラル通信がつながる前のホログラム表現をUEで再現してみようと思います!

で、作成したのがこちらです。
それなりに再現できたのではないかと思います!
一応、SkeletalMeshだけでなく、StaticMeshでも、どんなMeshにも対応できるような作りになってます。
データは以下で販売しているので、気になったら見てみてください!
https://heyyohanashima.gumroad.com/l/kntcdg
解説内容
ホログラムは、以下の4つの要素でできていて、また出現/消失も作成してありますが、今回は、このうち①と②の要素の作りの説明をしていきたいと思います。




出現/消失

概要
最初にこのホログラムを再現してみようと思った時は、Shaderであれこれしてみました。
ただ、色々やっても、ランダムに見えて少しだけ整列感があり、ちょっと下に落ちていっているように見えるノイズっぽい感じが表現できず、発想を変えてParticleでやってみたら良い感じになりました。
なので、このホログラム表現はNiagaraで作られています。ただ、キャラの元の色の反映はSceneCaptureを使い、アウトラインは背面法と同じような感じでCustomStencilを使って実装しています。
基本的な仕組みは、以前解説したScreen Spaceでのパーティクル発生の内容と同じで、対象Meshのバウンディングボックスに合わせてParticleを配置し、CustomStencilによるマスクで不要なParticleを切り取っていく形になります。
Meshのセットアップ
StaticMeshでもSkeletalMeshでも同じなので、ここではSkeletalMeshで説明します。

Target_SkeletalMeshが、元となるMeshで、これをSceneCaptureして色を取得します。ただ、実際のシーンでは映ってほしくないので、Visible in Scene Capture Onlyにチェックを入れます。

Target_SkeletalMeshの子に、同じSkeletalMeshを入れます。これをCustomStencilのBufferに書き込むことで、アウトラインを含んだホログラム全体のマスクとして使用します。逆に、実際のシーンやSceneCaptureにも映ってほしくないので、Render in Main Passをオフにし、Hidden In Scene Captureにチェックを入れます。
そして、Render Custom Depth Passをオンにし、CustomDepth Stencil Valueに任意の値を入れてください。この値はNiagara内でCustomStecilの値でParticleを消す処理で、同じ値を設定するようにします。

Target_SkeletalMesh_StencilMaskに割り当てるMaterialは、CustomStencilに書き込むだけなので見た目は何でも良いですが、アウトラインのために、少しだけ法線方向に膨らませる処理をMaterialに入れます。

これでMeshのセットアップは終わりです。
SceneCpatureのセットアップ

SceneCaptureのPrimitive Render Modeを、Use ShowOnly Listにして、上記でセットアップしたActorをShow Only Actorsとして設定し、Capture SourceをSceneColor (HDR) in RGB, Inv Opacity in Aに設定します。
そして、Tickで毎フレーム、シーンを映すカメラと同じ位置・回転・FOVになるように処理を入れます。
これで、ホログラムの元となるMeshの色とマスクをRender TargetとしてTextureで取得できるので、それをNiagaraで使用します。
また、Render Targetの解像度比率は、プレイ時の画面の解像度比率と一致している必要があるので注意してください。
Niagaraの実装内容


SceneCaptureで左側のTextureが取得でき、Custom StencilのBufferから右側のマスクが取得できます。CustomStencilを書き込んでいるMeshを法線方向に少し膨らませているので、右側のマスクが左側のキャラが映っている部分より少し大きくなっています。Niagaraで、これらを使い、メイン部分のParticleと、アウトラインを作ります。

このホログラム表現のNiagara SystemのParticle Spawnまでの処理です。上述したホログラムの4つの要素は全て一つのEmitterだけで実装しています。
黄色で囲った部分に関しては、仕組みは上記で挙げた記事と一緒なので説明は割愛しますが、NumXYのパラメータとJitter Positionのパラメータをいい感じに調整することで、少し整列感のあるノイズの感じを出しています。

メインとアウトライン部分の実装は、赤く囲まれたところの処理になります。
ここまでの処理で、CustomStencilのマスクを元に、Meshに重なるParticleだけ残っている状態になっています。

ここからメインとアウトライン部分を作ります。元のMeshの色情報と、アウトラインのマスク情報が必要なので、それを取得しているのがSampleTextureになります。
SampleTextureは、その名の通り、SceneCaptureで焼き付けているRenderTextureからRGBAをサンプルし、RGBをRT Color、AをRT Alphaというパラメータに格納しています。

取得した色情報を使いParticleに色を付ければ(色情報がないParticleの色を白にする)アウトラインは出ますが、下の左側のようにかなりParticleの量が多くなってしまうので、それを間引く処理をFilter Outlineとその後のKill Particlesで行っています。


Filter Outlineの処理としては、Particle毎のランダムの値に対して、Outline Alive Ratioの値より高い値のParticleを殺す処理になります(0.06を入れれば6%のParticleが生き残る)。ただ、そのままやるとメインの部分のParticleも消してしまうので、Outline Maskを使って、アウトライン部分のParticleにのみ影響するようにしています。Sample Textureで取得したRT Alphaは、対象のMeshが映っている所以外のマスクがとれる(SceneCpatureでInv Opacity in Aに設定してあるため)ので、Outline Maskに入れることで、アウトラインのマスクとして使うことができます。


アウトラインの間引きができたので、後はメインとアウトライン部分の色付けだけですが、各Particleがアウトラインであれば、Filter Outlineの所でOutlineというアトリビュートを1にするようにしているので、アウトラインであれば任意の色、それ以外ではRT Colorにするという設定をしているだけです。(実際はスキャンラインとスキャッターもアウトラインと同じ色にしてるので、それぞれ同じようにアトリビュートを作り、そのすべて以外ならRT Colorにするという実装になっています)

後は、少しだけ下にノイズが動いている感じを出すために、Gravity Forceを弱くかけ、下に落としてあげます。Particleの寿命は0.15~0.25秒にしてあるので、出て下に少し動いて消えるといった感じでノイズ感を出しています。

これで、メインとアウトライン部分の実装の解説は終わりです!
おわりに
VFXアーティストにとって、ホログラムはいつの時代も魅力的な題材ですよね。
だいたいShaderであれこれしてホログラム表現をすることが多いかと思いますが、今回はParticleでホログラム表現することで、丁度通信状態の悪いノイジーな感じが出せて、表現の幅を広げることができた気がします!
以下で販売しているデータでは、今回解説しなかったスキャンラインやスキャッター、出現/消失の実装が全て入ってるのと、SkeletalMeshとStaticMeshの両方のホログラムが入っているので、ぜひ覗いてみてください!
https://heyyohanashima.gumroad.com/l/kntcdg
次は、カイラル通信正常化後のホログラム表現に挑戦できればと思っています!