vvvvで映像的な何かを作る

ども、キドユウタと申します。

今回初めての記事で何を書こうか考えましたが、vvvvの映像制作の記事ってそんなになかったりノードの説明もされていなかったりするものがありました。なので、それを補った記事を書いてみようと思います。制作することで色々ノウハウも覚えられるといいですね。
ただ、とても長くなりますので気長に制作してちょっとずつ理解してもらえれば幸いです。

# vvvvは知っていますでしょうか？
割となんでもできちゃうビジュアルプログラミングという認識だと思います。
私もそんな認識ですのであしからず。

# 映像作りたい！でも…
映像コンテンツを作るには、AfterEffectsとかopenFrameworksとか使ってみたいけど、高くて買えなかったりプログラミング難しくて思い通りできないとか色々あると思います。

そんな人でも簡単に作れてしまう映像を紹介できればと思っております。
~~フリーソフトのAviUtlでも色々作れるんですけどね~~

今回は2016/3/19に東京工科大学でvvvvオフ会と称した講習で制作した映像コンテンツについて解説していきたいと思います。
![tumblr_inline_o4fxvyt5t11twtkl6_1280.jpg](https://qiita-image-store.s3.amazonaws.com/0/109168/e9548d14-19a6-afd0-a0b0-a65aea055ad1.jpeg)
↑こんな感じです（私のtumblrのブログを遡ると動画もあります）

# vvvvを開いて作ってみよ
## とりあえずはRenderer
なにはともあれRendererですね。今回はDX11でやっていきますのでRenderer(DX11)を使います。
私はアス比がすごい気になる人種なのでここでウィンドウサイズとアス比を合わせるようにしています。
それからCamera(Transform Softimage)をRendererに繋いでおきましょう。

<img width="358" alt="Screen Shot 2016-05-05 at 03.05.12.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/109168/9e4cf7fc-eb07-17be-2a9e-1d4d267cfa8e.jpeg">

## 球体を作ろう
描画にはConstant(DX11 Effect)を使用。シェーダー定数？とかそんな意味らしいですが、そこまで詳しくないので割愛します。
描画するためのジオメトリを繋いであげることでやっと描画されます。今回はSphere(DX11 Geometry)にします。

<img width="265" alt="Screen Shot 2016-05-05 at 00.51.00.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/109168/c0042dd7-0605-3fdc-8098-664f7d2bcdd1.jpeg">

<img width="428" alt="Screen Shot 2016-05-05 at 00.52.30.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/109168/0338d0e0-00f7-f573-eb8d-e67ab26627f6.jpeg">

## ランダム配置させる
動きをつけるにはTransformを使います。今回はTransform(Transform 3d vector)で3次元で動かしていきます。
※ここではSpreadの理解が必要になります。AquaLampさんの記事で明確に説明されていますのでご参照ください：
http://qiita.com/AquaLamp/items/99ce03d1e265f756ae44

ランダム配置にはRandomSpread(Spreads)を使います。名の通りランダムなスプレッドです。これをtranslateに繋げることでランダム配置が出来ます。それからscaleにも繋げて個々の大きさも変えてみます。
translateは正しくランダム配置できていますが、scaleがおかしなことに…

<img width="725" alt="Screen Shot 2016-05-05 at 01.29.45.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/109168/77a75ce9-d0b4-9a0e-a823-46ae0d957e99.jpeg">

これはscaleのxyzそれぞれの値が関係しています。
ここの値の動きを説明すると、RandomSpreadにより[2, 4, 3, 5, ...]と値があるとします。Transform(Transform 3d vector)のscaleはxyzの3つの値（こんな感じ[x:0, y:0, z:0]）が入ります。これらを繋げるとscaleには[x:2, y:4, z:3]となります。このおかげで楕円形になってしまうのです！どうしよう！
これを解決するためにVector(3d Join)を使います。これにより、RandomSpreadで[2, 4, 3, 5, ...]とすると、Vector(3d Join)のxyzに[2, 4, 3, 5, ...]がそれぞれ入ります。ここまで来たら説明しなくてもわかりますかね。
このVectorのoutputにはspreads１つ目=[x:2, y:2, z:2]、spreads2つ目=[x:4, y:4, z:4]...
になる。実際に触るとわかると思います。

<img width="731" alt="Screen Shot 2016-05-05 at 01.46.45.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/109168/f298e992-d36f-d001-f8d8-7b1916cd0344.jpeg">

## 動かしてみよう
アニメーションをつけるためにLFO(Animation)とDamper(Animation)を使います。
vvvvを使っている人には馴染みが深いですかね。
LFOは指定した秒間で0から１へ数値を作ってくれる割と使う子です。
Damperは値が違う値になった時にその間を補完してくれる子です。モーフィングみたいなやつですね。LFOのCyclesというoutputは0から1へ数値を作った回数をカウントしてくれます。これをRandomSpreadのRandom Seedに繋げます。Random Seedについては擬似乱数とかについて調べるいいかも。
これのおかげでRandomSpreadの値はカウントされるたびに変化します。しかし、これでは座標が変わっただけでアニメーションではない。そこでDamperで値の間を補完してくれます。実際に触るととてもよくわかると思います。
これはvvvvでアニメーションを作る時にはよく使われると思いますので2つのノードは覚えておくことをオススメします！

<img width="731" alt="Screen Shot 2016-05-05 at 02.16.52.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/109168/1779667f-aa42-ada6-ba68-560020d2e346.jpeg">

## 色つけてテクスチャを作って貼ってみよ
白いままじゃ面白味がないですよね。
なので先に色をつけてテクスチャを作ってしまいましょう。
Constantノードにはcolorのinputがありますので、HSV(Color Join)とLinearSpread(Spreads)を用いて色をつけていきます。
HSVは説明せずともわかると思います。LinearSpreadはRandomSpreadとは違い。例えばinputのwidthを2としてspreadを4とした時のoutputは[-0.75, -0.25, 0.25, 0.75]は出力されます。使って覚えていきましょ。

<img width="866" alt="Screen Shot 2016-05-05 at 02.52.13.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/109168/efdf3e20-311b-7480-2e86-bceff684d3a9.jpeg">

テクスチャはDX11ではなくDX9で作っていきます。理由は無いわけではないですが、テクスチャつけるのがこのやり方が個人的に楽なんです。許してください。
下図を見ていただければ多少どうなっているか理解出来るといい感じです。
Quad(DX9)で横長の長方形を一つ作り、LinearSpreadでボーダー柄を作っています。
これをConstantのTextureに入れるためにDX9のRendererで描画したものはDX9Texture(EX9 Texture)によってテクスチャに変換されます。しかし、DX9とDX11は互換性がないのでこのままでは使えないのでDX9toDX11(DX11. Texture)でさらに変換させます。これでやっとDX11のConstantにテクスチャとして使うことができます。

<img width="631" alt="Screen Shot 2016-05-05 at 03.17.45.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/109168/bcd397fe-f0b5-23fc-ee2e-3fed1acd2c79.jpeg">

## 細かい動きをつけていこう
やっとそれっぽい映像が出来そうな感じになってますね。
ここからは細かいところをやっていきたいと思います。
Transformのrotate、回転部分は今まで解説したのでわかると思いますが、RandomSpreadでSphere個々に多様な回転をつけてLFOとDamperでアニメーションをつけています。DamperのFilter Timeというものは変化前の値と変化後の値、その変化する時間を指定しています。ここでは10秒で目的の値に変化するといった感じです。

それから左のTransformのtranlate、座標部分ではMapノードを追加しています。Widthが5の時のRandomSpreadがoutputする値は-2.5~2.5となります。これを0~5にしたい時にMap(Value)を使います。Source Minimum,Maximumに元の値(ここでは-2.5と2.5)、Destination Minimum,Maximumには変換させたい値を与えてあげると、調整がとても楽になります。
自分好みの映像を作ってあげてみてください。

<img width="407" alt="Screen Shot 2016-05-05 at 03.57.38.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/109168/b4c51d61-6ae2-30d1-1d42-d9f1f5ad211c.jpeg">

因みにここで私はtranslateのz軸を0の値のままにしてあります。scaleの大きさへんがだけでも十分奥行きが出るために今回はz軸を0のままにしています。

## 完成！
<img width="400" alt="Screen Shot 2016-05-05 at 04.18.48.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/109168/8d3175f7-457f-f327-d076-a42c41ca15e1.jpeg">

これでvvvvによる映像が完成です！
私はこれにFFTノードを用いて音同期でインタラクティブなコンテンツにしたり、kinectを用いて丸が体にまとわり付くようにしたりして遊んでます。
一つのコンテンツが出来るとそこから簡単に色んなことに発展できるのがvvvvの強みな気がします。
そこまで難しくなかった人もちょっと難しかった人もvvvvの面白さを知ってもらえたなら幸いです。

では、よいvvvvライフを！