Pinterest
Загрузка шейдера...
Pinterest
Социальный интернет-сервис, фотохостинг, позволяющий пользователям добавлять в режиме онлайн изображения, помещать их в тематические коллекции и делиться ими с другими пользователями. Изображения можно «приколоть» (англ. to pin) к коллекциям, которые называются «досками» (англ. boards).
erWidth / window.innerHeight, 0.1, 1000);
this.renderer = new THREE.WebGLRenderer({
canvas: document.getElementById('canvas-webgl'),
antialias: true,
alpha: true
});
this.clock = new THREE.Clock();
this.particles = null;
this.init();
}
init() {
// Настройка рендерера
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.renderer.setClearColor(0x000011, 1);
// Позиция камеры
this.camera.position.z = 5;
// Создание системы частиц для тумана
this.createFogParticles();
// Обработка ресайза
window.addEventListener('resize', () => this.onWindowResize());
// Скрываем загрузку
document.getElementById('loading').style.display = 'none';
// Запуск анимации
this.animate();
}
createFogParticles() {
const particleCount = 1000;
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
// Создаем случайные позиции и цвета для частиц
for (let i = 0; i < particleCount; i++) {
// Позиции в большом объеме
positions[i * 3] = (Math.random() - 0.5) * 50;
positions[i * 3 + 1] = (Math.random() - 0.5) * 20;
positions[i * 3 + 2] = (Math.random() - 0.5) * 50;
// Цвета от голубого до белого
colors[i * 3] = 0.7 + Math.random() * 0.3; // R
colors[i * 3 + 1] = 0.8 + Math.random() * 0.2; // G
colors[i * 3 + 2] = 0.9 + Math.random() * 0.1; // B
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
// Материал частиц
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.6,
blending: THREE.AdditiveBlending,
sizeAttenuation: true
});
this.particles = new THREE.Points(geometry, material);
this.scene.add(this.particles);
}
animate() {
requestAnimationFrame(() => this.animate());
const time = this.clock.getElapsedTime();
// Анимация частиц - плавное движение
if (this.particles) {
const positions = this.particles.geometry.attributes.position.array;
for (let i = 0; i < positions.length; i += 3) {
// Плавное движение в разных направлениях
positions[i] += Math.sin(time * 0.5 + i) * 0.01; // X
positions[i + 1] += Math.cos(time * 0.3 + i) * 0.008; // Y
positions[i + 2] += Math.sin(time * 0.4 + i) * 0.012; // Z
// Возврат частиц в область видимости
if (positions[i] > 25) positions[i] = -25;
if (positions[i] < -25) positions[i] = 25;
if (positions[i + 1] > 10) positions[i + 1] = -10;
if (positions[i + 1] < -10) positions[i + 1] = 10;
if (positions[i + 2] > 25) positions[i + 2] = -25;
if (positions[i + 2] < -25) positions[i + 2] = 25;
}
this.particles.geometry.attributes.position.needsUpdate = true;
// Легкое вращение всей системы
this.particles.rotation.y = time * 0.05;
this.particles.rotation.x = Math.sin(time * 0.1) * 0.1;
}
this.renderer.render(this.scene, this.camera);
}
onWindowResize() {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerWidth, window.innerHeight);
}
}
// Инициализация когда страница загружена
window.addEventListener('load', () => {
try {
new FogEffect();
} catch (error) {
console.error('Error initializing fog effect:', error);
document.getElementById('loading').textContent = 'Ошибка загрузки шейдера';
}
});
// Резервная инициализация
setTimeout(() => {
if (!window.fogEffect) {
try {
new FogEffect();
} catch (error) {
document.getElementById('loading').textContent = 'Не удалось загрузить WebGL';
}
}
}, 2000);