マッチムーVJ

##はじめに
[北千住デザイン](https://kitasenjudesign.com/)という名前でthreejsを使ってブラウザVJをやっています。今回はそのVJネタのひとつを説明します。

##やったこと
ARみたく、実写と動的なCGを組み合わせてVJをしたいと考えた（こういう合成を**マッチムーブ**というらしい）。
ただARは現状では精度が低かったり、リアルタイムが前提の表現なので、映像作品とみたときイマイチな場合がある。そこで、実写映像をあらかじめ撮影して別のソフトで3Dトラッキングし、それにWebGLで描画された音に反応する映像をオーバーレイさせるという方法をとってみた。静的な映像と動的な映像のハイブリットといった感じ。

![alt](http://68.media.tumblr.com/0cb993c0ab2b570c1d14072fc2c90e6e/tumblr_oe2lrhUVYP1t1xi2oo1_250.gif)![alt](http://68.media.tumblr.com/7a0426a20cc9286ad4ccd061839aa374/tumblr_oe1wwph1Iz1t1xi2oo1_250.gif)![ver6.gif](https://qiita-image-store.s3.amazonaws.com/0/17747/6026b508-f3fa-0d1b-74c0-5fcfcd326a90.gif)

こんな感じで、背景はふつうのリニアな映像、手前の動いている物体は、音に合わせてリアルタイムに変形している。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">キマイラ <a href="https://twitter.com/hashtag/BRDG7?src=hash">#BRDG7</a>  @ 渋谷WWW X<br><br>DE DE MOUSE🐭 x HEXPIEXLS with 北千住デザイン✨<br><br>これヤバすぎて🐼顔が凄くにやけた☺️☺️☺️ <a href="https://t.co/775uMeOcBh">pic.twitter.com/775uMeOcBh</a></p>&mdash; KG (@keiji_307) <a href="https://twitter.com/keiji_307/status/777558184818987008">2016年9月18日</a></blockquote>

##トラッキング
実写のトラッキングにはCinema4d Studioを使った（会社にあったから）。やり方は[この辺を見ればわかる](http://www.maxonjapan.jp/archives/297) 。トラッキングができたら、[Cinema4DはPythonを使える機能がある](http://qiita.com/_nabe/items/9c1ff9ad47be7476571f)ので、それを使い、毎フレーム、カメラの座標・回転（クォータニオン）・FOVをjsonに書き出す。ただcinema4dとthreejsは座標系が違う（左手・右手）ので書き出す際注意が必要。

Cinema4dのPythonのコードはこんな感じ
https://gist.github.com/kitasenjudesign/d739c6123e0b55bc77445d2db6f608d1

書き出したJSONはこんな感じ

```json:
    "frames": [
        {
            "fov": 32.70611613573759, 
            "frame": 0, 
            "q": [
                0.01175325347189373, 
                0.9667209890999054, 
                0.04514531549377907, 
                -0.25154381478281923
            ], 
            "x": -141.4472256273544, 
            "y": 68.24724022421263, 
            "z": -198.63611330979802
        },...
```

これをthreejsに持っていき、映像の再生時間と合わせて、毎フレーム、PerspectiveCameraのパラメータを更新すれば良い。

※AfterEffectsでも同様のことができるようです。他の3Dソフトでもできると思う。
https://medium.com/@Jam3/mtchmv-a54624f6232#.jwdrxnan1

##Video再生
WebGLのキャンバスを透明にして下にVideoタグを敷くという方法もあるが、今回はポストプロセスもかけたかったのでVideoをCanvasにキャプチャしてthreejsの中の板ポリに貼り付けた。（やり方はググれば出てくる）
その際、板ポリはカメラに関係なくずっと正面を向いていてほしい。毎フレーム、板ポリをLookAtするという手段もあるが、めんどいので、以下のようにシェーダーを書いた。

```js:こんな感じにジオメトリとシェーダーマテリアルを用意
geo = new THREE.PlaneBufferGeometry(2, 2, 1, 1);
mat = new THREE.ShaderMaterial({
			vertexShader: _vertexShader,
			fragmentShader: _fragmentShader,
			uniforms: {
				texture: { type: 't', value: _texture }	
			}
});
mesh = new THREE.Mesh(geo,mat);

```


```glsl:VertexShader
varying vec2 vUv;
void main()
{
  vUv = uv;
  vec4 hoge = vec4(position, 1.0);//マトリックス計算しない
  hoge.z = 1.0;//最背面のz=1に。
  gl_Position = hoge;
}	
```

```glsl:FragmentShader
uniform sampler2D texture;
varying vec2 vUv;                                             
void main()
{
  //テクスチャを書き出してるだけ
  gl_FragColor = texture2D(texture, vUv);
}	
```

##影
影もつけたい。ShadowMaterialっていうのを使うと透明なPlaneに影だけ落としてくれる。ありがたい。
http://stackoverflow.com/questions/35710130/shadow-catcher-in-three-js-shadow-on-transparent-material

##クリッピング
地面から飛び出してくるような演出もしたい。3Dオブジェクトをクリッピングせねばならない。シェーダーを自分で書いても良い（たとえばy<0ならdiscardするとか）。けれど、めんどうなので、これもthreejsのクリッピング機能を使う。ありがたい。
https://threejs.org/examples/?q=clipp#webgl_clipping

##おわりに
Threejsはめんどいこともやってくれて素晴らしい。WebGLは手軽だし、VJみたいなことも十分できる。今回のように他のツールと組み合わせて、なんかやるのもいいのかもしれない。