Навіщо туторіали?
Симуляції на цьому сайті цікаво спостерігати, але питання, які виникають найчастіше, завжди однакові: Як мені побудувати щось подібне? і З чого почати? Статті пояснюють теорію, що стоїть за кожною симуляцією, але туторіали дають готовий проєкт наприкінці. Ці три нові заповнюють прогалини, які постійно виникали.
Туторіал #9 — Побудуйте сонячну систему на Three.js
Ідея
Сонячна система — одна з класичних ідей «першого справжнього проєкту» в 3D — потрібні орбіти, ієрархічні трансформації (місяці обертаються навколо планет, які обертаються навколо Сонця), текстури та камера. Вона торкається майже кожної концепції Three.js одразу, що робить її ідеальним туторіалом середнього рівня.
Що ви побудуєте
За шість кроків туторіал проходить: створення початкової сцени,
камери, рендерера та OrbitControls; побудову сяючого Сонця за
допомогою MeshBasicMaterial і
PointLight; додавання текстурованих планет з
правильними орбітальними радіусами; налаштування еліптичних орбіт
Кеплера за допомогою Math.cos та
Math.sin з ексцентриситетом; додавання кільця Сатурна
за допомогою RingGeometry та прозорої текстури; і
нарешті цикл анімації з фіксованим кроком часу.
// Еліптична орбіта за рівняннями Кеплера
const a = planetData.distance; // велика піввісь
const e = planetData.eccentricity || 0; // ексцентриситет
const angle = elapsed * planetData.speed;
planet.mesh.position.set(
a * Math.cos(angle),
0,
a * (1 - e * e) / (1 + e * Math.cos(angle)) * Math.sin(angle)
);
Найскладнішою частиною було пояснити закони Кеплера, не перетворивши це на лекцію з фізики. Компроміс: показати математику прямо в тексті, зробити код коротким і посилатися на повну статтю Сонячна система та Кеплер для тих, хто хоче побачити виведення формул.
Туторіал #10 — Шейдери вогню та води на GLSL
Ідея
Цей навмисно складний. Більшості розробників симуляцій рано чи
пізно доводиться писати власний шейдер, і крива навчання жорстока —
немає console.log, немає дебаггера, немає стеків
викликів. Цей туторіал бере два поширені ефекти (вогонь і вода) і
показує, як побудувати їх суто на фрагментному коді GLSL.
Що ви побудуєте
Знову шість кроків: налаштування ShaderMaterial з
вершинним та фрагментним шейдерами; написання функції фрактального
шуму fbm() з нуля; анімація градієнта вогню за
допомогою уніформи часу; побудова прокручуваної водної поверхні з
шаруватим шумом та альфа-краєм у стилі Френеля; поєднання обох у
демо з розділеним екраном; і профілювання продуктивності за
допомогою renderer.info.
// Фрактальний броунівський рух — основа обох ефектів
float fbm(vec2 p) {
float sum = 0.0;
float amp = 0.5;
for (int i = 0; i < 5; i++) {
sum += amp * noise(p);
p *= 2.0;
amp *= 0.5;
}
return sum;
}
Ключовий навчальний момент полягає в тому, що вогонь і вода використовують ту саму функцію шуму — вони лише відрізняються кольоровим відображенням, напрямком прокрутки та змішуванням. Коли ви це усвідомите, процедурні шейдери стають зрозумілими.
Туторіал #11 — Збереження налаштувань за допомогою localStorage
Ідея
Кожна симуляція на цьому сайті має повзунки, перемикачі та
пресети — і щоразу при перезавантаженні вони скидаються. Цей
туторіал для початківців показує, як це виправити за допомогою
трьох браузерних API дедалі більшої складності:
localStorage, JSON та
IndexedDB.
Що ви побудуєте
Перші три кроки охоплюють типовий шлях:
localStorage.setItem/getItem, серіалізацію повного
об'єкта параметрів за допомогою JSON.stringify та
автоматичне відновлення при DOMContentLoaded з
безпечним злиттям Object.assign, щоб нові параметри,
додані в оновленнях коду, не зникали.
Кроки 4–6 охоплюють крайні випадки, що трапляються у продакшені:
ключ версії _v з функцією міграції на випадок зміни
схеми, обробка QuotaExceededError з визначенням
можливості через storageAvailable(), та мінімальна
обгортка IndexedDB на випадок, коли ви переростаєте 5 МБ.
// Безпечне відновлення зі злиттям схеми
function loadParams(defaults) {
try {
const raw = localStorage.getItem('sim-params');
if (!raw) return { ...defaults };
const saved = JSON.parse(raw);
if (saved._v !== defaults._v) {
saved = migrate(saved, defaults._v);
}
return Object.assign({}, defaults, saved);
} catch {
return { ...defaults };
}
}
Це найкоротший з трьох, приблизно 35 хвилин — навмисно. Збереження стану — це інструмент, а не проєкт. Зайдіть, вивчіть шаблон, поверніться до побудови своєї симуляції.
Пов'язані симуляції: перехресні посилання по бібліотеці
Пишучи ці туторіали, я також додав блоки «Пов'язані симуляції» до 16 статей на сайті. Кожен блок розташований над навігацією статті і показує сітку з 4 карток пов'язаних симуляцій. Ідея проста: якщо ви читаєте про боїдів, ви маєте бути на відстані одного кліка від симуляції зграї, моделі хижак-жертва та мурашиної колонії.
Блоки використовують вбудовані стилі з CSS-змінними, тому вони
автоматично успадковують темну/світлу тему сайту. Ніякого
додаткового стилю, жодної збірки, жодного JavaScript — лише HTML і
var(--color-*).
Чого я навчився
Писати туторіали принципово інакше, ніж писати статті. Статті пояснюють як щось працює; туторіали пояснюють як зробити, щоб це запрацювало. Це означає, що кожен блок коду має справді виконуватися. Кожен крок має давати видимий результат. І порядок концепцій має значення набагато більше, ніж у довідковій статті, де можна перестрибувати місцями.
Найбільший урок: почніть з результату. Покажіть готове демо на початку, а потім розберіть його крок за кроком у зворотному порядку. Коли читач уже бачить, до чого йде справа, кожен проміжний крок відчувається вмотивованим, а не довільним.
Усі три туторіали вже доступні. Почніть з того, що відповідає вашому рівню:
Сонце, планети, кільця та місяці — повна орерія з текстурованими мешами, еліптичними орбітами та ієрархічними трансформаціями.
Напишіть градієнт вогню та прокручувану водну поверхню з необробленого коду фрагментного шейдера. Жодних бібліотек — лише чистий GLSL.
Зберігайте значення повзунків, пресети та стан інтерфейсу між перезавантаженнями за допомогою localStorage, JSON, версіонування та резервного варіанту IndexedDB.