bloom / index.html
joung's picture
Add 3 files
47b1948 verified
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>λ²šκ½ƒ ν©λ‚ λ¦¬λŠ” μ• λ‹ˆλ©”μ΄μ…˜</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
background: linear-gradient(to bottom, #87CEEB, #E0F7FA);
}
canvas {
display: block;
}
.info {
position: absolute;
bottom: 20px;
width: 100%;
text-align: center;
color: white;
font-family: 'Arial', sans-serif;
text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
pointer-events: none;
}
.controls {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
}
.control-btn {
background: rgba(255,255,255,0.7);
border: none;
border-radius: 50%;
width: 40px;
height: 40px;
margin: 5px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
transition: all 0.3s ease;
}
.control-btn:hover {
background: rgba(255,255,255,0.9);
transform: scale(1.1);
}
</style>
</head>
<body>
<div class="info">
<h1 class="text-4xl font-bold mb-2">μ•„λ¦„λ‹€μš΄ λ²šκ½ƒλ‚˜λ¬΄</h1>
<p class="text-xl">λ΄„μ˜ κ²½μ΄λ‘œμ›€μ„ λŠκ»΄λ³΄μ„Έμš”</p>
</div>
<div class="controls">
<button class="control-btn" id="zoomIn">+</button>
<button class="control-btn" id="zoomOut">-</button>
<button class="control-btn" id="resetView">↻</button>
</div>
<script>
// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
// Enhanced lighting
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2);
directionalLight.position.set(5, 10, 7);
scene.add(directionalLight);
// Add hemisphere light for more natural outdoor lighting
const hemisphereLight = new THREE.HemisphereLight(0xffffbb, 0x080820, 0.5);
scene.add(hemisphereLight);
// Create larger cherry blossom tree trunk
const trunkGeometry = new THREE.CylinderGeometry(1.5, 2.5, 15, 12);
const trunkMaterial = new THREE.MeshPhongMaterial({
color: 0x8B4513,
flatShading: true,
shininess: 30
});
const trunk = new THREE.Mesh(trunkGeometry, trunkMaterial);
trunk.position.y = 7.5;
trunk.castShadow = true;
scene.add(trunk);
// Create branches with more detail
const branchMaterial = new THREE.MeshPhongMaterial({
color: 0x8B4513,
flatShading: true
});
function createBranch(length, angle, position, parent = null) {
const branchGeometry = new THREE.CylinderGeometry(
length * 0.05,
length * 0.1,
length,
8
);
const branch = new THREE.Mesh(branchGeometry, branchMaterial);
if (parent) {
parent.add(branch);
branch.position.copy(position);
} else {
scene.add(branch);
branch.position.copy(position);
}
branch.rotation.z = angle;
// Add some randomness to branches
branch.rotation.x = Math.random() * 0.3 - 0.15;
branch.rotation.y = Math.random() * 0.3 - 0.15;
branch.castShadow = true;
return branch;
}
// Main branches (more and larger)
const mainBranches = [];
const branchCount = 8;
for (let i = 0; i < branchCount; i++) {
const angle = (i / branchCount) * Math.PI * 2;
const length = 8 + Math.random() * 4;
const height = 10 + Math.random() * 5;
const x = Math.cos(angle) * 1.5;
const z = Math.sin(angle) * 1.5;
const branch = createBranch(length, angle * 0.8, new THREE.Vector3(x, height, z));
mainBranches.push(branch);
// Add secondary branches
const secondaryCount = 3 + Math.floor(Math.random() * 3);
for (let j = 0; j < secondaryCount; j++) {
const secLength = length * (0.4 + Math.random() * 0.2);
const secAngle = angle + (Math.random() * 0.6 - 0.3);
const secHeight = height - length * (0.2 + j * 0.2);
const secBranch = createBranch(
secLength,
secAngle,
new THREE.Vector3(0, -length * (0.2 + j * 0.2), 0),
branch
);
// Add tertiary branches
if (Math.random() > 0.5) {
const terCount = 2 + Math.floor(Math.random() * 2);
for (let k = 0; k < terCount; k++) {
const terLength = secLength * (0.4 + Math.random() * 0.2);
const terAngle = secAngle + (Math.random() * 0.4 - 0.2);
createBranch(
terLength,
terAngle,
new THREE.Vector3(0, -secLength * (0.3 + k * 0.2), 0),
secBranch
);
}
}
}
}
// Create cherry blossom petals (more and larger)
const petals = [];
const petalCount = 1500; // Increased petal count
const petalColors = [
0xFFB6C1, 0xFF69B4, 0xFF1493, 0xFFC0CB, 0xFFE4E1,
0xFFA07A, 0xFF82AB, 0xFF6EB4, 0xFF83A8, 0xFF8FBC
];
// More detailed petal geometry
const petalShape = new THREE.Shape();
petalShape.moveTo(0, 0);
petalShape.bezierCurveTo(0.5, 0.1, 0.8, 0.3, 0.8, 0.6);
petalShape.bezierCurveTo(0.8, 0.9, 0.5, 1.0, 0.2, 0.8);
petalShape.bezierCurveTo(-0.1, 0.6, -0.1, 0.3, 0, 0);
const petalGeometry = new THREE.ShapeGeometry(petalShape);
petalGeometry.scale(0.08, 0.08, 0.08); // Larger petals
// Create petals with more variation
for (let i = 0; i < petalCount; i++) {
const petalMaterial = new THREE.MeshBasicMaterial({
color: petalColors[Math.floor(Math.random() * petalColors.length)],
transparent: true,
opacity: 0.7 + Math.random() * 0.2,
side: THREE.DoubleSide
});
const petal = new THREE.Mesh(petalGeometry, petalMaterial);
// Initial position around the tree (larger area)
petal.position.x = (Math.random() - 0.5) * 30;
petal.position.y = 5 + Math.random() * 25;
petal.position.z = (Math.random() - 0.5) * 30;
// Random rotation and scale
petal.rotation.x = Math.random() * Math.PI;
petal.rotation.y = Math.random() * Math.PI;
petal.rotation.z = Math.random() * Math.PI;
const scale = 0.8 + Math.random() * 0.4;
petal.scale.set(scale, scale, scale);
// Store velocity for animation with more variation
petal.userData = {
velocity: new THREE.Vector3(
(Math.random() - 0.5) * 0.02,
-0.03 - Math.random() * 0.05,
(Math.random() - 0.5) * 0.02
),
rotationSpeed: new THREE.Vector3(
Math.random() * 0.02,
Math.random() * 0.02,
Math.random() * 0.02
),
wobble: Math.random() * 0.02,
wobbleSpeed: 0.01 + Math.random() * 0.02
};
scene.add(petal);
petals.push(petal);
}
// Larger ground with more detail
const groundGeometry = new THREE.CircleGeometry(50, 64);
const groundMaterial = new THREE.MeshPhongMaterial({
color: 0x7CFC00,
side: THREE.DoubleSide,
shininess: 10
});
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
ground.position.y = 0;
ground.receiveShadow = true;
scene.add(ground);
// Add grass texture to ground
const grassGeometry = new THREE.CircleGeometry(50, 64);
const grassMaterial = new THREE.MeshPhongMaterial({
color: 0x5A8F29,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.3
});
const grass = new THREE.Mesh(grassGeometry, grassMaterial);
grass.rotation.x = -Math.PI / 2;
grass.position.y = 0.01;
scene.add(grass);
// Add more fallen petals on the ground
for (let i = 0; i < 300; i++) {
const petal = new THREE.Mesh(petalGeometry, new THREE.MeshBasicMaterial({
color: petalColors[Math.floor(Math.random() * petalColors.length)],
transparent: true,
opacity: 0.6 + Math.random() * 0.3,
side: THREE.DoubleSide
}));
petal.position.x = (Math.random() - 0.5) * 45;
petal.position.y = 0.01;
petal.position.z = (Math.random() - 0.5) * 45;
petal.rotation.x = Math.random() * Math.PI;
petal.rotation.y = Math.random() * Math.PI;
petal.rotation.z = Math.random() * Math.PI;
const scale = 0.06 + Math.random() * 0.04;
petal.scale.set(scale, scale, scale);
scene.add(petal);
}
// Add some background elements (distant trees)
for (let i = 0; i < 10; i++) {
const angle = (i / 10) * Math.PI * 2;
const distance = 35 + Math.random() * 10;
const tree = new THREE.Mesh(
new THREE.ConeGeometry(3, 8, 5),
new THREE.MeshPhongMaterial({
color: 0x2E8B57,
flatShading: true
})
);
tree.position.x = Math.cos(angle) * distance;
tree.position.z = Math.sin(angle) * distance;
tree.position.y = 4;
scene.add(tree);
}
// Camera position - start further back to see the whole tree
camera.position.set(0, 15, 25);
camera.lookAt(0, 10, 0);
// Handle window resize
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// Add controls
document.getElementById('zoomIn').addEventListener('click', () => {
camera.position.z *= 0.9;
});
document.getElementById('zoomOut').addEventListener('click', () => {
camera.position.z *= 1.1;
});
document.getElementById('resetView').addEventListener('click', () => {
camera.position.set(0, 15, 25);
camera.lookAt(0, 10, 0);
});
// Enhanced animation loop
let time = 0;
function animate() {
requestAnimationFrame(animate);
time += 0.01;
// Animate petals with more natural movement
petals.forEach(petal => {
// Move petal with slight wobble
petal.position.x += petal.userData.velocity.x + Math.sin(time * petal.userData.wobbleSpeed) * petal.userData.wobble;
petal.position.y += petal.userData.velocity.y;
petal.position.z += petal.userData.velocity.z + Math.cos(time * petal.userData.wobbleSpeed) * petal.userData.wobble;
// Rotate petal
petal.rotation.x += petal.userData.rotationSpeed.x;
petal.rotation.y += petal.userData.rotationSpeed.y;
petal.rotation.z += petal.userData.rotationSpeed.z;
// Reset petal position when it falls below ground
if (petal.position.y < -5) {
petal.position.x = (Math.random() - 0.5) * 20;
petal.position.y = 25 + Math.random() * 10;
petal.position.z = (Math.random() - 0.5) * 20;
// Randomize velocity again
petal.userData.velocity.set(
(Math.random() - 0.5) * 0.02,
-0.03 - Math.random() * 0.05,
(Math.random() - 0.5) * 0.02
);
}
});
// Gentle camera movement
camera.position.x = Math.sin(time * 0.2) * 5;
camera.position.z = 25 + Math.cos(time * 0.2) * 5;
camera.lookAt(0, 10, 0);
renderer.render(scene, camera);
}
animate();
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=joung/bloom" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>