Dunia kebisingan Perlin yang kabur

gambar

Apa itu Perlin noise?


Kebisingan Perlin ditemukan pada tahun 1983 oleh Ken Perlin (yang menerima penghargaan dari Akademi Seni dan Ilmu Gambar bergerak Amerika untuk pencapaian ini). Anda tahu, pada masa itu semua orang berjuang untuk fotorealisme, tetapi selalu kurang. Ken Perlin menemukan algoritma kebisingan ini untuk menghilangkan penampilan "komputer" model 3D yang menyedihkan. Noise adalah penghasil angka acak dalam grafik komputer. Ini adalah pola acak dan tidak terstruktur, dan berguna ketika Anda membutuhkan sumber bagian terperinci yang kurang dalam struktur yang jelas 1 . Perlin noise adalah algoritma multidimensi yang digunakan dalam generasi prosedural, tekstur, generasi elevasi, generasi peta, generasi permukaan, generasi verteks, dan sebagainya dan seterusnya. Tabel di bawah 2 menunjukkan batas kemungkinan kebisingan Perlin:

DimensiKebisingan Mentah (Skala Abu-abu)Aplikasi
1

Objek vektor terlihat digambar tangan
2
Objek seperti tekstur dan api prosedural
3
Perlin Noise Digunakan dalam Bantuan Minecraft

Perlin memberikan definisi kebisingan sebagai berikut: kebisingan adalah perkiraan terhadap white noise, terbatas pada kisaran satu oktaf 3 . Definisi formal kebisingan adalah sebagai berikut:

fN(y1,y2, cdots,yn;x1,x2, cdots,xn)=P(N(x1),N(x2), cdots,N(xn))


Dimana N(x)- fungsi kebisingan. Kebisingan Perlin adalah kebisingan prosedural . “ Prosedural kata sifat digunakan dalam ilmu komputer untuk memisahkan entitas yang dijelaskan oleh kode program dari yang dijelaskan oleh struktur data.” 4 Artinya, sesuatu yang dihasilkan , dan tidak diatur keras. Apa yang baik untuk menggunakan noise prosedural alih-alih, misalnya, membuat noise secara manual? Suara proseduralnya kompak , mis. Membutuhkan lebih sedikit ruang. Itu tidak bisa dipisahkan , yaitu, aperiodik . Ini parametrik , dapat diakses secara acak ; ia juga memiliki banyak keuntungan lain yang menyederhanakan kehidupan artis ... Tapi bukankah ini tujuan utama kita - untuk melayani artis? Kemarin saya membuat plug-in untuk After Effects, yang bisa dilihat di posting saya sebelumnya. Saya tidak memperhitungkan kepentingan artis dalam dirinya, hanya kepentingan ego saya, jadi tidak ada yang mengunduhnya. Saya mengerti pelajaran: Melayani artis, bukan diri Anda sendiri.

Sebelum Perlin, kebisingan gradien kisi-kisi muncul. Mereka dihasilkan oleh interpolasi antara nilai acak, dan dalam kebisingan Perlin, kisi kubik digunakan untuk setiap titik, dan kemudian interpolasi spline dilakukan. "Sebuah gradien pseudo-acak diperoleh dengan hashing titik kisi dan menggunakan hasilnya untuk memilih gradien." 5 Hash ini berubah menjadi 12 vektor dan diinterpolasi dari pusat ke tepi menggunakan polinomial derajat kelima. Sulit membayangkan, bukan? Jangan khawatir. Saya akan menunjukkan ini dalam gambar 6 dan pseudo-code 7 .


"... diinterpolasi dari pusat ke tepi menggunakan polinomial tingkat lima"

Dan di sini adalah pseudocode Perlin klasik tanpa fungsi hash:

// Function to linearly interpolate between a0 and a1 // Weight w should be in the range [0.0, 1.0] float lerp(float a0, float a1, float w) { return (1.0 - w)*a0 + w*a1; // as an alternative, this slightly faster equivalent formula can be used: // return a0 + w*(a1 - a0); } // Computes the dot product of the distance and gradient vectors. float dotGridGradient(int ix, int iy, float x, float y) { // Precomputed (or otherwise) gradient vectors at each grid node extern float Gradient[IYMAX][IXMAX][2]; // Compute the distance vector float dx = x - (float)ix; float dy = y - (float)iy; // Compute the dot-product return (dx*Gradient[iy][ix][0] + dy*Gradient[iy][ix][1]); } // Compute Perlin noise at coordinates x, y float perlin(float x, float y) { // Determine grid cell coordinates int x0 = int(x); int x1 = x0 + 1; int y0 = int(y); int y1 = y0 + 1; // Determine interpolation weights // Could also use higher order polynomial/s-curve here float sx = x - (float)x0; float sy = y - (float)y0; // Interpolate between grid point gradients float n0, n1, ix0, ix1, value; n0 = dotGridGradient(x0, y0, x, y); n1 = dotGridGradient(x1, y0, x, y); ix0 = lerp(n0, n1, sx); n0 = dotGridGradient(x0, y1, x, y); n1 = dotGridGradient(x1, y1, x, y); ix1 = lerp(n0, n1, sx); value = lerp(ix0, ix1, sy); return value; } 

Perlu juga diketahui bahwa “semua fungsi kebisingan, kecuali untuk kebisingan Perlin dan kebisingan konvolusi yang dijernihkan, kira-kira mirip strip. Suara Perlin hanyalah pita lemah, yang dapat menyebabkan masalah dengan distorsi dan hilangnya detail. ” 8 Selain itu, Perlin noise tidak memiliki distribusi amplitudo Gaussian. Yaitu, titik-titik kebisingan tidak tersebar berdasarkan fungsi Gaussian, yang tidak akan kami pertimbangkan dalam artikel ini. Ada banyak hal di mana Perlin sangat nyaman, tetapi ada hal-hal di mana dia sangat lemah. Pada tabel di bawah 9 Anda dapat melihatnya sendiri.



Perlin noise dalam praktiknya: implementasi GLSL


Jadi, mari kita bicara tentang kebisingan Perlin di GLSL. Perlin noise dapat digunakan sebagai gelombang, sebagai warna difus, sebagai bahan difus, sebagai cahaya yang berkedip, atau sebagai bintik pada tekstur. Secara pribadi, saya menggunakannya dalam contoh ini sebagai secercah warna.


Saat saya menulis artikel ini, saya berpikir tentang membuat plug-in untuk After Effects yang menambahkan fungsionalitas kebisingan Perlin.

Perlin's noise paling sederhana dapat dibuat 10 sebagai berikut:

 float rand(vec2 c){ return fract(sin(dot(c.xy ,vec2(12.9898,78.233))) * 43758.5453); } float noise(vec2 p, float freq ){ float unit = screenWidth/freq; vec2 ij = floor(p/unit); vec2 xy = mod(p,unit)/unit; //xy = 3.*xy*xy-2.*xy*xy*xy; xy = .5*(1.-cos(PI*xy)); float a = rand((ij+vec2(0.,0.))); float b = rand((ij+vec2(1.,0.))); float c = rand((ij+vec2(0.,1.))); float d = rand((ij+vec2(1.,1.))); float x1 = mix(a, b, xy.x); float x2 = mix(c, d, xy.x); return mix(x1, x2, xy.y); } float pNoise(vec2 p, int res){ float persistance = .5; float n = 0.; float normK = 0.; float f = 4.; float amp = 1.; int iCount = 0; for (int i = 0; i<50; i++){ n+=amp*noise(p, f); f*=2.; normK+=amp; amp*=persistance; if (iCount == res) break; iCount++; } float nf = n/normK; return nf*nf*nf*nf; } 


 #define M_PI 3.14159265358979323846 float rand(vec2 co){return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);} float rand (vec2 co, float l) {return rand(vec2(rand(co), l));} float rand (vec2 co, float l, float t) {return rand(vec2(rand(co, l), t));} float perlin(vec2 p, float dim, float time) { vec2 pos = floor(p * dim); vec2 posx = pos + vec2(1.0, 0.0); vec2 posy = pos + vec2(0.0, 1.0); vec2 posxy = pos + vec2(1.0); float c = rand(pos, dim, time); float cx = rand(posx, dim, time); float cy = rand(posy, dim, time); float cxy = rand(posxy, dim, time); vec2 d = fract(p * dim); d = -0.5 * cos(d * M_PI) + 0.5; float ccx = mix(c, cx, dx); float cycxy = mix(cy, cxy, dx); float center = mix(ccx, cycxy, dy); return center * 2.0 - 1.0; } // p must be normalized! float perlin(vec2 p, float dim) { /*vec2 pos = floor(p * dim); vec2 posx = pos + vec2(1.0, 0.0); vec2 posy = pos + vec2(0.0, 1.0); vec2 posxy = pos + vec2(1.0); // For exclusively black/white noise /*float c = step(rand(pos, dim), 0.5); float cx = step(rand(posx, dim), 0.5); float cy = step(rand(posy, dim), 0.5); float cxy = step(rand(posxy, dim), 0.5);*/ /*float c = rand(pos, dim); float cx = rand(posx, dim); float cy = rand(posy, dim); float cxy = rand(posxy, dim); vec2 d = fract(p * dim); d = -0.5 * cos(d * M_PI) + 0.5; float ccx = mix(c, cx, dx); float cycxy = mix(cy, cxy, dx); float center = mix(ccx, cycxy, dy); return center * 2.0 - 1.0;*/ return perlin(p, dim, 0.0); } 

Namun, ini adalah versi redone dari kebisingan Perlin, yang dibuat pada tahun 2002. Pergi ke Gist untuk melihat bagaimana kebisingan klasik Perlin direalisasikan.

Yah, itu saja untuk hari ini. Sebuah posting pendek, saya tahu, dan tidak memiliki konten asli, tetapi sejauh ini saya kehabisan ide, karena saya belum membaca Real-Time Rendering . Buku ini penuh dengan konsep dan ide untuk belajar dan belajar. Aku mencintainya!


Secara paralel, saya membaca buku lain - Fundamentals of Computer Graphics . Saya sedikit terjebak pada topik Kurva Tersirat, tetapi saya akan meminta kerabat saya dengan gelar PhD dalam matematika untuk membantu saya.


Referensi


  • Sebuah Survei Fungsi Kebisingan Prosedural, Forum Grafik Komputer, Volume 29 (2010), Nomor 8, pp 2379-2600
  • Kebisingan Komputasi yang Efisien, Jurnal Alat Grafik Volume 16, No. 2: 85-94

  1. Sebuah Survei, dkk
  2. flafla2.imtqy.com/2014/08/09/perlinnoise.html
  3. A. Lagaue et al
  4. A. Lagae, dkk
  5. A. Lagae, dkk
  6. Dari flafla2.imtqy.com/2014/08/09/perlinnoise.html
  7. Dari Wikipedia
  8. A. Lagae, dkk
  9. Diadaptasi dari A. Lagae, et al
  10. gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83

Source: https://habr.com/ru/post/id441312/


All Articles