初めまして!
今年の7月に中途入社したKOOと申します。
エンジニア
KOO
Webの動きを表現するのが好きで、
これからどんどん情報を発信していきたいと思っています。
よろしくお願いいたします!
エンジニア
KOO
さて、今回はThree.jsを使って動くページを作成してみたいと思います。
See the Pen
Three.jsで簡単な動きサイトを作ってみた by KOO (@Xueni-Gu)
on CodePen.
目次
基本的なテンプレートを設定
// HTML-Three.js ライブラリの読み込み
src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"
// CSS-画面全体のレイアウト設定
body {
margin: 0; overflow: hidden;
}
canvas {
display: block;
}
#text-overlay {
position: absolute;
top: 50%;
left: 20%;
transform: translateY(-50%);
color: white;
font-weight: bold;
font-family: Arial, sans-serif;
font-size: 36px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
}
// Three.jsのセットアップ
// シーン、カメラ、レンダラーの作成
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
// ウィンドウのリサイズ処理
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
地球のメッシュを作成
SphereGeometryを作成し、カメラの位置とレンダリングを設定
// 地球のジオメトリを作成
const earthGeometry = new THREE.SphereGeometry(1, 64, 64);
// 地球のメッシュを作成
const earth = new THREE.Mesh(earthGeometry);
scene.add(earth);
// カメラの位置を設定
camera.position.set(1, 0, 4); // カメラを少し遠ざける
// レンダリング
renderer.render(scene, camera);
地球のマテリアルを作成
// 地球のジオメトリを作成
const earthGeometry = new THREE.SphereGeometry(1, 64, 64);
// 地球のマテリアルを作成
const earthMaterial = new THREE.MeshPhongMaterial({
specular: new THREE.Color('grey'),
});
// 地球のメッシュを作成
const earth = new THREE.Mesh(earthGeometry, earthMaterial);
scene.add(earth);
画面が見えるように光も追加
// 環境光を追加
const ambientLight = new THREE.AmbientLight(0xffffff, 0.2);
scene.add(ambientLight);
// 平行光源を追加して太陽光をシミュレート
const sunLight = new THREE.DirectionalLight(0xffffff, 1);
sunLight.position.set(5, 3, 5);
scene.add(sunLight);
地球のテクスチャを作成
// 地球のジオメトリを作成
const earthGeometry = new THREE.SphereGeometry(1, 64, 64);
// 地球のテクスチャを読み込む
const textureLoader = new THREE.TextureLoader();
const earthTexture = textureLoader.load('https://threejs.org/examples/textures/planets/earth_atmos_2048.jpg');
const earthNormalMap = textureLoader.load('https://threejs.org/examples/textures/planets/earth_normal_2048.jpg');
const earthSpecularMap = textureLoader.load('https://threejs.org/examples/textures/planets/earth_specular_2048.jpg');
// 地球のマテリアルを作成
const earthMaterial = new THREE.MeshPhongMaterial({
map: earthTexture,
normalMap: earthNormalMap,
specularMap: earthSpecularMap,
specular: new THREE.Color('grey'),
shininess: 10
});
// ....
// アニメーションループ(シーンを継続的に更新し再描画するために、アニメーションループが必要です。)
function animate() {
requestAnimationFrame(animate);
// 地球をゆっくり回転させる
earth.rotation.y += 0.002;
renderer.render(scene, camera);
}
animate();
これでもう完成ですが、見た目をさらによくするために、雲層と大気圏も作りましょう。
雲層を追加
//...
// 雲層を作成
const cloudsGeometry = new THREE.SphereGeometry(1.01, 64, 64);
const cloudsTexture = textureLoader.load('https://threejs.org/examples/textures/planets/earth_clouds_1024.png');
const cloudsMaterial = new THREE.MeshPhongMaterial({
map: cloudsTexture,
transparent: true,
opacity: 0.4 // 雲の不透明度を下げる
});
const clouds = new THREE.Mesh(cloudsGeometry, cloudsMaterial);
earth.add(clouds);
// カメラの位置を少し調整し、センターに移動
camera.position.set(0, 0, 5);
//...
// アニメーションループ
function animate() {
requestAnimationFrame(animate);
// 地球をゆっくり回転させる
earth.rotation.y += 0.002;
clouds.rotation.y += 0.0023;
renderer.render(scene, camera);
}
animate();
大気圏を追加
// 大気圏の光輪効果を作成
const atmosphereGeometry = new THREE.SphereGeometry(1.1, 64, 64);
const atmosphereMaterial = new THREE.ShaderMaterial({
vertexShader: `
varying vec3 vNormal;
void main() {
vNormal = normalize(normalMatrix * normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
varying vec3 vNormal;
void main() {
float intensity = pow(0.7 - dot(vNormal, vec3(0.0, 0.0, 1.0)), 2.0);
gl_FragColor = vec4(0.3, 0.6, 1.0, 1.0) * intensity;
}
`,
blending: THREE.AdditiveBlending,
side: THREE.BackSide
});
const atmosphere = new THREE.Mesh(atmosphereGeometry, atmosphereMaterial);
scene.add(atmosphere);
最後に背景を追加したら完成です!
星空の背景を追加
// 星空の背景を追加
const starsGeometry = new THREE.BufferGeometry();
const starsMaterial = new THREE.PointsMaterial({color: 0xffffff, size: 0.02});
const starsVertices = [];
for (let i = 0; i < 10000; i++) {
const x = THREE.MathUtils.randFloatSpread(2000);
const y = THREE.MathUtils.randFloatSpread(2000);
const z = THREE.MathUtils.randFloatSpread(2000);
starsVertices.push(x, y, z);
}
starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starsVertices, 3));
const starField = new THREE.Points(starsGeometry, starsMaterial);
scene.add(starField);
おわりに
いかがでしょうか?基本的な考え方は、まずシーン、カメラ、レンダラーを設定し、カメラの位置を調整します。そのあとでSphereGeometryを三つ作成し、それぞれに異なるマテリアルを与えて、同じ場所に配置します。
最後まで読んでいただき、ありがとうございます。これからも頑張ります!
記事を読んで興味を持った方はぜひコチラから↓