Fungsi acak / berisik untuk GLSL

179

Karena vendor driver GPU biasanya tidak repot-repot mengimplementasikannya noiseXdi GLSL, saya mencari seperangkat fungsi utilitas "pengacakan grafis swiss army knife" , sebaiknya dioptimalkan untuk digunakan dalam GPU shaders. Saya lebih suka GLSL, tetapi kode bahasa apa pun akan membantu saya, saya setuju menerjemahkannya sendiri ke GLSL.

Secara khusus, saya berharap:

a) Fungsi pseudo-acak - N-dimensional, distribusi seragam lebih dari [-1,1] atau lebih [0,1], dihitung dari benih M-dimensional (idealnya adalah nilai apa pun, tapi saya setuju dengan benih yang ditahan) untuk, katakanlah, 0..1 untuk distribusi hasil yang seragam). Sesuatu seperti:

float random  (T seed);
vec2  random2 (T seed);
vec3  random3 (T seed);
vec4  random4 (T seed);
// T being either float, vec2, vec3, vec4 - ideally.

b) Derau terus menerus seperti Perlin Noise - lagi, distribusi N-dimensional, + - seragam, dengan himpunan nilai terbatas dan, well, terlihat bagus (beberapa opsi untuk mengonfigurasi tampilan seperti level Perlin bisa berguna juga). Saya berharap tanda tangan seperti:

float noise  (T coord, TT seed);
vec2  noise2 (T coord, TT seed);
// ...

Saya tidak terlalu suka teori bilangan acak, jadi saya paling bersemangat mencari solusi yang sudah dibuat , tapi saya juga menghargai jawaban seperti "ini rand 1D yang sangat bagus, efisien (), dan biarkan saya jelaskan Anda bagaimana membuat rand N - dimensi yang baik () di atasnya ... " .

Kos
sumber

Jawaban:

263

Untuk hal-hal yang tampak sederhana secara acak, saya menggunakan oneliner ini yang saya temukan di internet di suatu tempat:

float rand(vec2 co){
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

Anda juga dapat menghasilkan tekstur suara menggunakan PRNG apa pun yang Anda suka, lalu unggah ini dengan cara normal dan sampel nilai-nilai dalam shader Anda; Saya bisa menggali sampel kode nanti jika Anda mau.

Juga, periksa file ini untuk implementasi GLSL dari Perlin dan Simplex noise, oleh Stefan Gustavson.

appas
sumber
14
Bagaimana Anda menggunakan vec2 co? apakah jangkauannya? benih?
Ross
12
Waspadalah terhadap shader fragmen titik-mengambang berpresisi rendah dengan algoritma ini (mis., ARM Mali S3): stackoverflow.com/questions/11293628/… . Proyek github.com/ashima/webgl-noise tampaknya tidak memiliki masalah lowp.
PT
4
FWIW, fungsi yang dijelaskan di sini dibahas secara lebih rinci di sini .
Loomchild
3
FYI: Distribusi fungsi itu mengerikan.
Tara
3
Saya pemula di GLSL, adakah yang bisa menjelaskan mengapa co.xydigunakan, bukan co?
kelin
83

Terjadi pada saya bahwa Anda dapat menggunakan fungsi hash integer sederhana dan memasukkan hasilnya ke mantissa float. IIRC spesifikasi GLSL menjamin integer 32-bit unsigned dan representasi float IEEE binary32 sehingga harus portabel.

Saya mencoba ini sekarang. Hasilnya sangat bagus: sepertinya persis statis dengan setiap input yang saya coba, tidak ada pola yang terlihat sama sekali. Sebaliknya, potongan populer dosa / fraktur memiliki garis diagonal yang cukup menonjol pada GPU saya yang diberi input yang sama.

Salah satu kelemahannya adalah ia membutuhkan GLSL v3.30. Dan meskipun tampaknya cukup cepat, saya belum mengukur kinerjanya secara empiris. AMD Shader Analyzer mengklaim 13.33 piksel per jam untuk versi vec2 pada HD5870. Kontras dengan 16 piksel per jam untuk cuplikan dosa / fraktur. Jadi tentu sedikit lebih lambat.

Inilah implementasi saya. Saya meninggalkannya dalam berbagai permutasi ide untuk membuatnya lebih mudah untuk mendapatkan fungsi Anda sendiri.

/*
    static.frag
    by Spatial
    05 July 2013
*/

#version 330 core

uniform float time;
out vec4 fragment;



// A single iteration of Bob Jenkins' One-At-A-Time hashing algorithm.
uint hash( uint x ) {
    x += ( x << 10u );
    x ^= ( x >>  6u );
    x += ( x <<  3u );
    x ^= ( x >> 11u );
    x += ( x << 15u );
    return x;
}



// Compound versions of the hashing algorithm I whipped together.
uint hash( uvec2 v ) { return hash( v.x ^ hash(v.y)                         ); }
uint hash( uvec3 v ) { return hash( v.x ^ hash(v.y) ^ hash(v.z)             ); }
uint hash( uvec4 v ) { return hash( v.x ^ hash(v.y) ^ hash(v.z) ^ hash(v.w) ); }



// Construct a float with half-open range [0:1] using low 23 bits.
// All zeroes yields 0.0, all ones yields the next smallest representable value below 1.0.
float floatConstruct( uint m ) {
    const uint ieeeMantissa = 0x007FFFFFu; // binary32 mantissa bitmask
    const uint ieeeOne      = 0x3F800000u; // 1.0 in IEEE binary32

    m &= ieeeMantissa;                     // Keep only mantissa bits (fractional part)
    m |= ieeeOne;                          // Add fractional part to 1.0

    float  f = uintBitsToFloat( m );       // Range [1:2]
    return f - 1.0;                        // Range [0:1]
}



// Pseudo-random value in half-open range [0:1].
float random( float x ) { return floatConstruct(hash(floatBitsToUint(x))); }
float random( vec2  v ) { return floatConstruct(hash(floatBitsToUint(v))); }
float random( vec3  v ) { return floatConstruct(hash(floatBitsToUint(v))); }
float random( vec4  v ) { return floatConstruct(hash(floatBitsToUint(v))); }





void main()
{
    vec3  inputs = vec3( gl_FragCoord.xy, time ); // Spatial and temporal inputs
    float rand   = random( inputs );              // Random per-pixel value
    vec3  luma   = vec3( rand );                  // Expand to RGB

    fragment = vec4( luma, 1.0 );
}

Tangkapan layar:

Output acak (vec3) di static.frag

Saya memeriksa tangkapan layar dalam program pengeditan gambar. Ada 256 warna dan nilai rata-rata adalah 127, artinya distribusinya seragam dan mencakup kisaran yang diharapkan.

Spasial
sumber
17
+1 untuk ide dan implementasi yang bagus. Saya akan mempertanyakan klaim bahwa karena ada 256 warna dan nilai rata-rata adalah 127, distribusinya harus seragam (dalam arti sempit). Mungkin seragam, tapi saya pikir kita belum tahu itu. Misalnya distribusi kurva lonceng bisa memiliki rata-rata dan jumlah warna yang sama, tetapi tidak akan seragam.
LarsH
Memilih ini karena alasan yang diberikan oleh @LarsH.
Autumnsault
Ya, itu cukup baik untuk sebagian besar aplikasi yang tidak membutuhkan keseragaman. :-)
itmuckel
5
Tampaknya sangat seragam, dengan persepsi saya tentang histogram .... Saya akan mengatakan itu cukup baik untuk sebagian besar aplikasi yang memerlukan keseragaman juga. (Satu-satunya nilai yang tampaknya dihasilkan kurang dari yang lain adalah 0 dan 255)
leviathanbadger
Terima kasih. Probabilitas saya berkarat. Setelah melihat set instruksi GCN, ini harus sangat cepat pada perangkat keras baru karena mereka secara langsung mendukung operasi bitfield dalam set instruksi mereka. Tes yang saya lakukan berlari pada perangkat keras yang lebih lama.
Spasial
73

Implementasi Gustavson menggunakan tekstur 1D

Tidak, tidak sejak 2005. Hanya saja orang-orang bersikeras mengunduh versi lama. Versi yang ada di tautan yang Anda berikan hanya menggunakan tekstur 2D 8-bit.

Versi baru oleh Ian McEwan dari Ashima dan saya sendiri tidak menggunakan tekstur, tetapi berjalan sekitar setengah kecepatan pada platform desktop biasa dengan banyak bandwidth tekstur. Pada platform seluler, versi tanpa tekstur mungkin lebih cepat karena tekstur sering menjadi hambatan yang signifikan.

Repositori sumber kami yang dikelola secara aktif adalah:

https://github.com/ashima/webgl-noise

Koleksi versi kebisingan tanpa tekstur dan penggunaan tekstur ada di sini (hanya menggunakan tekstur 2D):

http://www.itn.liu.se/~stegu/simplexnoise/GLSL-noise-vs-noise.zip

Jika Anda memiliki pertanyaan spesifik, jangan sungkan untuk mengirim email langsung kepada saya (alamat email saya dapat ditemukan di classicnoise*.glslsumbernya.)

Stefan Gustavson
sumber
4
Ya, implementasi yang saya maksudkan, kode Anda di davidcornette.com yang ditautkan dengan @dep, memang menggunakan tekstur 1D: glBindTexture(GL_TEXTURE_1D, *texID);dll. Tidak jelas apa yang Anda maksud dengan "tautan yang Anda berikan", karena Anda mengutip dari jawaban saya tetapi jawaban itu tidak terhubung ke implementasi Anda. Saya akan memperbarui jawaban saya untuk mengklarifikasi apa yang saya maksudkan dan mencerminkan informasi baru yang Anda berikan. Mengkarakterisasi orang sebagai "ngotot" mengunduh versi lama adalah distorsi yang tidak membuat Anda menghargai.
LarsH
1
PS Anda mungkin ingin menulis kepada David Cornette (ia memiliki info kontak di davidcornette.com ) dan memintanya untuk mengubah tautannya di davidcornette.com/glsl/links.html untuk menautkan ke repo sumber Anda. Saya juga akan mengirim email kepadanya.
LarsH
1
PPS Bisakah Anda mengklarifikasi, versi mana yang hanya menggunakan tekstur 2D 8-bit? Kedengarannya itu mungkin pilihan yang baik untuk platform tertentu ...
LarsH
31

Kebisingan Emas

// Gold Noise ©2015 [email protected]
// - based on the Golden Ratio
// - uniform normalized distribution
// - fastest static noise generator function (also runs at low precision)

float PHI = 1.61803398874989484820459;  // Φ = Golden Ratio   

float gold_noise(in vec2 xy, in float seed){
       return fract(tan(distance(xy*PHI, xy)*seed)*xy.x);
}

Lihat Kebisingan Emas di browser Anda sekarang!

masukkan deskripsi gambar di sini

Fungsi ini telah meningkatkan distribusi acak di atas fungsi saat ini dalam jawaban @appas pada 9 September 2017:

masukkan deskripsi gambar di sini

Fungsi @appas juga tidak lengkap, mengingat tidak ada seed yang disediakan (uv bukan seed - sama untuk setiap frame), dan tidak bekerja dengan chipset berpresisi rendah. Gold Noise berjalan pada presisi rendah secara default (jauh lebih cepat).

Dominic Cerisano
sumber
Terima kasih telah memposting ini. Apakah Anda mempertimbangkan untuk memposting versi runnable, misalnya di shadertoy.com, sehingga orang dapat mencobanya di dalam browser?
LarsH
@snb Shadertoy.com sedang menjalani perawatan bulan ini, bersabarlah. Saya juga dengan jelas mendokumentasikan persyaratan untuk nilai benih irasional dalam kode di sana. Karena noise emas mengembalikan skalar, membuat vektor dengannya sepele, dan juga didokumentasikan dalam kode.
Dominic Cerisano
7
Saya tidak berpikir ini berbeda dari fungsi noise lainnya. apa buktimu bahwa ini memiliki sifat khusus. hanya karena Anda menggunakan banyak bilangan irasional tidak membuatnya istimewa.
M.kazem Akhgary
2
@ Dominic: "Ini memiliki distribusi yang unggul untuk fungsi yang sama": ini harus dibuktikan. tan () benar-benar buruk. baik tan () dekat pi / 2 dan sqrt () mendekati nol sangat mungkin untuk menghasilkan hasil yang berbeda pada perangkat keras yang berbeda karena semua fraktur (non-linear * besar) didasarkan pada bit yang kurang signifikan. Nilai input yang kecil atau tinggi akan berdampak juga. Juga, dinamika bit mungkin sangat bervariasi tergantung pada lokasi.
Fabrice NEYRET
2
NB: Saat ini GLSL memiliki bilangan bulat, jadi tidak ada lagi alasan untuk tidak menggunakan generator hash berbasis int "serius" ketika distribusi kualitas (dan dinamika) diperlukan, dengan kinerja yang sama. (kecuali untuk perangkat yang sangat low-end).
Fabrice NEYRET
12

Ada juga implementasi bagus yang dijelaskan di sini oleh McEwan dan @StefanGustavson yang terlihat seperti suara Perlin, tetapi "tidak memerlukan pengaturan apa pun, yaitu bukan tekstur atau array yang seragam. Cukup tambahkan ke kode sumber shader Anda dan panggil ke mana pun Anda inginkan".

Itu sangat berguna, terutama mengingat implementasi awal Gustavson, yang dikaitkan dengan @dep, menggunakan tekstur 1D, yang tidak didukung dalam GLSL ES (bahasa shader dari WebGL).

Lars
sumber
1
Ini adalah jawaban terbaik untuk OP b) permintaan jenis kebisingan! Berikut ini tautan langsung github.com/ashima/webgl-noise . Ada versi 2d, 3d dan 4d yang siap sebagai kode GLSL 120.
user362515
3

Gunakan ini:

highp float rand(vec2 co)
{
    highp float a = 12.9898;
    highp float b = 78.233;
    highp float c = 43758.5453;
    highp float dt= dot(co.xy ,vec2(a,b));
    highp float sn= mod(dt,3.14);
    return fract(sin(sn) * c);
}

Jangan gunakan ini:

float rand(vec2 co){
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

Anda dapat menemukan penjelasan dalam Perbaikan untuk rSL (-satu baris GLSL) kanonik untuk OpenGL ES 2.0

hoangdado
sumber
Saya membaca sekilas artikel tersebut tetapi saya masih tidak yakin, apakah 3,14 dalam modperkiraan pi?
Kaan E.
2

Baru saja menemukan versi derau 3d untuk GPU ini, ini adalah yang tercepat yang tersedia:

#ifndef __noise_hlsl_
#define __noise_hlsl_

// hash based 3d value noise
// function taken from https://www.shadertoy.com/view/XslGRr
// Created by inigo quilez - iq/2013
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

// ported from GLSL to HLSL

float hash( float n )
{
    return frac(sin(n)*43758.5453);
}

float noise( float3 x )
{
    // The noise function returns a value in the range -1.0f -> 1.0f

    float3 p = floor(x);
    float3 f = frac(x);

    f       = f*f*(3.0-2.0*f);
    float n = p.x + p.y*57.0 + 113.0*p.z;

    return lerp(lerp(lerp( hash(n+0.0), hash(n+1.0),f.x),
                   lerp( hash(n+57.0), hash(n+58.0),f.x),f.y),
               lerp(lerp( hash(n+113.0), hash(n+114.0),f.x),
                   lerp( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);
}

#endif
com. dimengerti
sumber
1
Gold Noise (di atas) jelas merupakan yang tercepat, karena ia memiliki operasi yang jauh lebih sedikit dan hanya melakukan satu hash - yang ini menyebut fungsinya hash 8 kali, sambil melakukan interpolasi linear bersarang (lerps). Juga yang ini memiliki distribusi yang lebih rendah terutama pada presisi rendah.
Dominic Cerisano
1
Oh good point, ini adalah grafik jenis kebisingan perlin dari shadertoh oleh Inigo Quilez. Kode yang bagus Dominic ill check it l8r
com.prehensible
@Fabrice Sepertinya Anda tidak memahami pertanyaan OP, jawaban saya, kode saya atau komentar saya .. Kebisingan Emas berkelanjutan oleh definisi OP - ia menerima uv dan seed dan membuktikannya dengan memberikan shader. Segala sesuatu tentang komentar Anda salah. Anda terus membingungkan fungsi hash dengan fungsi noise acak semu. Mereka tidak sama. Fungsi kebisingan tidak memiliki persyaratan untuk menghasilkan pengidentifikasi unik seperti fungsi hash (seluruh titik hashing).
Dominic Cerisano
Tolong tolong, Dominic, baca lebih lanjut dan pelajari lebih lanjut sebelum mengklaim hal-hal tentang istilah yang Anda pikir Anda pahami sementara itu tidak terjadi. Tidak hanya istilah-istilah ini benar-benar tepat dan terdefinisi dengan baik dalam sastra, ditambah saya melakukan pekerjaan di lapangan, tetapi juga OP membuktikan dia memahami istilah-istilah dengan contoh-contoh yang dia berikan setelah. Petunjuk: "terus menerus" + "noise" + "seperti Perlin". en.wikipedia.org/wiki/Perlin_noise
Fabrice NEYRET
Continuous adalah satu-satunya kasus menambahkan klausa loop, banyak fungsi noise loop dan menurunkan setelah cara tertentu karena pembulatan bit terutama untuk grafis. Kawan-kawan, itu hanya komunikasi yang terputus dari Anda, gunakan waktu Anda untuk penelitian penting.
com.preh
1

Versi lurus, bergerigi dari 1d Perlin, pada dasarnya adalah lfo zigzag acak.

half  rn(float xx){         
    half x0=floor(xx);
    half x1=x0+1;
    half v0 = frac(sin (x0*.014686)*31718.927+x0);
    half v1 = frac(sin (x1*.014686)*31718.927+x1);          

    return (v0*(1-frac(xx))+v1*(frac(xx)))*2-1*sin(xx);
}

Saya juga telah menemukan 1-2-3-4d kebisingan perlin di situs web shadertoy pemilik inigo quilez perlin tutorial, dan voronoi dan sebagainya, ia memiliki implementasi cepat dan kode untuk mereka.

com. dimengerti
sumber
1

hash: Saat ini webGL2.0 sudah ada sehingga bilangan bulat tersedia di (w) GLSL. -> untuk hash portabel berkualitas (dengan biaya yang sama dari hash float jelek) sekarang kita dapat menggunakan teknik hashing "serius". IQ menerapkan beberapa di https://www.shadertoy.com/view/XlXcW4 (dan banyak lagi)

Misalnya:

  const uint k = 1103515245U;  // GLIB C
//const uint k = 134775813U;   // Delphi and Turbo Pascal
//const uint k = 20170906U;    // Today's date (use three days ago's dateif you want a prime)
//const uint k = 1664525U;     // Numerical Recipes

vec3 hash( uvec3 x )
{
    x = ((x>>8U)^x.yzx)*k;
    x = ((x>>8U)^x.yzx)*k;
    x = ((x>>8U)^x.yzx)*k;

    return vec3(x)*(1.0/float(0xffffffffU));
}
Fabrice NEYRET
sumber
0

Silakan lihat di bawah ini contoh cara menambahkan white noise ke tekstur yang diberikan. Solusinya adalah dengan menggunakan dua tekstur: noise putih asli dan murni, seperti ini: white noise wiki

private static final String VERTEX_SHADER =
    "uniform mat4 uMVPMatrix;\n" +
    "uniform mat4 uMVMatrix;\n" +
    "uniform mat4 uSTMatrix;\n" +
    "attribute vec4 aPosition;\n" +
    "attribute vec4 aTextureCoord;\n" +
    "varying vec2 vTextureCoord;\n" +
    "varying vec4 vInCamPosition;\n" +
    "void main() {\n" +
    "    vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
    "    gl_Position = uMVPMatrix * aPosition;\n" +
    "}\n";

private static final String FRAGMENT_SHADER =
        "precision mediump float;\n" +
        "uniform sampler2D sTextureUnit;\n" +
        "uniform sampler2D sNoiseTextureUnit;\n" +
        "uniform float uNoseFactor;\n" +
        "varying vec2 vTextureCoord;\n" +
        "varying vec4 vInCamPosition;\n" +
        "void main() {\n" +
                "    gl_FragColor = texture2D(sTextureUnit, vTextureCoord);\n" +
                "    vec4 vRandChosenColor = texture2D(sNoiseTextureUnit, fract(vTextureCoord + uNoseFactor));\n" +
                "    gl_FragColor.r += (0.05 * vRandChosenColor.r);\n" +
                "    gl_FragColor.g += (0.05 * vRandChosenColor.g);\n" +
                "    gl_FragColor.b += (0.05 * vRandChosenColor.b);\n" +
        "}\n";

Fragmen yang dibagikan berisi parameter uNoiseFactor yang diperbarui pada setiap rendering oleh aplikasi utama:

float noiseValue = (float)(mRand.nextInt() % 1000)/1000;
int noiseFactorUniformHandle = GLES20.glGetUniformLocation( mProgram, "sNoiseTextureUnit");
GLES20.glUniform1f(noiseFactorUniformHandle, noiseFactor);
klimletov
sumber
0

Saya telah menerjemahkan salah satu implementasi Java Ken Perlin ke GLSL dan menggunakannya dalam beberapa proyek di ShaderToy.

Di bawah ini adalah interpretasi GLSL yang saya lakukan:

int b(int N, int B) { return N>>B & 1; }
int T[] = int[](0x15,0x38,0x32,0x2c,0x0d,0x13,0x07,0x2a);
int A[] = int[](0,0,0);

int b(int i, int j, int k, int B) { return T[b(i,B)<<2 | b(j,B)<<1 | b(k,B)]; }

int shuffle(int i, int j, int k) {
    return b(i,j,k,0) + b(j,k,i,1) + b(k,i,j,2) + b(i,j,k,3) +
        b(j,k,i,4) + b(k,i,j,5) + b(i,j,k,6) + b(j,k,i,7) ;
}

float K(int a, vec3 uvw, vec3 ijk)
{
    float s = float(A[0]+A[1]+A[2])/6.0;
    float x = uvw.x - float(A[0]) + s,
        y = uvw.y - float(A[1]) + s,
        z = uvw.z - float(A[2]) + s,
        t = 0.6 - x * x - y * y - z * z;
    int h = shuffle(int(ijk.x) + A[0], int(ijk.y) + A[1], int(ijk.z) + A[2]);
    A[a]++;
    if (t < 0.0)
        return 0.0;
    int b5 = h>>5 & 1, b4 = h>>4 & 1, b3 = h>>3 & 1, b2= h>>2 & 1, b = h & 3;
    float p = b==1?x:b==2?y:z, q = b==1?y:b==2?z:x, r = b==1?z:b==2?x:y;
    p = (b5==b3 ? -p : p); q = (b5==b4 ? -q : q); r = (b5!=(b4^b3) ? -r : r);
    t *= t;
    return 8.0 * t * t * (p + (b==0 ? q+r : b2==0 ? q : r));
}

float noise(float x, float y, float z)
{
    float s = (x + y + z) / 3.0;  
    vec3 ijk = vec3(int(floor(x+s)), int(floor(y+s)), int(floor(z+s)));
    s = float(ijk.x + ijk.y + ijk.z) / 6.0;
    vec3 uvw = vec3(x - float(ijk.x) + s, y - float(ijk.y) + s, z - float(ijk.z) + s);
    A[0] = A[1] = A[2] = 0;
    int hi = uvw.x >= uvw.z ? uvw.x >= uvw.y ? 0 : 1 : uvw.y >= uvw.z ? 1 : 2;
    int lo = uvw.x <  uvw.z ? uvw.x <  uvw.y ? 0 : 1 : uvw.y <  uvw.z ? 1 : 2;
    return K(hi, uvw, ijk) + K(3 - hi - lo, uvw, ijk) + K(lo, uvw, ijk) + K(0, uvw, ijk);
}

Saya menerjemahkannya dari Lampiran B dari Bab 2 dari Noise Hardware Ken Perlin di sumber ini:

https://www.csee.umbc.edu/~olano/s2002c36/ch02.pdf

Berikut ini adalah keteduhan publik yang saya lakukan pada Shader Toy yang menggunakan fungsi noise yang diposting:

https://www.shadertoy.com/view/3slXzM

Beberapa sumber bagus lain yang saya temukan tentang masalah kebisingan selama penelitian saya meliputi:

https://thebookofshaders.com/11/

https://mzucker.github.io/html/perlin-noise-math-faq.html

https://rmarcus.info/blog/2018/03/04/perlin-noise.html

http://flafla2.github.io/2014/08/09/perlinnoise.html

https://mrl.nyu.edu/~perlin/noise/

https://rmarcus.info/blog/assets/perlin/perlin_paper.pdf

https://developer.nvidia.com/gpugems/GPUGems/gpugems_ch05.html

Saya sangat merekomendasikan buku shader karena tidak hanya memberikan penjelasan interaktif yang hebat tentang kebisingan, tetapi juga konsep shader lainnya.

EDIT:

Mungkin dapat mengoptimalkan kode yang diterjemahkan dengan menggunakan beberapa fungsi akselerasi perangkat keras yang tersedia di GLSL. Akan memperbarui posting ini jika saya akhirnya melakukan ini.

Andrew Meservy
sumber
juga, saya cukup yakin bahwa Perlin / Simplex Noise masih pseudo random. Dari yang saya ingat, hal yang menarik adalah Anda dapat melapisi dan "memperbesar" suara pada level yang berbeda untuk membuatnya tampak sangat mulus. Jangan mengutip saya tentang itu, tetapi sesuatu untuk dipikirkan.
Andrew Meservy
@ Zibri Sayangnya, saya tidak terlalu akrab dengan perintah C atau .sh. Tapi sepertinya fungsinya hanyalah generator angka pseudo-acak dan bukan fungsi noise. Perlu diingat juga bahwa glsl pixel shaders berjalan langsung di GPU. Anda tidak akan memiliki akses ke perpustakaan atau kemampuan CPU tambahan yang mungkin tersedia dalam C.
Andrew Meservy
Book Of Shaders memiliki penjelasan yang bagus tentang bagaimana Simplex Noise adalah versi Perlin Noise yang lebih efisien karena memiringkan kisi dan perhitungan yang kurang diperlukan per poin. Layak dibaca.
Andrew Meservy
juga melihat bab-bab tentang gerakan brownis fraktal dan voronoise
Andrew Meservy
Andrew Meservy: tidak ada perpustakaan yang diperlukan ... fungsi noise saya sangat sederhana: 2 64 bit int adalah status x (n) dan x (n-1). Rumus sederhana dan cepat adalah x (n + 1) = ROTR ( x (n) + x (n-1), 8). jika Anda mengkloning git saya dan menjalankannya, Anda akan melihatnya beraksi.
Zibri