夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

Unityでフェイズシフトシェーダーを作る その1

本日はシェーダー枠です。

 先日筆者が大好きなアニメのガンダムシリーズの最新作「機動戦士ガンダムSEED FREEDOM」の映画を見に行きました。

 ほかのシリーズと世界戦が違い独自の設定があるSEEDシリーズですが独特な設定の一つとしてフェイズシフト装甲というものがあります。

 物語中でも設定、演出ともに重要な立ち位置にいるものですが使用時の演出が独特のため今回はUnityのシェーダーでこちらを再現していきます。

〇フェイズシフトとは?

 フェイズシフト装甲は物語中で主にガンダムタイプのメカに採用されている架空の装甲材質です。

 通常はグレーですが、通電によって淡く発色し、通常の装甲をはるかに上回る物理防御を発揮します。

https://www.youtube.com/watch?v=cl9Mf9M_Cvg より

 この設定はピンチ時にグレーになるほか通常時は兵器らしからぬ鮮やかな色が変わるというアニメらしさを演出し、世界観をうまく作り出しているように思えます。

 フェイズシフトが展開されていない状態をフェイズシフトダウンと呼び、通常は発進時などに展開されます。

 また続編のSEED Destinyでは進化した技術としてVPS(バリアブル・フェイズシフト)と呼ばれる設定が登場します。

 これは、走行に通電する電力を状況に応じて最適化し、装備によって走行色が変わるというものです。

 こちらも装備によって色が変わるというアニメ的な演出を電力の最適化というようにうまく理由付けして落とし込んでいると思います。

〇シェーダー要綱

・パラメータによってフェイズシフトアクティブ、ダウン状態を再現可能

・グレー→テクスチャ色で変化可能

・フェイズシフトの展開は一様ではなくノイズが走りながら劇中の展開方法を再現

まずは上記二つの実装を行います。

〇パラメータで制御可能な基本的なグレースケールの実装

まずは基本となるパラメータで制御可能なグレースケールの機能を実装します。

グレースケールについてさらに具体化して表すと「RGBの各色成分同士の差が0に近い状態」と呼べます。

白黒はRGB=1,1,1とRGB=0,0,0であらわされます。 グレーの場合は0.5,0.5,0.5であらわされ、各成分の値にずれがないほど白黒になります。 これは光の三原色の原理を見ればわかりやすいです。

グレースケールを実装する手法はいくつかありますが、今回は各成分の輪を3で割ることで実装していきます。

これをHLSLで記述すると次のようになります。

float3 GrayscaleConvert(float3 inputColor)

float sumComponent = inputColor.r+inputColor.g + inputColor.b;

float3 output = float3(sumComponent,sumComponent,sumComponent);

return  output;

上記の処理をシェーダーグラフで実装します。

今回はCustomFunctionノードを使用しました。

Stringのタイプで直接次のようなコードを書き込んでいます。

float sumComponent = inputColor.r+inputColor.g + inputColor.b;

output = float3(sumComponent,sumComponent,sumComponent);

実行すると次のような結果が得られます。

この手法はグレースケールを実現するにあたって最もシンプルで処理としても軽いです。

しかしビジュアル上の問題はあります。

人間の目はRGBの各色を同じように感じることはありません。

具体的には緑色は明るく、青色は暗く感じます。

漫画のトーンをイメージすればわかりやすいですが、成分で数値的に一様にグレースケールするとこれらの人間的な視覚上の明るさのバランスを損なう場合があります。

これを考慮に入れた場合各成分のバイアスは次のようになるようです。

VisualGrayscale = 0.299*R+0.587*G+0.114*B

これによって視覚的明るさを考慮したグレースケールを再現できます。

下記は視覚的明るさを考慮した例になります。

これを変数としてパラメータを掛け合わせることで任意にグレースケールを調整可能になります。

 このシェーダーではPowerというパラメータをいじることで任意にグレースケールを調整可能です。

CustomFunctionノードの処理は次のように実装しています。

float sumComponent = inputColor.r*0.299+inputColor.g*0.587+ inputColor.b*0.114;

output = float3(sumComponent,sumComponent,sumComponent)*(1-Power)+float3(inputColor.r,inputColor.g,inputColor.b)*Power;
//グレースケールの値と元の成分をPowerのパラメータでミックス

以上でフェイズシフト装甲を再現するにあたって一番重要なグレースケールの機能を再現できました。

次回は劇中を参考にフェイズシフト遷移時のノイズ表現を再現します。