vvvvでループ映像作るときによく使うノードの組み合わせ

# はじめに

[vvvv Advent Calendar 2016](http://qiita.com/advent-calendar/2016/vvvv) の6日目の記事です。
5日目は @AquaLamp さんの [AEオフにvvvvを推しにいった話。](http://qiita.com/AquaLamp/items/4f1de17fbde3e119aa02) でした。

vvvvを使っていくつかループ映像を作っているのですが、だんだん自分のパッチに出てくるノードの組み合わせパターンがテンプレ化してきたので、いくつか晒しがてら解説します。別にループ映像に限った話でもないものが多いかもしれません。
また、今回のパッチはDX9で組んでいますが、DX11でも基本的に同じことはできるはずです。

下に書いた内容についてはこのパッチにまとめてあります。
[vvvv\-sandbox/20161206_NodePatternForLoop/tips\.v4p](https://github.com/clomie/vvvv-sandbox/blob/master/20161206_NodePatternForLoop/tips.v4p)

# LFO + LinearSpread でループする値の生成

`LFO (Animation)`の出力を`LinearSpread (Spreads)`のPhaseピンに設定すると、LinearSpreadの出力値がループします。値の範囲がループするまでの時間はLFOのPeriodで指定できます。
パッチの組み方を逆にしてLFOのPhaseにLinearSpreadの出力を設定しても似たようなことが可能ですが、出力範囲が固定だったり、個人的にループ映像を作る場合は1つのLFO出力でパッチ全体を制御したいので前者の形を選ぶことが多いです。

![LFOLinearSpread.PNG](https://qiita-image-store.s3.amazonaws.com/0/26489/a566a4f3-1e75-1529-edfe-f005c1a7d09d.png) ![LinearSpreadLFO.png](https://qiita-image-store.s3.amazonaws.com/0/26489/09c86a38-5dd5-2079-f059-560459f2b891.png)

実際使うときはLinearSpreadに`input=0.5`, `width=1.0`を設定して出力値の幅を0～1に固定してから、いろいろ処理を挟んだ後、最終的に`Map (Value)`ノードで出力値の幅を決める、というパターンが多いです。
出力値の間隔を一定でなくバラけさせたいので`RandomSpread (Spreads)`を挟むとか、順番をバラバラにしたくて`Randomize (Spreads)`を通すとか。
一番よくやるのは、TranslateのZに使うパターンです。オブジェクトが奥から飛んでくるタイプの映像作るときとか。

![ValueMarginRandomized.png](https://qiita-image-store.s3.amazonaws.com/0/26489/2a86af24-ad9d-3ae7-fdc0-575e44341b9f.png) ![LinearLFOSample.png](https://qiita-image-store.s3.amazonaws.com/0/26489/18a1f1d3-8f03-1c22-ccb8-a9ca5ac4418c.png)


# B-Splineの出力でカメラ位置と視点制御

カメラのPositionXYを`B-Spline (Value)`で生成します。似たようなことは以前に[vvvvでトンネル系のループ映像を作る](http://qiita.com/clomie/items/e2b3344348173a6d6e7a#b-spline%E3%81%A73d%E7%A9%BA%E9%96%93%E4%B8%8A%E3%81%AB%E6%9B%B2%E7%B7%9A%E3%82%92%E6%8F%8F%E3%81%8F)という記事でも触れているので、参照してもらえると良いかもしれません。B-Spline曲線を1ノードで複数出力する話とかも。
LFOのOutputをB-SplineのInputに入れて曲線の値を辿らせています。`LFO + 0.00`で出てきた値を位置座標のXY値、`LFO + 0.01`で出てきた値を視点座標のXYに使います。それぞれZ値は別に固定値で設定しています。

![CameraControl.png](https://qiita-image-store.s3.amazonaws.com/0/26489/4841e68c-e11b-3525-33ec-df48f2475b71.png)

実際の使い方ですが、InterestとLookAtを`LookAt (Transform Vector)`ノードに入力すればView行列ができるので、あとは`Perspective (Transform)`をProjection行列としてRendererに設定すれば良いです。
`Camera (Transform Softimage)`に設定したい場合は、InterestからLookAtを引いて出てきた方向ベクトルを、`Polar (3d Vector)`に設定すればYawとPitchが取り出せます。
`Rotate (Transform)` と組み合わせるとなんとなく雰囲気が出るような気がして多用しています。

![CameraControlSample1.png](https://qiita-image-store.s3.amazonaws.com/0/26489/173ca89c-720a-ab0d-c3c3-6145f53b954a.png) ![CameraControlSample2.png](https://qiita-image-store.s3.amazonaws.com/0/26489/9a09d57e-f640-8476-e810-0b7f77048154.png)

![capture.gif](https://qiita-image-store.s3.amazonaws.com/0/26489/3287454a-7b77-1c07-954b-7d657ff86e91.gif)


# Tweenerの入力にMonoFlop+Decayを使う

`Tweener (Value)`はイージングが超簡単にできるめちゃめちゃ便利なノードです。これだけでもよく使います。
`MonoFlop (Animation)`は入力を一定時間維持して勝手にOFFになるFlipFlopです。`Decay (Animation)`を挟んで0→1は滑らかに、1→0は一瞬で値が変わるようにしています。
これでMonoFlopの入力がイージング開始のトリガーになります。イージング終了後は勝手に0に戻ります。
MonoFlopのRetriggerableピンを0に設定したほうが使いやすいかな。

![Tweener.PNG](https://qiita-image-store.s3.amazonaws.com/0/26489/450b8e97-b1e1-b909-46f1-006cf6f50bca.png)

`Perlin (3d)`をMonoFlopの入力ソースに使って、イージング出力は`Segment (EX9.Geometry 2d)`のInnerRadiusと、`UniformScale (Transform)`の両方に設定するパターンが多いです。
リアルタイムでやるならFFTの出力をMonoFlopに入力する感じの使い方とかもありだと思う。

![SegmentEasing.PNG](https://qiita-image-store.s3.amazonaws.com/0/26489/534e71a2-dbf3-5dad-3e4d-13224b5a3c48.png) ![easing.gif](https://qiita-image-store.s3.amazonaws.com/0/26489/075aed41-a8e4-431b-87fd-8290cca74e92.gif)


# Texture FilterのControlにPillowを使う

ポストエフェクト系ノードのいくつかはControlピンを持っていて、入力するTextureによって適用量を変化させることができます。
ここに`Pillow (EX9.Texture Source)`を使うと画面の外側に向かって適用量が増えるようなポストエフェクトができます。`ShiftRGB (EX9.Texture Filter)`との組み合わせで使うと色収差的な感じになるのでよく使っています。

![TextureControlPillow.PNG](https://qiita-image-store.s3.amazonaws.com/0/26489/df6edb4e-14cc-64bc-c6ec-84b57773ae40.png)

ちなみにデフォルトのShiftRGBだとレンズ感が微妙なのが不満だったのと、そもそもControlピンの使い方を知らなかった頃に、ShiftRGBをベースに自作したポストエフェクトがあるのでこれも晒しておきます。DX11用ですが。

[vvvv\-sandbox/ShiftRGBRadial at master · clomie/vvvv\-sandbox](https://github.com/clomie/vvvv-sandbox/tree/master/ShiftRGBRadial)

Controlピンの使い方については、[一昨年のAdventCalendarのポストエフェクトに関する記事](http://qiita.com/hurafula/items/0c1fa29b44dcccb7b8ab#control%E3%82%A4%E3%83%B3%E3%83%AC%E3%83%83%E3%83%88%E3%81%AE%E3%81%82%E3%82%8Bfilter)がとても参考になるのでおすすめです。

# 動画への書き出しについて

ちょっとノードの話から逸れます。
DX9なら`Writer (EX9.Texture NRT)`、DX11なら`Writer (DX11.Texture 2d NRT Advanced)`で連番画像を書き出してから別のソフトで動画に変換しています。この方法だとフレーム落ちなしで書き出せるので。
mp4にしたいときはBMPかPNGの30fpsで書き出して、AviUtl + x264guiExでそのままmp4に変換しています。取っ付きにくいならaviにしてから更に別のエンコーダ使っても良いと思う。
gifにしたいときはPNGの25fpsで書き出して、適当なツールでフレーム間ウェイト40msに設定して変換しています。

# まとめ
ひとまずこんなもんで！
全部組み合わせて、後は各種ポストエフェクトによろしくしてもらったのが下の映像です。

![summary.gif](https://github.com/clomie/vvvv-sandbox/raw/master/20161206_NodePatternForLoop/summary.gif)

ソースはGitHubに置いてあります。
[vvvv\-sandbox/20161206\_NodePatternForLoop at master · clomie/vvvv\-sandbox](https://github.com/clomie/vvvv-sandbox/tree/master/20161206_NodePatternForLoop)