3D空間に動画が埋め込める

Three.jsの例、canvas_materials_video.htmlを見る。

WebGLを使ったwebgl_materials_video.htmlも試したけど動かなかったw
だからCanvasの方を見ていく。
でも、必要最低限の動作で見たいから、重要な部分だけを抽出していく。

まず動画をHTMLのソースに埋め込んである。
<video id="video" autoplay style="display:none">
 <source src="textures/sintel.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"' />
 <source src="textures/sintel.ogv" type='video/ogg; codecs="theora, vorbis"' />
</video>
例では2つの同じ内容の動画が埋め込まれているけど、再生できれば片方だけでOKだった。

次にmaterialを作る。
動画を映す"スクリーン"の大きさや素材を決める感じに似てる。
image = document.createElement( 'canvas' );
image.width = 480;
image.height = 204;
imageContext = image.getContext( '2d' );
texture = new THREE.Texture( image );
var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: true } );
動画の下にはこの動画が反射して映っている。
だからこっちも反射用のmaterialを作る。
imageReflection = document.createElement( 'canvas' );
imageReflection.width = 480;
imageReflection.height = 204;
imageReflectionContext = imageReflection.getContext( '2d' );
imageReflectionGradient = imageReflectionContext.createLinearGradient( 0, 0, 0, 204 );
imageReflectionGradient.addColorStop( 1, 'rgba(240, 240, 240, 0.8)' );
textureReflection = new THREE.Texture( imageReflection );
var materialReflection = new THREE.MeshBasicMaterial( { map: textureReflection, overdraw: true } );
赤いところが動画そのものの部分とは違うところで、雰囲気ある効果的な反射を作っている。

スクリーンができたら、今度はスクリーンの"設置"に取りかかる。
var plane = new THREE.PlaneGeometry( 480, 204, 0, 0 );
mesh = new THREE.Mesh( plane, material );
mesh.rotation.x = Math.PI / 2;
scene.add(mesh);
反射の方も同じように、
var plane = new THREE.PlaneGeometry( 480, 204, 0, 0 );
mesh = new THREE.Mesh( plane, materialReflection );
mesh.rotation.x = - Math.PI / 2;
mesh.doubleSided = true;
scene.add(mesh);
緑の部分で反転した動画が映るようになる。
これ、重要。
1行目、元の例では前で作ったplaneを利用していたから、ここでは改めて作らなくてもOK。

ここまででスクリーンの設置ができた。あとはスクリーン上で継続して再生させるだけ。
renderの中、
if ( video.readyState === video.HAVE_ENOUGH_DATA ) {
  imageContext.drawImage( video, 0, 0 );
  if ( texture ) texture.needsUpdate = true;
  if ( textureReflection ) textureReflection.needsUpdate = true;
}
imageReflectionContext.drawImage( image, 0, 0 );
imageReflectionContext.fillStyle = imageReflectionGradient;
imageReflectionContext.fillRect( 0, 0, 480, 204 );
3D空間内でプロモーションビデオを流す場合、この方法は使える。
2012/08/02 23:00
タグ