- 新卒ブログとは?
- 2024年4月に新卒入社したLIGメンバーが、日々の学びや気づきを綴るブログです。彼らがふだんどんなことを学んでいるのか、気軽にのぞいてみてください。
こんにちは、新米エンジニアのにっしーです。
Webサイトでの表現の幅を広げたいと思い、Webブラウザ上で3DCGを制作することができるJavaScriptのライブラリ「Three.js」を勉強しています。
この連載では、Three.jsを使った制作物を紹介していきますので、同じようにThree.jsの勉強をされているみなさんの参考になれば幸いです!
今回は主にテクスチャの勉強として、惑星とその周りにパーティクルを散らせた宇宙空間的なものを作りました!
ちなみに前回は、テキストジオメトリとボックスジオメトリを活用して自分の名前をデコデコにしました。まだの方はこちらもぜひご覧ください!
Three.jsで3DCGを作ろう!〜テキストを3D空間に配置する〜
※導入方法などは端折らせていただきますので、あらかじめご了承ください。
完成系
さっそくですが、今回作成したものがこちらです!
実装方法
1.シーン、カメラ等もろもろを準備
これは、three.jsを作る上である程度お作法のようなものなので、深掘りすることはせず準備していきます。 three.jsの基本をおさらいしてみよう!〜基礎の基礎編〜
気になる方はこちらのブログで細かく紹介されているので、ご覧ください。
// canvasを取得
const canvas = document.getElementById(“canvas”) as HTMLCanvasElement;
if (!canvas) return;
// シーン
const scene = new THREE.Scene();
// サイズ
const sizes = {
width: window.innerWidth,
height: window.innerHeight,
};
// カメラ
const camera = new THREE.PerspectiveCamera(
75,
sizes.width / sizes.height,
0.1,
1000
);
camera.position.set(1, 0, 3);
// レンダラー
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: true,
alpha: true,
});
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(window.devicePixelRatio);
//メッシュ
// 2で作成。
// ブラウザのリサイズ処理
const onWindowResize = () => {
sizes.width = window.innerWidth;
sizes.height = window.innerHeight;
camera.aspect = sizes.width / sizes.height;
camera.updateProjectionMatrix();
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(window.devicePixelRatio);
};
window.addEventListener(“resize”, onWindowResize);
// クリーンアップ関数
return () => {
window.removeEventListener(“resize”, onWindowResize);
renderer.dispose();
};
2.メッシュを用意
2-1.惑星の作成
はじめにスフィアジオメトリにテクスチャを貼り付けて、惑星を作成していきます。
今回テクスチャはこちらのサイトからを引用してきました!(https://planetpixelemporium.com/earth.html)他の惑星も同様にできるので、好きなものを持ってきてください!
// テクスチャのimport
import img1 from “@/image/earthmap1k.jpg”;
// スフィアジオメトリの作成。(半径,水平のセグメント数,垂直セグメント数)
const circleGeometry = new THREE.SphereGeometry(1, 36, 36);
// テクスチャの読み込み
let txLoader = new THREE.TextureLoader();
let normalMap = txLoader.load(img1.src);
// マテリアルの作成
const circleMaterial = new THREE.MeshBasicMaterial({
color:0xffffff,
map: normalMap,
});
// メッシュを作成
const circle = new THREE.Mesh(circleGeometry, circleMaterial);
// シーンに追加
scene.add(circle);
2-2.自転するアニメーションの追加
先ほどのコードのままだと動きがないので、縦横に回転するアニメーションを作成していきます。
const animate = () => {
circle.rotation.x += 0.002;
circle.rotation.y += 0.001;
// シーンのレンダリング
requestAnimationFrame(animate);
}
animate();
2-3.星の作成
惑星の周りを星をイメージして粒子を散布させていきます。
const particlesGeometry = new THREE.BufferGeometry();
const count = 1000;
const positions = new Float32Array(count * 3);
const colors = new Float32Array(count * 3);
for (let i = 0; i < count * 3; i++) {
positions[i] = (Math.random() – 0.5) * 10;
colors[i] = Math.random();
};
particlesGeometry.setAttribute(
“position”,
new THREE.BufferAttribute(positions, 3)
);
particlesGeometry.setAttribute(
“color”,
new THREE.BufferAttribute(colors, 3)
);
// パーティクルマテリアル
const pointsMaterial = new THREE.PointsMaterial({
size: 0.05,
vertexColors: true,
blending: THREE.AdditiveBlending,
});
// パーティクルメッシュ
const particlesMesh = new THREE.Points(particlesGeometry, pointsMaterial);
scene.add(particlesMesh);
2-4.星が回るアニメーションの付与
先ほどの惑星と同様にアニメーションの付与を行っていきます。
自転のアニメーションに続けて書いていきます。
// アニメーションループ
const animate = () => {
// パーティクルの回転などを追加する場合はここで行う
particlesMesh.rotation.y += 0.002;
circle.rotation.x += 0.002;
circle.rotation.y += 0.001;
// シーンのレンダリング
renderer.render(scene, camera);
requestAnimationFrame(animate);
};
animate();
完成!
先ほどの2つを組み合わせて完成です。
今回参考にさせていただいた動画
まとめ
今回、テクスチャを駆使して宇宙空間を作ってみました!
自動で永続的に動くようにアニメーションを制作しましたが、個人的にユーザがぐりぐり動かせるほうが楽しいので、次回はユーザが触りながら楽しめるものを作っていこうと思います。
パーティクルがいろいろ応用できそうなので、実装方法を忘れないように見直したいなと思いました。まだまだ業務で使えるレベルではないので、いつか業務で活用できるように引き続き学習していきたいです。
それでは「第3回Three.jsで3DCGを作ろう!」でお会いしましょう!
にっしーでした。