スタートページ> Javascript> CANVAS> WebGL
WebGL(Web Graphics Library)は、3次元グラフィックスを描画する技術仕様(API)です。ほとんどのWebブラウザが標準装備している JavaScript と CANVVAS を用いて描画できます。
WebGL は、OpenGLの派生仕様で、豊富な機能がありますが、生で記述するのはあまりにもコードが長くなり複雑になります。
それを解決するために、多様なライブラリが公表されていますが、THREE.js は代表的なライブラリです。
これも多様な機能をもっていますが、基本的な機能を用いるだけで、容易に3次元グラフィックスを作成できます。
ここでは、私がWebにあるいくつかの入門サイトを参考にして、「それなりに理解してコーディングしたら、思ったように描けた」ことをまとめたものです。
「基本のk」だけであり、基本の中でも「被写体の各面に独自の色をつける」ことや「床に影を付ける」ことすら未解決な状態で、私が今後勉強するときの足掛かりとしようとするものです。
入門・解説 ICS MEDIA「Three.js入門サイト」https://ics.media/tutorial-three/
公式ドキュメント 「Three.js - Javascript 3D Livrary」https://threejs.org/
右図を作成するソースコードを、別ウインドウに表示します。
THREE.js をインストールして使うこともできますが、次の指定をすれば利用できます。
(three@0.140.2 はバージョンです。最新版はこのサイトで確認してください。
<script src="https://unpkg.com/three@0.140.2/build/three.min.js"></script>
シーンのオプション
シーンの背景色。光源がないときはシーン全体は暗闇(黒一色)になっています。次により背景色を変えることができます。
色の指定は、0x808080 (""で囲まない)のような16進表示が標準ですが "silver" のような形式も使えます。
scene.background = new THREE.Color("silver");
座標軸(後述)の表示。右図の赤と緑の細線が表示されます。
var axes = new THREE.AxesHelper(1000);
scene.add(axes);
シーンは3次元空間なので、位置や大きさは (x,y,z) で与える必要があります。ところが CANVAS は2次元平面です。
上のDで、CANVAS を width = 400, height = 300 とすると、
CANVAS の中央 (200, 150) が原点 (0,0,0) になります。
X軸は右側は+、Y軸は上方向が+になります。
Z軸は、原点から手前に垂直で手前が+になります。見えません。
ここで、CANVAS に入る範囲 xmin~xmax, ymin~ymax がどう設定されるのか私にはわかりませんが、
どうも CANVAS での width, height で計算されているようで、カメラが原点にあるよきは、-400~400になるようです。
Z軸は目盛りはX・Y軸と同じですが、範囲には制限がないようです。
参照:CANVAS での位置関係
基本設定
var camera = new THREE.PerspectiveCamera(fov, aspect); // A
camera.position.set(positionx, positiony, positionz); // B
オプション
var camera = new THREE.PerspectiveCamera(fov, aspect, near, far); // C
camera.lookAt(new THREE.Vector3(x, y, z)); // D
A:カメラの特性
Perspective 遠近法。カメラに近い部分は大きく、遠い部分は小になります。通常はこれになります。
Orthographic 平行法。遠近の差はありません。ここでは省略します。
fov;カメラの視角。標準値 = 45。これを変えると広角撮影、望遠撮影になります。
aspect:カメラ撮影による横縦比。一般には CANVAS の width/height に一致させます。
B:カメラの位置です。カメラはシーンの外部にあるので、positionz を大きい値にする必要があります。
カメラはシーンの構成要素ではないので、Bだけで登録したことになります。
C:カメラに撮影する距離を、near~far に限定します。近写体、遠写体を消すのに有効です。
D:カメラの向きを (x,y,z) に向けます。この指定がないと (0, 0, 0) を向いています。
((positionx, positiony,0) を向いているのではとも思うのですが、未確認です)
実際の3次元グラフィックスでは、自動車、建物、人物など複雑な被写体を対象になりますが、それには高度な技術、センス、複雑な作業を伴います。THREE.js でも多様な幾何学的被写体が標準的に提供していますが、ここでは立方体と球体に限定します。
被写体(object)の設定には、次の5行が基本になります。
var geometry = new THREE.BoxGeometry(width, height, depth); // A
var material = new THREE.MeshNormalMaterial(); // B
var box = new THREE.Mesh(geometry, material); // C
box.position.set(positionx, positiony, positionz); // D
scene.add(box); // E
A:geometry とは形状のこと。Box(直方体), Sphere(球体)など多くの標準形状があります。
width などは、幅(X軸)、高さ(Y軸)、奥行(Z軸)のサイズです。これらのパラメタは形状により異なります。
参照:「geometry(被写体の形状)」
B:material は、被写体の表面の性状です。色の指定、光の影響などです。
Normalは、面を一様にベタ塗りし、光の影響を受けません。パラメタを省略すると自動的に彩色されます。
PhongMaterial は光を敏感に受ける方法です。光がないと全てが黒色になります。
参照:「material(1)」
C:geometry と material が与えられれば、被写体が定義されます。ここではその被写体を box と命名しています。
D:position は被写体 box が存在する位置を与えます。
E:scene.add とは、この box をシーンに追加することです(DとEの順序は逆でもかまいません)。
このようにして、いくつもの被写体をシーンに取り込むことができます。
光源がないときは、シーン全体は背景色一色になっています。MeshFaceMaterialなど受光をベースにした material の被写体は黒体になっており、光源を与えることにより、明暗のある物体として見えます。
A以外は「被写体の設定」と同じです。
var light = new THREE.PointLight(色, 強さ); // A
light.position.set(positionx, positiony, positionz); // D
scene.add(light); // E
A:光源のタイプには、Ambient(環境光源)、Directional(平行光源)、Point(点光源)、Spot(スポットライト)などがあり、組合せて使うことができます。
参照:「光源と影」
先に scene.add て追加した object の位置や角度を変更することができます。
光源やカメラの位置や向きの指定など、多様な変更ができますが、最も代表的なものは、被写体の位置や角度でしょう。
sphere.position.x = -200; // sphere の中心のx座標を -200 に変更する。
box.rotation.x = 15; // box をX軸に対して15°回転させる。
3次元空間であるシーンを、カメラの位置や向きにより、2次元平面である CANVAS に描画することです。
その基本方法は、「撮影環境の設定」で定義され、ここでは renderer となっています。
撮影の記述は、次の1行だけです。
renderer.render(scene, camera);
3Dグラフィックの魅力は、被写体やカメラを連続的に移動して、動画を作成できることでしょう。
右図では、sphere の平行移動と box の回転をさせています。
移動の基本パターン
var interval = 20; // 1回の移動・撮影の遅延期間 20/1000秒
var i = 0; // 繰返し回数のカウント
var timerId = setInterval(function(){ // ループの開始
// 移動の指定
sphere.position.x += 2; // 1回にx軸方向へ 2 移動
:
box.rotation.x += 0.05; // 1回に 0.1°回転
:
renderer.render(scene, camera); // レンダリング(撮影)
// 移動の変更が必要な場合
if ( (i%50) ) … // 50回ごとに…
if (sphere.position.x >= 300) … // 右側端に達したら…
:
if (i >= imax) clearInterval(timerId); // 回転打切条件
i = i+1;
}, interval); // ループの終了
参照:「被写体の移動」、「カメラの移動」
多くの Three.js の解説では、次の方法が紹介されています。
利点があるのかもしれませんが、速度の変更や回転終了などを指定する方法を私は知りません。
tick(); // 回転させる関数の呼び出し
// 回転関数
function tick() {
:
renderer.render(scene, camera);
requestAnimationFrame(tick);
}