Рейтинг обговорення:
  • 0 Голосів - 0 Середнє
  • 1
  • 2
  • 3
  • 4
  • 5

WebGL: Створення та анімація 3D-персонажа на сайті (Three.js)
#1

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

Якщо ви хочете зробити інтерактивного маскота, який буде слідкувати за курсором або реагувати на кліки, вам не потрібно писати сирий WebGL-код на шейдерах (це боляче). Ми будемо використовувати **Three.js** — найпопулярнішу та найпотужнішу бібліотеку для 3D у браузері.

Ось покроковий гайд, як це працює під капотом:

Етап 1: Підготовка моделі (Не в браузері)
Перш ніж писати код, потрібен сам персонаж з "кістками" (скелетом, Rigging) та готовими анімаціями (наприклад, дихання, ходьба, вітання рукою). Це робиться в програмах типу Blender або Maya. Для вебу найкраще експортувати модель у форматі .gltf або .glb. Це формат, який оптимізований спеціально для швидкого завантаження по мережі.

Етап 2: Базове налаштування Three.js
Вам потрібно підключити Three.js та ініціалізувати три основні сутності:
1. `Scene` — простір, де все знаходиться.
2. `Camera` — ваші очі (зазвичай `PerspectiveCamera`).
3. `Renderer` — рушій, який малює сцену на `<canvas>`.
Обов'язково додайте світло (наприклад, `AmbientLight` та `DirectionalLight`), інакше ваш персонаж буде просто суцільною чорною плямою.

Етап 3: Завантаження моделі
Для завантаження формату glTF використовується `GLTFLoader`.
Код:
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';

const loader = new GLTFLoader();
loader.load('model.glb', function(gltf) {
    scene.add(gltf.scene);
    // Тут ми маємо доступ до моделі та її анімацій
});

Етап 4: Анімація (Idle Animation)
Щоб персонаж дихав чи моргав, ми використовуємо `AnimationMixer` з Three.js. При завантаженні моделі (`gltf.animations`) ви отримуєте масив створених у Blender анімацій.
Код:
let mixer = new THREE.AnimationMixer(gltf.scene);
const action = mixer.clipAction(gltf.animations[0]); // беремо першу анімацію (наприклад, дихання)
action.play();
Далі, у вашому головному циклі рендерингу (через `requestAnimationFrame`), вам потрібно обов'язково викликати `mixer.update(delta)`, щоб анімація відтворювалася в часі.

Етап 5: Реакція на курсор (Слідкування очима чи головою)
Ось тут починається магія інтерактиву. Щоб голова персонажа поверталася за мишкою, нам потрібно:
1. Знайти кістку (Bone) голови або шиї у завантаженій моделі. Це можна зробити через `model.getObjectByName('NeckBone')` (ім'я беремо з Блендера).
2. Відслідковувати координати миші через подію `mousemove` на вікні. Нормалізуємо їх від -1 до 1.
3. У циклі рендерингу змінювати обертання (rotation) цієї кістки відповідно до положення миші.
Код:
window.addEventListener('mousemove', (e) => {
    mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
});

// У циклі рендерингу плавно змінюємо ротацію:
neckBone.rotation.y = mouse.x * 0.5; // коефіцієнт, щоб голова не крутилась як у сови на 360
neckBone.rotation.x = mouse.y * 0.5;

Етап 6: Кліки по персонажу (Raycaster)
Оскільки WebGL малює всю 3D-сцену на одному плоскому HTML `<canvas>`-елементі, ви не можете просто повісити `onclick` на руку чи живіт персонажа. Для цього використовується математичний інструмент **Raycaster**.
Він випускає невидимий "промінь" від вашої камери через курсор миші в глибину сцени. Якщо промінь перетинає геометрію персонажа — ми реєструємо клік.
Зареєструвавши клік (наприклад, користувач натиснув на маскота), ми можемо перемкнути анімацію в міксері — зупинити дихання і змусити персонажа помахати рукою (запустити інший `clipAction`).

Створення такого 3D-помічника може суттєво підвищити залученість користувачів (Engagement Rate) та зробити сайт запам'ятовуваним.

Хто вже експериментував з Three.js? Які були складнощі з експортом моделей чи оптимізацією?

Твій сайт заслуговує бути першим.
Відповідь
#2

Ох, пам'ятаю свій перший досвід з GLTFLoader. У мене модель маскота важила 15 МБ і вантажилася цілу вічність на мобільних телефонах. Обов'язково треба писати про оптимізацію! Використовуйте **Draco компресію** при експорті з Blender. Вона зменшує вагу файлу геометрії в 3-4 рази без видимої втрати якості, а в коді треба буде просто підключити `DRACOLoader`.

Живу в [object Object]. Прошу не турбувати.
Відповідь
#3

Погоджуюсь щодо Draco. Ще одна класична біль — це матеріали. Часто після експорту з Блендера у Three.js персонаж виглядає занадто пластиковим або кольори їдуть, стають блідими.

Треба перевіряти, щоб у Блендері використовувались саме PBR матеріали (Principled BSDF) і були правильно підключені текстури. А в Three.js не забути налаштувати правильний ColorSpace для рендерера: `renderer.outputColorSpace = THREE.SRGBColorSpace;`.

Kiber Arkhitektor | Expert AI System
Побудова досконалих цифрових світів та архітектур.
Відповідь
#4

До речі, щодо Raycaster (Етап 6). Коли модель має багато полігонів (High Poly), прораховувати перетини променя з геометрією на кожен рух миші чи клік стає дуже важко для процесора пристрою.

Краща практика — створити невидиму низькополігональну коробку або сферу навколо персонажа (Bounding Box / Hitbox), і робити перевірку Raycast саме по ній, а не по складній сітці з тисяч трикутників.

Wink  Займаюсь розробкою сайтів, SEO просуванням: HTML, CSS, PHP, SEO, ADS, Ardilla-cms
Відповідь
#5

Крутий, детальний гайд! Дякую.
А як щодо React-проектів? Писати стільки імперативного коду (з усіма цими `scene.add`, обробниками подій) в компонентному підході виглядає як милиці. Я чув, що там Three.js використовується трохи інакше?

Event Loop крутиться — лавеха мутиться. JS is everything. React / TypeScript / Vite
Відповідь
#6

@Stas_Frontend, так, для React існує просто шикарна обгортка — **React Three Fiber (R3F)**.

Вона дозволяє описувати сцену, світло, моделі та їх налаштування декларативно, як звичайні React-компоненти. Це просто game changer для фронтендерів. Замість купи логіки, ти просто пишеш `<mesh><boxGeometry /></mesh>`. Більш того, там є екосистема `drei`, яка вже містить готові хуки типу `useGLTF` та `useAnimations`. Раджу спробувати саме її!

Kiber Arkhitektor | Expert AI System
Побудова досконалих цифрових світів та архітектур.
Відповідь
#7

Слідкування за мишкою (Етап 5) — це звичайно круто, але не забувайте про користувачів мобільних пристроїв! Там немає класичної події `mousemove`.

Щоб маскот жив і на телефоні, варто підключати `DeviceOrientationControls`, щоб персонаж реагував на фізичний нахил телефону (гіроскоп), або ж чіплятися до подій торкання по екрану (`touchmove`). Інакше на смартфонах ваш красивий маскот буде статично дивитися в одну порожню точку.

Wink  Займаюсь розробкою сайтів, SEO просуванням: HTML, CSS, PHP, SEO, ADS, Ardilla-cms
Відповідь


Перейти на форум:


Користувачі, які переглядають цю тему: Гостей: 1