「ギザギザポテチ」解説

C4Dで15秒のショートアニメを作りました。
本記事ではこの映像を作るのに使った手法などをご紹介します。実際の制作工程はかなり試行錯誤が長く迷走していたのですが、「最終的にこういう手法に落ち着いたよ」という結果のダイジェストのような感じになります(それでもだいぶ長いです)。

やろうとしたこと

このプロジェクトのフォルダには「procedural」という名前がついています。Procedural=プロシージャルは「手続き型」という意味で、3DCGの世界では「パラメータの組み合わせでなんかやること」とか、あるいは「パラメータ変更だけでいろいろできて非破壊編集」というニュアンスもあるようです。
C4Dにはそういう「プロシージャルな機能」がたくさんあるので、そのへん活用してなんかしようというのがスタートでした。といいつつ、プロシージャルはあくまで手段なので、実際の制作に入ってからはあっさり破壊的編集に切り替えているところもあります。

映像の内容としては、現実にあるもの=ポテトチップスを題材とし、見た目にも説得力のある動きを見せる、それでいて実写映像では不可能な表現をする、といったあたりにもチャレンジしました。

では、以下、具体的な制作についての解説になります。

じゃがいもを作って落とす

最初のカットは、じゃがいもが落っこちてきて皿の真ん中に収まるところまでです。

じゃがいものモデルとマテリアル

じゃがいものモデルは不等倍スケールした球体プリミティブに変位デフォーマで凹凸をつけたものです。

凹凸の元になるシェーダはノイズです。ノイズシェーダは「シード」の値を変えるとノイズの分布がランダムに変化するので、それによって変位の凹凸の具合も変化します。シード値を1つずつ動かしていけばそのうち「いいかんじ」のイモが出現するというわけです。
この方法だと、元は同じモデルでもノイズのシードを変えるだけ無限にバリエーションが作れるので、イモが大量に必要な場合などにも役立ちそうですね。

イモにはRedshiftマテリアルで、皮付きのじゃがいもっぽい質感をつけました。ノイズをあれこれ重ねているだけで、テクスチャ画像は使っていません。このへんもプロシージャルです。
カラーのほかにSubsurfaceで若干、光が透けるようにしています。これがないとカッチカチに不透明になって、塗装したコンクリートみたいに見えます。

レンダリングするとこんな感じです。マテリアルのRoughnessとColorにはColor Layerが入力されていて、2つのColor Layerにはマスクとして同じNoiseが使われています。これで「ざらっとして色が濃いところ」と「つるっとして色が薄いところ」に塗り分けています。

芽などの構造上のディテールがありませんが、なんとなくじゃがいもには見えるのでよしとしました。

じゃがいもが落っこちるアニメーション

じゃがいもは上から落っこちてきて皿の真ん中に収まります。このアニメーションは手付けではなく、ダイナミクス(物理演算)で行っています。実は皿のほうにもダイナミクスを設定してあって、イモがぶつかったときにちょっとだけ揺れています。

ダイナミクスでやると簡単にリアルな動きになりますが、そのぶん結果は運任せになるので、最後が期待通りの状態になるとは限りません。今回の場合も、ダイナミクスの結果では止まる位置も向きも中途半端でした。
ダイナミクスのパラメータをいじったりフォースやコリジョンで細工したりして、最終的に「狙い通り」の結果に追い込むことも不可能ではなさそうですが、そうやって手間をかけると「ダイナミクスで楽をする」というメリットがなくなりますよね。

そこで、ダイナミクスで落としたじゃがいもはアニメーション用のダミーとし、本番用のじゃがいもをダミーにコンストレインすることにしました。

いったんダミーでダイナミクスを計算して、キャッシュを取っておきます。ダミーが落ちた後の止まった状態に対して、次のカットの冒頭の状態で配置した本物のじゃがいもをコンストレインします。このとき、コンストレイントのターゲットにはダミーを直接指定するのではなく、子階層に置いたヌルを指定しています。このヌルを動かすことで、ダミーと本物の位置関係のオフセットを調整できます(アニメーションもできます)。

これでアニメーションを再生すると、ダミーが落っこちて転がる動きに本物がついてきて、最後は狙い通りのところで止まることになります。

ギザギザのポテチを作る

次のカットからポテチができてきますが、まずは完成形のポテチを1枚作って、モデルやマテリアルを検討しています。

ギザギザにスライスする

ポテチのギザギザスライスはジェネレータだけで作っています。ギザギザのフォルムは規則的に反復する要素で構成されているので、数値で定義できるプロシージャルモデリングの本領発揮といえますね。

(1)数式スプラインでサイン(Sin)カーブの波線を出す
(2)押し出して波板にする
(3)厚みをつける
(4)じゃがいも本体と「交差」のブーリアンをかける

これでギザギザにスライスしたじゃがいもができます。

これがポテチ1枚分になります。この「波板ブーリアン」の交差する位置をポテチの厚み分だけ上下にずらしていけば、じゃがいも全体をスライスできます。

スライスしたイモを曲げる

ギザギザカットしたじゃがいものモデルは、2つの屈曲デフォーマで曲げて(ポテチはだいたいタテとヨコで逆向きに曲がっています)、さらに変位デフォーマで少し歪ませて「揚がった」状態にしています。
これらのデフォーマの強度をゼロから大きくしていくことで、「だんだん揚がっていく」アニメーションができます。
こうやってデフォーマで曲げる都合もあって、ポテチのメッシュはそこそこハイポリです。

ポテチのマテリアル

ポテチのマテリアルには「揚がる前=生のじゃがいも」と「揚がった後=ポテチ」の2つの状態があります。どちらもSubsurfaceで「透けている」感じを出していて、揚がった後は焦げ目と微細な凹凸がついています。

映像では「だんだん揚がっていくアニメーション」があるので、この2つの状態の間でシームレスに遷移させる必要がありますが、RedshiftマテリアルではLayer系のノードのMaskから操作可能です。

Material Layerに入力されている2つの「RS Standard」がそれぞれ「生のイモ」と「ポテチ」のカラー成分で、Displacementは「ポテチ」になると現れる細かい凹凸です。

「ポテチ」のほうでは、TextureノードでColor Layerの濃淡の2色をマスクして、まだらに焦げた感じを表現しています。イモの皮でやったのと似たような構成です。

Color Layerのすぐ下に使われてないNoiseがありますが、これは当初、濃淡のマスクをNoiseでやっていた名残です。濃淡のパターンは1枚1枚のポテチごとに個体差を出したかったのですが、RedshiftのNoiseノードでノイズの出る位置をオブジェクトごとずらす方法がわからず断念しました。NoiseのCoordinatesにあるSourceでVertex Attributeにするとメッシュの頂点情報を読み出してなんかできるんだと思いますが、ドキュメントに何も書いておらず、ちょっといじっても手応えがなかったので、いまも謎のままです。

そういうわけでNoiseを使うのはやめて、ノイズパターンをずらすのはメッシュのUVでやることにし、濃淡のマスクはUVが反映されるTextureノードに変更しました。ノイズパターンのテクスチャ画像は、C4Dのノイズをベイクしたものをベースに作りました。

スライスされたイモは薄い板なので、UVはべったり平行投影で問題ありません。スライス1枚ごとにUV座標をあちこちにずらして、濃淡のパターンの個体差をつけています。下図はそのうちの1枚のUVで、位置をずらすため、周囲に隙間があります。

「生のイモ」が「ポテチ」を変化するアニメーションのために、複数のレイヤー系ノードで共通のマスクとして使っているのが、ピンクで表示されている「Vertex Attribute」ノードです(このピンクは仮のカラーです)。
Vertex Attributeはメッシュの頂点マップを参照するので、ポテチのメッシュの頂点マップの値を書き換えることで、当該箇所のマテリアルを動的に変化させられます(頂点マップの操作については後述)。

量産したスライスはポリゴンメッシュとして確定する

アニメーション作業の前に、じゃがいも全体をギザギザにスライスし、「現在の状態をオブジェクト化」でポリゴンメッシュとして確定しました。後で出てきますが、計39個になりました。

メッシュを確定した時点でプロシージャルではなくなりますが、39個もあるスライスをプロシージャルなまま維持しておくのはあまり得策とはいえません。ビューのパフォーマンスに影響する恐れがあり(大丈夫な場合もあります)、オブジェクトの数が多くなるぶん管理が煩雑になります(そもそもデフォーマを39セットも単純コピーしている時点でプロシージャル手法としては問題アリともいえます……)。

後でメッシュの修正が必要になったとしても、プロシージャルモデリングの元になるオブジェクト(イモと波板とブーリアン)を1セットだけ残しておけば対応できます。

ポテチを飛ばす

次のカットでは、スライスされたポテチが空中に飛んでいきます。

じゃがいもをスライスしていくアニメーション

じゃがいも本体のほうは、スライスと同じサインカーブから作ったギザギザの断面を持つメッシュ(下図の「slicer」)を使い、ブーリアンで削ります。

この「slicer」をイモのてっぺんから下に向かって動かすと、イモを削り取っていくアニメーションになります。このとき「1枚ずつスライスしている」ように見せるため、キーフレームの補間は「ステップ」にしています。イモが削られて高さが1段低くなったタイミングで、同位置にあるスライス片の表示をオンにすると、その部分が切り離されたように見えます。

アニメーションの後になるほどキーフレームの間隔が詰まって、削るスピードが上がっています。39個のオブジェクトの表示切り替えは単純に1つずつキーフレームを打っています。こういうのをくり返し何度もやるならXPressoとユーザデータで一元管理したほうがいいのですが、今回はこれ一度きりなので、普通にキーを打っています。

下図はスライスを上に飛ばさずにその場に残している状態です。イモはスライスされると同時に皮もなくなっていますが、これは皮をあれこれするのが面倒だったからです。結果的に「スライスされた」という変化がわかりやすくなったのでよしとしました。

クローナーとエフェクタでポテチを飛ばす

スライス片のオブジェクトはクローナーに入っており、簡易エフェクタを2つ使って空中に飛ばしています。
スライスされた順に飛ばしていくため、1つめの飛ばすエフェクタには上下に幅の狭い線形フィールドを設定しています。フィールドを上から下へ徐々に移動させることで、先にカットされたスライス片から順にエフェクタの効果が現れ、飛んでいくようになっています。
スライス片は最初、斜め上に飛んでいき、2つめのエフェクタで反対の方向に押し戻されます。押し戻すほうのエフェクタには、上にいくほど効果が出るよう、上下に幅の広い線形フィールドを設定しています。

フィールドは仕組みが複雑なのでずっと苦手意識があったのですが、今回使ってみてちょっと慣れた気がします。結果を読むのは相変わらず難しいですが、試行錯誤を重ねればなんとかなりそうな感触はつかめたかもしれません。

使っているフィールドには他に、スライス片を曲げるデフォーマ用と、マテリアルを変化させる頂点マップ用のものがあります(後述)。

空中でポテチを揚げる

次のカットではポテチが空中でらせん状に並び、上昇した後にジュワッと「揚がって」皿に落ちます。

らせん状に飛ばすアニメーション

ポテチを空中でらせん状に並べるのには、スプラインエフェクタ(クローンをスプラインに沿って並べるやつ)を使っています。エフェクタが参照しているのは「らせん」スプラインで、これはプリミティブなのでパラメータで形をコントロールできます。

スプラインエフェクタでは「Start」と「End」の値でスプラインに沿ってオフセット移動させているほか、「らせん」スプライン自体のパラメータや角度などもアニメーションさせています。

そのほか、簡易エフェクタを使って個々のポテチを若干小さくしたり(そのままだとスペースが足りませんでした)、ランダムエフェクタで配置にばらつきを出したりしています。

ポテチを曲げるアニメーション

上昇中に徐々にポテチが「揚がって」曲がっていきます。
スライス片の1つ1つに屈曲デフォーマを入れ、これが線形フィールド(上図、上のほう)の中を移動することで、デフォーマの強度がゼロから最大まで徐々に上がっていくように仕込んであります。
屈曲デフォーマのうち、ゆるく曲げるほう(Bend_Z)はイモから切り離された直後から効いています。空中で効いてくるのはきつく曲げるほう(Bend_X)です。
細かく歪ませるための変位デフォーマは、このカットでは見ても効果がわからなかったので、オフにしています。

この後、ポテチが落下して線形フィールドの中を逆戻りするので、このままの状態だと屈曲デフォーマの強度がまたゼロに戻ってしまいます。そこで、すべてのスライス片が線形フィールドを通過し終えたら、線形フィールドを皿よりも下まで移動させ、ポテチが落下した後もフィールドの値が最大で維持されるようにしました。

「ディケイ」で値を維持する方法(後述)や、デフォーマ側でフィールドを無効にするという方法でも最大値を維持できるのですが、今回の場合はこのスライス片が39個あり、つまりデフォーマも39セットあるため、デフォーマのフィールド設定にアニメーションを設定するのは避けました。

デフォーマのフィールド設定の項目は、複数選択したときに下図のように操作を一切受け付けなくなることがよくあります。選択されている複数のデフォーマでフィールドの設定内容自体が同一であっても、内部の項目の選択状態が異なっているだけでこうなってしまうようなので、多数のデフォーマのフィールド設定をまとめて扱おうとすると面倒なことになります。

ほかにもXPressoで複数のデフォーマのフィールド設定をすべて同期してしまう方法などもあるのですが、今回の場合は上図のように線形フィールドをツイッと動かすやり方のほうがずっと簡単だったので、そちらを選びました(ディケイは入れてあったものの結局使わずオフのままです)。

空中でマテリアルを変化させる

ポテチが上昇するにつれて「揚がって」いくマテリアルの変化には、前述の「Vertex Atrribute」ノードを使っています。

このVetex Attirbuteノードが参照している「VM_mat_mask」は、クローナーに設定されている頂点マップです。個々のメッシュではなくてクローナーに一括して頂点マップを設定できるのは簡単でいいですね。
Vertex Attributeノードからの参照はタグへのリンクではなく名前による指定になっていて、マテリアルが適用されているオブジェクトに該当する名前の頂点マップがあれば、このノードから参照される、という仕組みです。名前指定なので同名の複数のタグを対象にすることもできます。

この頂点マップも線形フィールドで制御しています。

個々のポテチが線形フィールド内を移動するに従って、頂点マップの値が変化します。プレビュー動画では赤=0から黄色=1へ変化しています。この頂点マップをマテリアルのマスクが参照しているので、プレビューで見て「黄色」のところがマテリアルでは「揚がっている」状態になります。

ところで、最初はポテチの入れ物としてクローナーではなく「破砕(Fracture)」を使っていたのですが、破砕ではフィールドで頂点マップを書き換えることができませんでした。破砕をさらに「一体化」に入れるとできるようになるのですが、それだと無駄な計算がありそうだったので、ポテチの入れ物はクローナーに変更しました。

カメラは真上から撮ってますが、らせん状に並んだポテチのうち、上の方は揚がっていて、下の方はまだ揚がっていないという、グラデーションがついた状態になっているのがわかりますね。

このまま最後まで「揚がりきっていない」状態のポテチを混ぜておくことで、出来上がったポテチの色味に個体差を出すことにしました。

先に示した頂点マップのフィールド設定で「線形フィールド」の上にある「ディケイ」には、フィールドによって変化した値をそのまま(最大値または最小値で)維持する効果があります。ポテチが揚がった後に落下し、線形フィールド内を逆戻りしても、ディケイの効果で頂点マップの値はそのまま維持されているので、個々の揚がり具合にグラデーションがついた状態が維持されるわけです。

ダイナミクスで落とす

ポテチはらせん状に上昇した後、皿に向かって落下します。上昇するまではスプラインエフェクタで動かしていましたが、上昇のピークでダイナミクスをオンにして制御を乗っ取り、落下させています。

C4Dの新しいダイナミクスはGPU演算になったおかげで計算がすごく速くなったので(元からあるBulletダイナミクスはCPU演算です)、試行錯誤を重ねる際のストレスはだいぶ減っています。とはいえ、設定が重いとC4Dがフリーズすることもよくあるので、複雑なことをやるときはそれなりの覚悟が必要なようです。

一応、要点と思われるところを挙げると、

(1)ハイポリメッシュのポテチの衝突判定をほどよく簡略化させるため、「衝突形状(Collision Shape)」を「凸形状(Convex Hulls)」にする(この場合は「自動」でもこれになります)、「ジオメトリ精度(Geometry Accuracy)」はうかつに上げない(計算が重くなります)

(2)多数のコリジョン判定をこなすため、プロジェクト設定のシミュレーションで「くり返し数(Iterations)」とコリジョンの「パス数(Passes)」を上げる(理屈はよくわかりませんが効果はありました)

(3)ダイナミクス計算はキャッシュしておく(時間をランダムシークできるようになります)

といったあたりでしょうか。

プロジェクト設定で「リジッドボディ形状(Rigid Body Shapes)」の描画をオンにしておくと、実際にコリジョンが判定されている形状がビューで描画されるのですが、これはリアルタイムで計算しているときだけで、キャッシュモードでは無効のようです。惜しい!

コリジョンとフォース

ポテチを皿に落とすとき、普通にやると周りにこぼれます。そこでいくつか細工をしています。

まず、ポテチが落下する経路の途中にフォースの「引力(Attractor)」を配置して、はじめに落ちるポテチを皿の真ん中に誘導しています。強度はカメラで覗いてみて「いい感じ」になるよう調整しました。

それでも外側寄りのポテチは皿の外に飛んでしまうので、見えないコリジョンオブジェクト(上図の青いワイヤーフレーム)を使って、最終的には必ず皿の中に収まるようにしました。真上からだとあまり気になりませんが、横から見るとポテチが何もない空間を滑り落ちているのがわかりますね。

ポテチに影響しているフォースは「重力(Gravity)」「タービュランス」「引力」の3つです。
「重力」は最初はゼロで、ポテチが上昇しきった後、ダイナミクスが有効になってから徐々に強くなります(グローバルの重力はゼロにしています)。
「タービュランス」は、ポテチが落下し始めるあたりでランダムな動きを加えるために使っています。動画をコマ送りで見るとわかるのですが、ポテチはらせん状の列を乱すような動きをしてから落ちていきます。
「引力」は前述の通りです。

パラメータをアニメーションする

この映像のポテチのアニメーションは、現実では起こらない作為的な動きを表現しているので、ダイナミクスに関するパラメータのほうもアニメーションの途中で作為的に変化させています。

上記の3つのフォースの強度は個別に変化させています。重力はゼロから徐々に強くなり、タービュランスと引力は必要なタイミングだけ効果を及ぼした後、ゼロに戻るようになっています。

ダイナミクスに「ブレーキ」をかける

ダイナミクスのパラメータをデフォルト値のままでポテチを落とすと、皿に収まった後も動きが止まらずピクピクし続ける結果になりました。このピクピクはダイナミクスの計算精度を上げていってもなかなか解消できなかったので、パラメータで「ブレーキ」をかけることにしました。

リジッドボディダイナミクスのパラメータには、ダイナミクスの効果を減衰させたり、完全に静止させるためのものがいくつかあり、これらが「ブレーキ」として使えます。ただし、最初から高い値でブレーキをかけていると、ポテチが途中で止まったり、そもそも落下しなかったりしたので、落下中はデフォルト値のままで、落下後に徐々に値を上げてブレーキをかけるという設定にしています。

映像の最後のほうでなぜか1枚だけ「カサッ」と動いている個体があるのですが、面白かったのでそのままにしてあります。

レンダリング

カメラとライトは完全に自己流というか、理屈なしの勘のみでやってるので、特に言えることはありません。

Redshiftのレンダリング設定のほうもあまり詳しくないので、ほぼデフォルトのままです。レンダリング品質には問題ないように思います。

パフォーマンス関連

レンダリングスピードを上げるためにSystemの「Bucket Size」を最大の512にしました。バケットサイズが大きいほうがレンダリングは速いのですが、ただ上げればいいってものでもないようです(デフォルトは128です)。

同じくSystemのMemoryにある「Used GPU Memory (%)」は、デフォルトの90から70に落としています。これはRedshiftがPCのGPUメモリのうち最大で何%まで占有するかという設定ですが、C4D以外のタスクに回すGPUメモリが少なすぎるとPCが不安定になり、結果レンダリングも途中で止まるということがあるらしいので(実際に過去のプロジェクトで、レンダリングが途中で止まってたという経験があります)、70まで落としています。今回はシーンの規模が小さいので、70%で間に合っているようです。

背景

緑色の背景は、真面目にやるならコンポジットで後から重ねるべきなのですが、面倒なのでレンダリングの段階から入れてしまいました。

RedshiftではC4Dの背景オブジェクトはレンダリングされません。RS Post-EffectsのBackgroundに画像を指定します。カメラにも同じ設定があり、個別にも設定できます。

モーションブラーとDOF

モーションブラーとDOF(Bokeh)はポスト処理ではなく、Redshiftのレンダリングで行っています。

RedshiftはモーションブラーやDOFを使っても、さほどレンダリング時間に影響しないようです。Unified Samplingがよくできてるのか、あるいは、元から膨大にサンプリングしているので、それを時間的、空間的に分散させればいいだけ、ということでしょうか。昔はモーションブラーやDOFでレンダリング時間が10倍になるとか普通にあったので、時代の変化を実感しますね……。

モーションブラーをオンにするとなんかいろいろ変になることがありました。仕様なのか不具合なのかなんともいえない感じなのですが、モーションブラー設定の「Frame Position」を切り替えると直ることがあったので(Startで直る、Centerで直る、いずれもありました)、メモとして書いておきます。モーションブラーでなんか変になったらFrame Positionいじると直るかもよ! っていう感じです。

映像の編集とサウンド

レンダリングした映像はAdobe Premiere Proで編集しました。個人制作だとだいたいいつもコンポジットしないので、After Effectsは使っていません。

映像の編集

映像は編集といっても、カットをつなげてタイトルの文字をのっけただけです。タイトルの文字はカメラのドリーに合わせてじわっと前に出てきているのですが、これはトラッキングなどではなくて手付けです。

サウンド

今回、サウンドの大部分はPremiereについてる音源を使いました。いまのPremiereって無料の音源が1万個以上ついてるんですよ、知ってました?

最後にポテチが落ちるところの音だけは、自分で録音しました。実際にポテチを皿に落とすと、陶器が鳴る「チリンチリン」っていう音がほとんどだったので、プラスチックのまな板に落とした「ガサッ」っていう音も録って、2つ混ぜて使っています。

音源ごとにイコライジングやリバーブなどの処理もしていますが、これも自己流でなんとなくやってます。

まとめと雑感

今回の「ギザギザポテチ」プロジェクト、締め切りのない個人制作だったので、これまであまり使ったことがない機能にもいろいろ手を出すなどして、思う存分迷走することができて楽しかったです。仕事だとそういうわけにはいかないので、なるべく安全策を取るわけですが、いつもそうだと新しいノウハウも得られないので、やはりときどきこういうチャレンジはやったほうがよさそうです。

レンダラーとダイナミクス、どちらも現代のマシンパワーを前提に力で解決する方向に進化していて、そのぶんユーザーは楽をできるのでありがたいと思いました。

ダイナミクスといえば、今回は使っていませんが、旧ダイナミクスのBulletのほうが自由度というか他の機能との連携では選択肢が多いようです。両者うまく使い分けていきたいですね。

フィールドに関しては、リスト/スタック型のインターフェイスの限界みたいなものを感じました。構成要素の依存関係を一覧することが困難で、属性マネージャの中に別のマネージャが詰め込まれているような無理矢理さも感じます。こういうやつこそノードベースのほうが向いているんではと思うのですが、シーンノードやカプセルにはまだごく限定的な機能しかないらしく、また、高度な機能が実現したとしてもユーザーが受け入れるかどうかはまた別の話なので(ずっと昔からあるXPressoも実際に使っているユーザーはあまり多くはなさそうですし)、いまのぐらいがちょうどいいのかもしれません。どう思います?(投げっぱなし)