Enhance galaxy background with terrain generation and moon lighting effects
This commit is contained in:
206
index.html
206
index.html
@@ -6,6 +6,7 @@
|
||||
<title>Services Homepage</title>
|
||||
<link rel="stylesheet" href="/styles.css" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/simplex-noise/2.4.0/simplex-noise.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="galaxy-canvas"></canvas>
|
||||
@@ -35,10 +36,12 @@
|
||||
<small>Generated: static homepage — served by nginx in a container. Edit and rebuild to update.</small>
|
||||
</footer>
|
||||
<script>
|
||||
// Galaxy background animation - exact CodePen recreation
|
||||
// Galaxy background - exact CodePen recreation with moon and terrain
|
||||
(function initGalaxy(){
|
||||
var ww = window.innerWidth;
|
||||
var wh = window.innerHeight;
|
||||
console.clear();
|
||||
|
||||
var ww = window.innerWidth,
|
||||
wh = window.innerHeight;
|
||||
|
||||
var renderer = new THREE.WebGLRenderer({
|
||||
antialias: true,
|
||||
@@ -56,124 +59,131 @@
|
||||
camera.position.z = 5;
|
||||
camera.lookAt(new THREE.Vector3());
|
||||
|
||||
// Galaxy particles
|
||||
var particles = [];
|
||||
for(var i = 0; i < 20000; i++){
|
||||
var particle = new Particle();
|
||||
particles.push(particle);
|
||||
scene.add(particle.object);
|
||||
/* LIGHTS */
|
||||
var moonLight = new THREE.PointLight(0xffffff, 2, 150);
|
||||
scene.add(moonLight);
|
||||
|
||||
var moon;
|
||||
function createMoon() {
|
||||
var geometry = new THREE.SphereGeometry(8, 32, 32);
|
||||
var material = new THREE.MeshPhongMaterial({
|
||||
color: 0x26fdd9,
|
||||
shininess: 15,
|
||||
emissive: 0x2bb2e6,
|
||||
emissiveIntensity: 0.8
|
||||
});
|
||||
moon = new THREE.Mesh(geometry, material);
|
||||
moon.position.x = -9;
|
||||
moon.position.z = -6.5;
|
||||
moon.position.y = 1;
|
||||
moon.rotation.y = -1;
|
||||
scene.add(moon);
|
||||
moonLight.position.copy(moon.position);
|
||||
moonLight.position.y += 4;
|
||||
var moonLight2 = new THREE.PointLight(0xffffff, 0.6, 150);
|
||||
scene.add(moonLight2);
|
||||
moonLight2.position.x += 20;
|
||||
moonLight2.position.y -= 20;
|
||||
moonLight2.position.z -= 25;
|
||||
}
|
||||
|
||||
function Particle(){
|
||||
var radius = Math.random() * 120 + 5;
|
||||
var height = (Math.random() - 0.5) * 10;
|
||||
var angle = Math.random() * Math.PI * 2;
|
||||
// Initialize simplex noise
|
||||
var noise = new SimplexNoise();
|
||||
|
||||
this.object = new THREE.Object3D();
|
||||
this.object.position.y = height;
|
||||
|
||||
var geometry = new THREE.SphereGeometry(0.1, 4, 4);
|
||||
var material = new THREE.MeshBasicMaterial({ color: 0xffffff });
|
||||
var mesh = new THREE.Mesh(geometry, material);
|
||||
mesh.position.x = radius;
|
||||
|
||||
this.object.add(mesh);
|
||||
this.object.rotation.z = angle;
|
||||
|
||||
this.update = function(){
|
||||
this.object.rotation.z += 0.0002 + (120 - radius) * 0.00002;
|
||||
};
|
||||
}
|
||||
|
||||
// Terrain/Mountains - smooth shaded, not wireframe
|
||||
var terrain = new THREE.Object3D();
|
||||
|
||||
function createMountain(color, yPos, opacity, zOffset){
|
||||
var geometry = new THREE.PlaneGeometry(400, 400, 100, 100);
|
||||
var positionAttr = geometry.attributes.position;
|
||||
function createTerrain() {
|
||||
var geometry = new THREE.PlaneGeometry(150, 150, 120, 120);
|
||||
var m = new THREE.Matrix4();
|
||||
m.makeRotationX(Math.PI * -0.5);
|
||||
geometry.applyMatrix4(m);
|
||||
|
||||
for(var i = 0; i < positionAttr.count; i++){
|
||||
var x = positionAttr.getX(i);
|
||||
var y = positionAttr.getY(i);
|
||||
var distance = Math.sqrt(x * x + y * y);
|
||||
|
||||
// Smoother, wave-like mountains
|
||||
var z = Math.sin(x * 0.02) * Math.cos(y * 0.02) * 20;
|
||||
z += Math.sin(x * 0.01 + y * 0.01) * 10;
|
||||
z += Math.sin(distance * 0.01) * 15;
|
||||
|
||||
// Fade at edges for horizon effect
|
||||
var fade = Math.max(0, 1 - distance / 200);
|
||||
positionAttr.setZ(i, z * fade + zOffset);
|
||||
var positions = geometry.attributes.position;
|
||||
for(var i = 0; i < positions.count; i++) {
|
||||
var x = positions.getX(i);
|
||||
var z = positions.getZ(i);
|
||||
var ratio = noise.noise3D(x * 0.03, z * 0.03, 0);
|
||||
positions.setY(i, ratio * 10);
|
||||
}
|
||||
|
||||
positionAttr.needsUpdate = true;
|
||||
positions.needsUpdate = true;
|
||||
geometry.computeVertexNormals();
|
||||
|
||||
var material = new THREE.MeshLambertMaterial({
|
||||
color: color,
|
||||
transparent: true,
|
||||
opacity: opacity,
|
||||
side: THREE.DoubleSide,
|
||||
flatShading: false
|
||||
|
||||
var material = new THREE.MeshPhongMaterial({
|
||||
color: 0x198257,
|
||||
emissive: 0x032f50
|
||||
});
|
||||
|
||||
var mesh = new THREE.Mesh(geometry, material);
|
||||
mesh.rotation.x = -Math.PI / 2;
|
||||
mesh.position.y = yPos;
|
||||
terrain.add(mesh);
|
||||
var plane = new THREE.Mesh(geometry, material);
|
||||
scene.add(plane);
|
||||
}
|
||||
|
||||
// Create 3 layers - back to front
|
||||
createMountain(0x0d2847, -25, 0.4, -10); // Far layer - lighter blue
|
||||
createMountain(0x0a1f3d, -20, 0.6, -5); // Middle layer
|
||||
createMountain(0x061829, -15, 0.8, 0); // Close layer - darkest
|
||||
var stars = new THREE.Group();
|
||||
scene.add(stars);
|
||||
var starsLights = new THREE.Group();
|
||||
scene.add(starsLights);
|
||||
var starsAmount = 20;
|
||||
|
||||
function createStars() {
|
||||
var geometry = new THREE.SphereGeometry(0.3, 16, 16);
|
||||
var material = new THREE.MeshBasicMaterial({color: 0xffffff});
|
||||
for(var i = 0; i < starsAmount; i++) {
|
||||
var star = new THREE.Mesh(geometry, material);
|
||||
star.position.x = (Math.random() - 0.5) * 150;
|
||||
star.position.z = (Math.random() - 0.5) * 150;
|
||||
var ratio = noise.noise3D(star.position.x * 0.03, star.position.z * 0.03, 0);
|
||||
star.position.y = ratio * 10 + 0.3;
|
||||
stars.add(star);
|
||||
var velX = (Math.random() + 0.1) * 0.1 * (Math.random() < 0.5 ? -1 : 1);
|
||||
var velY = (Math.random() + 0.1) * 0.1 * (Math.random() < 0.5 ? -1 : 1);
|
||||
star.vel = new THREE.Vector2(velX, velY);
|
||||
var starLight = new THREE.PointLight(0xffffff, 0.8, 3);
|
||||
starLight.position.copy(star.position);
|
||||
starLight.position.y += 0.5;
|
||||
starsLights.add(starLight);
|
||||
}
|
||||
}
|
||||
|
||||
scene.add(terrain);
|
||||
function updateStar(star, index) {
|
||||
if(star.position.x < -75) {
|
||||
star.position.x = 75;
|
||||
}
|
||||
if(star.position.x > 75) {
|
||||
star.position.x = -75;
|
||||
}
|
||||
if(star.position.z < -75) {
|
||||
star.position.z = 75;
|
||||
}
|
||||
if(star.position.z > 75) {
|
||||
star.position.z = -75;
|
||||
}
|
||||
|
||||
// Lighting setup
|
||||
var ambientLight = new THREE.AmbientLight(0x4488ff, 0.5);
|
||||
scene.add(ambientLight);
|
||||
star.position.x += star.vel.x;
|
||||
star.position.z += star.vel.y;
|
||||
var ratio = noise.noise3D(star.position.x * 0.03, star.position.z * 0.03, 0);
|
||||
star.position.y = ratio * 10 + 0.3;
|
||||
|
||||
var directionalLight = new THREE.DirectionalLight(0xffffff, 0.3);
|
||||
directionalLight.position.set(50, 50, 50);
|
||||
scene.add(directionalLight);
|
||||
starsLights.children[index].position.copy(star.position);
|
||||
starsLights.children[index].position.y += 0.5;
|
||||
}
|
||||
|
||||
// Atmospheric point lights
|
||||
var pointLight1 = new THREE.PointLight(0x88ccff, 1.5, 150);
|
||||
pointLight1.position.set(0, 20, 0);
|
||||
scene.add(pointLight1);
|
||||
|
||||
var pointLight2 = new THREE.PointLight(0x4488cc, 1.0, 120);
|
||||
pointLight2.position.set(-40, 10, 30);
|
||||
scene.add(pointLight2);
|
||||
|
||||
var pointLight3 = new THREE.PointLight(0x6699ff, 0.8, 100);
|
||||
pointLight3.position.set(40, 10, -30);
|
||||
scene.add(pointLight3);
|
||||
|
||||
// Animation
|
||||
function render(){
|
||||
function render(a) {
|
||||
requestAnimationFrame(render);
|
||||
|
||||
particles.forEach(function(p){
|
||||
p.update();
|
||||
});
|
||||
|
||||
terrain.rotation.z += 0.00005;
|
||||
|
||||
for(var i = 0; i < starsAmount; i++) {
|
||||
updateStar(stars.children[i], i);
|
||||
}
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
window.addEventListener('resize', function(){
|
||||
function onResize() {
|
||||
ww = window.innerWidth;
|
||||
wh = window.innerHeight;
|
||||
camera.aspect = ww / wh;
|
||||
camera.updateProjectionMatrix();
|
||||
renderer.setSize(ww, wh);
|
||||
});
|
||||
}
|
||||
|
||||
render();
|
||||
createMoon();
|
||||
createTerrain();
|
||||
createStars();
|
||||
requestAnimationFrame(render);
|
||||
window.addEventListener('resize', onResize);
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
|
||||
Reference in New Issue
Block a user