Trzy nowe samouczki: Układ Słoneczny, shadery GLSL i localStorage

Sekcja samouczków właśnie urosła z 8 do 11. Układ Słoneczny w Three.js dla średniozaawansowanych, surowe shadery ognia i wody w GLSL dla odważnych oraz przyjazny dla początkujących przewodnik po zapisywaniu ustawień symulacji za pomocą localStorage. Oto historia stojąca za każdym z nich.

Po co samouczki?

Symulacje na tej stronie są przyjemne do oglądania, ale pytania, które pojawiają się najczęściej, są zawsze takie same: Jak zbudować coś takiego? i Od czego zacząć? Artykuły wyjaśniają teorię stojącą za każdą symulacją, ale samouczki dają na końcu działający projekt. Te trzy nowe wypełniają luki, które wciąż się pojawiały.

Samouczek #9 — Zbuduj Układ Słoneczny w Three.js

Pomysł

Układ Słoneczny to jeden z klasycznych pomysłów na „pierwszy prawdziwy projekt" w 3D — potrzebujesz orbit, hierarchicznych transformacji (księżyce krążą wokół planet, które krążą wokół Słońca), tekstur i rigu kamery. Dotyka niemal każdej koncepcji Three.js naraz, co czyni go idealnym samouczkiem dla średniozaawansowanych.

Co budujesz

Przez sześć kroków samouczek prowadzi przez: tworzenie początkowej sceny, kamery, renderera i OrbitControls; budowanie świecącego Słońca za pomocą MeshBasicMaterial i PointLight; dodawanie teksturowanych planet z właściwymi promieniami orbit; podłączanie orbit eliptycznych Keplera za pomocą Math.cos i Math.sin z mimośrodem; dodawanie pierścienia Saturna za pomocą RingGeometry i przezroczystej tekstury; a na końcu pętlę animacji ze stałym krokiem czasowym.

// Orbita eliptyczna z użyciem równań Keplera
const a = planetData.distance;           // półoś wielka
const e = planetData.eccentricity || 0;  // mimośród
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)
);

Najtrudniejsze było wyjaśnienie praw Keplera bez zamieniania tego w wykład z fizyki. Kompromis: pokaż matematykę wprost w tekście, zachowaj kod krótkim i podlinkuj pełny artykuł Układ Słoneczny i Kepler dla każdego, kto chce zobaczyć wyprowadzenie.

Samouczek #10 — Shadery ognia i wody w GLSL

Pomysł

Ten jest celowo trudny. Większość twórców symulacji prędzej czy później musi napisać własny shader, a krzywa uczenia się jest brutalna — nie ma console.log, nie ma debuggera, nie ma stack trace'ów. Ten samouczek bierze dwa popularne efekty (ogień i wodę) i pokazuje, jak zbudować je wyłącznie kodem fragmentów GLSL.

Co budujesz

Znów sześć kroków: konfiguracja ShaderMaterial z shaderami wierzchołków i fragmentów; napisanie funkcji szumu fraktalnego fbm() od zera; animowanie gradientu ognia za pomocą uniformu czasu; budowa przewijającej się powierzchni wody z warstwowym szumem i obrzeżem alfa w stylu Fresnela; połączenie obu w demo podzielonego ekranu; oraz profilowanie wydajności za pomocą renderer.info.

// Fraktalny szum Browna — rdzeń obu efektów
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;
}

Kluczowy moment nauki: ogień i woda używają tej samej funkcji szumu — różnią się tylko mapowaniem kolorów, kierunkiem przewijania i mieszaniem. Gdy to zrozumiesz, proceduralne shadery zaczynają mieć sens.

Samouczek #11 — Zapisywanie ustawień z localStorage

Pomysł

Każda symulacja na tej stronie ma suwaki, przełączniki i presety — i za każdym razem, gdy przeładujesz stronę, resetują się. Ten samouczek dla początkujących pokazuje, jak to naprawić za pomocą trzech API przeglądarki o rosnącym poziomie zaawansowania: localStorage, JSON i IndexedDB.

Co budujesz

Pierwsze trzy kroki obejmują typową ścieżkę: localStorage.setItem/getItem, serializację pełnego obiektu parametrów za pomocą JSON.stringify i automatyczne przywracanie przy DOMContentLoaded z bezpiecznym scalaniem Object.assign, tak aby nowe parametry dodane w aktualizacjach kodu nie znikały.

Kroki 4–6 obejmują skrajne przypadki, które gryzą w produkcji: klucz wersji _v z funkcją migracji na wypadek zmiany schematu, obsługę QuotaExceededError z detekcją funkcji storageAvailable() oraz minimalny wrapper IndexedDB na wypadek przekroczenia limitu 5 MB.

// Bezpieczne przywracanie ze scalaniem schematu
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 };
  }
}

To najkrótszy z trzech samouczków — ~35 minut — celowo. Trwałość danych to narzędzie, nie projekt. Wejdź, poznaj wzorzec, wróć do budowania symulacji.

Powiązane symulacje: krzyżowe linkowanie biblioteki

Pisząc te samouczki, dodałem też bloki „Powiązane symulacje" do 16 artykułów na stronie. Każdy blok znajduje się nad nawigacją artykułu i pokazuje siatkę 4 połączonych kart symulacji. Pomysł jest prosty: jeśli czytasz o boidach, powinieneś być o jedno kliknięcie od symulacji stada, modelu drapieżnik-ofiara i kolonii mrówek.

Bloki wykorzystują style inline z niestandardowymi właściwościami CSS, dzięki czemu dziedziczą tryb ciemny/jasny strony automatycznie. Bez dodatkowego arkusza stylów, bez etapu budowania, bez JavaScriptu — tylko HTML i var(--color-*).

Czego się nauczyłem

Pisanie samouczków fundamentalnie różni się od pisania artykułów. Artykuły wyjaśniają jak coś działa; samouczki wyjaśniają jak to sprawić, żeby działało. To znaczy, że każdy blok kodu musi rzeczywiście działać. Każdy krok musi dawać widoczny efekt. A kolejność koncepcji ma znacznie większe znaczenie niż w artykule referencyjnym, po którym można skakać dowolnie.

Największa lekcja: zacznij od wyniku. Pokaż gotowe demo na górze, a potem rozłóż je krok po kroku wstecz. Gdy czytelnik już widzi, do czego dąży, każdy pośredni krok wydaje się uzasadniony, a nie arbitralny.

Wszystkie trzy samouczki są już dostępne. Zacznij od tego, który pasuje do Twojego poziomu: