<div id="container" class="container"></div>
.container {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
import * as THREE from "https://cdn.skypack.dev/three@0.133.1";
import { OrbitControls } from "https://cdn.skypack.dev/three@0.133.1/examples/jsm/controls/OrbitControls";
// 建立場景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x040014);
// 建立相機
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(100, 100, 100); // 相機位置
camera.lookAt(scene.position) // 相機焦點
// 建立物體
// 球形體
const sphereGeometry = new THREE.IcosahedronGeometry(20, 1);
const sphereMaterial = new THREE.MeshPhongMaterial({
color: 0xffffff,
emissive: 0x000000,
specular: 0xffffff,
shininess: 100,
flatShading: true
});
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
// 行星環
const RingInsideGeometry = new THREE.RingGeometry(37, 28, 30, 30);
const RingMaterial = opacity => {
return new THREE.MeshPhongMaterial({
color: 0xffffff,
emissive: 0x000000,
specular: 0xffffff,
shininess: 100,
flatShading: true,
transparent: true,
opacity
});
}
const ringInside = new THREE.Mesh(RingInsideGeometry, RingMaterial(0.9));
const RingOutsideGeometry = new THREE.RingGeometry(42, 38, 30, 30);
const ringOutside = new THREE.Mesh(RingOutsideGeometry, RingMaterial(0.65));
const ringGroup = new THREE.Group();
ringGroup.rotation.x = THREE.MathUtils.degToRad(90);
ringGroup.add(ringInside, ringOutside);
const planet = new THREE.Group();
planet.add(sphere, ringGroup);
planet.rotation.x = THREE.MathUtils.degToRad(-30);
planet.rotation.y = THREE.MathUtils.degToRad(-10);
scene.add(planet);
// 群星背景
const geometry = new THREE.BufferGeometry();
const particleAmount = 2000;
const vertices = [...Array(particleAmount * 3)].map(() => 2000 * Math.random() - 1000);
geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
const particleTexture = new THREE.TextureLoader().load('https://i.imgur.com/9TwBBHH.png');
const material = new THREE.PointsMaterial({ size: 5, sizeAttenuation: true, map: particleTexture, transparent: true, alphaTest: 0.5, color: 0xf3f3af });
const particles = new THREE.Points(geometry, material);
scene.add(particles);
// 建立光源
// 環境光
const ambientLight = new THREE.AmbientLight(0x222222);
// 點光源
const pointLight = new THREE.PointLight(0x777777, 1, 0);
pointLight.position.set(100, 100, 0);
// 聚光燈
const spotLight = new THREE.SpotLight(0xffffff, 3, 150, Math.PI / 15, 1, 1);
spotLight.position.set(50, 100, -80);
spotLight.castShadow = true;
spotLight.shadow.mapSize.width = 1024;
spotLight.shadow.mapSize.height = 1024;
spotLight.shadow.camera.near = 10;
spotLight.shadow.camera.far = 200;
spotLight.shadow.focus = 1;
scene.add(ambientLight, pointLight, spotLight);
// 建立渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.getElementById('container')?.appendChild(renderer.domElement);
// 建立軌道控制器
const control = new OrbitControls(camera, renderer.domElement);
// 執行渲染
function animate() {
requestAnimationFrame(animate);
planet.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
// 監聽螢幕寬高變化來做簡單 RWD 設定
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight)
})
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.