LogoMark.png

WebGL

WebGL

https://developer.mozilla.org/ja/docs/Web/API/WebGL_API

WebGLとは、ブラウザ上で3次元CGを表示させるための標準仕様です。OpenGL ES からの派生言語で、OpenGL あるいは OpenGL ES 対応のハードが必要です。とはいっても、最近のPCはほとんど対応しているので問題ありません。

とりあえず、以下のページを見てその威力をお試し下さい(Chrome推奨)。
http://webglsamples.org/aquarium/aquarium.html
水族館が表示されれば、あなたのPC環境、ブラウザはOKです。
左メニューのChangeViewの右に小さなボタンがあります。
それをクリックすると、各種パラメータを変更できるスライダーが表示されます。

LINK

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がフレームごとに更新されています。



PAGES

GUIDE

TOOL

DATA

Last-modified: 2021-05-20 (木) 15:11:02