infinite-agents-public/threejs_viz/threejs_viz_2.html

264 lines
9.2 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three.js - Animated Lighting</title>
<style>
body {
margin: 0;
overflow: hidden;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #000;
}
canvas {
display: block;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 10px;
left: 10px;
color: white;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 8px;
font-size: 14px;
max-width: 400px;
z-index: 100;
}
#info h2 {
margin: 0 0 10px 0;
font-size: 18px;
}
#info .web-source {
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid rgba(255,255,255,0.3);
font-size: 12px;
opacity: 0.8;
}
#info a {
color: #4fc3f7;
text-decoration: none;
}
#info a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div id="info">
<h2>Animated Lighting</h2>
<p><strong>Technique:</strong> Dynamic lighting with moving light sources</p>
<p><strong>Learning:</strong> AmbientLight, DirectionalLight, PointLight configuration and animation</p>
<div class="web-source">
<strong>Web Source:</strong><br>
<a href="https://threejs.org/examples/#webgl_lights_pointlights" target="_blank">Three.js Lighting Examples</a><br>
<em>Applied: Multiple animated point lights with visible light spheres and material reactivity</em>
</div>
</div>
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
// Scene setup
let camera, scene, renderer;
let centralObject, lightHelpers = [];
let pointLights = [];
let clock;
init();
animate();
function init() {
// Clock for time-based animations
clock = new THREE.Clock();
// Camera setup
camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(0, 5, 10);
camera.lookAt(0, 0, 0);
// Scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x0a0a0a);
scene.fog = new THREE.Fog(0x0a0a0a, 20, 50);
// Renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Create visualization
createVisualization();
// Handle resize
window.addEventListener('resize', onWindowResize);
}
function createVisualization() {
// Ambient light - provides subtle base illumination
const ambientLight = new THREE.AmbientLight(0x222244, 0.3);
scene.add(ambientLight);
// Central object - complex geometry that shows lighting beautifully
const geometry = new THREE.IcosahedronGeometry(2, 1);
// MeshStandardMaterial reacts realistically to lights
const material = new THREE.MeshStandardMaterial({
color: 0x666666,
roughness: 0.4,
metalness: 0.6,
flatShading: false
});
centralObject = new THREE.Mesh(geometry, material);
scene.add(centralObject);
// Create three point lights with different colors
const lightConfigs = [
{ color: 0xff3366, distance: 0, decay: 2, intensity: 2 }, // Pink/Red
{ color: 0x3366ff, distance: 0, decay: 2, intensity: 2 }, // Blue
{ color: 0xffaa00, distance: 0, decay: 2, intensity: 2 } // Orange
];
lightConfigs.forEach((config, index) => {
// Create point light
const pointLight = new THREE.PointLight(
config.color,
config.intensity,
config.distance,
config.decay
);
// Initial position (will be animated)
const angle = (index / lightConfigs.length) * Math.PI * 2;
const radius = 5;
pointLight.position.set(
Math.cos(angle) * radius,
Math.sin(angle * 1.5) * 2,
Math.sin(angle) * radius
);
scene.add(pointLight);
pointLights.push(pointLight);
// Create visible sphere at light position
const sphereGeometry = new THREE.SphereGeometry(0.2, 16, 16);
const sphereMaterial = new THREE.MeshBasicMaterial({
color: config.color,
transparent: true,
opacity: 0.9
});
const lightHelper = new THREE.Mesh(sphereGeometry, sphereMaterial);
pointLight.add(lightHelper);
lightHelpers.push(lightHelper);
// Add a subtle glow effect around each light
const glowGeometry = new THREE.SphereGeometry(0.4, 16, 16);
const glowMaterial = new THREE.MeshBasicMaterial({
color: config.color,
transparent: true,
opacity: 0.2
});
const glow = new THREE.Mesh(glowGeometry, glowMaterial);
pointLight.add(glow);
});
// Add a ground plane to show light falloff
const planeGeometry = new THREE.PlaneGeometry(30, 30);
const planeMaterial = new THREE.MeshStandardMaterial({
color: 0x111122,
roughness: 0.8,
metalness: 0.2
});
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -Math.PI / 2;
plane.position.y = -3;
scene.add(plane);
// Add some additional objects to show lighting effects
const smallSphereGeometry = new THREE.SphereGeometry(0.5, 32, 32);
const smallSphereMaterial = new THREE.MeshStandardMaterial({
color: 0xcccccc,
roughness: 0.3,
metalness: 0.7
});
for (let i = 0; i < 5; i++) {
const smallSphere = new THREE.Mesh(smallSphereGeometry, smallSphereMaterial);
const angle = (i / 5) * Math.PI * 2;
const radius = 4;
smallSphere.position.set(
Math.cos(angle) * radius,
-1,
Math.sin(angle) * radius
);
scene.add(smallSphere);
}
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
const time = clock.getElapsedTime();
// Rotate central object slowly
centralObject.rotation.y = time * 0.3;
centralObject.rotation.x = Math.sin(time * 0.2) * 0.2;
// Animate each point light in orbit around the central object
pointLights.forEach((light, index) => {
// Each light has different orbit characteristics
const speed = 0.5 + index * 0.15;
const radius = 5 + Math.sin(time * 0.3 + index) * 0.5;
const verticalSpeed = 0.8 + index * 0.2;
// Calculate orbital position
const angle = time * speed + (index / pointLights.length) * Math.PI * 2;
light.position.x = Math.cos(angle) * radius;
light.position.z = Math.sin(angle) * radius;
light.position.y = Math.sin(time * verticalSpeed + index * 2) * 2;
// Vary light intensity slightly for dynamic effect
light.intensity = 2 + Math.sin(time * 2 + index) * 0.5;
});
// Slowly rotate camera around the scene
const cameraAngle = time * 0.1;
const cameraRadius = 10;
camera.position.x = Math.cos(cameraAngle) * cameraRadius;
camera.position.z = Math.sin(cameraAngle) * cameraRadius;
camera.position.y = 5 + Math.sin(cameraAngle * 0.5) * 2;
camera.lookAt(0, 0, 0);
renderer.render(scene, camera);
}
</script>
</body>
</html>