サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

three.js入門 02: フォンマテリアルとライトを使う


three.js入門 01: 3次元空間で立方体を回す」は、できるだけ少ないコードで3次元空間に立方体をつくって、アニメーションで回しました。本稿はこのコード002「3次元空間につくった立方体をアニメーションで回す」に手を加えます。立方体のマテリアルを差し替え、シーンにライトを置きましょう。

01 立方体の素材をフォンマテリアルに差し替える

「three.js入門 01」のコード002では、立方体のマテリアルとしてMeshNormalMaterialのオブジェクトを与えていました。これをフォンマテリアルのMeshPhongMaterial()コンストラクタで差し替えます。引数は、プロパティとその値を納めたオブジェクトです。ここでは、colorプロパティで色を定めることにしましょう。この値は関数(createCube())に引数(color)として加えました。このマテリアルは、正確にはブリンフォン(Blinn-Phong)鏡面反射モデルを用いているとのことです(Wikipedia「Blinn–Phong shading model」参照)。


// var cube = createCube(side, side, side);
var cube = createCube(side, side, side, 0x0000FF);

// function createCube(width, height, depth) {
function createCube(width, height, depth, color) {
	var geometry = new THREE.BoxGeometry(width, height, depth);
	// var material = new THREE.MeshNormalMaterial();
	var material = new THREE.MeshPhongMaterial({color: color});
	var cube = new THREE.Mesh(geometry, material);
	return cube;
}

ここでコードを実行すると、立方体が見えません。MeshNormalMaterialのオブジェクトは少し変わっていて、カラーを発色しました。けれども、普通のマテリアルは光を当てなければ、暗闇に紛れてしまうのです。

02 シーンにライトを加える

シーンにライトを加えましょう。光を放つ光源にはいくつかの種類があります(Wikipedia「3次元コンピュータグラフィックス」の「ライティング(照光、Lighting)」参照)。基本的なのは、太陽光と同じ平行光源(directional light)です(図001)。拡散することなく平行に進み、距離によって弱まることがありません。

図001■3次元表現で使われる光源の種類

図001
*Tcpp's fileより引用

平行光源のコンストラクタDirectionalLight()には、第1引数に色が渡せます(デフォルト値0xFFFFFF)。ライトのオブジェクトのObject3D.positionプロパティを参照して、Vector3.set()メソッドで3次元空間の位置が決められます。関数から返されたオブジェクトは、変数(light)に納めたうえで、シーン(scene)に加えました。これで、青い立方体がライトに照らされて回ります(図002)。


var light = createLight(0xFFFFFF, 10, 0, 25);

scene.add(light);

function createLight(color, x, y, z) {
	var light = new THREE.DirectionalLight(color);
	light.position.set(x, y, z);
	return light;
}

図002■青い立方体がライトに照らされて回る

図002

03 JavaScriptコードを<head>要素に移す

「three.js入門 01」のコード002は、<script>要素を<body>要素の中に置きました。コードから<body>要素を参照したためです。けれど、<head>要素に含めたほうが管理はしやすいでしょう。イベントリスナーを使えば、DOMが参照できるまで待てます。HTMLドキュメントの読み込みと解析を終えたとき起こるイベントがDOMContentLoadedです(「DOMContentLoaded周りの処理を詳しく調べてみました」参照)。つぎのように初期化の関数(init())を定めて、イベントリスナーに加えます。これで、JavaScriptコードは<head>要素に移せます。


var scene;  // = new THREE.Scene();
var camera;  // = new THREE.PerspectiveCamera(30, width / height, 1, 1000);
var renderer;  // = createRenderer(width, height);
var cube;  // = createCube(side, side, side, 0x0000FF);
function init() {
	scene = new THREE.Scene();
	camera = new THREE.PerspectiveCamera(30, width / height, 1, 1000);
	renderer = createRenderer(width, height);
	cube = createCube(side, side, side, 0x0000FF);
	var light = createLight(0xFFFFFF, 10, 0, 25);
	camera.position.z = 100;
	scene.add(cube);
	scene.add(light);
	update();
}

// update();
window.addEventListener('DOMContentLoaded', init);

書き改めたスクリプトは、つぎのコード001にまとめました。合わせて、サンプル001をjsdo.itに掲げておきます。

コード001■フォンマテリアルの立方体にライトを当てて回す


var width = window.innerWidth;
var height = window.innerHeight;
var side = Math.min(width, height) / 50;
var scene;
var camera;
var renderer;
var cube;
function init() {
	scene = new THREE.Scene();
	camera = new THREE.PerspectiveCamera(30, width / height, 1, 1000);
	renderer = createRenderer(width, height);
	cube = createCube(side, side, side, 0x0000FF);
	var light = createLight(0xFFFFFF, 10, 0, 25);
	camera.position.z = 100;
	scene.add(cube);
	scene.add(light);
	update();
}
function createRenderer(width, height) {
	var renderer = new THREE.WebGLRenderer();
	renderer.setSize(width, height);
	document.body.appendChild(renderer.domElement);
	return renderer;
}
function createCube(width, height, depth, color) {
	var geometry = new THREE.BoxGeometry(width, height, depth);
	var material = new THREE.MeshPhongMaterial({color: color});
	var cube = new THREE.Mesh(geometry, material);
	return cube;
}
function createLight(color, x, y, z) {
	var light = new THREE.DirectionalLight(color);
	light.position.set(x, y, z);
	return light;
}
function update() {
	cube.rotation.x += 0.01;
	cube.rotation.y += 0.01;
	requestAnimationFrame(update);
	renderer.render(scene, camera);
}
window.addEventListener('DOMContentLoaded', init);

サンプル001■three.js r84: Rotating a cube with light


作成者: 野中文雄
作成日: 2017年4月20日


Copyright © 2001-2016 Fumio Nonaka.  All rights reserved.