WebGPUTest / index.html
awacke1's picture
Update index.html
363ad46 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js Spaceship Fly-Through</title>
<style>
body { margin: 0; overflow: hidden; }
canvas { display: block; }
</style>
</head>
<body>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/[email protected]/build/three.module.js",
"three/addons/": "https://unpkg.com/[email protected]/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { WebGLRenderer } from 'three';
// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 5, 10);
const renderer = new WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
// Lighting
const ambientLight = new THREE.AmbientLight(0x404040, 0.5);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight.position.set(1, 1, 1);
scene.add(directionalLight);
// Spaceship (simple cone)
const shipGeometry = new THREE.ConeGeometry(0.5, 2, 32);
const shipMaterial = new THREE.MeshStandardMaterial({ color: 0x00ff00, metalness: 0.8, roughness: 0.2 });
const spaceship = new THREE.Mesh(shipGeometry, shipMaterial);
spaceship.position.set(0, 0, 0);
scene.add(spaceship);
// Particle system for buildings
const buildingCount = 50; // Reduced for performance
const buildingGeometry = new THREE.BufferGeometry();
const buildingPositions = new Float32Array(buildingCount * 3);
const buildingColors = new Float32Array(buildingCount * 3);
const buildingSizes = new Float32Array(buildingCount);
for (let i = 0; i < buildingCount; i++) {
buildingPositions[i * 3] = (Math.random() - 0.5) * 200;
buildingPositions[i * 3 + 1] = Math.random() * 10;
buildingPositions[i * 3 + 2] = (Math.random() - 0.5) * 200;
buildingColors[i * 3] = 0.2;
buildingColors[i * 3 + 1] = 0.6;
buildingColors[i * 3 + 2] = 1.0;
buildingSizes[i] = Math.random() * 2 + 1;
}
buildingGeometry.setAttribute('position', new THREE.BufferAttribute(buildingPositions, 3));
buildingGeometry.setAttribute('color', new THREE.BufferAttribute(buildingColors, 3));
buildingGeometry.setAttribute('size', new THREE.BufferAttribute(buildingSizes, 1));
const buildingMaterial = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.7,
sizeAttenuation: true
});
const buildings = new THREE.Points(buildingGeometry, buildingMaterial);
scene.add(buildings);
// Particle system for people
const peopleCount = 100; // Reduced for performance
const peopleGeometry = new THREE.BufferGeometry();
const peoplePositions = new Float32Array(peopleCount * 3);
const peopleColors = new Float32Array(peopleCount * 3);
const peopleSizes = new Float32Array(peopleCount);
for (let i = 0; i < peopleCount; i++) {
peoplePositions[i * 3] = (Math.random() - 0.5) * 150;
peoplePositions[i * 3 + 1] = Math.random() * 5;
peoplePositions[i * 3 + 2] = (Math.random() - 0.5) * 150;
peopleColors[i * 3] = 1.0;
peopleColors[i * 3 + 1] = 0.8;
peopleColors[i * 3 + 2] = 0.8;
peopleSizes[i] = Math.random() * 0.5 + 0.2;
}
peopleGeometry.setAttribute('position', new THREE.BufferAttribute(peoplePositions, 3));
peopleGeometry.setAttribute('color', new THREE.BufferAttribute(peopleColors, 3));
peopleGeometry.setAttribute('size', new THREE.BufferAttribute(peopleSizes, 1));
const peopleMaterial = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true,
transparent: true,
opacity: 0.6,
sizeAttenuation: true
});
const people = new THREE.Points(peopleGeometry, peopleMaterial);
scene.add(people);
// Instanced cubes
const cubeCount = 30; // Reduced for performance
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
const cubeMaterial = new THREE.MeshStandardMaterial({ color: 0xff00ff, metalness: 0.5, roughness: 0.4 });
const cubeMesh = new THREE.InstancedMesh(cubeGeometry, cubeMaterial, cubeCount);
const dummy = new THREE.Object3D();
for (let i = 0; i < cubeCount; i++) {
dummy.position.set(
(Math.random() - 0.5) * 100,
Math.random() * 10,
(Math.random() - 0.5) * 100
);
dummy.scale.setScalar(Math.random() * 0.5 + 0.5);
dummy.updateMatrix();
cubeMesh.setMatrixAt(i, dummy.matrix);
}
scene.add(cubeMesh);
// Camera movement
let time = 0;
function updateCamera() {
time += 0.01;
camera.position.z -= 0.5; // Forward movement
camera.position.x = Math.sin(time * 0.5) * 5; // Side-to-side
camera.position.y = Math.cos(time * 0.3) * 2 + 5; // Up-down
camera.lookAt(new THREE.Vector3(0, 0, camera.position.z - 100));
}
// Parallax and repetition
function updateObjects() {
const positions = buildings.geometry.attributes.position.array;
for (let i = 0; i < buildingCount; i++) {
positions[i * 3 + 2] += 0.5;
if (positions[i * 3 + 2] > camera.position.z + 100) {
positions[i * 3 + 2] -= 200;
}
}
buildings.geometry.attributes.position.needsUpdate = true;
const peoplePos = people.geometry.attributes.position.array;
for (let i = 0; i < peopleCount; i++) {
peoplePos[i * 3 + 2] += 0.7; // Faster for parallax
if (peoplePos[i * 3 + 2] > camera.position.z + 100) {
peoplePos[i * 3 + 2] -= 200;
}
}
people.geometry.attributes.position.needsUpdate = true;
for (let i = 0; i < cubeCount; i++) {
cubeMesh.getMatrixAt(i, dummy.matrix);
dummy.matrix.decompose(dummy.position, dummy.quaternion, dummy.scale);
dummy.position.z += 0.6;
if (dummy.position.z > camera.position.z + 100) {
dummy.position.z -= 200;
}
dummy.updateMatrix();
cubeMesh.setMatrixAt(i, dummy.matrix);
}
cubeMesh.instanceMatrix.needsUpdate = true;
}
// Animation loop
function animate() {
try {
requestAnimationFrame(animate);
updateCamera();
updateObjects();
renderer.render(scene, camera);
} catch (error) {
console.error('Rendering error:', error);
}
}
animate();
// Handle window resize
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// Error handling for WebGL
if (!renderer.getContext()) {
console.error('WebGL is not supported in this browser.');
alert('WebGL is not supported. Please use a modern browser like Chrome or Firefox.');
}
</script>
</body>
</html>