LogoMark.png

WebGL の変更点


#author("2021-05-20T15:11:02+09:00;2020-02-02T18:01:54+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/]] 
以下の、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/]]
以下の、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/]]
以下の、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/]]
以下の、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/]]
テクスチュアが''動画''(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/]]
以下の、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/]]
トラックボール風の操作を可能にするライブラリ、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がフレームごとに更新されています。
~
~