webデザイン 第10回:html5実践 three.jsで3dプログラミング
TRANSCRIPT
Webデザイン 第10回:HTML5実践 Three.jsで3Dプログラミング
2013年11月18日、 11月25日 多摩美術大学 情報デザイン学科メディア芸術コース 担当:田所淳
今日の内容‣ Three.js というJavaScriptのライブラリを使用して、Webブラウザ上で3Dプログラミングに挑戦します!
Webブラウザで3Dグラフィクスを扱う
WebGLについて‣ Webブラウザ上で3Dグラフィクスを扱うには… ‣ WebGLという標準仕様が策定されている ‣ 非営利団体のKhronos Groupで管理 ‣ 公式サイト: http://www.khronos.org/webgl/
WebGLについて‣ ただし、WebGLで自由に3DCGのプログラミングするのは、かなり大変…
‣ 3D座標の操作のための様々な数学的な知識を前提とする !
‣ そこで今回は、JavaScriptで容易に3Dを扱うことのできるライブラリを導入してみたい
Three.js について
Three.jsとは‣ WebGL (とCanvas) を使用して高度な3D表現を可能とする、Javascriptのライブラリ
‣ MITライセンスの、オープンソースプロジェクト ‣ Mr. Doobを中心に多くのコラボレーターと共に開発が現在も進行中 !
‣ ※ MITライセンス - ソフトウェアライセンスのひとつ ‣ ソフトウェアを誰でも無償で無制限に扱って良い。ただし、著作権表示および本許諾表示をソフトウェアのすべての複製または重要な部分に記載しなければならない。
‣ 作者または著作権者は、ソフトウェアに関してなんら責任を負わない。
Three.js‣ まずは、Three.jsのプロジェクトページをみてみる ‣ http://mrdoob.github.com/three.js/
Three.js‣ 様々な素晴しいサンプルがあるので、いくつか紹介
jsdo.it でThree.jsを使うには‣ jsdo.it には、あらかじめThree.jsが組込まれている! ‣ Three.jsを使用する際には、Javascriptのエディタで、Add Libraryボタンを押し、Three.jsを選択する
Three.js を使ってみる!!
Three.jsを使ってみる‣ Three.jsでの3Dオブジェクト描画の考え方 ‣ シーン、カメラ、ライト、メッシュ(物体) !
‣ 「シーンの中に物体(メッシュ)を配置して、ライティングしたものをカメラで撮影する」
Three.jsを使ってみる‣ Three.jsでの3Dオブジェクト描画の考え方 ‣ シーン、カメラ、ライト、メッシュ(物体)
camera
light
mesh (= object)
scene
Three.jsを使ってみる‣ 物体(mesh)は、材質(material)と形状(geometry)から成り立っている
mesh (= object)
material 材質
geometry 形状
+=
Three.jsを使ってみる‣ テンプレートをfork ‣ 最低限の設定をしたテンプレートをjsdo.itにアップしました ‣ まずはこのプログラムをForkしてください ‣ http://jsdo.it/yoppa/d2ad
//画面設定 var b = document.body; var d = document.documentElement; var WIDTH = Math.max(b.clientWidth , b.scrollWidth, d.scrollWidth, d.clientWidth); var HEIGHT = Math.max(b.clientHeight , b.scrollHeight, d.scrollHeight, d.clientHeight); !//コンテナとレンダラーの配置 var $container = $('#container'); var renderer = new THREE.WebGLRenderer(); renderer.setSize(WIDTH, HEIGHT); $container.append(renderer.domElement);
Three.jsを使ってみる‣ テンプレートには描画するコンテナの設定とWebGLのレンダラーの追加が行われている
!// シーンの生成 var scene = new THREE.Scene();
Three.jsを使ってみる‣ まずは、WebGLのシーンを追加
!// カメラ配置 var camera = new THREE.PerspectiveCamera(45, WIDTH/HEIGHT, 1, 1000); camera.position.z = 300; !// ライト配置 var light = new THREE.DirectionalLight(0xffffff, 1.5); light.position.x = 0.5; light.position.y = 0.5; light.position.z = 1; scene.add(light);
Three.jsを使ってみる‣ 次に、カメラとライトの配置
!// 立方体のジオメトリとマテリアル設定 var geometry = new THREE.CubeGeometry(100, 100, 100); var material = new THREE.MeshLambertMaterial({color: 0x336699});
Three.jsを使ってみる‣ 立方体のジオメトリと、マテリアルを設定
// メッシュ生成 var mesh = new THREE.Mesh(geometry, material);
Three.jsを使ってみる‣ 設定したジオメトリとマテリアルで、メッシュを生成
// メッシュを回転 mesh.rotation.x = 30 * Math.PI / 180.0; mesh.rotation.y = -30 * Math.PI / 180.0;
Three.jsを使ってみる‣ メッシュを、回転 (横に-30°、縦に30°)
// メッシュをシーンに追加 scene.add(mesh); !//シーンを描画する renderer.render(scene, camera);
Three.jsを使ってみる‣ メッシュをシーンに追加して、レンダラで描画
Three.jsを使ってみる‣ 完成!! 光のあたった立方体が表示されるはず
Three.jsを使ってみる‣ このように、Three.jsでは、簡単に3Dの物体を表示することができる
‣ 実際には高度な数学的な知識が必要な、3D座標の回転も簡単 !
‣ では、マウスの位置によって回転角度を変化させてみる
// メッシュ生成 var mesh = new THREE.Mesh(geometry, material); // メッシュをシーンに追加 scene.add(mesh); !// マウスの位置でメッシュを回転 renderer.domElement.addEventListener('mousemove', function(e) { mesh.rotation.x = e.pageY/ 100.0; mesh.rotation.y = e.pageX/ 100.0; ! //シーンを描画する renderer.render(scene, camera); }, false);
Three.jsを使ってみる‣ メッシュの回転とシーンの追加、レンダリングの部分を変更
Three.jsを使ってみる‣ マウスの位置で回転するようになったはず
Three.jsを使ってみる‣ 最後にテクスチャを貼ってみる ‣ まずはファイルをアップロード ‣ jsdo.it の Filesタブに画像をドラッグして、URLをコピーする
// 立方体のジオメトリとマテリアル設定 var geometry = new THREE.CubeGeometry(100, 100, 100); // テクスチャを読み込み var texture = new THREE.ImageUtils.loadTexture('http://jsrun.it/assets/6/Q/A/m/6QAmH.jpg3'); // テクスチャを反映 var material = new THREE.MeshLambertMaterial({map: texture}); // メッシュ生成 var mesh = new THREE.Mesh(geometry, material); // メッシュをシーンに追加 scene.add(mesh);
Three.jsを使ってみる‣ マテリアルの設定に、テクスチャを追加
Three.jsを使ってみる‣ テクスチャーが貼れた!!
Three.jsを使用したアニメーション
ここまでの復習‣ ここまでのプログラムについてこれていない方は、こちらから
‣ まず下記のURLのプログラムをFORK ‣ 手元のプログラムをみながら復習と補足
!http://jsdo.it/yoppa/yN9x
//立方体の表示: 基本 !//画面設定 var b = document.body; var d = document.documentElement; var WIDTH = Math.max(b.clientWidth , b.scrollWidth, d.scrollWidth, d.clientWidth); var HEIGHT = Math.max(b.clientHeight , b.scrollHeight, d.scrollHeight, d.clientHeight); !//コンテナとレンダラーの配置 var $container = $('#container'); var renderer = new THREE.WebGLRenderer(); renderer.setSize(WIDTH, HEIGHT); $container.append(renderer.domElement); !//立方体ジオメトリ var geometry = new THREE.CubeGeometry(100, 100, 100); //マテリアル var material = new THREE.MeshLambertMaterial({color: 0x3366cc}); //メッシュの生成 var mesh = new THREE.Mesh(geometry, material);
前回の復習‣ Javascriptコード
//メッシュの回転 mesh.rotation = {x: 0.5, y: 0.5, z: 0.0}; !//カメラを配置 var camera = new THREE.PerspectiveCamera(40, WIDTH / HEIGHT, 1, 1000); camera.position.z = 400; camera.lookAt(mesh.position); !//シーンを生成し、メッシュ追加 var scene = new THREE.Scene(); scene.add(mesh); !//ライト追加 var light = new THREE.DirectionalLight(0xffffff, 1.5); light.position = {x: 0, y: 0.2, z: 1} scene.add(light); !//レンダリング renderer.render(scene, camera);
前回の復習‣ Javascriptコード
前回の復習‣ 完成、(静止した)立方体が表示される
Three.jsを使用したアニメーション‣ Three.jsでアニメーションを実現するには ‣ プログラムをより構造化していく必要あり !
‣ 準備 (初期設定) → 更新 (アニメーション) → 描画
Three.jsを使用したアニメーション‣ Three.jsでの構造化のイメージ
init (初期化)
animation (更新)
render (更新)ループ
//画面設定、グローバルな変数の設定など ... !//プログラム構造 init(); animate(); !function init() { /* 初期化に関するコード */ } !function animate() { /* 更新に関するコード */ render(); // レンダー呼び出し } !function render() { renderer.render(scene, camera); //レンダリング }
Three.jsを使用したアニメーション‣ Javascriptコードでのイメージ
Three.jsを使用したアニメーション‣ 先程作成した、立方体の描画のコードを、この構造にあてはめていく
//画面設定 var b = document.body; var d = document.documentElement; var WIDTH = Math.max(b.clientWidth , b.scrollWidth, d.scrollWidth, d.clientWidth); var HEIGHT = Math.max(b.clientHeight , b.scrollHeight, d.scrollHeight, d.clientHeight); !//Three.jsのシーンに関係するグローバルな変数 var mesh, scene, camera, renderer, light; !//プログラム構造 init(); animate(); !function init() { ! //コンテナとレンダラーの配置 var $container = $('#container'); renderer = new THREE.WebGLRenderer(); renderer.setSize(WIDTH, HEIGHT); $container.append(renderer.domElement);
Three.jsを使用したアニメーション‣ Javascript
//立方体ジオメトリ var geometry = new THREE.CubeGeometry(100, 100, 100); //マテリアル var material = new THREE.MeshLambertMaterial({color: 0x3366cc}); ! //ジオメトリとマテリアルから、メッシュの生成 mesh = new THREE.Mesh(geometry, material); mesh.rotation.x += 20 / 180.0 * Math.PI; //カメラを配置 camera = new THREE.PerspectiveCamera(40, WIDTH / HEIGHT, 1, 1000); camera.position.z = 400; camera.lookAt(mesh.position); //シーンを生成し、メッシュ追加 scene = new THREE.Scene(); scene.add(mesh); //ライト追加 light = new THREE.DirectionalLight(0xffffff, 1.5); light.position = {x: 0, y: 0.2, z: 1} scene.add(light); }
Three.jsを使用したアニメーション‣ Javascript
!//アニメーション function animate() { requestAnimationFrame( animate ); render(); } !//レンダリング function render() { renderer.render(scene, camera); }
Three.jsを使用したアニメーション‣ Javascript
Three.jsを使用したアニメーション‣ まずは、静止した立方体が表示される(はず)
Three.jsを使用したアニメーション‣ この立方体を動かすには ‣ 変化させたいパラメータを、animateの中で演算する !
‣ 位置、回転、サイズ、色 ...etc. !
‣ では、試しに回転角度を変化させてみる
//アニメーション function animate() { ! mesh.rotation.y += 5 / 180.0 * Math.PI; ! requestAnimationFrame( animate ); render(); }
Three.jsを使用したアニメーション‣ Javascript
追加
Three.jsを使用したアニメーション‣ 立方体が、ぐるぐる回転する!!
Three.jsを使用したアニメーション‣ 立方体のスケールも変更してみる ‣ sin関数と、cos関数で、幅と高さを別々に変形
//アニメーション function animate() { mesh.rotation.y += 5 / 180.0 * Math.PI; ! mesh.scale.x = 0.4 * Math.sin( Date.now() / 100.0) + 1.0; mesh.scale.y = 0.4 * Math.cos( Date.now() / 100.0) + 1.0; ! requestAnimationFrame( animate ); render(); }
Three.jsを使用したアニメーション‣ Javascript
Three.jsを使用したアニメーション‣ 立方体が、グニャグニャと変形
応用:たくさんの図形をアニメーション
応用:たくさんの図形をアニメーション‣ たくさんの図形を同時に動かす ‣ 配列 (Array) とくりかえし (for) の使用法がポイント! !
‣ すこしずつ、回転スピードと、伸縮スピードをずらしながら、たくさんの立方体を描いてみる!!
//画面設定 var b = document.body; var d = document.documentElement; var WIDTH = Math.max(b.clientWidth , b.scrollWidth, d.scrollWidth, d.clientWidth); var HEIGHT = Math.max(b.clientHeight , b.scrollHeight, d.scrollHeight, d.clientHeight); !//Three.jsのシーンに関係するグローバルな変数 var scene, camera, renderer, light; var mouseX = 0, mouseY = 0; var windowHalfX = window.innerWidth / 2; var windowHalfY = window.innerHeight / 2; var mesh = []; var NUM = 100; !//プログラム構造 init(); animate(); !function init() { ! //コンテナとレンダラーの配置 var $container = $('#container');
応用:たくさんの図形をアニメーション‣ Javascript
//立方体ジオメトリ var geometry = new THREE.CubeGeometry(100, 100, 100); //マテリアル var material = new THREE.MeshLambertMaterial({color: 0x3366cc}); //くりかえし for(var i = 0; i < NUM; i++){ //ジオメトリとマテリアルから、メッシュの生成 mesh[i] = new THREE.Mesh(geometry, material); mesh[i].rotation.x += i / 180.0 * Math.PI; scene.add(mesh[i]); } //カメラを配置 camera = new THREE.PerspectiveCamera(40, WIDTH / HEIGHT, 1, 1000); camera.position.z = 400; camera.lookAt(mesh[0].position); //ライト追加 light = new THREE.DirectionalLight(0xffffff, 1.5); light.position = {x: 0, y: 0.2, z: 1} scene.add(light);
応用:たくさんの図形をアニメーション‣ Javascript
//アニメーション function animate() { //くりかえし for(var i = 0; i < NUM; i++){ mesh[i].rotation.y += i / 18000.0 * Math.PI; mesh[i].scale.x = 0.8 * Math.sin( i * Date.now() / 20000.0) + 1.0; mesh[i].scale.y = 0.8 * Math.cos( i * Date.now() / 30000.0) + 1.0; } requestAnimationFrame( animate ); render(); } !//レンダリング function render() { ! //カメラの視点をマウスで移動 camera.position.x += ( mouseX - camera.position.x ); camera.position.y += ( - mouseY - camera.position.y ); camera.lookAt(mesh[0].position); //レンダリング renderer.render(scene, camera); }
応用:たくさんの図形をアニメーション‣ Javascript
応用:たくさんの図形をアニメーション‣ 複雑に変形を繰り返す立方体の組み合わせ ‣ http://jsdo.it/yoppa/bmak
応用:たくさんの図形をアニメーション‣ 今週はここまで!