この記事は、Three.js Advent Calendar 2016 13日目の記事です。
#displacementに触れたきっかけ
絵に凹凸がついたり、白と黒を判別するところが不思議な感じがして、触れてみたくなりました。
静止画にできるなら動画にも適用できるかも、と試してみたところ、うまくいきました。
#video displacementについて
コード自体短く、シンプルなので、要点を書いていきます。
demoでは、凹凸が見やすいようにニ画面にしてあります。
ニ画面のやり方はこの記事が参考になります。
#videoのソース
まず、videoタグを書いて
オートプレイ、ループ、インライン、ミュートを追加します。
ios10からvideoをインラインで再生可能になったため、このようにしています。
ios9より以前の端末ではうまく映らない可能性があります。
<video id="video" src="01.mp4" autoplay loop playsinline muted></video>
そして、javascript側で
video = document.getElementById("video"); // 指定IDの要素を取得
要素を取得します。
#video { display: none; }
videoが重なって映ってしまうため、videoタグの方をnoneにしていますが、もっと良い方法があるかもしれません。
カラーとして映るvideoTextureと凹凸を判別するvideoTextureを別々に設定することも可能です。
texture = new THREE.VideoTexture(video);
material = new THREE.MeshPhongMaterial({
side: THREE.DoubleSide, // 両面に映す
map: texture, // テクスチャ
displacementMap: texture, // displacementのテクスチャ
displacementScale: -12 // displacementの大きさ
});
全体のコードものせておきます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>displacement</title>
<style>
* {
overflow: hidden;
}
#displ {
margin: 0;
padding: 0;
border: 0;
}
#button {
position: absolute;
top: 10px;
left: 10px;
}
#video {
display: none;
}
</style>
<script src="js/three.min.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/main.js"></script>
</head>
<body>
<div id="displ"></div>
<div id="button">
<input type="button" value="はじめから" onclick="video.load();" />
<input type="button" value="再生" onclick="video.play();" />
<input type="button" value="一時停止" onclick="video.pause();" />
</div>
<video id="video" src="001.mp4" autoplay loop playsinline muted></video>
</body>
</html>
var initScene, render,
renderer, scene, cameraL, cameraR, light, light2, controls,
geometry, material, texture, plane;
var SCREEN_WIDTH = window.innerWidth,
SCREEN_HEIGHT = window.innerHeight;
function initScene() {
scene = new THREE.Scene();
// 左側のカメラ
cameraL = new THREE.PerspectiveCamera(75, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 1000);
cameraL.position.set(0, 0, 70);
controls = new THREE.OrbitControls(cameraL);
scene.add(cameraL);
// 右側のカメラ
cameraR = new THREE.PerspectiveCamera(75, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 1000);
cameraR.position.set(45, 5, 0);
cameraR.lookAt({x: 0, y: 0, z: 0});
scene.add(cameraR);
light = new THREE.AmbientLight(0xffffff);
scene.add(light);
light2 = new THREE.DirectionalLight(0xffffff, 1);
light2.position.set(20, 20, 20);
scene.add(light2);
video = document.getElementById("video"); // 指定IDの要素を取得
geometry = new THREE.PlaneGeometry(96, 54, 256, 256);
texture = new THREE.VideoTexture(video);
texture.minFilter = THREE.LinearFilter;
texture.magFilter = THREE.LinearFilter;
texture.format = THREE.RGBFormat;
material = new THREE.MeshPhongMaterial({
side: THREE.DoubleSide, // 両面に映す
map: texture, // テクスチャ
displacementMap: texture, // displacementのテクスチャ
displacementScale: -12 // displacementの大きさ
});
plane = new THREE.Mesh(geometry, material);
plane.geometry.verticesNeedUpdate = true;
scene.add(plane);
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
renderer.setClearColor(0xaaaaaa);
renderer.autoClear = false;
document.getElementById("displ").appendChild(renderer.domElement);
document.addEventListener('keydown', onKeyDown, false);
keydown = {};
function onKeyDown(event) {
switch (event.keyCode) {
case 87:
/*W*/ video.load();
break;
case 83:
/*S*/ video.play();
break;
case 88:
/*X*/ video.pause();
break;
}
}
render();
}
function render() {
requestAnimationFrame(render);
controls.update();
plane.geometry.verticesNeedUpdate = true;
cameraL.aspect = 0.5 * SCREEN_WIDTH / SCREEN_HEIGHT;
cameraR.aspect = 0.5 * SCREEN_WIDTH / SCREEN_HEIGHT;
cameraL.updateProjectionMatrix();
cameraR.updateProjectionMatrix();
renderer.setViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
renderer.clear();
renderer.setViewport(1, 1, 0.5 * SCREEN_WIDTH - 2, SCREEN_HEIGHT - 2);
renderer.render(scene, cameraL);
renderer.setViewport(0.5 * SCREEN_WIDTH + 1, 1, 0.5 * SCREEN_WIDTH - 2, SCREEN_HEIGHT - 2);
renderer.render(scene, cameraR);
}
window.onload = initScene;
#最後に
どう使うかが悩み所ですが、音楽と合わせて、凹凸を出したりしたら面白いのではないかなど考えています。
displacement、とても面白いのでまた何か作りたいものです。
では、最後までありがとうございました。