この記事に関連する IlluGen のプロジェクトファイルは、こちらからダウンロードできます。
Download Here(ここからダウンロード)
ゲームのVFXを作るうえで、私がこれまで観てきた中でも特に大きな影響を受けた動画のひとつが、2013年のGDCでJulian Loveが行った、Diablo 3のVFXとテックアートに関するプレゼンテーションです。彼の講演では、エフェクトをゲームプレイに合致させるためにデザイナーとどう連携するかという話から、プレイヤーに視覚情報を伝える際にアーティストとして何を考えるべきかまで、幅広く語られています。
私、そしてこのプレゼンを観た多くのアーティストが特に興味深いと感じたのは、とてもシンプルな式、
を使うだけで、繰り返しパターンだと見抜きにくい、尽きることのない興味深いモーションが生み出せる点でした。フリップブックのような手法では、十分長く見ていると、たいてい繰り返しパターンが分かってしまいます。VFXという分野では、現実の焚き火のように、ただ眺めているだけで魅了される表現を作るのは、ある意味で私たちの責務でもあり、ループする表現の多くは、おそらくこれほどの作り込みに値します。Julianの言葉を借りれば、エフェクトを見ているときに「ぼーっとできる」ことが大事なのです。
この方法でモーションを生み出すというプレゼンと解説は本当に素晴らしいと思いますが、実装しようとすると、予期していなかった落とし穴がいくつかあることに気づくかもしれません。ただの掛け算でしょ?――そう単純ではありません。もしGDC講演をまだ観ていないのなら、私は強くおすすめしますが、観ていない人でも置いていかれないように、できる限り分かりやすく情報を伝えられるよう最善を尽くします。私はこの記事を書いている間にJulian本人と話す機会にも恵まれ、多くの人が尊敬してきた当人から、追加の知見を直接得ることができました。
私がUnrealでD3のVFX手法を使おうとしたとき、それはそのままではうまく動かず、そのときのトラブルも、この記事を書く理由の一部になっています。最後に前置きとして、以下にある黄色いDiablo風のテキストが付いた画像や動画は、GDC講演スライド由来のコンテンツであり、教育および論評目的でのフェアユースとして使用しています。ずっと前にこれを私たちみんなに共有してくれたBlizzardに感謝します。以上を踏まえて、さっそく見ていきましょう。
Fig. 1 では、左側に4つのテクスチャがあります。Texture 1、2、3 はすべて同じノイズテクスチャですが、スクロールする各レイヤーごとにUVスケールが異なります。Texture 4 は、スクロールノイズに定まった形を与えるためのソフトマスクです。
ここで注目したいのは、このケースではRGBチャンネルがベタの白である一方、最終的にRGBの明るさと不透明度を決めるのはアルファだという点です。また、一部の領域では白飛びしたまま変形していく白い形状も現れますが、これは実際のカラー入力と組み合わせる際には望ましい場合があります。
この4つのテクスチャを乗算した結果は、右側のたった7つのパーティクルに適用され、それによって非常に複雑なモーションが生まれます。
注:各テクスチャレイヤーの位置とスクロール速度は、位相合わせとパターン認識を防ぐために、パーティクルごとにランダム化されています。
Fig. 1 のノイズとアルファ形状マスクのテクスチャを作るために、IlluGenを使います。ノイズ形状がモーションにどう影響するかを探るため、テクスチャサンプルのRGBチャンネルに異なる種類のノイズをパックしていきます。GDC講演全体を通して、彼らはアルファチャンネルと一緒にカラーチャンネルも実際に利用しているため、ノイズのような要素に対してチャンネルパッキングが可能かどうかは、試しながら進めてみないと分からない部分があります。
Fig. 2 では、3つのユニークなノイズタイプを作り、それらにauto-levelをかけ、納得がいくまでアーティスティックに調整します。スモークのアルファチャンネルについては Fig. 3 のとおりで、私は最終結果をブラーしています。私の経験では、このほうがマスクとしてうまく機能します。マスクが細かすぎると、モーフするノイズがその上を通過したときに静的なディテールが見えてしまい、たいていのケースでは望ましくありません。
次に、テクスチャをUnrealへ書き出し、スクロールするマテリアルを作ります。Fig. 4 のマテリアルの出発点では、translucent unlit の shading model を使い、白い RGB 入力を emissive に入れています。Tex4.A のコメントボックスには、スモークマスクと、後の検証で使う RGB グラデーションが入っています。Tex4.A を掛ける前には、Scale by Mids 関数が見えます。D3 の講演では触れられていなかったことですが、多くの場合、この手法をさまざまな VFX で安定して機能させるには、テクスチャのミッドレンジをコントロールできる必要があります。
私は、自分の D3 インスパイア実装をトラブルシュートしていたときに Julian と短い会話をしましたが、多くのケースで狙ったモーションを確実に得るには、「ミッドレンジの色を加算的にも減算的にもスケールできる関数」が必要だと彼は言っていました。これについては後でもう少し触れますが、私は中間グレーを基準にグレースケールテクスチャのレンジをスケールし、モーションが現れる範囲や値の差を調整できる関数を作りました。
乗算を重ねれば重ねるほど、ノイズのレンジを制限したくなる。私は Scale by Mids という関数を作った。これは中間グレーを基準に、グレースケールテクスチャのレンジをスケールするものだ。テクスチャに黒が多くなると、動きの大半が食われてしまう。
私が確認を取らなかった点のひとつは、Scale by Mids 関数をテクスチャごとに適用すべきかどうかです。私はアルファ乗算の最後にまとめて入れる方法を選びましたが、ぜひ実験してみてほしいと思います。実際、この記事の後半では、この関数をどこに置くべきかについても試しています。
次に示すのが実装の中核で、テクスチャ位置とスクロール速度をパーティクルごとにランダム化します。これには、dynamic parameter を使って Niagara 側でパーティクルごとの変数を制御するなど、いくつか方法があります。しかし私は、マテリアルだけで完結する方法を選び、Particle Random Value ノードを使いました。Particle Random Value ノードは GPU パーティクルでしか動かないと聞いたことがありますが、私はそうは感じませんでした。少なくとも UE5.7 では、その話は当てはまらないように思えます。
また、panner の速度を設定するときは、値を 0 より大きくし、最大 1 に clamp したほうがよいことにも気づきました。これをしないと、一部のパーティクルインスタンスが遅すぎるスクロールになり、シームレスでまとまりのある動きが壊れてしまう可能性があります。テクスチャ座標は、上から下へ UV スケールで 0.5、1.0、2.0 です。
((Tex1.A * Tex2.A * 2) * Tex3.A * 2) の部分に移ると、ここは単純にテクスチャを掛け合わせてモーションをブレンドしているだけなので、説明は不要でしょう。Fig. 5 のグラフにおける最後の multiply は、Scale by Mids 関数内の subtract ノードの A ピンに接続されます。
Fig. 6 のように、Niagara でスポーンした 7 つのパーティクルにこのマテリアルを適用すると、Fig. 1 の D3 の例にかなり近い見た目になります。
ここまでうまくいったので、IlluGen で作った残り 2 つのノイズも見てみましょう。Fig. 7 では、shard ノイズはそれほど悪くありませんが、Voronoi ノイズは思ったほど良く見えません。その理由は、次の「よくある問題」セクションで明らかになります。
私の考えでは、避けたい結果は主に 3 種類あります。
- 1不適切なスクロール速度によって、モーフしているように見える錯覚が壊れてしまうこと。
- 2不正確なオクターブ設定によって、テクスチャが位相合わせ(phasing)を起こしてしまうこと。
- 3形状の縁に十分なミッド値がないために、黒が動きの大半を食ってしまうことです。
左のような不適切なスクロール速度では、時間とともにテクスチャがモーフしているように見える錯覚が壊れ、実際には 2 枚のテクスチャが互いに流れているだけ、という見た目になってしまいます。右側では、スクロール速度が近いため、狙っているモーフ感をうまく捉えられています。
また、2 枚のパーティクルスプライトが重なっている場合でも、それぞれにランダム化されたスクロール速度の差が大きすぎると、同じ問題が起こりえます。そのため、マテリアル内でランダムなパーティクル値に clamp ノードを追加し、すべてのパーティクルで最低限のスクロール速度が維持されるようにしています。
テクスチャ座標のオクターブサイズには、0.25、0.5、1.0、2.0…のような値を使うのが適しています。これらは、それぞれ後続の数を 2 で割って得られる値だからです。0.8、1.0、1.2 のようなオクターブセットを使ってしまうと、Fig. 9 にあるような位相合わせの問題を生むことがあります。こうした落とし穴には注意してください。
問題1と同様に、ノイズ形状に十分な値レンジを与えないことは、得られるモーションに大きく影響し、たとえ Scale by Mids 関数があっても修正できなくなることがあります。Fig. 10 の左側中央を見ると、大きな黒い空洞がただテクスチャ上をパンしているだけのようにも見えますが、これが絶えずモーフしているように見える錯覚を壊してしまいます。これが、Fig. 7 の Voronoi の例が「悪くはないが、期待したほどではない」見た目になったのと同じ理由です。
この方法はアルファチャンネルのモーションを作るのに非常にうまく機能するので、カラーに対しても同じようにうまく機能するはずです。ここまで学んだことを応用するために、Fig. 12 に示されている Arcane Orb を再現しながら、色の扱いを探っていきます。
その前に、「Blend-Add」――Unreal では Alpha Composite と呼ばれているもの――について話しておきましょう。私の調査では、これは pre-multiplied alpha と同じものでもあると思っています。アルファブレンドモードは非常に複雑な話題なので、ここでは慎重に進めます。
UE や Unity における Alpha Composite についてもっと詳しく知りたいなら、Martin Ellis による記事を読むことをおすすめします。要点はこうです。Diablo で呪文が大量に発生する場面で、VFX に additive ブレンディングを使ってしまうと、画面上の呪文の量が多すぎて、最終的にはすべてが巨大な白い塊になってしまいます。Blend(Translucent)では、additive ほど強く emissive に目立たせることができません。Blend-Add(Alpha Composite)は、本質的には、描画したい emissive 部分の背後に黒い背景を置くような形になり、情報量の多いシーンでもその発光部分をより目立たせる助けになります。
Alpha Composite の欠点は、対応するアルファチャンネルを持った独自色のノイズを使うようなエフェクトを組む場合、テクスチャパッキングがあまり現実的な選択肢ではなくなることです。もちろん、グレースケールのテクスチャに対してエンジン側でグラデーションを適用することはできますが、私の Arcane Orb の例で見ていくように、テクスチャ内の色差が大きすぎたため、テクスチャパッキングは不可能でした。
煙や霧のような、明るくない要素では、alpha composite ブレンディングを使う利点はそれほど大きくないと私は思います。これは、emissive シェーディングが重要な役割を果たすエフェクトのために取っておくべきでしょう。
このエフェクトが私にとって特に印象的だったのは、とてもシンプルなテクスチャ構成でありながら、非常に豊かなモーションを持っているからです。では始めましょう。まずは IlluGen に入り、銀河のようなスパイラルテクスチャ(Fig. 12 の TEX1)を作ります。要点は、Fig. 13 の Cartesian to Polar ノードを、斜めストライプのノイズと組み合わせて使い、スパイラル形状を作ることです。そこから色を加え、Directional Blur ノードを使って Cartesian to Polar ノードによって生じる継ぎ目を取り除きます。IlluGen の Directional Blur ノードの優れた点のひとつは、カラーを入力すると Chroma Shift パラメータが使えることで、私はこれを使って最終テクスチャの色がほんの少しだけ映えるようにしました。
最後に Fig. 14 でアルファチャンネルを作り、Alpha Merge でそれを統合します。アルファチャンネルには、スパイラル形状の上にスモーキーで炎っぽいノイズが焼き込まれているのが分かるでしょう。こうしたのは、Alpha Composite では「色が出る場所」と「黒が出る場所」の両方を制御でき、参照画像ではスパイラルの影響範囲の外側に、かすんだスモークのような効果があるように見えるからです。
Fig. 12 の TEX1 を見返すと、参照元のスパイラルテクスチャには実際にはアルファチャンネルが付いていないことが分かります。では、これはどういうことでしょうか。正直なところ分かりません。ただ、私の推測では、D3 側で追加のマスキング処理が行われているものの、それを明示していないのだと思います。Unreal では、スパイラル全体の形状に対するアルファチャンネルがないと、スパイラルマスクを切り分ける方法がありません。Fig. 16 を見てください。スパイラルにアルファチャンネルを含めず、それをマテリアル内で使わないと、パンしているノイズがスプライトの端に当たり、硬いエッジが出てしまいます。
Fig. 16 と 17 の銀河マテリアルを見ると、すでに星空のような星雲テクスチャが表示されていることに気づくでしょう。このテクスチャ、つまり Fig. 12 の TEX2 を作るには、UV Noise ノードを使ってラフな Voronoi テクスチャを生成すれば十分です。その後、Blur や Levels といったいくつかのユーティリティノードを通してから、最初の色を加えます。
面白いことに、私は今日まで Color Adjust ノードを使う必要がありませんでした。元のテクスチャを見ると、白、青、紫、緑、黄の領域が、それぞれ似たような明るさのまま別々の場所に存在しています。これは、単一のカラーグラデーションだけではプロシージャルに実現できません。そこで、いくつかのシェイプをマスクとして使い、Color Adjust を適用しましたが、これは予想以上にうまく機能しました。
エクスポート前の最後のノードは Alpha Merge で、ここでは元のベースノイズをアルファチャンネルとして使っています。これらすべてを sRGB テクスチャとして Unreal へ書き出します。
次に、Fig. 17 のマテリアルをいくつかの Niagara スプライトに適用します。Fig. 20 では、このパーティクルシステムのこのレイヤーにおける、スプライトのサイズや動き、そして最終結果を確認できます。これほどシンプルなのに、とても見栄えが良いです。
次に、かなり明るい発光スプライトを 2 枚スポーンするシンプルな Niagara システムを作り、Alpha Composite のブレンドモードを使います。中心のスプライトが常に銀河スパイラルの上に描画されるよう、ソート順もきちんと設定しました。シーンを照らすために、私はポイントライトを 1 つ置いただけです。最終的なエフェクトは、参照と同じく、常時 12 個のパーティクルで構成されています。
待って、Fig. 21 は参照に忠実じゃないじゃないか、Nick! 「参照では、星は中心から外に放り出されていて、吸い込まれてはいない……」――ええ、そこに気づいてくれて嬉しいです。Fig. 22 では、私の最終エフェクトにおける”外向きにパンする星”と”内向きにパンする星”を並べて比較しています。私は個人的には内向きのほうが好きですが、D3 の開発陣が外向きを選んだのもすごく良いと思います。ほかの要素が非常に速く動いている中でも、全体の動きを少し抑え、より多くの”物質”がその場に留まって見えるところが気に入っています。
そして最後に、記録のために、グロウ用マテリアルとテクスチャ作成についても示しておきます。エッジにごくわずかなきらめき、あるいは瞬きのようなものが入っているのが分かるかもしれません。Fig. 23 にあるように、テクスチャのミッド値を引き上げることで Scale by Mids がどう役立つかを示すには、ちょうどよい例だと思いました。グロウ用テクスチャの生成は Fig. 24 で確認できます。
ここまでの一連の再現は、IlluGen と D3 の比較的シンプルなテクニックを使うことで、かなり手早く組み立てることができました。では、次の例に進みましょう。
私たちはEmberGenの開発者ですから、ゲームの中で煙シミュレーションのフリップブックを見るだけでも、とても嬉しくなります。さらに言えば、動的にライティングされる煙に対して、適切に実装された6点ライティングを見るのも大好きです。私の知る限り、Diablo 3 はこれらの技術を使ってはいません。彼らが実現していたのは、ふわっとしていて、しっかり見え、しかも尽きることのないモーションをたっぷり備えた煙でした。
D3チームは、明るい側から暗い側へと移る手描きのカラーグラデーションを煙の色として使い、それを適用することで、ボリューム感のある煙に見せていたようです。テクスチャを確認したい場合は、Fig. 25 の7秒付近を見てください。
講演の中でJulianは、手描きのライティングをうまく機能させるには、通常であれば大量のスプライトバリエーションが必要になると言っています。なぜなら、手描きのプリライトスプライトでは、簡単にパターンを見抜けてしまうからです。ところが、アルファチャンネルでカラーグラデーションをパーティクルごとにマスクすれば、バリエーション用のスプライトシートは不要になります。パーティクルごとにランダム化されたモーションが、その役割を担ってくれるからです。
制約もあります。ゲーム内の太陽の位置の都合で、影はスモークの下半分に来る必要があるため、スモークスプライトを大きく回転させることはできません。私の知る限り、Diablo 3 はゲームプレイ全体を通して同じ時間帯が保たれており、さらに、ほぼアイソメトリックで、一定の視点にロックされたカメラシステムの恩恵も受けています。別のレベルでライティングが異なる場合でも、スプライトを少し回転させて新しいライティングに合わせれば済みます。このライティング手法の検証の後半では、こうした静的な制約から抜け出す方法も試していきます。
ここで、さまざまなエフェクトを試している中で得た、ひとつ興味深い観察があります。マテリアルグラフでは、形状マスク、この場合は Tex1.A を過剰に乗算しないよう注意してください。たとえば Tex1.A * (Tex2.A * Tex3.A * 2) のように、Tex1.A がマスクで、Tex2.A と Tex3.A がノイズだとすると、通常はその最終結果にさらに * 2 を掛けたいとは思わないはずです。想定していない形でアルファチャンネルが白飛びしてしまう可能性があるからです。普通、* 2 を掛けたいのは、すでに乗算済みのパンノイズやカラーに対してです。
Arcane Orb のグロウマテリアルでは、私は Mask * Noise * 2 を使いました。全体の明るさを確実に出したかったからです。要するに、どのチャンネルに * 2 を掛けるのかは、意図を持って選ぶべきだということです。
この余談はさておき、スモークの再現を進めましょう。Fig. 2 の R チャンネルに入っている元のノイズを、スモークの主なモーションを駆動するために使います。残る作業は、Fig. 25 の Tex1 を作ることだけです。まずは、ライティング方向をテストし、可視化するために、アーティスティックなノイズを入れない非常に基本的なグラデーションを作り、硬いエッジを持つテクスチャを用意します。その後、シンプルなスモークマスクを作り、Alpha チャンネルにパックします。
次に、Unreal でマテリアルを作ります。これまでのマテリアルと比べたときの主な違いは、Tex2.A に対して Scale by Mids を直接使い、そこで特定のレンジを作っている点です。ここでは Alpha Composite シェーディングは使わず、基本的な Translucent Unlit マテリアルにしています。残りの部分は、これまで使ってきたのと同じ乗算の計算と、パーティクルのランダム化です。いいですね。
では、スモークを動かす Niagara システムを作りましょう。このケースでは、常時およそ54個のパーティクルが存在し、グラデーションの位置を崩すために、ごくわずかなランダム回転も加えています。参照側では、アクティブなパーティクルは約60個で、同様に小さなランダム回転が使われていました。
悪くありません。次は、放射状のばらつきを持った、より自然なグラデーションを作りましょう。放射状のばらつきを加える主な方法は、Fig. 29 のように UV Radial でテクスチャを歪ませ、その暗い部分に追加のノイズを加えることです。
参照の色を合わせたいとき、IlluGen のグラデーション用スポイトツールは非常に便利です。グラデーションを始めたい位置をクリックし、そのままピクセル上をドラッグして、終わったら離します。そうすると、自動的にグラデーションへキーが追加されます。私は Fig. 30 で、グラデーションを反転し、各グラデーションキーの間隔を均等化しました。
この新しいグラデーションの結果は、Fig. 31 で非常に良く見えます。モーションは D3 で見たものと完璧に一致しているわけではありませんが、私は十分に近いと思っています。
ここで止めて、今日はこれで十分と言ってもよいでしょう。D3 がやっていたこと自体は、すでに再現できています。ただ私は、この技法をもう少し先まで押し広げてみたいと思いました。色と影のためにカスタムグラデーションを使いながら、しかも大きなオーバーヘッドなしに、太陽の位置へ動的に反応させることは可能なのか。それが気になったのです。
最初に知りたかったのは、D3の疑似ボリュームライティングが、Default Lit のライティングモードと比べてどう見えるか、という点です。このシェーディングモデルは Unreal に標準で備わっています。Unreal のマテリアルエディタで、私は次のように設定を変更しました。
- Generate Spherical Particle Normals を有効にする
- Shading Model:Default Lit
- Lighting Mode:Volumetric Directional
- スモークの色を Particle Color 由来にして Base Color へ接続する
- Emissive は使わず、D3式のカラーグラデーションも使わない
結果は Fig. 32 を見てください。
これは悪くありません。太陽光やその方向に反応し、シーン内のほかのライトからの光も受けます。私がここで問題だと感じるのは、D3の方法とは違って、表現しようとしているボリュームのハイライトとシャドウの色をコントロールできないことです。
Fig. 31 で使った Unlit モードの D3 グラデーションベースのシェーダに戻りつつ、グラデーションを太陽方向へ向けるためのノードをいくつか追加します。ここで先に断っておくと、私が使っている方法は粗く、完璧ではありません。私は本職のテックアーティストではないので、この先に出てくる問題を正しく解決するための知識には限りがあります。
ありがたいことに、RTVFX の Discord サーバーにいる Deathrey が、Fig. 33 にある正しい解決方法を見つけるのを手伝ってくれました。これにより、カメラがどこにあっても、テクスチャを太陽の方向へ正しく向けられるようになります。誤った方法と正しい方法の両方を試して、カメラ角度が変わったときにパーティクルのライティングがどう変化するかを見比べてみることをおすすめします。Fig. 34 では、この新しい仕組みによってテクスチャが本当に太陽方向を向くことを、矢印テクスチャを使って確認しています。
では矢印を差し替えて、IlluGen から新しいグラデーションテクスチャを読み込みましょう。これは元の D3 実装から 45 度回転させたもので、グラデーションが正しい向きになるようにするためのものです。Fig. 35 では、その結果が実際に確認できます。太陽の位置を変えたときにレンガやスモークに出ている色のにじみは、Unreal の TSR 実装によるもので、かなり見苦しいので申し訳ありません。ただ、ほとんどの太陽角度とカメラ角度では、スモークは正しくライティングされているように見えます。
これは素晴らしく、さらに先の実験に向けて十分な可能性を与えてくれます。カラーグラデーションを使って動的にライティングされたスモークが作れると分かった今、では現実の暗いスモークプルームをサンプリングしたらどうなるでしょうか。Fig. 36 は、カスタムグラデーションを得るための良い方法です。
総合的に見れば、グラデーションを太陽の位置に反応させるところで止めるのが、おそらくちょうどよいのでしょう。これ以上先へ進むと、解決すべき痛みや問題が増えるばかりだからです。……とはいえ、好奇心というものは、もう少しライティング機能を足してみたくなるものです。なので、このまま進めます。
完成と言う前に、まだ追加したい機能が 2 つあります。ひとつは、スモークがポイントライトや太陽から色を受け取れるようにすること。もうひとつは、太陽がスモークの背後にあるときにリムライトを入れることです。Fig. 32 で使っていた Default Lit と Generate Spherical Normals を、新しいマテリアル(Fig. 37)でも有効にすれば、理屈の上では両方の長所を得られるはずです。残念ながら、私のレベルにおけるポストライティング設定では、初期状態のままではそううまくいきませんでした。
シェーダグラフには露出補正ノード Eye Adaptation Inverse を入れているにもかかわらず、私のシーンでは、直射日光下で太陽の明るさが極端に明るいスポットを生んでしまいます。シーン内には、曇り空を太陽が横切って日差しが差し込むように見せるための雲マスクがあり、それが太陽の前をパンしています。そして日光が現れると、こうした明度の問題が発生します。
また、シーン全体が青みがかった色味を持っているため、黄色寄りのグラデーションを使っていても、Default Lit のライティングモデルがこちらの色をかなり上書きしてしまうのが分かります。そこで、できる限り明度を改善するために、マテリアル設定の中にある Directional Light Intensity パラメータを見つけて 0.1 に設定しました。さらに Fig. 38 では、ノードグラフ内の Brightness パラメータも 0.5 に設定しています。これによって Fig. 39 の結果が得られ、明るさとしては多少受け入れやすくなりましたが、その代わり、特定のライティング条件ではグラデーションに硬いラインが出るという別の問題が発生します。
Brightness パラメータは、納得できるまでさらに下げ続けることもできますが、ここではいったんこの値のままにしておきます。IlluGen 側では Blur ノードの半径を大きくして、この硬いラインを和らげたうえでテクスチャを再インポートしました。その結果、Fig. 40 では改善しているように見えます。
次に私は、太陽のない環境でポイントライトがどう作用するのかを Fig. 41 で確認したくなりました。ポイントライトが明るすぎると、残念ながら依然として色が白飛びする問題は起こります。ただし、これはシーン内のほかのポストプロセス設定によるもので、このレベル固有の現象かもしれません。実際、最終版のスモークでは別のレベルでもテストしましたが、同じ問題は起きませんでした。
これは特定のライティング条件でのみ現れるオプション機能で、ここで私たちがやっていることは、おそらく rim lighting(リムライト)または back lighting(バックライト)と呼ばれるものです。私たちの会社がボリューム系のことを扱っているとはいえ、私はライティングやボリューム表現の専門家ではありません。ただ、これは見栄えの良い結果になる可能性があり、少なくとも、あなたがこのアイデアをさらに発展させるためのヒントにはなるかもしれません。
リムライトを実現するには、Fig. 42 にあるノード群をグラフに追加し、その結果を Emissive チャンネルへ接続します。今回は Default Lit を使っているため、スモーク自体は Base Color に入っており、Emissive チャンネルはリムライトの出力に使うことができます。
最終結果は Fig. 43 です。いい感じです。
私は、最終版のスモークを別の環境でも試してみることにしました。新しい環境設定に合わせて、マテリアル内のいくつかの明度パラメータを少し調整する必要がありました。Fig. 44 を見てください。方向光でライティングされ、カラーグラデーションで制御され、太陽の色とポイントライトを受け取り、さらにリムライト/バックライトまで備えたスモークです。
もし私が本当に D3 の技法を使ってスモークのライティングをするなら、おそらく「太陽の方向に合わせてグラデーションを回転させる」ところで止めると思います。ライティングの色を変える必要があるなら、別のグラデーションを読み込み、レベルごとにスモークプルームをインスタンス化できるようにしておくだけにするでしょう。Default Lit のシェーディングモードをグラデーションと併用すると、問題がかなり多く発生しますし、環境の多いゲームの中でどれほど安定するのか、私には分かりません。これは、この技法をどこまで拡張できるかを試す、楽しい挑戦でした。少なくとも、楽しんでもらえたなら嬉しいです。
2013年の Diablo 3 VFX 講演を深掘りすることは、私にとってとても興味深い旅であり、数多くの驚きと挑戦に満ちたものでした。本当に、自分が分かっていると思っていたことを揺さぶられましたし、その過程で IlluGen と Unreal の両方において多くの新しいスキルを身につけることができました。あなたも何か新しいことを学び、制作中のゲームでこれらの技法を試してみようと思ってくれたなら嬉しいです。
本当なら、この講演に登場したエフェクトをもっと再現したかったですし、ここで学んだことを使って、まったく新しいエフェクトを実装してみたかったとも思っています。ですが、私はすでにこの1本の記事のために、調査・執筆・実装を合わせて約65時間を費やしています。これらの技法については、次の記事でもきっと活用するつもりです。私たちの多くにインスピレーションを与えてくれたあの講演を行ってくれたこと、そして私の質問に時間を割いて答えてくれ、現代的なエンジンの中でこれをどう実現すべきかについて意見をくれたことに対して、Julian Love に心から感謝したいと思います。
これは、私の新しいニュースレター「Gotta be less than 2ms」の第2回記事です。
ゲーム開発向け IlluGen
