Funzioni casuali / di rumore per GLSL


179

Dato che i venditori di driver GPU di solito non si preoccupano di implementare noiseXin GLSL, sto cercando un set di funzioni di utilità di "random random graphics coltellino svizzero" , preferibilmente ottimizzato per l'uso all'interno di shader GPU. Preferisco GLSL, ma codificare qualsiasi lingua farà per me, sono d'accordo nel tradurlo da solo in GLSL.

In particolare, mi aspetterei:

a) Funzioni pseudo-casuali : distribuzione N-dimensionale uniforme su [-1,1] o sopra [0,1], calcolata dal seme M-dimensionale (idealmente essendo qualsiasi valore, ma sono d'accordo con il contenimento del seme a, diciamo, 0..1 per una distribuzione uniforme dei risultati). Qualcosa di simile a:

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) il rumore continuo come Perlin Noise - ancora una volta, N-dimensionale, + - distribuzione uniforme, con set vincolata di valori e, beh, guardando bene (alcune opzioni per configurare l'aspetto come i livelli Perlin potrebbe essere utile troppo). Mi aspetterei firme come:

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

Non sono molto interessato alla teoria della generazione di numeri casuali, quindi preferirei ardentemente una soluzione prefabbricata , ma apprezzerei anche risposte come "ecco un ottimo 1D rand (), e lasciami spiegare come creare un buon rand N-dimensionale () sopra di esso ... " .

Risposte:


263

Per cose molto semplici dall'aspetto pseudocasuale, uso questo oneliner che ho trovato su Internet da qualche parte:

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

Puoi anche generare una trama di rumore usando qualunque PRNG ti piaccia, quindi caricarlo normalmente e campionare i valori nel tuo shader; Se lo desideri, posso estrarre un campione di codice in seguito.

Inoltre, controlla questo file per le implementazioni GLSL di rumore Perlin e Simplex, di Stefan Gustavson.


14
Come si usa vec2 co? è la gamma? seme?
Ross,

12
Fai attenzione agli shader di frammenti in virgola mobile a bassa precisione con questo algoritmo (ad es. ARM Mali di S3): stackoverflow.com/questions/11293628/… . Il progetto github.com/ashima/webgl-noise non sembra avere problemi di lowp.
PT

4
FWIW, la funzione descritta qui è discussa in maggior dettaglio qui .
Loomchild,

3
Cordiali saluti: La distribuzione di quella funzione è orribile.
Tara,

3
Sono newb in GLSL, qualcuno può spiegare perché co.xyviene utilizzato, invece di co?
Kelin,

83

Mi viene in mente che potresti usare una semplice funzione hash intera e inserire il risultato nella mantissa di un float. IIRC la specifica GLSL garantisce numeri interi senza segno a 32 bit e rappresentazione float binaria32 IEEE, quindi dovrebbe essere perfettamente portatile.

Ho provato questo proprio ora. I risultati sono molto buoni: sembra esattamente statico con ogni input che ho provato, nessun modello visibile affatto. Al contrario, il popolare frammento di sin / fratt ha linee diagonali abbastanza pronunciate sulla mia GPU dato gli stessi input.

Uno svantaggio è che richiede GLSL v3.30. E anche se sembra abbastanza veloce, non ho quantificato empiricamente le sue prestazioni. L'analizzatore di shader di AMD rivendica 13.33 pixel per orologio per la versione vec2 su un HD5870. Contrasto con 16 pixel per orologio per lo snippet sin / fract. Quindi è sicuramente un po 'più lento.

Ecco la mia implementazione. L'ho lasciato in varie permutazioni dell'idea per rendere più facile derivare le proprie funzioni.

/*
    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 );
}

Immagine dello schermo:

Output di random (vec3) in static.frag

Ho ispezionato lo screenshot in un programma di modifica delle immagini. Ci sono 256 colori e il valore medio è 127, il che significa che la distribuzione è uniforme e copre l'intervallo previsto.


17
+1 per una buona idea e implementazione. Metterei in dubbio l'affermazione secondo cui poiché ci sono 256 colori e il valore medio è 127, la distribuzione deve essere uniforme (in senso stretto). Potrebbe essere uniforme, ma non credo che lo sappiamo ancora. Ad esempio, una distribuzione della curva a campana potrebbe avere la stessa media e numero di colori, ma non sarebbe uniforme.
LarsH

Votato in basso per il motivo fornito da @LarsH.
Autumnsault,

Bene, è abbastanza buono per la maggior parte delle applicazioni che non richiedono uniformità. :-)
itmuckel

5
Sembra molto uniforme, secondo la mia percezione dell'istogramma .... Direi che è abbastanza buono per la maggior parte delle applicazioni che hanno bisogno anche di uniformità. (Gli unici valori che sembrano essere generati meno degli altri sono 0 e 255)
leviathanbadger

Grazie. La mia probabilità è arrugginita. Dopo aver esaminato il set di istruzioni GCN, questo dovrebbe essere molto veloce su hardware più recente perché supportano direttamente le operazioni bitfield nei loro set di istruzioni. I test che ho eseguito sono stati eseguiti su hardware meno recente.
Spaziale

73

L'implementazione di Gustavson utilizza una trama 1D

No, non dal 2005. È solo che le persone insistono per scaricare la vecchia versione. La versione che si trova sul collegamento fornito utilizza solo trame 2D a 8 bit.

La nuova versione di Ian McEwan di Ashima e io non usa una trama, ma gira a circa la metà della velocità su piattaforme desktop tipiche con molta larghezza di banda delle trame. Su piattaforme mobili, la versione senza testo potrebbe essere più veloce perché il texturing è spesso un collo di bottiglia significativo.

Il nostro repository di risorse gestito attivamente è:

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

Una raccolta di entrambe le versioni del rumore sia textureless che texture-texture è qui (usando solo trame 2D):

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

Se hai domande specifiche, non esitare a inviarmi un'e-mail direttamente (il mio indirizzo e-mail si trova nelle classicnoise*.glslfonti).


4
Sì, l'implementazione a cui mi riferisco, il tuo codice su davidcornette.com a cui @dep si è collegato, utilizza una trama 1D: glBindTexture(GL_TEXTURE_1D, *texID);ecc. Non è chiaro cosa intendi con "il link che hai fornito", dal momento che citi dalla mia risposta ma quella risposta non era collegata alla tua implementazione. Aggiornerò la mia risposta per chiarire a cosa mi riferisco e rifletterò le nuove informazioni fornite. Caratterizzare le persone come "insistere" sul download della vecchia versione è una distorsione che non ti dà credito.
LarsH,

1
PS Potresti voler scrivere a David Cornette (ha le informazioni di contatto su davidcornette.com ) e chiedergli di cambiare il suo link su davidcornette.com/glsl/links.html per collegarlo al tuo repository di origine. Lo manderò anche per email.
LarsH,

1
PPS Puoi chiarire, quale versione utilizza solo trame 2D a 8 bit? Sembra che potrebbe essere una buona opzione per alcune piattaforme ...
LarsH,

31

Rumore d'oro

// Gold Noise ©2015 dcerisano@standard3d.com
// - 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);
}

Guarda subito Gold Noise nel tuo browser!

inserisci qui la descrizione dell'immagine

Questa funzione ha migliorato la distribuzione casuale rispetto alla funzione corrente nella risposta di @appas al 9 settembre 2017:

inserisci qui la descrizione dell'immagine

Anche la funzione @appas è incompleta, dato che non viene fornito alcun seed (uv non è un seed - lo stesso per ogni frame) e non funziona con chipset di bassa precisione. Il rumore dell'oro funziona a bassa precisione per impostazione predefinita (molto più veloce).


Grazie per aver pubblicato questo Considereresti di pubblicare una versione eseguibile, ad esempio su shadertoy.com, in modo che le persone possano provarlo nel browser?
LarsH

@snb Shadertoy.com è in manutenzione questo mese, abbi un po 'di pazienza. Inoltre ho documentato chiaramente il requisito per i valori seed irrazionali nel codice lì. Poiché il rumore dell'oro restituisce uno scalare, costruire vettori con esso è banale e anche documentato nel codice.
Domenico Cerisano,

7
Non penso che sia diverso dalle altre funzioni di rumore. qual è la tua prova che questo ha proprietà speciali. solo perché usi un mucchio di numeri irrazionali non lo rende speciale.
M.kazem Akhgary,

2
@Dominic: "Ha una distribuzione superiore a funzioni simili": questo deve essere dimostrato. tan () è davvero mal condizionato. sia tan () vicino a pi / 2 sia sqrt () vicino a zero hanno molto probabilità di produrre risultati diversi su diversi hardware poiché tutti i frattali (non lineari * grandi) sono basati su bit meno significativi. Anche i valori di input piccoli o alti avranno un impatto. Inoltre, la dinamica dei bit probabilmente varia molto anche in base alla posizione.
Fabrice NEYRET,

2
NB: oggigiorno i GLSL hanno numeri interi, quindi non c'è più motivo di non utilizzare generatori di hash "gravi" basati su int quando è richiesta una distribuzione (e dinamica) di qualità, con prestazioni simili. (eccetto per dispositivi di fascia molto bassa).
Fabrice NEYRET,

12

C'è anche una bella implementazione descritta qui da McEwan e @StefanGustavson che assomiglia al rumore di Perlin, ma "non richiede alcuna configurazione, cioè non trame né array uniformi. Basta aggiungerlo al codice sorgente dello shader e chiamarlo dove vuoi".

È molto utile, soprattutto dato che l'implementazione precedente di Gustavson, a cui @dep si collegava, utilizza una trama 1D, che non è supportata in GLSL ES (il linguaggio shader di WebGL).


1
Questa è la risposta migliore alla richiesta del tipo di rumore dell'OP! Ecco un link diretto github.com/ashima/webgl-noise . Esistono versioni 2d, 3d e 4d pronte come codice GLSL 120.
user362515,

3

Usa questo:

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);
}

Non usare questo:

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

Puoi trovare la spiegazione in Miglioramenti al canonico GLSL rand () per OpenGL ES 2.0


Ho sfogliato l'articolo ma non sono ancora sicuro, è 3.14 in modun'approssimazione di pi?
Kaan E.

2

Ho appena trovato questa versione del rumore 3D per GPU, di fatto è la più veloce disponibile:

#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

1
Il rumore dell'oro (sopra) è quindi ovviamente il più veloce, poiché ha molte meno operazioni e esegue solo un hash - questo chiama la sua hash fuction 8 volte, mentre esegue interpolazioni lineari nidificate (lerps). Anche questo ha una distribuzione inferiore soprattutto a bassa precisione.
Dominic Cerisano,

1
Oh buon punto, è un grafico del tipo di rumore perlin da shadertoh di Inigo Quilez. Bel codice, Dominic, lo verificherò l8r
com.prehensible il

@Fabrice Non sembra che tu capisca la domanda del PO, la mia risposta, il mio codice o il mio commento. Il rumore dell'oro è continuo dalla definizione del PO - accetta uv e un seme e lo dimostra fornendo uno shader. Tutto nel tuo commento è sbagliato. Continui a confondere le funzioni hash con le funzioni pseudo casuali del rumore. Non sono gli stessi. Le funzioni di rumore non hanno l'obbligo di generare identificatori univoci come le funzioni di hash (l'intero punto effettivo di hash).
Domenico Cerisano,

Per favore, per favore, Dominic, leggi di più e impara di più prima di rivendicare cose sui termini che pensi di aver capito mentre non è così. Non solo questi termini sono totalmente precisi e ben definiti nella letteratura, inoltre lavoro sul campo, ma anche l'OP dimostra di aver capito i termini dagli esempi che ha fornito. Suggerimento: "continuo" + "rumore" + "come Perlin". en.wikipedia.org/wiki/Perlin_noise
Fabrice NEYRET

Continuo è solo il caso dell'aggiunta di una clausola loop, molte funzioni di rumore eseguono il loop e si degradano dopo un certo modo a causa dell'arrotondamento dei bit soprattutto per la grafica. Ragazzi, è solo una comunicazione interrotta da te, usa il tuo tempo per ricerche importanti.
com.prehensible,

1

Una versione dritta e frastagliata di 1d Perlin, essenzialmente un lfo zigzag casuale.

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);
}

Ho anche trovato il rumore 1-2-3-4d perlin sul sito web del tutorial di shadertoy inigo quilez perlin tutorial, e voronoi e così via, ha implementazioni e codici rapidi per loro.


1

hash: al giorno d'oggi webGL2.0 è presente, quindi gli interi sono disponibili in (w) GLSL. -> per hash portatili di qualità (a costi simili a quelli dei brutti hash float) ora possiamo usare tecniche di hashing "serie". Il QI ne ha implementato alcune in https://www.shadertoy.com/view/XlXcW4 (e altro)

Per esempio:

  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));
}

0

Di seguito, vedi un esempio di come aggiungere rumore bianco alla trama renderizzata. La soluzione è utilizzare due trame: rumore bianco originale e puro, come questo: rumore bianco 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";

Il frammento condiviso contiene il parametro uNoiseFactor che viene aggiornato su ogni rendering dall'applicazione principale:

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

0

Ho tradotto una delle implementazioni Java di Ken Perlin in GLSL e l'ho usata in un paio di progetti su ShaderToy.

Di seguito è l'interpretazione GLSL che ho fatto:

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);
}

L'ho tradotto dall'appendice B del capitolo 2 dell'hardware del rumore di Ken Perlin a questa fonte:

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

Ecco un'ombra pubblica che ho fatto su Shader Toy che utilizza la funzione di rumore pubblicata:

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

Alcune altre buone fonti che ho trovato sull'argomento del rumore durante la mia ricerca includono:

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

Consiglio vivamente il libro degli shader in quanto non solo fornisce una grande spiegazione interattiva del rumore, ma anche altri concetti di shader.

MODIFICARE:

Potrebbe essere in grado di ottimizzare il codice tradotto utilizzando alcune delle funzioni accelerate dall'hardware disponibili in GLSL. Aggiornerò questo post se finisco per farlo.


inoltre, sono abbastanza sicuro che Perlin / Simplex Noise sia ancora pseudo casuale. Da quello che ricordo, la cosa interessante è che puoi sovrapporre e "ingrandire" il rumore a diversi livelli per renderlo molto fluido. Non citarmi su questo, ma qualcosa a cui pensare.
Andrew Meservy,

@Zibri Sfortunatamente, non ho familiarità con i comandi C o .sh. Ma sembra che la funzione sia semplicemente un generatore di numeri pseudo-casuale e non una funzione di rumore. Inoltre, tieni presente che i pixel shader glsl vengono eseguiti direttamente sulla GPU. Non avrai accesso a nessuna di quelle librerie o funzionalità CPU aggiuntive che potrebbero essere disponibili in C.
Andrew Meservy,

Il libro degli shader ha una grande spiegazione di come Simplex Noise sia una versione più efficiente di Perlin Noise a causa dell'inclinazione della griglia e dei calcoli meno necessari per punto. Sicuramente vale la pena leggere.
Andrew Meservy,

vedere anche i capitoli sul movimento browniano frattale e voronoise
Andrew Meservy,

Andrew Meservy: nessuna libreria necessaria ... la mia funzione noise è molto semplice: 2 ints a 64 bit sono lo stato x (n) e x (n-1). La formula semplice e veloce è x (n + 1) = ROTR ( x (n) + x (n-1), 8). se cloni il mio git ed eseguilo, lo vedrai in azione.
Zibri
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.