Создание 3D-сайтов на WebGL: от основ до публикации проекта

Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • Студенты и начинающие веб-разработчики
  • Профессиональные разработчики, интересующиеся 3D-графикой
  • Дизайнеры и специалисты по UX/UI, желающие интегрировать 3D-элементы в свои проекты

    3D-графика на веб-страницах перестала быть прерогативой исключительно крупных студий с большими бюджетами. WebGL открыл двери для создания трехмерных интерактивных сцен прямо в браузере — без плагинов и сложных настроек. Будь то визуализация архитектурного проекта, интерактивный каталог товаров или захватывающая игра — все это теперь доступно на обычном сайте. Но как начать работу с этой технологией, если вы только осваиваете трехмерное пространство в вебе? Давайте разберемся вместе. 🚀

Хотите быстро освоить создание впечатляющих 3D-сайтов? В курсе Обучение веб-разработке от Skypro вы не только изучите основы HTML, CSS и JavaScript, но и погрузитесь в мир трехмерной графики с WebGL. Наставники-практики покажут, как превратить обычный сайт в интерактивное 3D-пространство, которое запомнят ваши пользователи. От базовых принципов до продвинутых техник — ваш путь к созданию сайтов будущего начинается здесь!

Основы WebGL и подготовка среды разработки 3D-сайта

WebGL (Web Graphics Library) — это JavaScript API для рендеринга интерактивной трехмерной графики без использования плагинов. Он работает в любом современном браузере и использует графический процессор (GPU) для ускорения обработки и отображения графики. WebGL — это веб-стандарт, который дает разработчикам доступ к низкоуровневым графическим примитивам, похожим на OpenGL ES 2.0.

Прежде чем погрузиться в код, давайте подготовим рабочую среду:

  • Редактор кода: Visual Studio Code, Sublime Text или любой другой по вашему предпочтению
  • Веб-браузер: Chrome или Firefox с инструментами разработчика
  • Локальный сервер: Live Server для VS Code или аналогичный плагин

Чистый WebGL требует написания шейдеров на языке GLSL и работы с матрицами трансформаций — это сложно для начинающих. Поэтому мы будем использовать библиотеку Three.js, которая значительно упрощает работу с 3D-графикой.

Библиотека Преимущества Сложность Лучше для
Чистый WebGL Полный контроль, высокая производительность Высокая Продвинутых разработчиков
Three.js Баланс между контролем и простотой, отличная документация Средняя Большинства проектов
Babylon.js Встроенная физика, интеграция с GUI Средняя Игр и сложных интерактивных приложений
A-Frame Декларативный HTML-синтаксис, VR-готовность Низкая Быстрых прототипов и VR

Для установки Three.js вы можете использовать npm:

npm install three

Или подключить CDN в HTML-файле:

HTML
Скопировать код
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script>

Артем Валевский, технический директор проекта

Помню, как в 2019 году к нам обратился клиент с амбициозным запросом — создать конфигуратор мебели с возможностью рассмотреть каждый предмет со всех сторон в режиме реального времени. У нас был опыт с 3D-моделированием, но не в веб-среде. Первые попытки использовать чистый WebGL оказались мучительными — мы тратили часы на отладку шейдеров и матричные преобразования.

Переломный момент наступил, когда мы перешли на Three.js. За два дня мы смогли создать работающий прототип с базовыми возможностями вращения и масштабирования моделей. Клиент был в восторге от скорости разработки! А мы поняли важный урок: не нужно изобретать велосипед, когда есть качественные библиотеки, которые решают базовые задачи.

Пошаговый план для смены профессии

Настройка проекта и интеграция WebGL в веб-страницу

Создадим базовую структуру проекта. Начнем с HTML-страницы, которая будет содержать наш 3D-контент:

HTML
Скопировать код
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My First WebGL Site</title>
<style>
body { margin: 0; overflow: hidden; }
canvas { display: block; }
</style>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script>
<script src="main.js"></script>
</body>
</html>

Теперь создадим файл main.js, где напишем базовый код для инициализации WebGL-сцены с помощью Three.js:

JS
Скопировать код
// Основные компоненты сцены
let scene, camera, renderer;

// Функция инициализации
function init() {
// Создание сцены
scene = new THREE.Scene();
scene.background = new THREE.Color(0xf0f0f0);

// Создание камеры
camera = new THREE.PerspectiveCamera(
75, // угол обзора
window.innerWidth / window.innerHeight, // соотношение сторон
0.1, // ближняя плоскость отсечения
1000 // дальняя плоскость отсечения
);
camera.position.z = 5;

// Создание рендерера
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// Обработчик изменения размера окна
window.addEventListener('resize', onWindowResize);

// Запуск анимации
animate();
}

// Функция обновления камеры и рендерера при изменении размера окна
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}

// Функция анимации
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}

// Запуск приложения
init();

После запуска этого кода вы увидите пустую серую сцену. Теперь давайте разберемся с основными компонентами, которые мы использовали:

  • Scene (Сцена): контейнер для всех объектов, камер и источников света.
  • Camera (Камера): определяет, что именно мы видим. Мы используем PerspectiveCamera, которая имитирует зрение человека.
  • Renderer (Рендерер): отвечает за отрисовку сцены с помощью WebGL.

Обратите внимание на функцию animate() — она создает цикл рендеринга с помощью requestAnimationFrame, который будет вызываться примерно 60 раз в секунду, обеспечивая плавную анимацию. 🔄

Создание базовых 3D-объектов и сцен на вашем сайте

Теперь, когда у нас есть базовая настройка, добавим на сцену некоторые 3D-объекты. Three.js предоставляет множество готовых геометрий для создания базовых фигур.

Давайте добавим в нашу функцию init() код для создания куба:

JS
Скопировать код
// В функции init() после создания рендерера

// Создание куба
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x44aa88 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

// Добавляем анимацию вращения в функцию animate
function animate() {
requestAnimationFrame(animate);

// Вращение куба
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;

renderer.render(scene, camera);
}

Теперь у нас есть вращающийся куб! 🎲 Но давайте сделаем нашу сцену более интересной, добавив различные 3D-объекты с разными материалами:

JS
Скопировать код
// Создаем функцию для добавления объектов на сцену
function createObjects() {
// Куб
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
const cubeMaterial = new THREE.MeshPhongMaterial({ color: 0x44aa88 });
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.x = -2;
scene.add(cube);

// Сфера
const sphereGeometry = new THREE.SphereGeometry(0.8, 32, 32);
const sphereMaterial = new THREE.MeshPhongMaterial({ color: 0xaa8844 });
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.x = 0;
scene.add(sphere);

// Тор
const torusGeometry = new THREE.TorusGeometry(0.6, 0.2, 16, 100);
const torusMaterial = new THREE.MeshPhongMaterial({ color: 0x8844aa });
const torus = new THREE.Mesh(torusGeometry, torusMaterial);
torus.position.x = 2;
scene.add(torus);

// Добавляем свет
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);

const pointLight = new THREE.PointLight(0xffffff, 1);
pointLight.position.set(5, 5, 5);
scene.add(pointLight);

// Возвращаем объекты для анимации
return { cube, sphere, torus };
}

// В функции init() вызываем создание объектов
const objects = createObjects();

// Обновляем функцию animate для вращения всех объектов
function animate() {
requestAnimationFrame(animate);

// Вращение объектов
objects.cube.rotation.x += 0.01;
objects.cube.rotation.y += 0.01;

objects.sphere.rotation.x += 0.01;
objects.sphere.rotation.z += 0.01;

objects.torus.rotation.x += 0.01;
objects.torus.rotation.y += 0.01;

renderer.render(scene, camera);
}

Обратите внимание, что мы заменили MeshBasicMaterial на MeshPhongMaterial. Последний реагирует на свет, что делает наши объекты более реалистичными, но для его работы мы должны добавить источники света в сцену.

Вот список распространенных типов геометрий в Three.js:

Геометрия Описание Типичное использование
BoxGeometry Куб или прямоугольный параллелепипед Строительные блоки, контейнеры
SphereGeometry Сфера с настраиваемым разрешением Планеты, мячи, частицы
CylinderGeometry Цилиндр с настраиваемыми верхним/нижним радиусами Колонны, стволы деревьев
ConeGeometry Конус с настраиваемой высотой и радиусом Маркеры, конусы
TorusGeometry Кольцо (бублик) Колесо, кольцо, декоративные элементы
PlaneGeometry Плоская прямоугольная поверхность Пол, стены, экраны

Для сложных 3D-моделей лучше использовать импорт из внешних форматов, таких как glTF или OBJ. Three.js имеет загрузчики для различных форматов, которые позволяют импортировать модели, созданные в Blender, Maya или других 3D-редакторах.

Мария Соколова, 3D-дизайнер

Когда я начала сотрудничать с веб-разработчиками, существовал серьезный разрыв между созданием 3D-моделей в специализированных программах и их интеграцией в веб. Модели приходилось сильно упрощать, а текстуры сжимать до неузнаваемости.

Однажды мы работали над сайтом для музея современного искусства, где нужно было показать скульптуры в интерактивном формате. Я создала детализированные модели в Blender, но когда дело дошло до импорта в веб, возникли проблемы с производительностью.

Решением стало использование glTF формата и правильной оптимизации моделей. Мы разработали процесс, при котором сохраняли высокое качество визуализации, но при этом модели загружались быстро даже на мобильных устройствах. Секрет был в создании нескольких LOD-версий (Level of Detail) каждой модели и правильном запекании текстур и карт нормалей. После внедрения этой технологии виртуальная выставка работала безупречно, а посетители сайта проводили в среднем на 4 минуты больше времени, изучая экспонаты.

Работа с текстурами и освещением в 3D-графике на WebGL

Чтобы наши 3D-объекты выглядели реалистично, необходимо добавить текстуры и настроить освещение. Текстуры — это изображения, которые "оборачиваются" вокруг 3D-объекта, придавая ему детализированный вид.

Давайте модифицируем наш код, чтобы добавить текстуру к сфере:

JS
Скопировать код
// Загрузчик текстур
const textureLoader = new THREE.TextureLoader();

// Создаем функцию для добавления объектов на сцену
function createObjects() {
// ... Предыдущий код ...

// Сфера с текстурой
const sphereGeometry = new THREE.SphereGeometry(0.8, 32, 32);

// Загружаем текстуры
const earthTexture = textureLoader.load('textures/earth_map.jpg');
const earthBumpMap = textureLoader.load('textures/earth_bump.jpg');
const earthSpecMap = textureLoader.load('textures/earth_spec.jpg');

const sphereMaterial = new THREE.MeshPhongMaterial({ 
map: earthTexture,
bumpMap: earthBumpMap,
bumpScale: 0.05,
specularMap: earthSpecMap,
specular: new THREE.Color('grey'),
shininess: 15
});

const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.x = 0;
scene.add(sphere);

// ... Остальной код ...
}

Здесь мы использовали несколько типов карт текстур:

  • map: Основная цветовая текстура
  • bumpMap: Карта неровностей, создающая иллюзию рельефа
  • specularMap: Определяет, какие части поверхности более блестящие

Теперь давайте усовершенствуем освещение нашей сцены. Хорошее освещение критически важно для создания реалистичной 3D-среды:

JS
Скопировать код
// Функция для настройки освещения
function setupLighting() {
// Удаляем предыдущие источники света, если они есть
scene.children.forEach(child => {
if (child.isLight) scene.remove(child);
});

// Базовое окружающее освещение
const ambientLight = new THREE.AmbientLight(0xffffff, 0.3);
scene.add(ambientLight);

// Основной направленный свет (имитация солнца)
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(5, 3, 5);
directionalLight.castShadow = true; // Включаем отбрасывание теней

// Настройка области теней
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 20;
directionalLight.shadow.camera.left = -5;
directionalLight.shadow.camera.right = 5;
directionalLight.shadow.camera.top = 5;
directionalLight.shadow.camera.bottom = -5;

// Разрешение карты теней
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;

scene.add(directionalLight);

// Дополнительный мягкий свет с противоположной стороны
const fillLight = new THREE.DirectionalLight(0x9999ff, 0.3);
fillLight.position.set(-5, 3, -5);
scene.add(fillLight);
}

Для работы с тенями нужно также включить их в рендерере и настроить объекты для отбрасывания и приема теней:

JS
Скопировать код
// В функции init()
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // Мягкие тени

// Для объектов, которые должны отбрасывать тени
cube.castShadow = true;
sphere.castShadow = true;
torus.castShadow = true;

// Создаем пол для приема теней
const floorGeometry = new THREE.PlaneGeometry(20, 20);
const floorMaterial = new THREE.MeshPhongMaterial({ 
color: 0xeeeeee,
side: THREE.DoubleSide
});
const floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.rotation.x = Math.PI / 2;
floor.position.y = -2;
floor.receiveShadow = true;
scene.add(floor);

Различные типы материалов в Three.js по-разному взаимодействуют со светом:

  • MeshBasicMaterial: Не реагирует на свет, всегда показывает свой базовый цвет
  • MeshLambertMaterial: Матовая поверхность, реагирует на свет без бликов
  • MeshPhongMaterial: Поверхность с бликами, имитирует пластик или металл
  • MeshStandardMaterial: Физически корректное освещение с параметрами шероховатости и металличности
  • MeshPhysicalMaterial: Расширенная версия StandardMaterial с дополнительными параметрами (прозрачность, преломление и т.д.)

Правильное сочетание текстур и освещения — это ключ к созданию реалистичных и привлекательных 3D-сцен. Экспериментируйте с различными типами материалов и источников света, чтобы добиться желаемого эффекта. ✨

Оптимизация и публикация 3D-сайта на базе WebGL

После создания впечатляющей 3D-сцены необходимо убедиться, что она будет работать быстро и плавно даже на устройствах с ограниченными ресурсами. Оптимизация — критически важный шаг в разработке WebGL-приложений.

Вот ключевые аспекты оптимизации производительности WebGL:

  • Оптимизация моделей: Уменьшение количества полигонов, использование LOD (Level of Detail)
  • Оптимизация текстур: Сжатие изображений, использование mipmaps, текстурных атласов
  • Управление памятью: Освобождение неиспользуемых ресурсов, обработка событий потери контекста
  • Эффективное рендеринг: Использование техник, таких как frustum culling, occlusion culling

Давайте реализуем некоторые из этих оптимизаций в нашем коде:

JS
Скопировать код
// Функция для управления ресурсами
function setupResourceManagement() {
// Миникарты для текстур – уменьшают артефакты при уменьшении объектов
textureLoader.setPath('textures/');
const textures = {
earth: textureLoader.load('earth_map.jpg', function(texture) {
texture.minFilter = THREE.LinearMipMapLinearFilter;
texture.generateMipmaps = true;
texture.anisotropy = renderer.capabilities.getMaxAnisotropy();
}),
};

// Функция для очистки ресурсов
function disposeResources() {
for (const key in textures) {
textures[key].dispose();
}

// Очистка геометрий и материалов
scene.traverse(object => {
if (object.isMesh) {
object.geometry.dispose();

if (object.material.isMaterial) {
disposeMaterial(object.material);
} else {
// Массив материалов
for (const material of object.material) {
disposeMaterial(material);
}
}
}
});
}

// Вспомогательная функция для очистки материалов
function disposeMaterial(material) {
for (const key in material) {
const value = material[key];
if (value && typeof value.dispose === 'function') {
value.dispose();
}
}
}

// Обработка потери контекста WebGL
const canvas = renderer.domElement;
canvas.addEventListener('webglcontextlost', function(event) {
event.preventDefault();
console.warn('WebGL context lost. Reinitializing...');
// Остановка анимации и очистка ресурсов
cancelAnimationFrame(animationId);
});

canvas.addEventListener('webglcontextrestored', function() {
console.info('WebGL context restored.');
// Переинициализация сцены
init();
});

// При закрытии страницы очищаем ресурсы
window.addEventListener('beforeunload', disposeResources);

return { textures, disposeResources };
}

Для лучшей производительности на различных устройствах можно реализовать адаптивное качество рендеринга:

JS
Скопировать код
// Функция для адаптации качества рендеринга
function setupAdaptiveQuality() {
let quality = 'high'; // По умолчанию высокое качество
const devicePixelRatio = window.devicePixelRatio || 1;

// Оценка возможностей устройства
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
const performanceNow = performance.now();

// Тест производительности
const testObject = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1, 50, 50, 50),
new THREE.MeshBasicMaterial()
);
scene.add(testObject);

// Рендерим тестовый кадр
renderer.render(scene, camera);
scene.remove(testObject);
testObject.geometry.dispose();
testObject.material.dispose();

const renderTime = performance.now() – performanceNow;

// Определяем качество на основе теста и типа устройства
if (renderTime > 20 || isMobile) {
quality = 'low';
} else if (renderTime > 10) {
quality = 'medium';
}

// Настраиваем параметры рендерера в соответствии с качеством
switch(quality) {
case 'low':
renderer.setPixelRatio(Math.min(devicePixelRatio, 1));
renderer.setSize(window.innerWidth * 0.8, window.innerHeight * 0.8);
renderer.shadowMap.enabled = false;
break;
case 'medium':
renderer.setPixelRatio(Math.min(devicePixelRatio, 1.5));
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap;
break;
case 'high':
renderer.setPixelRatio(devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
break;
}

return quality;
}

При публикации 3D-сайта важно учесть следующие аспекты:

Аспект Рекомендации
Загрузка ресурсов Используйте прогрессивную загрузку, показывайте экран загрузки, предварительно загружайте критические ресурсы
Сжатие файлов Минифицируйте JavaScript, используйте сжатие gzip/Brotli, оптимизируйте текстуры
CDN Используйте CDN для распределения нагрузки и ускорения доставки ресурсов
Мобильная совместимость Тестируйте на различных устройствах, предусматривайте альтернативы для устаревших браузеров
SEO Используйте серверный рендеринг или предварительный рендеринг для индексации контента

Для обеспечения загрузки и публикации сайта с оптимальной производительностью, необходимо правильно структурировать код и ресурсы:

JS
Скопировать код
// Создаем систему загрузки ресурсов
const loadingManager = new THREE.LoadingManager();

// Элементы UI для загрузки
const loadingElement = document.getElementById('loading-screen');
const progressBar = document.getElementById('progress-bar');

loadingManager.onProgress = function(url, itemsLoaded, itemsTotal) {
const progress = (itemsLoaded / itemsTotal * 100).toFixed(0);
progressBar.style.width = progress + '%';
progressBar.textContent = progress + '%';
};

loadingManager.onLoad = function() {
// Скрываем экран загрузки с анимацией fade-out
loadingElement.classList.add('fade-out');

// После завершения анимации полностью скрываем элемент
setTimeout(() => {
loadingElement.style.display = 'none';
}, 500);

// Запускаем основную анимацию
animate();
};

// Обновляем наш загрузчик текстур
const textureLoader = new THREE.TextureLoader(loadingManager);

🚀 После оптимизации и подготовки всех ресурсов, ваш WebGL-сайт готов к публикации! Разместите все файлы на веб-сервере, убедитесь, что сервер настроен для правильной отдачи MIME-типов для всех ресурсов, и наслаждайтесь вашим трехмерным веб-пространством.

Создание 3D-сайтов с WebGL открывает невероятные возможности для визуализации и интерактивности в вебе. Начав с простых фигур и постепенно добавляя сложность, вы можете создавать впечатляющие трехмерные интерфейсы, продуктовые визуализации или интерактивные истории. Ключ к успеху — баланс между визуальной привлекательностью и производительностью. Помните, что даже самый красивый 3D-сайт не будет эффективен, если пользователи покинут его из-за долгой загрузки или низкого FPS. Экспериментируйте, оптимизируйте, и превращайте ваши идеи в осязаемые трехмерные миры прямо в браузере!

Загрузка...