#author("2021-05-20T15:11:02+09:00;2020-02-02T18:01:54+09:00","default:inoue.ko","inoue.ko") #author("2026-07-28T16:07:26+09:00;2026-07-28T13:58:43+09:00","default:inoue.ko","inoue.ko") *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 --http://www.khronos.org/webgl/ --http://wgld.org/sitemap.html -ThreeJS --http://mrdoob.github.com/three.js/ --http://threejsdoc.appspot.com/doc/index.html --[[HTML5による物理シミュレーション環境の構築>http://www.natural-science.or.jp/article/20120220155529.php]] --[[@ITの記事|TreeJS>http://www.atmarkit.co.jp/fwcr/design/benkyo/webgraphics05/01.html]] --[[小山田晃浩氏による解説動画>http://youtu.be/_F0AxtUiXS8]] -ThreeJS Editor --http://threejs.org/editor/ ~ ~ **ThreeJS ライブラリによるWebGLの活用 WebGLをそのまま記述するのは、かなり煩雑な作業になります。そこで、JavaScriptライブラリの[[Three.js>http://mrdoob.github.com/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 をダウンロードしておいて下さい。 -http://mrdoob.github.com/three.js/ ~ &color(red){以下の事例中、テクスチュアを張ったものは、ローカル環境では動かないことがあります。サーバーにアップしてから動作確認してみて下さい。}; &color(red){Google Chrome, Firefoxで動作確認しています。}; &color(red){IE(Internet Explorer)では動きません。}; ~ ~ ***事例1 [[→DEMO とりあえず3D表示>https://design.kyusan-u.ac.jp/SampleSite/ThreeJS01/]] ***事例1 [[→DEMO とりあえず3D表示>https://design.cs.kyusan-u.ac.jp/SampleSite/ThreeJS01/]] 以下の、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 回転するサンプル>https://design.kyusan-u.ac.jp/SampleSite/ThreeJS02/]] ***事例2 [[→DEMO 回転するサンプル>https://design.cs.kyusan-u.ac.jp/SampleSite/ThreeJS02/]] 以下の、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>https://design.kyusan-u.ac.jp/SampleSite/ThreeJS02_2/]] ***事例2の別解 [[→DEMO>https://design.cs.kyusan-u.ac.jp/SampleSite/ThreeJS02_2/]] 以下の、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 テクスチュアを張ってみる>https://design.kyusan-u.ac.jp/SampleSite/ThreeJS03/]] ***事例3 [[→DEMO テクスチュアを張ってみる>https://design.cs.kyusan-u.ac.jp/SampleSite/ThreeJS03/]] 以下の、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 動画を張ってみる>https://design.kyusan-u.ac.jp/SampleSite/ThreeJS03_2/]] ***事例3-2 [[→DEMO 動画を張ってみる>https://design.cs.kyusan-u.ac.jp/SampleSite/ThreeJS03_2/]] テクスチュアが''動画''(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 マウスでグルグルする>https://design.kyusan-u.ac.jp/SampleSite/ThreeJS04/]] ***事例4 [[→DEMO マウスでグルグルする>https://design.cs.kyusan-u.ac.jp/SampleSite/ThreeJS04/]] 以下の、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); } // ANIMATION function animate(){ renderer.render(scene, camera); } ~ ~ ***事例5 [[→DEMO マウスでグルグルする2>https://design.kyusan-u.ac.jp/SampleSite/ThreeJS05/]] ***事例5 [[→DEMO マウスでグルグルする2>https://design.cs.kyusan-u.ac.jp/SampleSite/ThreeJS05/]] トラックボール風の操作を可能にするライブラリ、TrackballControlsを使ってみました。これは、ダウンロードした[[Three.js>http://threejs.org/]]の中のサンプルファイルとして含まれています。具体的には以下の場所にあります。 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がフレームごとに更新されています。 ~ ~