Unity を検索

動くアート ― シェーダーグラフでアニメーション付きマテリアルを視覚的に作成しよう

2018年10月5日 カテゴリ: Engine & platform | 12 分 で読めます
取り上げているトピック
シェア

Is this article helpful for you?

Thank you for your feedback!

Unity 2018.2 でシェーダーグラフに「Vertex Position(頂点座標)」の入力が追加され、メッシュの調整とアニメーション化が可能になりました。本記事では、ユーザー独自の頂点アニメーションシェーダーの作成方法と、いくつかの一般的な例(風や水のシェーダーなど)をご紹介します。

シェーダーグラフにまだ馴染みのない方は、主な機能について説明した Tim Cooper のブログ記事をお読みください。また、Unity の YouTube チャンネルで Andy Touch の講演動画「Shader Graph Introduction」(英語)もご視聴いただけます。

このシーンはテクスチャやアニメーションアセットを一切使用していません。すべての要素の色付けとアニメーション化は、シェーダーグラフを使って行われています。

シェーダーはレンダリングパイプラインの非常に強力な要素で、シーンアセットの表示に対する高度な制御を可能にするものです。一連の入力や操作によって、アセットの各種レンダリングプロパティ(サーフェスの色やテクスチャからメッシュの頂点位置まで)を調整するシェーダーの作成が可能です。また、それらを組み合わせて複雑で表情豊かなアニメーションを作ることもできます。本記事では、頂点アニメーションの作成を始めるためのガイドをお届けするとともに、マスクやプロパティの使用方法と、『Desert Island Scene』用のシェーダーがどのように作成されたかをご紹介します。

サンプルプロジェクトをダウンロードする

GitHub のレポジトリをクローンして入手または GitHub から .zip ファイルをダウンロードして入手

サンプルプロジェクト『Desert Island Scene』をダウンロードし、ご自分でシェーダーを操作してみてください!このプロジェクトには、シェーダーグラフの使用を開始するために必要なものがすべて含まれています。このプロジェクトは、バージョン 2018.2 以降の Unity で起動してください。

『Desert Island Scene』に含まれるすべてのシェーダーはカスタマイズされる前提で作成されていますので、インスペクターでシェーダーの色々な値を自由に変えてみてください!各オブジェクトには、値をデフォルトにリセットするプリセットファイルが含まれています。

このプロジェクトにはクリエイティブ・コモンズ(表示 4.0 国際)ライセンスが採用されています。

シェーダーグラフをインストールする

シェーダーグラフを使用するには、プロジェクトが以下の要件を満たしている必要があります。

シェーダーグラフをインストールするには、プロジェクトを作成するか 2018.2 以降のバージョンに更新し、メニューを Window > Package Manager > All の順に選択して、リストの中から「Shader Graph」 を探して「Install」をクリックしてください。

シーンビューでマテリアルにアニメーションが付いていない場合は、「Animated Materials」にチェックマークを入れてください。

Making something fancy with Shader Graph?
You can preview Animated Materials by clicking the little picture drop down at the top left of the scene view #UnityTips #Unity3D pic.twitter.com/AwxQ5jj2Sg

— John O'Reilly ? (@John_O_Really) July 17, 2018

Vertex Position(頂点座標)の基礎

複雑な計算を使って動きの作成を開始する前に、まずは、何を動かすのかを理解する必要があります。

シーン内のメッシュには以下の 4 種類の Space があります。

  • Object : メッシュのピボットを基準とした頂点座標
  • View : カメラを基準とした頂点座標
  • World : ワールドの原点を基準とした頂点座標
  • Tangent : 特殊なユースケースで使用([例]ピクセルごとのライティングなど)

 

Position ノードのドロップダウンメニューで、どの Space に影響を与えるか選択できます。

Split ノードを使って、どの軸に影響を与えるか選択できます。

Split ノードは 4 つのチャンネルへ出力します。最初の 3 つは Transform の軸(R=X、G=Y、B=Z)に対応しています。上の例では、オブジェクトの Y 軸に 1 を加えています。これはオブジェクトをそのローカル座標の Y 軸に沿って正方向に 1 動かすことに相当します。

場合によってはワールド空間においてオブジェクトを動かしたいこともあります。これを行うには、Position ノードで World を選択し、出力を Transform ノードを使用してオブジェクト空間に変換し戻します。

マスクを使用する

以上でメッシュの動かし方が理解できました。ここで、エフェクトを制御する方法を理解しておくと役立ちます。

Lerp などのノードを使用すると、2 つの値の間でブレンドを行うことができます。T 入力は Lerp の制御値です。T 入力が 0 の時(黒く表示される)は A チャンネルが使用されています。入力が 1 の時(白く表示される)は B チャンネルが使用されています。下の例ではスライダーを使用して 2 つの入力をブレンドしています。このスライダーの代わりに、以下でご紹介する方法のどれかを使用することも可能です。

テクスチャマスク

白黒テクスチャの場合、詳細なシェイプを使用してメッシュを押し上げることができます。上の例で、白は範囲内における最大の高さを表し、黒はメッシュの位置に全く効果が及ぼされていない状態を表しています。黒の数値は 0 であり、0 をメッシュの位置に加えてもメッシュは動かないからです。

Vertex Position(頂点座標)にテクスチャを使用するには、通常の Sample Texture 2D ノードではなく Sample Texture 2D LOD ノードを使用する必要があります。テクスチャは、特殊な形状のマスクや一定量のフォールオフが必要な場合などに特に便利です。

UV マスク

テクスチャマスクと似ていますが、UV マスクでは、UV Unwrap に応じて、メッシュのどの部分に効果を及ぼすか選択できます。上のキャプチャー画像では、UV の U 軸を使用して左から右へのグラデーションを作成しています。グラデーションにオフセットを加えるには Add ノードを、強度を上げるには Multiply ノードを、フォールオフを増加させるには Power ノードを使用してください。

Vertex Color マスク

各頂点が、Vertex Color と呼ばれる一揃いの Vector3 情報を格納しています。Polybrush パッケージを使用すれば、頂点色をエディター内で直接ペイントできます。あるいは、3D モデリングソフトウェア(3ds Max、Maya、Blender、3D Coat、Modo など)を使って頂点色をアサインすることも可能です。ほとんどの 3D モデリングソフトウェアは、デフォルトでは RGB の最大値が各頂点にアサインされた形でモデルをエクスポートする設定になっていることも覚えておくと良いでしょう。

上のキャプチャー画像では、分割された Vertex Color ノードの成分のうち、赤(R)のチャンネルが Lerp ノードの T チャンネルに接続されて、マスクとして機能しています。入力が 0 の場合に Lerp ノードの A チャンネルが使用され、入力が 1 の場合に B チャンネルが使用されています。結果、上のセットアップでは、頂点に赤の頂点色が割り当てられている場合にのみ Y 軸に 1 が追加されることになります。

World Orientation マスク

Normal Vector ノードを使用すると、メッシュの面の向きによって入力をマスクすることができます。ここでも、効果を及ぼしたい軸(R=X、G=Y、B=Z)を Split ノードで選択できます。上のキャプチャー画像の例では、Y 軸を使ってマスクすることで、上を向いた面だけが正数値になるようにしています。0 と 1 の間でない値は Clamp ノードを使用してすべて破棄することがポイントです。

ワールド座標マスク

この一連のノードは、ワールド空間におけるオブジェクトの Y 軸座標が 0 より大きい場合に入力をマスクします。

プロパティ

シェーダーをビルドする時、思い通りのエフェクトを実現するための適正な入力値を得るのが難しいこともあります。このために(そして後々のプレハブとプリセットのカスタマイズのためにも)、プロパティを使用することが重要です。

プロパティを使用すれば、シェーダーがコンパイルされた後でその値を修正することができます。プロパティを作成するには、Blackboard(右画像)上で、「+」印をクリックしてください。プロパティには 6 つの種類があります。

  • Vector(1 ~ 4): 値を表す文字列です。Vector1 にはスライダーのオプションが付いています。
  • Color: RGB 値です。カラーピッカーと、オプションで HDR バージョンがあります。
  • Texture2D(および Texture2D Array): 2D テクスチャをサンプルします。
  • Texture 3D: 3D テクスチャをサンプルします。
  • Cubemap: 生成されたキューブマップをサンプルします。
  • Boolean: オフかオンの二択設定です。0 と 1 に相当します。

適用例

なびく旗

旗のシェーダーは、オブジェクト空間で、サイン波を旗を横切る形でパンさせて実現しています。UV マスクを使用して左側が動かないようにしています。

フル解像度画像

  1. UV マスクを反転して、それ自体に対して Multiply することで、Y 軸方向にスムーズなグラデーションが作り出されています。これを利用して、旗の中心をオールと反対側の方向へ動かしています。
  2. オブジェクト空間でサイン波が生成されています。プロパティで波の大きさ・周波数・速度を制御しています。波の X 軸を UV マスクでマスクすることで旗の左側の動きを抑えています。
  3. Gradient NoiseStep 関数内に 出力してから Alpha Clip Threshold 内に出力することで一部のピクセルを破棄し、旗の破れを表現しています。

風に吹かれる草とヤシの葉

風のシェーダーは、ワールド空間 Gradient Noise を単一の軸に沿ってパンさせることで、草と葉を穏やかに押し引きしています。

フル解像度画像

  1. ワールド座標を使って、Gradient Noise を Y 軸および X 軸の方向に配置しています。そのオフセットの速度と方向を Vector2 を使って制御できます。
  2. プロパティはオフセットの密度と強度を制御するために使用されます。Gradient Noise から 0.5 を引くことで、メッシュの押し引きが均等になります。
  3. UV マスクによって、葉と草の根本が動かないようにしています。最後に、Transform ノードを使ってワールド座標をオブジェクト座標に変換しています。

このシェーダーでは、カメラと貝の間の距離を計算し、それをマスクとして使用して上半分を回転させています。

フル解像度画像

  1. ゲームオブジェクトの位置とカメラの位置を Distance ノード内に入力することで、マスクを作成できます。One Minus ノードが距離を反転させるので、貝に近付くと正数値になります。Clamp ノードは、1 より大きい値と 0 より小さい値を破棄します。
  2. この UV マスクが貝の上部のみを回転させていますが、大抵の場合は、Vertex Color マスクの方がより簡単で融通が利きます。
  3. 貝の閉じた状態と開いた状態を Lerp ノードでブレンドしています。Rotation はゲームオブジェクトの Y 軸と Z 軸に適用されます。X 軸を中心に回転させています。

泳ぐ魚

このシェーダー内では、オブジェクトの軸方向に生成されるサイン波によって魚を動かしています。その上で、魚の頭部のマスクを取り除くことで頭部が動かないようにしています。

フル解像度画像

  1. オブジェクト空間の Y 軸と Z 軸に沿ってサイン波を生成しています。波の周波数と速度をプロパティで制御しています。
    X 軸と Y 軸を両方使用しているので、魚は、その幅と高さの分だけ動きます。
  2. サイン波の出力を Multiply して動きの大きさ・距離・強さを制御し、それをオブジェクトの X 軸に追加します。
  3. Lerp ノードで、UV チャンネルの X 軸を使用して魚の頭部をマスクします。Power ノードをプロパティと共に使用することで、動きのエフェクトを魚の後部に移動させることができます。

海の波

最後は、海のシェーダーです!このシェーダーは、メッシュの上部を、スケールと角度の異なる 3 つのサイン波を使用してオフセットします。これらのサイン波は、波の谷間と先端の色の生成にも使用されています。

フル解像度画像

  1. 3 つのサイン波がワールド空間に別々に生成されます。それぞれが、波の大きさ・周波数・速度・輻輳・角度を制御するプロパティを使用しています。
  2. その後、3 つのサイン波が 2 つの Add ノードと組み合わせられ、World Scale Gradient で Multiply されることで、波の先端の高さにバラつきが出ます。この後、組み合わせられた波の変位がオブジェクト座標に加算されます。
  3. 2 つの頂点マスクを使って、まず波を半球の上部のみに限定してから、泡が描画された時に波を再び下に押し下げています。

サイン波の生成

フル解像度画像

  1. X 軸と Z 軸を分割することで、波を 2 方向に生成しています。2 つの乗数を使用して各波の影響を設定しています。例えば、Z チャンネルに 0 を掛けると、X 軸方向のみにサイン波が出力されます。
  2. World Position ノードを X 軸と Z 軸に Split して、それらを Vector2 内で組み合わせると、ワールド空間内に UV 空間ができます。これにより Gradient Noise がワールド全体に平らに設定されます。この出力を Time に追加することによりサイン波がオフセットされ、元々は直線になるものを崩すことができます。
  3. Sine ノードはワールド空間と Time を使用して単純なサイン波を生成します。波の先端は Absolute ノードを使って負の値をフリップして作ります。その後 One Minus ノードでこれらの値を反転することで、波の先端が上に来るようにしています。

参考資料

シェーダーグラフの使用を開始したい方には、GDC で行われた Andy Touch の講演(英語)のご視聴をお勧めします。本記事でご紹介したもの以外のシェーダーグラフの例をご覧になりたい方は、Andy が GitHub で公開している Example Library をご利用ください。

各ノードの説明も含め、シェーダーグラフに関する詳細な資料は、 GitHub の Shader Graph developer Wiki(英語)をご参照ください。シェーダーグラフの世界を探索して、「Graphics Experimental Previews」フォーラム(英語) にもご参加ください!そして、あなたがシェーダーグラフで制作している素敵なプロジェクトをぜひご紹介ください!私の Twitter アカウント(@John_O_Really)に、お気軽にご連絡ください!

2018年10月5日 カテゴリ: Engine & platform | 12 分 で読めます

Is this article helpful for you?

Thank you for your feedback!

取り上げているトピック