言葉遊び/MV解説
ァネイロさんの「言葉遊び」映像をurabenotaさんと共同で制作しました。
今回は当解説にもurabenotaさんをお誘いし、前半melonade、後半urabenotaで各々技術周りの話を書きました。
[1/2] melonade
主に各種実装を担当させて頂いています。
1VERSE & BRIDGE
普段の制作ではp5.jsを愛用していますが、今回はurabenotaさんがビジュアルを作りこみやすいようurabenotaさんの環境に合わせた形で進めることにしました。
…が、左下の歌詞表示がモーラに合わせて少しずつスクロールして欲しかったので、テキストの横幅を楽に取得できることを理由にそこだけp5.jsでプリレンダして使ってます。
下準備編
ァネイロさんの楽曲は歌詞に仕掛けがあることが多いため、それを的確に表現するためにはデータの準備が必須です。
ブロックの上面と側面の文字のシーケンスはテキストデータとして作成します。特殊文字 "_" はその文字を引き延ばす処理を行うためのもので、読み仮名と組み合わせたときに便利に扱うことができます。過置換でも同じ手法を使いました。
ブロックの登場・伸縮タイミングや座標、各種演出の制御はMIDIデータとして用意します。データ作成用のツールとして、スクリプトによる拡張やプロジェクトファイルの構文解析が容易なDAW、REAPERを愛用しています。
私は普段から映像制作にDAWを使うことが多いです。音楽の時間単位をそのまま映像に転用できるのは大きな魅力です。
MIDIデータはノート番号を実装側でマッピングする前提で作るため、実装段階で随時追加・修正することが多いです。
これらのデータをAfterEffectsに持ち込むために、一旦Node.jsのスクリプトでJSONファイルに変換した上でフッテージとして読み込んでいます。
あまり知られていませんが、AfterEffectsはJSONファイルをフッテージとして読み込めます。Adobe独自のMGJSON(モーショングラフィックス JSON)という規格もあったりして面白いです。詳しくはAdobeのドキュメントを参照。
AfterEffects編
AfterEffects上でのシーンの構築にあたり、以下のプロセスで進めています。
全レイヤーをスクリプトで自動生成
エッセンシャルグラフィックスで共通のブロック要素を定義
エクスプレッションでブロック内外の各プロパティを処理
AfterEffectsのスクリプトは.jsxという拡張子で、Adobe ExtendScript言語というJavaScriptの拡張形式が使われています。ExtendScriptで使われているJavaScriptのバージョンは1999年にリリースされたES3のため古く、現在では標準にも関わらず使用できない構文が多く存在します。そのため、TypeScriptのターゲットをES3に設定して出力すると便利です。
AfterEffectsのエクスプレッションはプロパティに紐づくため、標準のエディタで記述するのが一般的です。しかし、エディタ自体の表示が狭く使いづらい上、レイヤーやプロパティを跨いだ変数や関数の定義は基本的に行えず、高度な構造化を行うのに十分な性能とは言えません。
そこで、別途.jsxファイルを作成し解決します。
.jsxファイルを使うとエクスプレッションで使用したい定数や関数をJavaScriptのオブジェクトとして記述することができます。
そのファイルをAfterEffectsのフッテージとして読み込み、エクスプレッション側で参照することでソースコードの共通化が容易になります。
.jsx単体でも使い勝手は良いですが、expression-globals-typescriptとrollup-plugin-ae-jsxを使うことでTypeScriptで記述することも可能です。
AfterEffectsのエクスプレッションをTypeScriptで作成する方法は、以下の記事で詳しく解説されています。
また、今回の制作ではAfterEffectsプロジェクト側の変更を最小限にし実装側でより多くの変更を行えるよう、自動化したいプロパティに予め共通のエクスプレッションを設定することを徹底しました。
例えば、上面・側面の文字のソーステキスト、位置、スケール等にはそれぞれ以下のblock関数を呼び出す共通のエクスプレッションが設定されていて、関数の内部でレイヤー名やプロパティ名などを用いて条件分岐を行い処理しています。
また、レイヤー番号をエッセンシャルプロパティに渡すことで、レイヤーの複製だけでシーン全体の構築が可能になりました。
ブロックのアニメーションをurabenotaさんが作りやすいよう、ブロックが登場する部分や共通のモーラで縦に伸びる部分も含めた基本的な挙動は、AfterEffectsの範囲マーカーとタイムリマップを使用した半自動化に留めています。
最初の登場、伸縮、縦回転のフリップにそれぞれ範囲マーカーを設定し、タイムリマップのプロパティに設定したエクスプレッションからその区間をアニメーションとして適宜呼び出します。これにより、下準備で用意したインとアウトのタイミングを元にレイヤーの時間を再マッピングするだけでブロックがアニメーションするようになりました。
プロジェクトファイルは、urabenotaさんがデモを作り終えたタイミングで私が前述の実装を施し、それ以降の些細な修正は口頭で伝えて進めました。
スクリプトとエクスプレッションはそれぞれ外部ファイルとして読み込んでいるため、Gitでバージョン管理を行いました。私が適宜commit・pushし、urabenotaさん側でpullしてもらうことで同期を行いました。
九割方完成したあたりで、回文の演出としてカメラの180度回転と縦回転のフリップを用いることを決めました。手法を試す中、AfterEffectsのシェイプで実装する疑似3Dでは限界があるという結論に至りました。
Blender編
Blenderで再度実装していきます。Blender上でのシーンの構築にあたり、ブロックは個別のオブジェクトとしてスクリプトで自動生成、ブロック共通の処理はジオメトリノードで実装しています。
ジオメトリノードでの実装部分はそこそこの量がありますが、ブロックの挙動を見た目通りに手続き的に作っているだけなので割愛します。
ブロックを愚直に配置すると処理が重く、テキストを早期にResample Curveノードで軽量化したり、カメラの位置から表示域を推定し描画範囲外のオブジェクトを非表示にしたりなど最低限の工夫を施しました。
AfterEffects上ではブロックのアニメーションの変更をurabenotaさん側で実装の手間なくできるようタイムリマップを用いましたが、Blenderでの再実装が決まった時点でアニメーションの仕様がほとんど確定したため、こちらではアニメーションも手続き的に組んでます。
あとはオブジェクトの生成、ジオメトリノードの適用、プロパティに値を設定、登場・伸縮に合わせてリニアなキーフレームを設定、などをPythonスクリプトで自動化すればブロックの実装は完了です。
AfterEffectsとBlenderそれぞれでカメラの動きを自動生成しました。
AfterEffectsではエクスプレッションでブロックの座標一覧をカーブに補完するアルゴリズムを実装しカメラの動きを生成しています。Blenderではもっとシンプルにブロックの座標と時間をカメラの位置プロパティにキーフレームとして展開し、Blenderのグラフエディタ標準機能で滑らかにしてます。
HOOK
画面下部のコントローラーを五十音図モチーフで作りました。Novation LaunchpadやAbleton Pushを参考に設計しています。
パッドの形状が四角錐台なのはキーキャップが由来です。パッドの明滅と押し込みは前述の手法と同様にデータを準備し、キーフレームを自動生成しています。
2VERSE
早口言葉部分のリップシンクは、調声に使用されたSynthesizer Vのプロジェクトファイルから母音だけを抜き出した後、調声や音源毎の仕様による修正点を微調整したものをBlenderのキーフレームとして出力しています。
この部分はBlender上でPythonを実行する形ではなく、普段使いのPython環境でbpyモジュールを用いてプロジェクトファイルごと生成しました。
[2/2] urabenota
urabenotaです。本MVではビジュアル周りを担当させて頂いています。melonadeさんにお誘いいただきまして、自分もメイキングを寄稿させていただく運びとなりました。技術周りのお話が主になりますので、MVのコンセプトやグラフィックデザインにはあんまり触れません。ご了承ください。
HOOK
リリックモーション
Blenderで制作しました。
リリックのオブジェクトはYi Xiのモデルより手前・奥で分け、それぞれをビューレイヤーとコンポジションノードを用いて書き出しています。最終的にはAfterEffects上で合成します。
ビューレイヤーはコレクションの表示・非表示のプリセットを作成できる機能です。「ViewLayer」は全体表示用で、「front」はキャラモデルより手前にあたるオブジェクトのコレクションのみを表示してます。「back」も同様です。
コンポジションノードではレンダリングに関する細かな設定を行えます。今回は複数ビューレイヤーとクリプトマットの同時書き出しに使用しました(Cryptomatteに関しては後述)。また、サブパス名に\ (バックスラッシュ)を記述することで連番をそれぞれフォルダに格納できます。
通常1カットで複数レイヤーを書き出すならOpenEXRと呼ばれる画像フォーマットが便利です。というのも、マルチレイヤー方式によって1つの画像ファイルに複数レイヤーを格納できるため、連番がかさばらずに済みます。しかし自分の環境とは相性が悪いため、泣く泣くpng連番をいっぱい書き出しました。。。
アイテムボックス
面ごとに異なるマテリアルを割り当てて色分けした後、AfterEffects上でその色を取得、「コロラマ」と「CC Toner」を用いて時間経過に応じてそれぞれの面の色が変化するようにしています。
また、ボックスの奥側だけを見せるために、面の法線を全て反転させ、モデルの裏面を非表示に設定しました。
Yi Xiの3Dモデル
こちらもBlenderを用いて制作しています。3DCG感を排した2Dイラストのルックを目指しました(これは僕の好み)。
モデルはカメラ画角からのみ綺麗に映る設計になっていまして、それ以外からの見た目は一切考慮していません。ので、設計段階で映らないことが決まっていた下半身とか背中側に至っては制作していません。
顔パーツ・後ろ髪はそれぞれメッシュで平面的に作って配置しています。
ですので別画角から見るとかなり崩れが顕著ですね。この方式はベクターイラストを作る要領で画を作れるので楽ですが、更に細部を詰めるならグリースペンシルだったり、ペイントソフトで絵を描く方が効率的かも。
MVはカメラを作り手側で指定できるので、モデル作りや画作りが特定画角を意識するのみで済んで楽です。というか、そうしていかないと作業が多くって疲れます。工程を省いて生んだ余力は他部分のクオリティアップに回せるので、存外コストカットは最終出力に直結する要素だと思います。
アウトライン
全てAfterEffects上での後付けです。
まずBlenderから4種類の画像を書き出します。
下記2枚はCryptomatteと呼ばれるIDマット技術です。仔細は省きますが、ひとまずはレンダリング画像をオブジェクトごと・マテリアルごとに自動で色分けできる機能がある、という認識で大丈夫です。
これらを基にAfterEffects上でラインを生成します。
今回は複数のラインの出し方を併用しているので、項ごとに解説します。
①アウトライン
外の縁です。最下層のレイヤーに配置しています。単色なので分かりづらいですが、元画像を縁取っています。ポップ感を演出したかったので、他に比べてラインは太めです。
②オブジェクト・マテリアルマスクを基にしたライン
どちらも同様の工程なので、マテリアルマスクを例に説明します。
耳のラインのみ他に比べて細く出したかったので、この段階では出ないように設定します。アクションとしては、マスクの耳色を統合して一色にします。色置換には「F's color change」を使用(Hiroshi Furuhashi氏のフリープラグイン「F's plugins」に含まれている)。
ライン付けです。ここには「F's LineDetection」を使用しています。異なる色間に1ピクセルのラインを描画できるエフェクトです。この時点では線のアルファ値にムラがあるので、CC Thresholdで二値化しておきます。
線の厚み付けにはTumoiYorozu氏が制作された縁取りエフェクト「StrokeFx」を使用しています。レイヤースタイルの縁取りをエフェクト化したものです。こちらのエフェクトはAE煮鯖(AfterEffectsプラグイン・スクリプト情報共有コミュニティ)の会話中で制作・配布されているのですが、あまりにクローズドな公開形式だったので、表立って宣伝していいものかな。。。まあ、そういうものがあるということで、代替の機能やエフェクトを持っていればそちらでも。
仕上げにラフエッジを掛け、手書き線の揺らぎを出して完成です。
オブジェクトマスクに関しても同様の手順を行います。
二種類のマットで出せるラインが違うので併用しています。このカットだとジッパーの境になるラインがオブジェクトマスクでしか出せないです。
髪はライン色と同じ単色黒なので、そのあたりのラインは適当なままに。
加えて耳の線も出します。ここは細かいディティールを残しつつラインは出したかったので、線を細くしています。
③グリースペンシルで検出するライン
キャップのアジャスターと袖の皺に使用。
Blenderにはラインアートという機能があり、これを使うとオブジェクトの輪郭などに沿ってグリースペンシルで線を自動描画できます。今回はラインを加えたい任意の辺をマークし、描画する用途で用いました。
下記資料はベースカラー出力ままの画像ですが、それぞれの部位に1pxの青い線が付いていて、それが先の出力結果です。
この色をOLM Color Keyで抜き、先の手順で厚み付けすることで他同様のラインを出力できます。
④シェイプレイヤーで描くライン
今までの工程で出し切れなかった部分に、AfterEffectsのシェイプレイヤーを用いて手作業でラインを置きました。これはグリースペンシルを用いてみても良いかもしれません。
これまでの線を全て合成してアウトラインは完成になります。
グリースペンシルのラインアートに関して
この機能で太いラインを出す場合、手前にオブジェクトが重なった時にライン先がはみ出してしまい、それを避けるために他のプロジェクトでも1pxのラインアートをAE上で太くする手法を取ることがあります。
他にもキモいメッシュだとライン検出が不安定になりがちで、今回はメッシュの形がキモかったため上手く動作せず、AfterEffects上でのライン付けを採択しました。
しかし強く言っておきたいのが、僕は全然ラインアートを使用することもありますし、アウトラインを出すのにラインアートは有効な手立てだと思います!本当にケースバイケース!Freestyleに比べて非常に軽く、何よりビュー上で線のプレビューをしながら作業に取り組めるところが素晴らしいです。
一応その裏付けとして(宣伝にはなってしまいますが)、僕が過去携わったこちらのMV内で3Dオブジェクトに用いられるアウトラインは、全てラインアートと通常のグリースペンシルオブジェクトで出力しています。参考までに。
顔の影
顔の影は先のマテリアルマスクで肌色を抜き、AfterEffects上のシェイプレイヤーで描画・合成しています。後者はBlender上のシェーダーで作れば良かったです。
1VERSE & BRIDGE
melonadeさんが生成したカメラワークに加えて、演出として、「ことばのおばけ」部分でカメラを特定の画角に留めたい、という構想がありました。
しかし生成の兼ね合いでキーフレームが1フレーム感覚で打たれているので、これを弄って画角調整するのは骨が折れる話ですし、誤って必要な部分を削ってしまったら再度生成する必要があり面倒です。
ですから、今回はオブジェクトコンストレイントの「位置コピー」を使用しました。これはオブジェクトの位置を任意のオブジェクトの位置と同期させる機能で、その影響度を0から1でキーフレーム制御できます。ですから、元のキーフレームを弄ることがなく動きを追加ができて、そのうえ元の動きとの継ぎ目をブレンドするのも容易。とても便利!
本制作以外にも僕はカメラワークにオブジェクトコンストレイントを多用しています。便利な機能ですので、知ると制作の幅が広がるんじゃないでしょうか(他にはトラック、チャイルド、パスに追従をよく使う)。
2VERSE
早口言葉です。
リップシンク
melonadeさんの項で前述されたリップシンクの解説を引き継ぎます。先の解説では発話タイミングと母音に対応した1、2、3のキーフレームを取得しました。
口の切り替えにはジオメトリノードを用いました。
インスタンスとするオブジェクトにジオメトリノードを作成しプロパティにインデックスを追加、取得したキーフレームを貼り付けます。
そして母音それぞれの口の形を作りコレクション「a」「i」「u」にそれぞれ格納。それをインデックススイッチで表示を切り替える寸法です。
ただ、同じ母音が連続する場所では口の動きがぎこちなく見えてしまいますし、間に口を閉じる動きを加えれば、より自然に見えるでしょう。そのため手動で調整を施していきます。
連続しがちだった「あ」の口の別パターンを二種類、閉じた口を追加で制作し、インデックススイッチに登録します。
最後にインデックスを追加した分キーフレームを調整し、リップシンクは完成です。
顔の接写
顔の接写になる部分は、元のモデルからディティール調整を行うためにそれ専用のモデルに切り替えています。外から見たらかなり変な感じ。
書いた人
melonade @melodynade
urabenota @urabenota


コメント