LoginSignup
41
22

More than 5 years have passed since last update.

マッチムーVJ

Last updated at Posted at 2016-12-24

はじめに

北千住デザインという名前でthreejsを使ってブラウザVJをやっています。今回はそのVJネタのひとつを説明します。

やったこと

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

altaltver6.gif

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

トラッキング

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

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

書き出した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するという手段もあるが、めんどいので、以下のようにシェーダーを書いた。

こんな感じにジオメトリとシェーダーマテリアルを用意
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);

VertexShader
varying vec2 vUv;
void main()
{
  vUv = uv;
  vec4 hoge = vec4(position, 1.0);//マトリックス計算しない
  hoge.z = 1.0;//最背面のz=1に。
  gl_Position = hoge;
}   
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みたいなことも十分できる。今回のように他のツールと組み合わせて、なんかやるのもいいのかもしれない。

41
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
41
22