top of page
Buscar

Galería de Arte 3D - Paisajes Infinitos EN HTML



<!DOCTYPE html>

<html lang="es">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Galería de Arte 3D - Paisajes Infinitos</title>

<style>

* {

margin: 0;

padding: 0;

box-sizing: border-box;

}

body {

background: #000;

overflow: hidden;

font-family: 'Georgia', serif;

}

position: relative;

width: 100vw;

height: 100vh;

}

#poem-overlay {

position: absolute;

top: 20px;

left: 20px;

color: rgba(255, 255, 255, 0.9);

font-size: 18px;

line-height: 1.6;

text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8);

z-index: 100;

max-width: 300px;

padding: 20px;

background: rgba(0, 0, 0, 0.3);

border-radius: 10px;

backdrop-filter: blur(10px);

transition: opacity 1s ease-in-out;

}

position: absolute;

bottom: 20px;

right: 20px;

z-index: 100;

color: white;

background: rgba(0, 0, 0, 0.5);

padding: 15px;

border-radius: 10px;

backdrop-filter: blur(10px);

}

.control-btn {

background: rgba(255, 255, 255, 0.1);

border: 1px solid rgba(255, 255, 255, 0.3);

color: white;

padding: 8px 15px;

margin: 3px;

border-radius: 5px;

cursor: pointer;

transition: all 0.3s ease;

}

.control-btn:hover {

background: rgba(255, 255, 255, 0.2);

transform: translateY(-2px);

}

position: absolute;

top: 20px;

right: 20px;

color: white;

font-size: 24px;

text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8);

z-index: 100;

}

</style>

</head>

<body>

<div id="container">

<div id="title">Paisajes Infinitos</div>

<div id="poem-overlay"></div>

<div id="controls">

<div>Escena Actual: <span id="scene-name">Amanecer</span></div>

<button class="control-btn" onclick="nextScene()">Cambiar Escena</button>

<button class="control-btn" onclick="toggleAnimation()">Pausar/Reanudar</button>

</div>

</div>


<script>

// Variables globales

let scene, camera, renderer, canvas;

let brushStrokes = [];

let currentScene = 0;

let animationRunning = true;

let poems = [];

let currentPoem = 0;

// Banco de poemas (triadas)

const poemBank = [

{

title: "Aurora Dorada",

verses: [

"El sol despierta lento,",

"pintando cielos de oro,",

"la tierra se estremece."

]

},

{

title: "Crepúsculo Ardiente",

verses: [

"Fuego en el horizonte,",

"las nubes se sonrojan,",

"el día se despide."

]

},

{

title: "Luna Plateada",

verses: [

"Reina de la noche,",

"bañas el mundo en plata,",

"susurras secretos."

]

},

{

title: "Pincel del Tiempo",

verses: [

"Cada trazo cuenta",

"la historia del momento,",

"arte que no muere."

]

},

{

title: "Colores Salvajes",

verses: [

"Rojos que gritan,",

"azules que cantan suave,",

"arcoíris del alma."

]

},

{

title: "Viento Creador",

verses: [

"Sopla inspiración,",

"mueve el pincel invisible,",

"crea sin descanso."

]

},

{

title: "Sombras Danzantes",

verses: [

"Bailan con la luz,",

"forman figuras etéreas,",

"poesía visual."

]

},

{

title: "Infinito Lienzo",

verses: [

"Sin límites ni bordes,",

"el espacio es mi papel,",

"pinto con estrellas."

]

},

{

title: "Melodía Cromática",

verses: [

"Cada color suena,",

"sinfonía de matices,",

"música para ojos."

]

},

{

title: "Eterno Renacer",

verses: [

"Cada amanecer",

"es un nuevo comienzo,",

"arte sin final."

]

}

];

// Configuraciones de escenas

const sceneConfigs = [

{

name: "Amanecer",

skyColor: [1.0, 0.8, 0.6],

lightColor: [1.0, 0.9, 0.7],

brushColors: [

[1.0, 0.7, 0.3], [1.0, 0.8, 0.4], [0.9, 0.6, 0.2],

[1.0, 0.9, 0.6], [0.8, 0.5, 0.1]

]

},

{

name: "Atardecer",

skyColor: [0.8, 0.4, 0.6],

lightColor: [1.0, 0.5, 0.3],

brushColors: [

[1.0, 0.3, 0.2], [0.9, 0.4, 0.1], [0.8, 0.2, 0.4],

[1.0, 0.6, 0.2], [0.7, 0.1, 0.3]

]

},

{

name: "Noche de Luna",

skyColor: [0.1, 0.1, 0.3],

lightColor: [0.8, 0.8, 1.0],

brushColors: [

[0.6, 0.7, 1.0], [0.4, 0.5, 0.8], [0.3, 0.3, 0.7],

[0.8, 0.8, 0.9], [0.2, 0.2, 0.5]

]

},

{

name: "Abstracto",

skyColor: [0.2, 0.2, 0.2],

lightColor: [1.0, 1.0, 1.0],

brushColors: [

[Math.random(), Math.random(), Math.random()],

[Math.random(), Math.random(), Math.random()],

[Math.random(), Math.random(), Math.random()],

[Math.random(), Math.random(), Math.random()],

[Math.random(), Math.random(), Math.random()]

]

}

];

// Clase para pinceladas 3D

class BrushStroke {

constructor(scene, config) {

this.scene = scene;

this.config = config;

this.points = [];

this.geometry = new THREE.BufferGeometry();

this.material = new THREE.LineBasicMaterial({

color: new THREE.Color(...this.getRandomColor()),

linewidth: Math.random() * 3 + 1,

transparent: true,

opacity: 0.8

});

this.line = new THREE.Line(this.geometry, this.material);

this.age = 0;

this.maxAge = 200 + Math.random() * 300;

this.initializePath();

scene.add(this.line);

}

getRandomColor() {

const colors = this.config.brushColors;

return colors[Math.floor(Math.random() * colors.length)];

}

initializePath() {

const startX = (Math.random() - 0.5) * 20;

const startY = (Math.random() - 0.5) * 10;

const startZ = (Math.random() - 0.5) * 20;

this.direction = new THREE.Vector3(

(Math.random() - 0.5) * 2,

(Math.random() - 0.5) * 2,

(Math.random() - 0.5) * 2

).normalize();

for (let i = 0; i < 50; i++) {

const point = new THREE.Vector3(

startX + this.direction.x * i * 0.2 + Math.sin(i * 0.1) * 2,

startY + this.direction.y * i * 0.2 + Math.cos(i * 0.1) * 2,

startZ + this.direction.z * i * 0.2 + Math.sin(i * 0.15) * 1.5

);

this.points.push(point);

}

this.geometry.setFromPoints(this.points);

}

update() {

this.age++;

// Añadir nuevo punto

if (this.points.length < 100) {

const lastPoint = this.points[this.points.length - 1];

const newPoint = lastPoint.clone();

// Movimiento orgánico

newPoint.add(new THREE.Vector3(

(Math.random() - 0.5) * 0.5,

(Math.random() - 0.5) * 0.5,

(Math.random() - 0.5) * 0.5

));

this.points.push(newPoint);

this.geometry.setFromPoints(this.points);

}

// Desvanecimiento

const fadeStart = this.maxAge * 0.7;

if (this.age > fadeStart) {

const fadeProgress = (this.age - fadeStart) / (this.maxAge - fadeStart);

this.material.opacity = 0.8 * (1 - fadeProgress);

}

// Rotación sutil

this.line.rotation.y += 0.001;

this.line.rotation.x += 0.0005;

return this.age < this.maxAge;

}

destroy() {

this.scene.remove(this.line);

this.geometry.dispose();

this.material.dispose();

}

}

// Inicialización

function init() {

// Crear escena

scene = new THREE.Scene();

// Configurar cámara

camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

camera.position.set(0, 5, 15);

// Configurar renderer

renderer = new THREE.WebGLRenderer({ antialias: true });

renderer.setSize(window.innerWidth, window.innerHeight);

renderer.setClearColor(new THREE.Color(...sceneConfigs[currentScene].skyColor));

document.getElementById('container').appendChild(renderer.domElement);

// Iluminación

const ambientLight = new THREE.AmbientLight(0x404040, 0.6);

scene.add(ambientLight);

const directionalLight = new THREE.DirectionalLight(

new THREE.Color(...sceneConfigs[currentScene].lightColor), 0.8

);

directionalLight.position.set(10, 10, 5);

scene.add(directionalLight);

// Crear elementos del paisaje base

createLandscape();

// Iniciar ciclos

startPoemCycle();

animate();

}

function createLandscape() {

// Suelo/terreno base

const groundGeometry = new THREE.PlaneGeometry(50, 50, 32, 32);

const groundMaterial = new THREE.MeshLambertMaterial({

color: 0x2d5a3d,

transparent: true,

opacity: 0.3

});

const ground = new THREE.Mesh(groundGeometry, groundMaterial);

ground.rotation.x = -Math.PI / 2;

ground.position.y = -5;

scene.add(ground);

// Elementos atmosféricos según la escena

if (currentScene === 2) { // Noche

createMoon();

createStars();

} else if (currentScene === 0) { // Amanecer

createSun(-10, 3, -10);

} else if (currentScene === 1) { // Atardecer

createSun(10, 2, -8);

}

}

function createMoon() {

const moonGeometry = new THREE.SphereGeometry(2, 16, 16);

const moonMaterial = new THREE.MeshLambertMaterial({

color: 0xffffff,

emissive: 0x222222

});

const moon = new THREE.Mesh(moonGeometry, moonMaterial);

moon.position.set(8, 8, -15);

scene.add(moon);

}

function createStars() {

const starGeometry = new THREE.BufferGeometry();

const starPositions = [];

for (let i = 0; i < 1000; i++) {

starPositions.push(

(Math.random() - 0.5) * 200,

Math.random() * 100,

(Math.random() - 0.5) * 200

);

}

starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starPositions, 3));

const starMaterial = new THREE.PointsMaterial({

color: 0xffffff,

size: 0.5

});

const stars = new THREE.Points(starGeometry, starMaterial);

scene.add(stars);

}

function createSun(x, y, z) {

const sunGeometry = new THREE.SphereGeometry(3, 16, 16);

const sunMaterial = new THREE.MeshBasicMaterial({

color: currentScene === 0 ? 0xffd700 : 0xff4500,

emissive: currentScene === 0 ? 0x664400 : 0x441100

});

const sun = new THREE.Mesh(sunGeometry, sunMaterial);

sun.position.set(x, y, z);

scene.add(sun);

}

function clearScene() {

// Limpiar pinceladas

brushStrokes.forEach(stroke => stroke.destroy());

brushStrokes = [];

// Limpiar toda la escena

while(scene.children.length > 0) {

const child = scene.children[0];

scene.remove(child);

if (child.geometry) child.geometry.dispose();

if (child.material) child.material.dispose();

}

// Recrear iluminación

const ambientLight = new THREE.AmbientLight(0x404040, 0.6);

scene.add(ambientLight);

const directionalLight = new THREE.DirectionalLight(

new THREE.Color(...sceneConfigs[currentScene].lightColor), 0.8

);

directionalLight.position.set(10, 10, 5);

scene.add(directionalLight);

}

function nextScene() {

currentScene = (currentScene + 1) % sceneConfigs.length;

// Limpiar escena actual

clearScene();

// Actualizar colores de fondo

renderer.setClearColor(new THREE.Color(...sceneConfigs[currentScene].skyColor));

// Recrear paisaje

createLandscape();

// Actualizar UI

document.getElementById('scene-name').textContent = sceneConfigs[currentScene].name;

}

function createBrushStroke() {

if (brushStrokes.length < 20) {

const stroke = new BrushStroke(scene, sceneConfigs[currentScene]);

brushStrokes.push(stroke);

}

}

function updateBrushStrokes() {

for (let i = brushStrokes.length - 1; i >= 0; i--) {

if (!brushStrokes[i].update()) {

brushStrokes[i].destroy();

brushStrokes.splice(i, 1);

}

}

}

function animate() {

if (!animationRunning) {

requestAnimationFrame(animate);

return;

}

// Crear nueva pincelada aleatoriamente

if (Math.random() < 0.1) {

createBrushStroke();

}

// Actualizar pinceladas existentes

updateBrushStrokes();

// Rotación lenta de la cámara

const time = Date.now() * 0.0005;

camera.position.x = Math.cos(time) * 20;

camera.position.z = Math.sin(time) * 20;

camera.lookAt(0, 0, 0);

// Actualizar colores abstractos en escena abstracta

if (currentScene === 3) {

sceneConfigs[3].brushColors = [

[Math.random(), Math.random(), Math.random()],

[Math.random(), Math.random(), Math.random()],

[Math.random(), Math.random(), Math.random()],

[Math.random(), Math.random(), Math.random()],

[Math.random(), Math.random(), Math.random()]

];

}

renderer.render(scene, camera);

requestAnimationFrame(animate);

}

function startPoemCycle() {

function showNextPoem() {

const poemElement = document.getElementById('poem-overlay');

const poem = poemBank[currentPoem];

poemElement.innerHTML = `

<h3 style="color: #ffd700; margin-bottom: 10px;">${poem.title}</h3>

${poem.verses.map(verse => `<div>${verse}</div>`).join('')}

`;

currentPoem = (currentPoem + 1) % poemBank.length;

}

showNextPoem();

setInterval(showNextPoem, 10000); // Cambiar cada 10 segundos

}

function toggleAnimation() {

animationRunning = !animationRunning;

}

// Event listeners

window.addEventListener('resize', () => {

camera.aspect = window.innerWidth / window.innerHeight;

camera.updateProjectionMatrix();

renderer.setSize(window.innerWidth, window.innerHeight);

});

// Auto cambio de escena cada 30 segundos

setInterval(() => {

if (animationRunning) {

nextScene();

}

}, 30000);

// Inicializar cuando la página cargue

window.addEventListener('load', init);

// Efectos de partículas adicionales

function createParticleSystem() {

const particleCount = 500;

const particles = new THREE.BufferGeometry();

const positions = [];

const colors = [];

for (let i = 0; i < particleCount; i++) {

positions.push(

(Math.random() - 0.5) * 100,

Math.random() * 50,

(Math.random() - 0.5) * 100

);

const color = sceneConfigs[currentScene].brushColors[

Math.floor(Math.random() * sceneConfigs[currentScene].brushColors.length)

];

colors.push(...color);

}

particles.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));

particles.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));

const particleMaterial = new THREE.PointsMaterial({

size: 0.1,

vertexColors: true,

transparent: true,

opacity: 0.6

});

const particleSystem = new THREE.Points(particles, particleMaterial);

scene.add(particleSystem);

return particleSystem;

}

// Añadir sistema de partículas después de 5 segundos

setTimeout(() => {

createParticleSystem();

}, 5000);

</script>

</body>

</html>












ree

 
 
 

Comentarios


bottom of page