Domanda

Come la GPU fornitori di driver di solito non si preoccupano di implementare noiseX in GLSL, sto cercando un "grafica randomizzazione coltellino svizzero" set funzione di utilità, preferibilmente ottimizzata per l'utilizzo all'interno shader GPU . Io preferisco GLSL, ma il codice qualsiasi lingua farà per me, sto bene con la traduzione per conto mio per GLSL.

In particolare, mi aspetto:

a) pseudocasuale funzioni - N-dimensionale, la distribuzione uniforme su [-1,1] o su [0,1], calcolati dal seme M-dimensionale (idealmente essere qualsiasi valore, ma sto bene con avere il seme trattenuto per, diciamo, 0..1 per la distribuzione risultato uniforme). Qualcosa di simile:

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) 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 aspetto firme come:

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

Io non sono molto in teoria generazione di numeri casuali, quindi avevo il più ardentemente andare per un soluzione pre-made , ma mi piacerebbe anche apprezzare risposte come "di qui molto buono, efficiente rand 1D (), e lasciate che vi spieghi come fare un buon N-dimensionale rand () su di esso ... ".

È stato utile?

Soluzione

Per molto semplice roba pseudo-guardando, io 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);
}

Si può anche generare una texture di rumore utilizzando qualsiasi PRNG che ti piace, quindi caricare questo nel modo normale e assaggiare i valori nel vostro Shader; Posso scavare un esempio di codice in seguito, se vuoi.

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

Altri suggerimenti

  

implementazione di Gustavson utilizza un 1D consistenza

No non lo fa, non dal 2005. E 'solo che le persone insistono sul download della vecchia versione. La versione che si trova sul link fornito usi solo a 8-bit 2D texture.

La nuova versione di Ian McEwan di Ashima e il sottoscritto non usa una texture, ma funziona a circa la metà della velocità su piattaforme desktop tipici con un sacco di larghezza di banda texture. Su piattaforme mobili, la versione textureless potrebbe essere più veloce perché texturing è spesso un collo di bottiglia significativo.

Il nostro repository dei sorgenti mantenuto attivamente è:

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

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

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

Se avete domande specifiche, sentitevi liberi di scrivermi direttamente (il mio indirizzo e-mail può essere trovato nelle fonti classicnoise*.glsl.)

Mi viene in mente che si potrebbe usare una semplice funzione di hash intero e inserire il risultato in mantissa di un galleggiante. IIRC garanzie del GLSL spec a 32 bit numeri interi senza segno e rappresentazione galleggiante binary32 IEEE quindi dovrebbe essere perfettamente portatile.

Ho dato a questo una prova in questo momento. I risultati sono molto buoni: sembra esattamente come statico con ogni ingresso ho provato, senza schemi visibili a tutti. In contrasto con il peccato popolare / frammento fract è abbastanza pronunciato linee diagonali sul mio GPU dato gli stessi ingressi.

Uno svantaggio è che richiede GLSL v3.30. E anche se sembra abbastanza veloce, non ho empiricamente quantificato le sue prestazioni. AMD Shader Analyzer sostiene 13.33 pixel per clock per la versione vec2 su una HD5870. Contrasto con 16 pixel per clock per il peccato / frammento di fract. Quindi è certamente un po 'più lento.

Ecco la mia esecuzione. Ho lasciato in varie permutazioni di l'idea di rendere più facile per derivare le proprie funzioni da.

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

Cattura schermo:

Uscita di casuale (vec3) in static.frag

I ispezionato lo screenshot in un programma di editing di immagini. Ci sono 256 colori e il valore medio è 127, cioè la distribuzione è uniforme e copre l'intervallo previsto.

Oro Rumore

// Gold Noise ©2015 dcerisano@standard3d.com 
//  - based on the Golden Ratio, PI and Square Root of Two
//  - superior distribution
//  - fastest noise generator function
//  - works with all chipsets (including low precision)

float PHI = 1.61803398874989484820459 * 00000.1; // Golden Ratio   
float PI  = 3.14159265358979323846264 * 00000.1; // PI
float SQ2 = 1.41421356237309504880169 * 10000.0; // Square Root of Two

float gold_noise(in vec2 coordinate, in float seed){
    return fract(tan(distance(coordinate*(seed+PHI), vec2(PHI, PI)))*SQ2);
}

See oro rumore nel tuo browser in questo momento!

entrare descrizione dell'immagine qui

Questa funzione ha una migliore distribuzione casuale sopra la funzione attuale, in risposta @appas' a partire dal 9 settembre 2017:

entrare descrizione dell'immagine qui

La funzione @appas è incompleta, dato non c'è seme fornito (UV non è un seme - uguale per ogni frame), e non funziona con chipset bassa precisione. piste d'oro di rumore a bassa precisione di default (molto più veloce).

C'è anche una bella realizzazione descritto qui da McEwan e @StefanGustavson che assomiglia Perlin rumore, ma "non richiede alcuna configurazione, vale a dire non trame né matrici uniformi. Basta inserirlo al codice sorgente dello shader e lo chiamano dove vuoi".

Questo è molto utile, tanto più che in precedenza implementazione di Gustavson, che @dep legato a, utilizza una texture 1D, che è non supportato in GLSL ES (la lingua degli shader di WebGL).

Appena trovato questa versione del rumore 3D per GPU, alledgedly è quello 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

Una scala, la versione frastagliata di 1d Perlin, essenzialmente uno zigzag lfo 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);
}

Inoltre ho trovato disturbo Perlin 1-2-3-4d il proprietario shadertoy Inigo Quilez Perlin esercitazione sito web, e Voronoi e così via, che non abbia piena implementazioni veloci e codici per loro.

hash: Al giorno d'oggi webGL2.0 c'è così interi sono disponibili in (w) GLSL. -> per hash portatile di qualità (ad un costo simile a hash galleggiante brutti) ora possiamo usare "gravi" le tecniche di hashing. IQ implementato alcuni in https://www.shadertoy.com/view/XlXcW4 (e più )

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

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

È possibile trovare la spiegazione in Miglioramenti alla canonica one-liner GLSL rand () per OpenGL ES 2.0

Si prega di vedere di seguito un esempio come aggiungere rumore bianco per la texture rendering. La soluzione è quella di utilizzare due texture: rumore bianco originale e pura, come questo: wiki rumore bianco

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 parametro uNoiseFactor che viene aggiornato ogni resa dal principale dell'applicazione:

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

ho tradotto una delle implementazioni Java di Ken Perlin in GLSL e lo ha utilizzato in un paio di progetti ShaderToy.

Di seguito è riportato l'interpretazione GLSL 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);
}

ho tradotto dal Appendice B dal capitolo 2 del rumore Hardware di Ken Perlin a questa fonte:

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

Ecco una tonalità pubblico che ho fatto su di Shader giocattolo che utilizza la funzione di rumore Inviato:

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

Alcune altre fonti buone che ho trovato sul tema del rumore durante la mia ricerca includono:

https://thebookofshaders.com/11/

https://mzucker.github.io/html/perlin Rumore-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

mi raccomando il libro di shaders in quanto non solo fornisce una grande spiegazione interattiva del rumore, ma altri concetti di shader pure.

EDIT:

Potrebbe essere in grado di ottimizzare il codice tradotto utilizzando alcune delle funzioni con accelerazione hardware disponibili in GLSL. Sarà aggiornare questo post se finisco a fare questo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top