import * as THREE from 'https://unpkg.com/three@0.160.0/build/three.module.js'; import { createSun } from './sun.js'; import { createMountains } from './mountains.js'; // Scene setup const scene = new THREE.Scene(); scene.background = new THREE.Color(0x090012); scene.fog = new THREE.Fog(0x090012, 20, 120); const camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.1, 500 ); camera.position.set(0, 2, 15); camera.rotation.x = -0.1; const renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('bg'), antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(Math.min(window.devicePixelRatio, 1.5)); // Grid const size = 200; const divisions = 200; const grid = new THREE.GridHelper(size, divisions, 0xff00ff, 0xff00ff); grid.material.transparent = true; grid.material.opacity = 0.4; scene.add(grid); // --- Occlusion floor (invisible) --- const floorGeometry = new THREE.PlaneGeometry(size, size); const floorMaterial = new THREE.MeshBasicMaterial({ color: 0x090012, // matches background opacity: 0.5, // invisible transparent: true }); const floor = new THREE.Mesh(floorGeometry, floorMaterial); floor.rotation.x = -Math.PI / 2; // horizontal floor.position.y = 0; // same height as grid scene.add(floor); // Sun const { sun, glow } = createSun(); scene.add(sun); scene.add(glow); let scroll = 0; let sunAngle = 0; // Mountains const mountains = createMountains(); scene.add(mountains); // Animation function function animate() { scroll += 0.05; grid.position.z = scroll % 10; renderer.render(scene, camera); } // Start loop with pause/resume on tab visibility renderer.setAnimationLoop(animate); document.addEventListener('visibilitychange', () => { if (document.hidden) { renderer.setAnimationLoop(null); } else { renderer.setAnimationLoop(animate); } }); // Handle window resize window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); });