プログラミング/JavaScript/three.js/再入門 の履歴(No.2)
更新準備†
https://cdnjs.com/libraries/three.js
へ行き、Copy Script Tag ボタン </> を押すと
LANG:html <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js" integrity="sha512-dLxUelApnYxpLt6K2iomGngnHO83iUvZytA3YjDUCjT0HDOHKXnVYdf3hU4JjM8uEhxf9nD1/ey98U3t2vZ0qQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
が手に入る。
そこでテスト用には、
LANG:html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"
integrity="sha512-dLxUelApnYxpLt6K2iomGngnHO83iUvZytA3YjDUCjT0HDOHKXnVYdf3hU4JjM8uEhxf9nD1/ey98U3t2vZ0qQ=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body>
<!-- ここに html を書く -->
<script>
window.addEventListener("DOMContentLoaded", setup);
function setup() {
// ここにコードを書く
}
</script>
</body>
</html>
のようなひな形を使えば良さそう。
立方体のチュートリアル†
レンダリングの基本†
公式チュートリアル:
https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene
一部こちらも参考にさせていただいて:
https://ics.media/entry/14771/
three.js で描画するには以下の手順を踏むことになる
- 描画先を指定してレンダラーを作る
- シーンを作る
- シーンにオブジェクトや光源を追加する
- カメラを作る
- シーンとカメラを指定してレンダリングする
ここでは、
LANG:html <canvas id="canvas1" width="800", height="600">
に書き込むことにする。
LANG:js
// ここにコードを書く
// 描画先の canvas エレメント
const canvas = document.querySelector("#canvas1");
// レンダラーを作成 (描画先を指定した)
const renderer = new THREE.WebGLRenderer({canvas: canvas});
renderer.setSize( canvas.width, canvas.height );
renderer.setPixelRatio(window.devicePixelRatio);
// カメラを作成 (画角、アスペクト比、描画開始距離、描画終了距離)
const camera = new THREE.PerspectiveCamera(
45, canvas.width / canvas.height, 0.1, 10000 );
camera.position.set(0, 0, +1000); // x, y, z
// シーンを作成
const scene = new THREE.Scene();
// ここでシーンにオブジェクトや光源を追加する
// setup_scene(scene);
// レンダリング
renderer.render(scene, camera);
これで正しくレンダリングされる。
ただし、オブジェクトも光源もないシーンなので真っ暗なまま。
オブジェクトと光源を追加してみる†
LANG:js
// ここでシーンにオブジェクトや光源を追加する
setup_objects(scene);
setup_lights(scene);
function setup_lights(scene) {
// 平行光源
const light = new THREE.DirectionalLight(0xff80ff);
light.intensity = 1;
light.position.set(1, 1, 1);
scene.add(light); // シーンに追加
// 環境光
const ambient = new THREE.AmbientLight( 0x80ffff );
ambient.intensity = 0.2;
scene.add(ambient); // シーンに追加
}
function setup_objects(scene) {
// 箱を作成
const geometry = new THREE.BoxGeometry(300, 300, 300); // 形状
const material = new THREE.MeshStandardMaterial({color: 0x8080ff}); // 単色の材質
const box = new THREE.Mesh(geometry, material); // 形状と材質を指定してメッシュを作成
box.rotation.x = 3.14/4;
box.rotation.y = 3.14/4;
scene.add(box); // シーンに追加
}
これで立方体が表示された。
アニメーションさせる†
一定時間間隔でシーンを変更しつつ renderer.render を呼ぶための機構が備わっている。
LANG:js // レンダリング renderer.render(scene, camera);
としていた部分を、
LANG:js
function renderFrame() {
renderer.render( scene, camera );
scene.update(); // シーンを更新する
// 次フレームの描画を予約
requestAnimationFrame( renderFrame );
}
// 次フレームの描画を予約
requestAnimationFrame( renderFrame );
とするとともに、オブジェクトの追加時に
LANG:js
function setup_objects(scene) {
// 箱を作成
const geometry = new THREE.BoxGeometry(300, 300, 300); // 形状
const material = new THREE.MeshStandardMaterial({color: 0x8080ff}); // 単色の材質
const box = new THREE.Mesh(geometry, material); // 形状と材質を指定してメッシュを作成
box.rotation.x = 3.14/4;
box.rotation.y = 3.14/4;
scene.add(box); // シーンに追加
// シーンの更新方法を指定(箱を回転させる)
scene.update = function() {
box.rotation.x += 0.01;
box.rotation.y += 0.01;
}
}
のようにシーンの更新方法を登録しておく。
これでアニメーションが行われる。
ここまでのコード†
LANG:html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"
integrity="sha512-dLxUelApnYxpLt6K2iomGngnHO83iUvZytA3YjDUCjT0HDOHKXnVYdf3hU4JjM8uEhxf9nD1/ey98U3t2vZ0qQ=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body>
<canvas id="canvas1" width="800", height="600"></canvas>
<script>
window.addEventListener("DOMContentLoaded", init);
function init() {
// 描画先の canvas エレメント
const canvas = document.querySelector("#canvas1");
// レンダラーを作成 (描画先を指定した)
const renderer = new THREE.WebGLRenderer({canvas: canvas});
renderer.setSize( canvas.width, canvas.height );
renderer.setPixelRatio(window.devicePixelRatio);
// カメラを作成 (画角、アスペクト比、描画開始距離、描画終了距離)
const camera = new THREE.PerspectiveCamera(
45, canvas.width / canvas.height, 0.1, 10000 );
camera.position.set(0, 0, +1000); // x, y, z
// シーンを作成
const scene = new THREE.Scene();
// ここでシーンにオブジェクトや光源を追加する
setup_objects(scene);
setup_lights(scene);
// レンダリング
renderer.render(scene, camera);
function renderFrame() {
renderer.render( scene, camera );
scene.update(); // シーンを更新する
// 次フレームの描画を予約
requestAnimationFrame( renderFrame );
}
// 次フレームの描画を予約
requestAnimationFrame( renderFrame );
}
function setup_lights(scene) {
// 平行光源
const light = new THREE.DirectionalLight(0xff80ff);
light.intensity = 1;
light.position.set(1, 1, 1);
scene.add(light); // シーンに追加
// 環境光
const ambientLight = new THREE.AmbientLight( 0x80ffff );
ambientLight.intensity = 0.2;
scene.add( ambientLight );
}
function setup_objects(scene) {
// 箱を作成
const geometry = new THREE.BoxGeometry(300, 300, 300); // 形状
const material = new THREE.MeshStandardMaterial({color: 0x8080ff}); // 単色の材質
const box = new THREE.Mesh(geometry, material); // 形状と材質を指定してメッシュを作成
box.rotation.x = 3.14/4;
box.rotation.y = 3.14/4;
scene.add(box); // シーンに追加
// シーンを更新する(箱を回転させる)
scene.update = function() {
box.rotation.x += 0.01;
box.rotation.y += 0.01;
}
}
</script>
</body>
</html>
任意形状のメッシュを生成†
LANG:js
function setup_objects(scene) {
// 正方形の頂点セット
// 実際には2つの三角形を組み合わせて正方形にしているため
// (0,0,0) と (100,100,0) が2回表れる
const vertices = new Float32Array( [
0, 0, 0,
100, 0, 0,
100, 100, 0,
100, 100, 0,
0, 100, 0,
0, 0, 0,
] );
const geometry = new THREE.BufferGeometry();
// 頂点あたりの引数の数を itemSize = 3 として指定
geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
geometry.computeVertexNormals(); // これを忘れると表示されない
const material = new THREE.MeshStandardMaterial( { color: 0xff0000 } );
material.side = THREE.DoubleSide; // 裏側も描画
const mesh = new THREE.Mesh( geometry, material );
scene.add(mesh);
// シーンを更新する(箱を回転させる)
scene.update = function() {
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
mesh.rotation.z += 0.005;
}
}
ExtrudeGeometry で厚みのある形状†
https://threejs.org/docs/#api/en/geometries/ExtrudeGeometry
LANG:js
function setup_objects(scene) {
const h = 120, w = 80;
const shape = new THREE.Shape();
shape.moveTo( 0,0 );
shape.lineTo( 0, w );
shape.lineTo( h, w );
shape.lineTo( h, 0 );
shape.lineTo( 0, 0 );
const extrudeSettings = {
steps: 2, // 押し出し方向の分割数
depth: 160, // 押し出し長さ
bevelEnabled: true,
bevelThickness: 30, // 押し出し方向
bevelSize: 30, // 面内方向
bevelOffset: 20, // 外形からの距離(って何だ?)
bevelSegments: 1 // 大きくすると丸くなる
};
const geometry = new THREE.ExtrudeGeometry( shape, extrudeSettings );
geometry.computeVertexNormals(); // これを忘れると表示されない
const material = new THREE.MeshStandardMaterial( { color: 0xffffff } );
material.side = THREE.DoubleSide; // 裏側も描画
const mesh = new THREE.Mesh( geometry, material );
scene.add(mesh);
// シーンを更新する(箱を回転させる)
scene.update = function() {
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
mesh.rotation.z += 0.005;
}
}
右は bevelSegments = 10 としたもの。
Counter: 7738 (from 2010/06/03),
today: 3,
yesterday: 7




