Three.js(r74)で画像に波紋のようなエフェクトをかけてみたので、その方法をまとめる。大まかな方法としては、画像をテクスチャにしたマテリアルで平面オブジェクトを作成し、x軸、y軸に沿って配置(z軸上の位置は0)する。波紋が起きたときにz軸上の位置をずらして波紋のように見えるようにする。z軸上の位置のずれを求めるには正弦波を使う。厳密には波動方程式を利用するらしいが、詳しい知識はないので深入りはしない。以下のような式で波紋のように見えるz軸上の位置が求められる。
z = a * sin2π(r/λ+vt)
a: 振幅
r: 中心からの距離
λ: 波長
v: 速度
t: 時間
1.オブジェクト作成
PlaneGeometryの第3,4引数の分割数は、少ないと滑らかに波紋が変化しないので、ある程度の数値にしておく。
2.z軸上のずれを計算する関数を作成
z = a * sin2π(r/λ+vt)
a: 振幅
r: 中心からの距離
λ: 波長
v: 速度
t: 時間
1.オブジェクト作成
PlaneGeometryの第3,4引数の分割数は、少ないと滑らかに波紋が変化しないので、ある程度の数値にしておく。
// 平面ジオメトリ作成 var geometry = new THREE.PlaneGeometry( 4, 3, 32, 32); // マテリアルの作成 var material = new THREE.MeshPhongMaterial( { map: new THREE.TextureLoader().load( 'persimmon.jpg' ), color: 0xffffff } ); // オブジェクトの作成 var plane = new THREE.Mesh( geometry, material ); // オブジェクトをシーンに追加 scene.add( plane );
2.z軸上のずれを計算する関数を作成
// r: 中心からの距離 // time: 時間 // 波の移動の向きを逆にするために速度-1として計算 // 波長は1として計算 function calcDisp( r, time ) { return 0.2*Math.sin(2*Math.PI*(r*2 - time)); }
3.レンダリングループの中でオブジェクトの頂点情報を変化させる
レンダリングループの中でz軸上の変化を計算し、オブジェクトの位置情報である頂点情報をアップデートする。
// 減衰率 var mu0 = 0.995; // 減衰係数 var mu = 1.0; function render(){ // requestAnimationFrameで自分自身を呼び出し続けることでレンダリングを繰り返す requestAnimationFrame( render ); var time = Date.now() * 0.0001; var data = []; var vertices = plane.geometry.vertices; // 頂点情報のx、y座標から計算した中心からの距離と時間情報をもとにz軸上のずれを計算 for ( var i = 0; i < vertices.length; i++ ) { var pos = new THREE.Vector2( vertices[i].x, vertices[i].y ); data[i] = mu*calcDisp( pos.length(), time ); } // 減衰係数を減らしていくことで波紋の振幅を徐々に減衰させる mu *= mu0; // 計算結果を頂点情報に反映させる for( var i = 0; i < data.length; i++ ) { vertices[i].z = data[i]; } plane.geometry.verticesNeedUpdate = true; // レンダリング renderer.render(scene,camera); }
以上とその他のThree.jsに必要な処理を記述したhtmlを開くと、画像の中心から波紋が広がる。静止画だとわかりづらいが、以下のようになる。
0 件のコメント:
コメントを投稿