WebGL
https://developer.mozilla.org/ja/docs/Web/API/WebGL_API
WebGLとは、ブラウザ上で3次元CGを表示させるための標準仕様です。OpenGL ES からの派生言語で、OpenGL あるいは OpenGL ES 対応のハードが必要です。とはいっても、最近のPCはほとんど対応しているので問題ありません。
- WebGL 対応ブラウザがあれば動作します(特別なプラグインは不要)。
現在のところ Google Chromeが確実に動きます。
- 特別な開発環境は不要。テキストエディタのみで楽しめます。
- HTML5 の canvas タグを利用する
- javascript で記述できる
とりあえず、以下のページを見てその威力をお試し下さい(Chrome推奨)。
http://webglsamples.org/aquarium/aquarium.html
水族館が表示されれば、あなたのPC環境、ブラウザはOKです。
左メニューのChangeViewの右に小さなボタンがあります。
それをクリックすると、各種パラメータを変更できるスライダーが表示されます。
LINK
- WebGL
- ThreeJS
- ThreeJS Editor
ThreeJS ライブラリによるWebGLの活用
WebGLをそのまま記述するのは、かなり煩雑な作業になります。そこで、JavaScriptライブラリのThree.jsを使った事例を紹介します。Three.jsは、Mr.Doob氏を中心にオープンソースで開発が進められているWebGLを簡単に記述できるようにしたライブラリ(WebGLのラッパーライブラリ)で、WebGL関連のJSライブラリとしては、ほぼ標準といえる地位を確立しています。
WebGLには、HTML5の canvas が使われているのですが、Three.jsを使ったプログラミングでは、Three.jsが動的にcanvasを生成するので、こちらで作成するHTMLにはcanvasタグを書く必要はありません。描画領域となるスペース、例えば<body> 、 <div id="container"> などにappendChild することで、自動的にレンダリング領域が設定されます。
ThreeJSのダウンロード
ThreeJSを使うには、ライブラリJSファイルをサイトのディレクトリに入れて
htmlのヘッダー部分で
<script src="three.min.js"></script>
などとするのが一般的です。
ということで、以下のサイトから three.min.js をダウンロードしておいて下さい。
以下の事例中、テクスチュアを張ったものは、ローカル環境では動かないことがあります。サーバーにアップしてから動作確認してみて下さい。
Google Chrome, Firefoxで動作確認しています。
IE(Internet Explorer)では動きません。
事例1 →DEMO とりあえず3D表示
以下の、index.html sample.js そして、DLした three.min.js の3つを同じフォルダに入れてお試し下さい。シーン設定をして、カメラとオブジェクトとライトを置いてレンダリング・・・・。とてもオーソドックスな流れで記述できるので、とっつきやすいのではないでしょうか。
index.html | ほとんど何もありません。JSを読み込むだけです。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <script type="text/javascript" src="three.min.js"></script> <script type="text/javascript" src="sample.js"></script> <title>ThreeJS | WebGL Sample</title> </head> <body> </body> </html>
sample.js | ThreeJSによる3D表示のおおまかな流れです。
// Global Value var WIDTH = window.innerWidth; var HEIGHT = window.innerHeight; var VIEW_ANGLE = 45; var ASPECT = WIDTH/HEIGHT; var NEAR = 1; var FAR = 1000; // MAIN window.onload = function(){ // RENDER var renderer = new THREE.WebGLRenderer( { antialias: true } ); renderer.setSize( WIDTH, HEIGHT ); document.body.appendChild( renderer.domElement ); // SCENE var scene = new THREE.Scene(); // CAMERA var camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR ); camera.position.z = 50; scene.add( camera ); // MAKE MESH & MATERIALS var geometry = new THREE.CubeGeometry(10, 10, 10); var material = new THREE.MeshLambertMaterial( { color: 0xff0000 } ); var cube = new THREE.Mesh( geometry, material); cube.rotation.y = 60; scene.add( cube ); // LIGHT var light = new THREE.DirectionalLight( 0xffffff, 1.0 ); light.position.set( 2, 5, 10 ); scene.add( light ); // RENDERING renderer.render( scene, camera ); }
事例2 →DEMO 回転するサンプル
以下の、index.html sample.js そして、DLした three.min.js の3つを同じフォルダに入れてお試し下さい。上の事例1の立方体を回転させるには・・・ シーンを組み立てるところまでは、まったく同じで、あとは、animation() という関数を繰り返し呼び出す・・・という設定で動きが実現します。
index.html | 事例1と同じです(省略)
sample.js | アニメーションの基本形です。
// Global Value var WIDTH = window.innerWidth; var HEIGHT = window.innerHeight; var VIEW_ANGLE = 45; var ASPECT = WIDTH/HEIGHT; var NEAR = 1; var FAR = 1000; // MAIN window.onload = function(){ // RENDER var renderer = new THREE.WebGLRenderer( { antialias: true } ); renderer.setSize( WIDTH, HEIGHT ); document.body.appendChild( renderer.domElement ); // SCENE var scene = new THREE.Scene(); // CAMERA var camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR ); camera.position.z = 50; scene.add( camera ); // MAKE MESH & MATERIALS var geometry = new THREE.CubeGeometry(10, 10, 10); var material = new THREE.MeshLambertMaterial( { color: 0xff0000 } ); var cube = new THREE.Mesh( geometry, material); scene.add( cube ); // LIGHT var light = new THREE.DirectionalLight( 0xffffff, 1.0 ); light.position.set( 2, 5, 10 ); scene.add( light ); // ANIMATION function animate() { requestAnimationFrame( animate ); cube.rotation.y += 0.02; renderer.render( scene, camera ); } animate(); }
事例2の別解 →DEMO
以下の、index.html sample.js そして、DLした three.min.js の3つを同じフォルダに入れてお試し下さい。window.onload で、init(); と animate(); を呼ぶ形。外部変数が増えますが、こちらの方がしくみがスッキリします。
index.html | 事例1と同じです(省略)
sample.js
// Global Value var WIDTH = window.innerWidth; var HEIGHT = window.innerHeight; var VIEW_ANGLE = 45; var ASPECT = WIDTH/HEIGHT; var NEAR = 1; var FAR = 1000; var renderer, scene, camera, cube, light; // MAIN window.onload = function(){ init(); animate(); } // INITIALIZE function init(){ // RENDER renderer = new THREE.WebGLRenderer( { antialias: true } ); renderer.setSize( WIDTH, HEIGHT ); document.body.appendChild( renderer.domElement ); // SCENE scene = new THREE.Scene(); // CAMERA var camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR ); camera.position.z = 50; scene.add( camera ); // MAKE MESH & MATERIALS var geometry = new THREE.CubeGeometry(10, 10, 10); var material = new THREE.MeshLambertMaterial( { color: 0xff0000 } ); cube = new THREE.Mesh( geometry, material); scene.add( cube ); // LIGHT light = new THREE.DirectionalLight( 0xffffff, 1.0 ); light.position.set( 2, 5, 10 ); scene.add( light ); } // ANIMATION function animate() { requestAnimationFrame( animate ); cube.rotation.y += 0.02; renderer.render( scene, camera ); }
事例3 →DEMO テクスチュアを張ってみる
以下の、index.html sample.js そして、three.min.js と適当な texture.jpg の4つを同じフォルダに入れてお試し下さい。
テクスチュアデータは以下から・・・
http://www.tutorialsforblender3d.com/Textures/Textures_index.html
index.html | 事例1と同じです(省略)
sample.js | MAKE MESH & MATERIALSのところが数行違うだけ。
// Global Value var WIDTH = window.innerWidth; var HEIGHT = window.innerHeight; var VIEW_ANGLE = 45; var ASPECT = WIDTH/HEIGHT; var NEAR = 1; var FAR = 1000; var renderer, scene, camera, cube, light; // MAIN window.onload = function(){ init(); animate(); } // INITIALIZE function init(){ // RENDER renderer = new THREE.WebGLRenderer( { antialias: true } ); renderer.setSize( WIDTH, HEIGHT ); document.body.appendChild( renderer.domElement ); // SCENE scene = new THREE.Scene(); // CAMERA var camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR ); camera.position.z = 50; scene.add( camera ); // MAKE MESH & MATERIALS var geometry = new THREE.CubeGeometry(10, 10, 10); var texture = THREE.ImageUtils.loadTexture('texture.jpg'); var material = new THREE.MeshLambertMaterial({map: texture}); cube = new THREE.Mesh( geometry, material); scene.add( cube ); // LIGHT light = new THREE.DirectionalLight( 0xffffff, 1.0 ); light.position.set( 2, 5, 10 ); scene.add( light ); } // ANIMATION function animate() { requestAnimationFrame( animate ); cube.rotation.y += 0.02; renderer.render( scene, camera ); }
事例3-2 →DEMO 動画を張ってみる
テクスチュアが動画(WebM)の場合。環境によっては動作しません。
index.html | video タグで動画を読み込んでおきます(但し非表示)
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <script type="text/javascript" src="three.min.js"></script> <script type="text/javascript" src="sample.js"></script> <title>ThreeJS | WebGL Sample</title> </head> <body> <video id="video" autoplay loop style="display:none"> <source src="sample.webm"> </video> </body> </html>
sample.js | video, texture は外部変数。 以下、事例3との変更点のみ
途中略 : // MAKE MESH & MATERIALS var geometry = new THREE.CubeGeometry(10, 10, 10); video = document.getElementById('video'); texture = new THREE.Texture( video ); texture.minFilter = THREE.LinearFilter; texture.magFilter = THREE.LinearFilter; material = new THREE.MeshLambertMaterial({map: texture}); cube = new THREE.Mesh( geometry, material); scene.add( cube ); : 途中略 : // ANIMATE function animate() { requestAnimationFrame( animate ); cube.rotation.y += 0.02; if ( video.readyState === video.HAVE_ENOUGH_DATA ) { if ( texture ) texture.needsUpdate = true; } renderer.render( scene, camera ); }
事例4 →DEMO マウスでグルグルする
以下の、index.html sample.js そして、DLした three.min.js の3つを
同じフォルダに入れてお試し下さい。
index.html | 事例1と同じです(省略)
sample.js | Mouse Controlsの部分でイベントリスナーを登録してます。
// Global Value var WIDTH = window.innerWidth; var HEIGHT = window.innerHeight; var VIEW_ANGLE = 45; var ASPECT = WIDTH/HEIGHT; var NEAR = 1; var FAR = 1000; var renderer, scene, camera, cube, light; var mousedown = false; // MAIN window.onload = function(){ init(); animate(); } // INITIALIZE function init(){ // RENDER renderer = new THREE.WebGLRenderer( { antialias: true } ); renderer.setSize( WIDTH, HEIGHT ); document.body.appendChild( renderer.domElement ); // SCENE scene = new THREE.Scene(); // CAMERA camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR ); camera.position.z = 50; scene.add( camera ); // MAKE MESH & MATERIALS var geometry = new THREE.CubeGeometry(10, 10, 10); var material = new THREE.MeshLambertMaterial( { color: 0xff0000 } ); cube = new THREE.Mesh( geometry, material); scene.add( cube ); // LIGHT light = new THREE.DirectionalLight( 0xffffff, 1.0 ); light.position.set( 2, 5, 10 ); scene.add( light ); // MOUSE CONTROLS renderer.domElement.addEventListener('mousedown', function(e){ mousedown = true; position = {x: e.pageX, y: e.pageY}; }, false); renderer.domElement.addEventListener('mouseup', function(e){ mousedown = false; }, false); renderer.domElement.addEventListener('mouseout', function(e){ mousedown = false; }, false); renderer.domElement.addEventListener('mousemove', function(e){ if(!mousedown) return; distance = {x: position.x - e.pageX, y: position.y - e.pageY}; cube.rotation.x -= distance.y * 0.01; cube.rotation.y -= distance.x * 0.01; position = {x: e.pageX, y: e.pageY}; animate(); }, false); } function animate(){ renderer.render(scene, camera); }
事例5 →DEMO マウスでグルグルする2
トラックボール風の操作を可能にするライブラリ、TrackballControlsを使ってみました。これは、ダウンロードしたThree.jsの中のサンプルファイルとして含まれています。具体的には以下の場所にあります。
examples/js/controls/TrackballControls.js
TrackballControls.js を同じフォルダに入れて、以下のようにindex.htmlのヘッダーで読み込んで下さい。
index.html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <script type="text/javascript" src="three.min.js"></script> <script type="text/javascript" src="TrackballControls.js"></script> <script type="text/javascript" src="sample.js"></script> <title>ThreeJS | WebGL Sample</title> </head> <body style="overflow:hidden;"></body> </html>
sample.js
// Global Value var WIDTH = window.innerWidth; var HEIGHT = window.innerHeight; var VIEW_ANGLE = 45; var ASPECT = WIDTH/HEIGHT; var NEAR = 1; var FAR = 1000; var container, renderer, scene, camera, controls, cube, light; // MAIN window.onload = function(){ init(); draw(); } function init(){ // RENDER renderer = new THREE.WebGLRenderer( { antialias: true } ); renderer.setSize( WIDTH, HEIGHT ); document.body.appendChild( renderer.domElement ); // SCENE scene = new THREE.Scene(); // CAMERA camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR ); camera.position.z = 50; scene.add( camera ); // CONTROLS controls = new THREE.TrackballControls( camera ); // MAKE MESH & MATERIALS var geometry = new THREE.CubeGeometry(10, 10, 10); var material = new THREE.MeshLambertMaterial( { color: 0xff0000 } ); cube = new THREE.Mesh( geometry, material); scene.add( cube ); // LIGHT light = new THREE.DirectionalLight( 0xffffff, 1.0 ); light.position.set( 2, 5, 10 ); scene.add( light ); } function draw(){ requestAnimationFrame( draw); renderer.render(scene, camera); controls.update(); }
わずか1行、controlsにカメラを登録するだけで、以下の操作が実現します。
- 左のドラッグでグルグル
- 右のドラッグで平行移動
- マウスホイールで拡大・縮小
尚、この事例では、 requestAnimationFrameによって、常時アニメーションしていて、controlsがフレームごとに更新されています。