手軽に3Dコンテンツを制作できる商用利用可能なJavaScriptライブラリ
JSライブラリの容量も126KB(GZIP)しかなく、とても軽量
参考
https://ics.media/entry/14771/ https://ics.media/tutorial-three/
<script src="https://unpkg.com/three@0.146.0/build/three.min.js"></script>
window.addEventListener("DOMContentLoaded", init); function init() { // 処理を追加 }
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Three.js Project</title> <script src="three.js"></script> // 追加 <script src="index.js"></script> // 追加 </head> <body> <canvas id="myCanvas"></canvas> // 追加 </body> </html>
WebGLにレンダリングするため
// レンダラー作成 const renderer = new THREE.WebGLRenderer({ canvas: document.querySelector("#myCanvas") }); // サイズ調整 const width = 820; const height = 540; renderer.setSize(width, height); // デバイスピクセル比設定:ぼやけ対策 renderer.setPixelRatio('window'.devicePixelRatio);
オブジェクトや光源の置き場
// シーン作成 const scene = new THREE.Scene(); // 背景色設定 scene.background = new THREE.Color( 0xffffff );
THREE.Sceneで作成した3D空間をカメラで取得し、レンダラーを介してcanvasで描画される
// カメラ作成 params(画角, アスペクト, 描画開始距離, 描画終了距離) const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 10000 ); // カメラの初期座標設定 (x: 0, y: 0, z: 0) camera.position.set(0, 0, 1000);
メッシュで作成:ジオメトリ(形状)とマテリアル(素材)を用意する
ジオメトリ:頂点情報、面情報を持つ。様々なジオメトリが用意されている
箱状の形状を生成するBoxGeometryを使用
// ジオメトリ生成 props(width, height, depth) const geometry = new THREE.BoxGeometry(200, 200, 200); // マテリアル生成 const material = new THREE.MeshStandardMaterial({ color: 0x86A8E7 }); // メッシュ作成 params(ジオメトリ, マテリアル) const box = new THREE.Mesh(geometry, material); // シーンに追加 scene.add(box);
// ライト作成 param(color); const light = new THREE.DirectionalLight(0x5FFBF1); light.intensity = 2; // 光の強さを倍にする light.position.set(1, 1, 2); // ライトの方向 scene.add(light); // シーンに追加 const light1 = new THREE.DirectionalLight(0xD16BA5); light1.intensity = 2; // 光の強さを倍にする light1.position.set(-1, -1, 2); // ライトの方向 scene.add(light1); // シーンに追加
// アニメーション function tick() { requestAnimationFrame(tick); // 引数の関数を毎フレーム実行 box.rotation.x += 0.01; // 箱回転 box.rotation.y += 0.01; // 箱回転 renderer.render(scene, camera); // 描画 } tick(); // 初回実行
引用元: 参考URL
THREE.Sceneクラス:3D空間を表す。add()で追加表示
THREE.PerspectiveCameraクラス:3D空間の視点制御
THREE.WebGLRendererクラス:
レンダリング、描画を行う。内部的にはWebGLのAPIを使用して表示している。
requestAnimationFrame
のタイミングでレンダリングを行う。
質感設定:カラーリング、画像・陰影の割り当て、ライティングの反射
THREE.MeshStandardMaterial
クラスを使用して
マテリアルを実装
球形ジオメトリ
イメージ:widthは横に対しての骨の数、heightは骨間の縦に対しての層の数
https://threejs.org/docs/#api/en/geometries/SphereGeometry
// ジオメトリ生成 props(radius, width, height) const geometry = new THREE.SphereGeometry(100, 100, 100);
オブジェクト作成手順
// ジオメトリ生成 const geometry = new THREE.SphereGeometry(100, 100, 100); // マテリアル生成 const material = new THREE.MeshStandardMaterial({ color: 0x86A8E7 }); // メッシュ作成 params(ジメトリ, マテリアル) const sphere = new THREE.Mesh(geometry, material); // シーンに追加 scene.add(sphere);
THREE.DirectionalLight:平行光源
const light = new THREE.DirectionalLight(0xFFFFFF); light.intensity = 2; // 光の強さを倍にする light.position.set(1, 1, 2); // ライトの方向 scene.add(light); // シーンに追加
THREE.AmbientLight:環境光。空間全体を照らす
GPUの制約から、2の累乗の高さ・幅である画像のみが利用可能
// ジオメトリ生成 props(radius, width, height) const geometry = new THREE.SphereGeometry(100, 100, 100); const loader = new THREE.TextureLoader(); const metalTexture = loader.load('texture/metal_01.jpg'); // マテリアル生成 const metalMaterial = new THREE.MeshStandardMaterial({ color: 0x666666, map: metalTexture }); // メッシュ作成 params(ジオメトリ, マテリアル) const sphere = new THREE.Mesh(geometry, metalMaterial); scene.add(sphere);
new THREE.TextureLoader();
でインスタンスを生成し、load('パス');
でファイル読み込み、
mapで設定する
代表的形状
💡 Basic : 光源の影響を受けない
平面
円柱
ドーナツ形状
💡 Standard : 光源の影響を受ける
直方体
球体
円錐
// ジオメトリ生成 props(radius, width, height) const geometry = new THREE.SphereGeometry(100, 100, 100); const planeGeometry = new THREE.PlaneGeometry(120, 120); const coneGeometry = new THREE.ConeGeometry(50, 100, 32); // (radius, height, radialSegments: 側面の数) const cylinderGeometry = new THREE.CylinderGeometry(50, 50, 100, 32); // (top-radius, bottom-radius, height, radialSegments) const torusGeometry = new THREE.TorusGeometry(50, 20, 16, 100); // (radius:ドーナツ自体の半径, tube:内部の半径, radialSegments, tubularSegments:パーツ数。多いと円に近づく) // マテリアル生成 const metalMaterial = new THREE.MeshStandardMaterial({ color: 0x86A8E7, map: metalTexture }); const standardMaterial = new THREE.MeshStandardMaterial({ color: 0x86A8E7 }); const basicMaterial = new THREE.MeshBasicMaterial({ color: 0x86A8E7 }); const planeMaterial = new THREE.MeshBasicMaterial({ color: 0x86A8E7, side: THREE.DoubleSide }); // メッシュ作成 params(ジオメトリ, マテリアル) const sphere = new THREE.Mesh(geometry, metalMaterial); const plane = new THREE.Mesh(planeGeometry, planeMaterial); plane.position.set(240, 0, 0); const cone = new THREE.Mesh(coneGeometry, standardMaterial); cone.position.set(-260, 0, 0); const cylinder = new THREE.Mesh(cylinderGeometry, basicMaterial); cylinder.position.set(-260, -200, 0); const torus = new THREE.Mesh(torusGeometry, basicMaterial); torus.position.set(0, -200, 0); // シーンに追加 scene.add(sphere); scene.add(plane); scene.add(cone); scene.add(cylinder); scene.add(torus);
カメラを自由に回転、移動が可能。多彩な表現が可能
// アニメーション function tick() { requestAnimationFrame(tick); // 引数の関数を毎フレーム実行 // カメラ自動回転 let rot = 0; rot += 0.5; // フレーム毎に0.5度足す const radian = (rot * Math.PI) / 180; // ラジアン変換 camera.position.x = 1000 * Math.sin(radian); // 角度に応じてカメラの位置を設定 camera.position.z = 1000 * Math.cos(radian); // 注視方向を設定 camera.lookAt(new THREE.Vector3(0, 0, 0)); renderer.render(scene, camera); // 描画 } tick(); // 初回実行
let rot = 0; // 角度 let mouseX = 0; // マウス座標 // マウス座標取得イベント、条件設定 document.addEventListener("mousemove", (event) => { mouseX = event.pageX; }); // アニメーション function tick() { requestAnimationFrame(tick); // 引数の関数を毎フレーム実行 // マウス位置に応じて角度設定。マウスのX座標がステージ幅の何%の位置にあるか取得し、360°で乗算 const targetRot = (mouseX / window.innerWidth) * 360; // イージング公式で滑らかに。val += (goalVal - currentVal) * minusVal rot += (targetRot - rot) * 0.02; const radian = (rot * Math.PI) / 180; // ラジアン変換 camera.position.x = 1000 * Math.sin(radian); // 角度に応じてカメラの位置を設定 camera.position.z = 1000 * Math.cos(radian); // 注視方向を設定 camera.lookAt(new THREE.Vector3(0, 0, 0)); renderer.render(scene, camera); // 描画 } tick(); // 初回実行
THREE.OrbitControls
クラス
手軽である分、カスタマイズの自由度の制限がある
細かいカメラワークの実現では物足りない
機能
CDNを利用
<script src="https://unpkg.com/three@0.147.0/examples/js/controls/OrbitControls.js"></script>
※Three.js r148(2022年12月リリース)以降よりES Modulesでの利用が推奨
THREE.OrbitControlsのコンストラクタへカメラのインスタンスとDOM要素を引数として渡すことでマウスと連動してインタラクションが効く。
第二引数はポインタの操作受付対象のDOM要素を指定する。
document.body
(画面内のどこでも操作を受付)かcanvas
要素
// カメラ作成 params(画角, アスペクト, 描画開始距離, 描画終了距離) const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 10000 ); // カメラの初期座標設定 (x: 0, y: 0, z: 0) camera.position.set(0, 0, 1000); // 追加箇所 カメラコントローラー作成 const controls = new THREE.OrbitControls(camera, document.body);
ポインタ操作対象をCanvasのみに絞る
function init() { // レンダラー作成 const canvasElement = document.querySelector("#myCanvas"); const renderer = new THREE.WebGLRenderer({ canvas: canvasElement, }); ~~~省略 // カメラコントローラー作成 const controls = new THREE.OrbitControls(camera, canvasElement);
コントロールを滑らかにする:インスタンスのプロパティを設定
TOP PAGE// カメラコントローラー作成 const controls = new THREE.OrbitControls(camera, canvasElement); controls.enableDamping = true; controls.dampingFactor = 0.2; ~~~省略 // アニメーション function tick() { // カメラコントローラーを更新 プロパティ使用時に必須 controls.update(); ~~~省略