はじめに
今日は、Three.jsで、雨(雪)、クリスマスツリー周辺に点滅するライトを実装してみたのでその備忘録メモ。
PointsMaterialは、大量に作ってもパフォーマンスが落ちないようで、使えるマテリアルですね。
雨や雪以外に、宇宙空間に星空を作りたい場合などにも有効だと思います。

1. 雨(雪)の作成
1.1 雨エフェクトの実装
雨粒をパーティクルシステムとしてシミュレートする方法です。雨粒は、ランダムな位置に配置され、重力で落ちていきます。
const rainCount = 10000; // 雨の粒子数
const rainGeometry = new THREE.BufferGeometry();
const rainPositions = new Float32Array(rainCount * 3);
for (let i = 0; i < rainCount; i++) {
rainPositions[i * 3] = Math.random() * 500 - 250; // X座標
rainPositions[i * 3 + 1] = Math.random() * 500 - 250; // Y座標
rainPositions[i * 3 + 2] = Math.random() * 500 - 250; // Z座標
}
rainGeometry.setAttribute('position', new THREE.BufferAttribute(rainPositions, 3));
const rainMaterial = new THREE.PointsMaterial({
color: 0xaaaaaa, // 灰色の雨
size: 0.1,
opacity: 0.8,
transparent: true,
});
const rain = new THREE.Points(rainGeometry, rainMaterial);
scene.add(rain);
function updateRain() {
const positions = rainGeometry.attributes.position.array;
for (let i = 0; i < positions.length; i += 3) {
positions[i + 1] -= 0.5; // Y座標を減少させて雨粒が落ちる
if (positions[i + 1] < -250) positions[i + 1] = 250; // 地面に当たったら上に戻す
}
rainGeometry.attributes.position.needsUpdate = true;
}
1.2 雪エフェクトの実装
雪も同様にパーティクルシステムを使用して、ランダムに降らせるエフェクトを作成します。
const snowCount = 10000; // 雪の粒子数
const snowGeometry = new THREE.BufferGeometry();
const snowPositions = new Float32Array(snowCount * 3);
for (let i = 0; i < snowCount; i++) {
snowPositions[i * 3] = Math.random() * 500 - 250; // X座標
snowPositions[i * 3 + 1] = Math.random() * 500 - 250; // Y座標
snowPositions[i * 3 + 2] = Math.random() * 500 - 250; // Z座標
}
snowGeometry.setAttribute('position', new THREE.BufferAttribute(snowPositions, 3));
const snowMaterial = new THREE.PointsMaterial({
color: 0xffffff, // 白色の雪
size: 0.3,
opacity: 0.7,
transparent: true,
});
const snow = new THREE.Points(snowGeometry, snowMaterial);
scene.add(snow);
function updateSnow() {
const positions = snowGeometry.attributes.position.array;
for (let i = 0; i < positions.length; i += 3) {
positions[i + 1] -= 0.5; // Y座標を減少させて雪粒が落ちる
if (positions[i + 1] < -250) positions[i + 1] = 250; // 地面に当たったら上に戻す
}
snowGeometry.attributes.position.needsUpdate = true;
}
2. クリスマスツリーの作成
当初は、自分でジオメトリを組み合わせて作ろうかと思いましたが、ちょっと味気なかったので、
また、https://sketchfab.com/ から素材をお借りしてきました。
以下は、MeshBasicMaterialを使った当初の実装サンプルです。
2.1 ツリーの作成
THREE.ConeGeometryを使用して、円錐型のクリスマスツリーを作成します。ツリーの上には星を置いて、完成度を高めます。
function createChristmasTree() {
const treeHeight = 10;
const treeGeometry = new THREE.ConeGeometry(5, treeHeight, 8); // 円錐形
const treeMaterial = new THREE.MeshBasicMaterial({ color: 0x228B22 }); // 緑色
const tree = new THREE.Mesh(treeGeometry, treeMaterial);
tree.position.set(0, treeHeight / 2, 0); // 地面に立つように配置
scene.add(tree);
// ツリーの上に星を追加
const starGeometry = new THREE.SphereGeometry(1, 32, 32);
const starMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 }); // 黄色
const star = new THREE.Mesh(starGeometry, starMaterial);
star.position.set(0, treeHeight, 0); // ツリーの頂上に配置
scene.add(star);
}
3. ポイントライトによるライトアップと点滅
3.1 ポイントライトを追加
ツリーを光らせるために、THREE.PointLight を使ってLEDライトをツリーに配置します。ここで、複数のライトをランダムに配置し、点滅させます。
function createLEDLights() {
const lightCount = 100; // LEDの数
for (let i = 0; i < lightCount; i++) {
const x = Math.random() * 10 - 5;
const y = Math.random() * 10 + 2;
const z = Math.random() * 10 - 5;
const color = Math.random() < 0.5 ? 0xff0000 : 0x00ff00; // 赤か緑
const light = new THREE.PointLight(color, 1, 10);
light.position.set(x, y, z);
scene.add(light);
}
}
3.2 ライトの点滅
ライトが点滅するように、時間に応じてライトの強さを変更します。Math.sinを使って、点滅効果をシミュレートします。
function updateLEDLights() {
scene.children.forEach(child => {
if (child instanceof THREE.PointLight) {
child.intensity = Math.sin(Date.now() * 0.005) * 0.5 + 0.5; // 点滅する強さ
}
});
}
4. アニメーションループ
上記のエフェクトを全て組み合わせるために、アニメーションループを使って定期的に更新を行います。
function animate() {
requestAnimationFrame(animate); // 次のフレームを呼び出し
updateRain(); // 雨の更新
updateSnow(); // 雪の更新
updateLEDLights(); // LEDライトの点滅
renderer.render(scene, camera); // シーンをレンダリング
}
animate(); // アニメーション開始
5. まとめ
- 雨(雪)のエフェクト:
THREE.BufferGeometryとTHREE.PointsMaterialを使って、雨や雪の粒子を表現。時間経過に応じて動かす。 - クリスマスツリー:
THREE.ConeGeometryを使用してツリーを作成し、THREE.SphereGeometryで星を追加。 - ライトアップ:
THREE.PointLightを使ってツリーの周りに複数のLEDライトを追加し、点滅させる。 - アニメーション:
requestAnimationFrameとアニメーションループで、動きのあるシーンを作成。
これで、クリスマスの雰囲気を盛り上げるシーンが完成しました!最適化や追加のエフェクトを試して、さらにクオリティを高めることもできます。
💬 コメント