Three.jsで3DCGを作ろう!〜動く宇宙空間を生み出す〜

Three.jsで3DCGを作ろう!〜動く宇宙空間を生み出す〜

Yuya Nishizawa

Yuya Nishizawa

新卒ブログとは?
2024年4月に新卒入社したLIGメンバーが、日々の学びや気づきを綴るブログです。彼らがふだんどんなことを学んでいるのか、気軽にのぞいてみてください。

こんにちは、新米エンジニアのにっしーです。

Webサイトでの表現の幅を広げたいと思い、Webブラウザ上で3DCGを制作することができるJavaScriptのライブラリ「Three.js」を勉強しています。

この連載では、Three.jsを使った制作物を紹介していきますので、同じようにThree.jsの勉強をされているみなさんの参考になれば幸いです!

今回は主にテクスチャの勉強として、惑星とその周りにパーティクルを散らせた宇宙空間的なものを作りました!

ちなみに前回は、テキストジオメトリとボックスジオメトリを活用して自分の名前をデコデコにしました。まだの方はこちらもぜひご覧ください!

※導入方法などは端折らせていただきますので、あらかじめご了承ください。

完成系

さっそくですが、今回作成したものがこちらです!

実装方法

1.シーン、カメラ等もろもろを準備

これは、three.jsを作る上である程度お作法のようなものなので、深掘りすることはせず準備していきます。
気になる方はこちらのブログで細かく紹介されているので、ご覧ください。

javascript

	
	// 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)他の惑星も同様にできるので、好きなものを持ってきてください!

javascript

// テクスチャの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.自転するアニメーションの追加

先ほどのコードのままだと動きがないので、縦横に回転するアニメーションを作成していきます。

javascript

	const animate = () => {
		circle.rotation.x += 0.002;
		circle.rotation.y += 0.001;
		// シーンのレンダリング
      	requestAnimationFrame(animate);
	}
	animate();

2-3.星の作成

惑星の周りを星をイメージして粒子を散布させていきます。

javascript


	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.星が回るアニメーションの付与

先ほどの惑星と同様にアニメーションの付与を行っていきます。
自転のアニメーションに続けて書いていきます。

javascript

	// アニメーションループ
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つを組み合わせて完成です。

今回参考にさせていただいた動画

【Three.js入門】パーティクルで星屑を描画してみよう

まとめ

今回、テクスチャを駆使して宇宙空間を作ってみました!

自動で永続的に動くようにアニメーションを制作しましたが、個人的にユーザがぐりぐり動かせるほうが楽しいので、次回はユーザが触りながら楽しめるものを作っていこうと思います。

パーティクルがいろいろ応用できそうなので、実装方法を忘れないように見直したいなと思いました。まだまだ業務で使えるレベルではないので、いつか業務で活用できるように引き続き学習していきたいです。

それでは「第3回Three.jsで3DCGを作ろう!」でお会いしましょう!

にっしーでした。

新卒採用募集中!
LIGは、Webデザインからグローバルなシステム開発まで、幅広い分野のコンサルティングから制作、運用までおこなう企業です。

  • 日本・フィリピン・ベトナムでの活躍チャンス
  • 最先端技術と多言語環境での成長
  • 有識者による月1回の勉強会

現在、海外拠点(フィリピン、ベトナム)に関われるエンジニアを募集しています。日本だけじゃなく世界で活躍することに興味のある方は、以下よりぜひご応募ください!

新卒採用ページへ

この記事のシェア数

フロントエンドエンジニアとして主に大手メーカーのWebサイト制作・保守業務を担当。JS、React、Nextのフレームワークに関しての深い知見を持つ。中学時代からIT分野に興味を持ち、高校でWebプログラミングの基礎を学ぶ。専門学校卒業を経て2024年に新卒入社。

このメンバーの記事をもっと読む
LIG新卒ブログ【2024】 | 16 articles
10年以上の開発実績があるLIGが、最適な開発体制や見積もりをご提案します
相談する サービス詳細を見る