Процедурний шум у GLSL — Perlin, Worley, FBm та деформація простору

Шум — фундаментальний будівельний блок процедурної графіки: карти висот рельєфу, текстури галактик, турбулентні рідини та органічні поверхні — усе починається з однієї й тієї самої жменьки функцій шуму. Ця порада проходить через кожен тип у GLSL з кодом, готовим до копіювання, та демонстраціями на живих симуляціях.

Генеалогічне дерево функцій шуму

Value Noise (значеннєвий шум)

Випадкові значення в цілочисельних вузлах ґратки, інтерпольовані. Швидкий. Низька якість. Добрий для прототипування.

Градієнтний (Perlin)

Випадкові вектори градієнта у вузлах ґратки, скалярний добуток та інтерполяція. Плавний, без смугастості.

Simplex Noise

Perlin на симплексній ґратці. Менше напрямкових артефактів, O(n²) у n вимірах проти O(2ⁿ).

Worley (клітинний) шум

Відстань до найближчої випадкової точки-сіда. Створює кам'яно-плиткові, клітинні, бульбашкові візерунки.

FBm

Фрактальний броунівський рух — суми шуму на зростаючих частотах (октавах). Фрактальна деталізація.

Деформація простору

Подача позиції, зміщеної шумом, у наступний виклик шуму. Турбулентність, дим, вогонь.

Хеш-функція — основа всього

Усім функціям шуму вище потрібне псевдовипадкове значення в кожному цілочисельному вузлі ґратки. Хеш-функція перетворює цілочисельну координату у число з плаваючою комою в діапазоні [0,1). Найшвидший надійний варіант у GLSL — однорядковий трюк sin/fract, хоча для промислової якості краще підходить 32-бітний хеш Ванга:

GLSL — хеш-функції
// Швидко і просто (на основі sin, на деяких GPU проблеми з точністю)
float hash11(float n) { return fract(sin(n) * 43758.5453); }
vec2  hash21(float n) { return fract(sin(vec2(n,n+1.0)) * vec2(43758.5453,22578.1459)); }

// Краще: цілочисельний хеш Ванга (потребує GLSL 3.30 / ES 3.00 з uint)
uint wangHash(uint seed) {
  seed = (seed ^ 61u) ^ (seed >> 16u);
  seed *= 9u;
  seed ^= seed >> 4u;
  seed *= 0x27d4eb2du;
  seed ^= seed >> 15u;
  return seed;
}
float hashFloat(uint seed) { return float(wangHash(seed)) / 4294967296.0; }

Perlin-шум у GLSL

Класичний градієнтний шум. Семплюйте в позиції p, знайдіть чотири навколишні цілочисельні кути, призначте кожному випадковий градієнт, обчисліть скалярний добуток зі зміщувальним вектором і інтерполюйте плавною кубічною або квінтичною функцією загасання.

GLSL — 2D Perlin-шум
// Напрямки градієнта (8 кардинальних + діагональних, класичний Perlin)
vec2 grad(vec2 p) {
  float a = hash11(dot(p, vec2(127.1, 311.7))) * 6.2832;
  return vec2(cos(a), sin(a));
}

float perlin(vec2 p) {
  vec2 i = floor(p);
  vec2 f = fract(p);
  vec2 u = f*f*f*(f*(f*6.0-15.0)+10.0); // квінтична інтерполяція

  float a = dot(grad(i + vec2(0,0)), f - vec2(0,0));
  float b = dot(grad(i + vec2(1,0)), f - vec2(1,0));
  float c = dot(grad(i + vec2(0,1)), f - vec2(0,1));
  float d = dot(grad(i + vec2(1,1)), f - vec2(1,1));

  return mix(mix(a,b,u.x), mix(c,d,u.x), u.y);
}

Фрактальний броунівський рух (FBm)

FBm — це просто сума шуму на кількох октавах — кожна октава подвоює частоту (лакунарність ≈ 2) і зменшує амплітуду вдвічі (коефіцієнт затухання ≈ 0.5). Це створює самоподібний фрактальний вигляд хмар, рельєфу та турбулентних рідин.

GLSL — FBm
float fbm(vec2 p, int octaves, float lacunarity, float gain) {
  float value = 0.0;
  float amplitude = 0.5;
  for (int i = 0; i < octaves; i++) {
    value += amplitude * perlin(p);
    p         *= lacunarity;   // частота вгору
    amplitude *= gain;         // амплітуда вниз
  }
  return value;
}

Деформація простору (Domain Warping)

Замість обчислення fbm(pos), обчислюйте fbm(pos + fbm(pos + offset1) + fbm(pos + offset2)). Кожен шар зміщує позицію семплювання наступного, створюючи турбулентні, органічні структури, неможливі з простим FBm.

Деформація простору = безкоштовна нелінійність. Іньйо Кілес (Inigo Quilez) вперше задокументував цю техніку у 2002 році. Два рівні деформації дають «турбулентність»; три рівні наближаються до реалістичного вигляду вогню й диму. Кожен додатковий рівень деформації коштує однієї додаткової оцінки FBm, але дає значно більшу візуальну складність.

Живі симуляції на основі шуму

Ці симуляції використовують функції шуму в основі своєї роботи — дослідіть їх, щоб побачити описані вище техніки в дії:

Використані алгоритми

Value Noise Градієнтний (Perlin) шум Simplex-шум Worley / клітинний шум Фрактальний броунівський рух Деформація простору Хеш Ванга IFS (система ітерованих функцій) Квінтична інтерполяція Розбиття Вороного