This is an old revision of the document!


Laboratorul 02. Perlin Noise

Perlin noise, dezvoltat de Ken Perlin în 1983, este o funcție de zgomot gradient utilizată pe scară largă în grafica computerizată pentru a crea texturi, terenuri și alte conținuturi procedurale cu aspect natural. Spre deosebire de zgomotul aleatoriu simplu, Perlin noise produce modele mai netede și mai coerente care imită neregularitățile întâlnite în natură.

Cum funcționează?

  1. Definirea unui grid: Spațiul este împărțit într-un grid în care fiecărui punct de intersecție (nod) i se atribuie un vector gradient pseudo-aleatoriu
  2. Determinarea celulei: Pentru orice punct dat în spațiu unde este necesară valoarea zgomotului, se identifică celula gridului în care se află. Această celulă este definită de nodurile înconjurătoare
  3. Vectori de offset: Se calculează vectorii de offset de la fiecare dintre nodurile colțului celulei până la punctul în cauză. Acești vectori reprezintă poziția relativă a punctului în cadrul celulei
  4. Produse scalare: Se calculează produsul scalar între fiecare vector gradient al nodului și vectorul său de offset corespunzător. Acest pas măsoară influența gradientului fiecărui colț asupra punctului
  5. Interpolare: Se amestecă aceste rezultate ale produsului scalar folosind o funcție de interpolare, adesea o funcție de atenuare, pentru a asigura tranziții fără întreruperi între valori. Această interpolare asigură că zgomotul se schimbă treptat, producând netezimea caracteristică a Perlin noise

Implementare

Pentru a genera o textură, Perlin noise primește ca input 2 parametri, x și y, coordonatele pixelilor din textură înmulțite cu un număr mic (frecvența).

for y in range(height):
    for x in range(width):
        n = perlin(x * frequency, y * frequency)

În implementare, se definește un grid, pe care va fi definită textura. Inpututul algoritmului se va afla într-o celulă a acestui grid. Pentru fiecare colț al fiecărei celule din grid se va genera un vector gradient constant. Outputul algoritmului va fi o interporlare între 4 valori, calculate în funcție de vectorul gradient al fiecărui colț și de datele de input, x și y.

Diferența dintre Perlin noise și value noise este modul în care sunt obținute aceste 4 valori. În timp ce value noise folosește un generator de numere pseudo-aleatoare, Perlin noise folosește un produs scalar între 2 vectori.

Pentru a calcula valorile necesare interpolării, se vor calcula 4 produse scalare. Pentru fiecare produs scalar, primul vector va fi generat pornind de la colțul curent la punctul de input, iar al doilea vector este vectorul gradient asignat fiecărui colț al gridului.

xf = x - floor(x)
yf = y - floor(y)

topRight = Vector2(xf - 1.0, yf - 1.0)
topLeft = Vector2(xf, yf - 1.0)
bottomRight = Vector2(xf - 1.0, yf)
bottomLeft = Vector2(xf, yf)

dotTopRight = dot(topRight, gradientTopRight)
dotTopLeft = dot(topLeft, gradientTopLeft)
dotBottomRight = dot(bottomRight, gradientBottomRight)
dotBottomLeft = dot(bottomLeft, gradientBottomLeft)

În implementarea originală a algoritmului, Ken Perlin a folosit un tabel de permutări cu 256 de intrări pentru a determina ce vector gradient este asociat fiecărei intersecții a gridului. Astfel, vectorii gradient ajung să se repete în funcție de dimensiunea texturii pe care o generăm. Tot în implementarea originală, Ken Perlin a folosit următorul tabel de permutări, însă în practică se poate folosi orice alt tabel de permutări.

int permutation[] = { 151, 160, 137,  91,  90,  15, 131,  13, 201,  95,  96,  53, 194, 233,   7, 225,
                      140,  36, 103,  30,  69, 142,   8,  99,  37, 240,  21,  10,  23, 190,   6, 148,
                      247, 120, 234,  75,   0,  26, 197,  62,  94, 252, 219, 203, 117,  35,  11,  32,
                       57, 177,  33,  88, 237, 149,  56,  87, 174,  20, 125, 136, 171, 168,  68, 175,
                       74, 165,  71, 134, 139,  48,  27, 166,  77, 146, 158, 231,  83, 111, 229, 122,
                       60, 211, 133, 230, 220, 105,  92,  41,  55,  46, 245,  40, 244, 102, 143,  54,
                       65,  25,  63, 161,   1, 216,  80,  73, 209,  76, 132, 187, 208,  89,  18, 169,
                      200, 196, 135, 130, 116, 188, 159,  86, 164, 100, 109, 198, 173, 186,   3,  64,
                       52, 217, 226, 250, 124, 123,   5, 202,  38, 147, 118, 126, 255,  82,  85, 212,
                      207, 206,  59, 227,  47,  16,  58,  17, 182, 189,  28,  42, 223, 183, 170, 213,
                      119, 248, 152,   2,  44, 154, 163,  70, 221, 153, 101, 155, 167,  43, 172,   9,
                      129,  22,  39, 253,  19,  98, 108, 110,  79, 113, 224, 232, 178, 185, 112, 104,
                      218, 246,  97, 228, 251,  34, 242, 193, 238, 210, 144,  12, 191, 179, 162, 241,
                       81,  51, 145, 235, 249,  14, 239, 107,  49, 192, 214,  31, 181, 199, 106, 157,
                      184,  84, 204, 176, 115, 121,  50,  45, 127,   4, 150, 254, 138, 236, 205,  93,
                      222, 114,  67,  29,  24,  72, 243, 141, 128, 195,  78,  66, 215,  61, 156, 180 };

Odată generat tabelul de permutări, este nevoie de o valoare din acest tabel pentru fiecare dintre colțuri. Există însă o restricție: un colț trebuie să primească întotdeauna aceeași valoare, indiferent care dintre cele 4 celule de grid care îl pot avea drept colț conține valoarea de input. De exemplu, dacă colțul din dreapta sus al celulei gridului (0, 0) are o valoare de 42, atunci colțul din stânga sus al celulei gridului (1, 0) trebuie să aibă, de asemenea, aceeași valoare de 42. Este același punct al gridului, deci aceeași valoare indiferent de celula gridului.

X = floor(x) & 255
Y = floor(y) & 255
    
valueTopRight = permutations[permutations[X+1]+Y+1];
valueTopLeft = permutations[permutations[X]+Y+1];
valueBottomRight = permutations[permutations[X+1]+Y];
valueBottomLeft = permutations[permutations[X]+Y];
gp/laboratoare/02.1741702490.txt.gz · Last modified: 2025/03/11 16:14 by maria_anca.balutoiu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0