Frage

Als GPU-Treiber-Anbieter nicht die Mühe in der Regel noiseX in GLSL zu implementieren, ich bin für eine Suche „graphics Randomisierung Schweizer Taschenmesser“ Nutzenfunktion Satz, optimiert vorzugsweise auf den Einsatz innerhalb GPU-Shadern . Ich ziehe es GLSL, aber Code jede Sprache für mich tun, ich bin in Ordnung mit ihm auf meinem eigenen GLSL zu übersetzen.

Insbesondere würde ich erwarten:

a) Pseudo-Zufallsfunktionen - N-dimensional, gleichmäßige Verteilung über [-1,1] oder über [0,1], berechnet aus M-dimensionaler Samen (im Idealfall ein beliebiger Wert ist, aber ich bin OK mit den Samen, die verhinderten, sagt: 0..1 für einheitliches Ergebnis Verteilung). So etwas wie:

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) Kontinuierlicher Lärm wie Perlin Noise - wieder, N-dimensional, + - gleichmäßige Verteilung, mit eingeschränktem Satz von Werten und, na ja, sieht gut aus (einige Optionen, um das Aussehen wie Perlin Ebene zu konfigurieren nützlich sein zu können). Ich würde erwarten, Unterschriften wie:

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

Ich bin nicht sehr viel in Zufallszahl-Erzeugungs Theorie, so würde ich mit Spannung gehe für eine vorgefertigte Lösung , aber ich auch Antworten schätzen würde wie "Ist hier ein sehr gut, effizient 1D rand (), und lassen Sie mich erklären, wie man eine gute N-dimensionalen rand () oben drauf machen ... ".

War es hilfreich?

Lösung

Für sehr einfache Pseudo-Zufall aussehenden Sachen, ich benutze diese oneliner, dass ich im Internet irgendwo gefunden:

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

Sie können auch eine Rausch Textur erzeugen mit was auch immer PRNG Sie möchten, dann laden Sie diese in der normalen Art und Weise und die Werte in der Shader-Probe; Ich kann später ein Codebeispiel graben, wenn Sie möchten.

Auch Besuche diese Datei für GLSL Implementierungen von Perlin und Simplex Lärm von Stefan Gustavson.

Andere Tipps

  

Gustavson Implementierung verwendet eine 1D-Textur

Nein, es nicht tut, nicht seit 2005. Es ist nur so, dass die Menschen darauf bestehen, auf die alte Version herunterzuladen. Die Version, die auf dem Link ist versorgen Sie verwendet nur 8-Bit-2D-Texturen.

Die neue Version von Ian McEwan von Ashima und selbst verwendet nicht eine Textur, sondern läuft in etwa der Hälfte der Geschwindigkeit auf typische Desktop-Plattformen mit vielen Textur Bandbreite. Auf mobilen Plattformen könnte die textureless Version schneller sein, weil Texturierung oft ein erheblicher Engpass ist.

Unsere aktiv gepflegt Quellrepository ist:

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

Eine Sammlung sowohl der textureless und Textur betriebene Versionen von Rauschen ist hier (nur mit 2D-Texturen):

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

Wenn Sie spezielle Fragen haben, zögern Sie nicht mich direkt an eine E-Mail (meine E-Mail Adresse in den classicnoise*.glsl Quellen gefunden werden.)

Es kommt zu mir, dass Sie eine einfache Integer-Hash-Funktion verwenden könnte und das Ergebnis in eine Mantisse des Schwimmers ein. IIRC der GLSL-Spezifikation garantiert 32-Bit-Integer ohne Vorzeichen und IEEE binary32 float Darstellung so sollte es durchaus tragbar sein.

gab ich dies einen Versuch gerade jetzt. Die Ergebnisse sind sehr gut: es sieht genauso aus wie statisch mit jedem Eingang Ich habe versucht, ohne sichtbare Muster überhaupt. Im Gegensatz hat die beliebte sin / fract Schnipsel ziemlich diagonale Linien auf meiner GPU bei gleichen Eingaben ausgesprochen.

Ein Nachteil ist, dass es GLSL v3.30 erfordert. Und obwohl es schnell genug scheint, ich habe nicht empirisch seine Leistung quantifiziert. AMDs Shader Analyzer behauptet 13.33 Pixel pro Takt für die vec2 Version auf einem HD5870. Kontrast mit 16 Pixel pro Takt für die sin / fract Schnipsel. So ist es sicherlich ein wenig langsamer.

Hier ist meine Implementierung. Ich habe es in verschiedenen Permutationen der Idee, es einfacher zu machen Sie Ihre eigenen Funktionen abzuleiten.

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

Screenshot:

Ausgabe von random (vec3) in static.frag

besichtigte ich den Screenshot in einem Bildbearbeitungsprogramm. Es gibt 256 Farben und der durchschnittliche Wert beträgt 127, was bedeutet, die Verteilung ist einheitlich und deckt den erwarteten Bereich.

Gold Rauschen

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

Gold Lärm in Ihrem Browser jetzt!

Diese Funktion hat eine verbesserte statistische Verteilung über die aktuelle Funktion in @appas' Antwort ab 9. September 2017:

Die @appas Funktion ist auch unvollständig, da es keine Samen geliefert wird (uv ist kein Saatgut - das gleiche für jeden Frame) und funktioniert nicht mit geringer Präzision Chipsatz. Gold Lärm läuft mit geringer Genauigkeit standardmäßig (viel schneller).

Es gibt auch eine schöne Umsetzung beschrieben hier von McEwan und @StefanGustavson dass sieht aus wie Perlin Lärm, aber „keine Einrichtung erforderlich ist, dh nicht Texturen noch einheitlich Arrays. fügen Sie einfach es zu einem Shader-Quellcode und nennen Sie es, wo immer Sie wollen.“

Das ist sehr praktisch, vor allem da Gustavson frühere Implementierung, die auf verknüpfte @dep, verwendet eine 1D-Textur, die ist nicht in GLSL ES (die Shader-Sprache von WebGL) unterstützt.

gefunden Gerade diese Version von 3D-Rauschen für GPU, alledgedly ist es die schnellste zur Verfügung:

#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

Eine gerade, gezackte Version von 1d Perlin, im Wesentlichen eine zufällige lfo Zickzack.

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

Ich habe auch 1-2-3-4d Perlin Noise auf shadertoy Inhaber inigo quilez perlin Tutorial-Website und voronoi und so weiter, er hat die volle schnelle Implementierungen und Codes für sie gefunden.

hash: Heutzutage ist webGL2.0 es so ganze Zahlen in (w) GLSL zur Verfügung stehen. -> für Qualität portable Hash (bei ähnlich Kosten als hässlich Schwimmer Hashes) können wir jetzt „ernst“ Hashing-Techniken verwenden. IQ implementiert einige in https://www.shadertoy.com/view/XlXcW4 (und mehr )

Z. B:.

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

Verwenden Sie dieses:

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

Diese Mitteilung nicht mehr verwendet werden:

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

Sie können die Erklärung in Verbesserungen der kanonischen Einzeiler GLSL rand () für OpenGL ES 2.0

Bitte beachten Sie unten ein Beispiel, wie weißes Rauschen auf die gerenderte Textur hinzufügen. Die Lösung ist zwei Texturen zu verwenden: Original und reines weißes Rauschen, wie diese: wiki weißes Rauschen

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";

Das Fragment geteilt enthält Parameter uNoiseFactor, die auf jeder Wiedergabe durch Hauptanwendung aktualisiert:

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

Ich habe eine von Ken Perlin Java-Implementierungen in GLSL übersetzt und verwendet es in ein paar Projekte auf ShaderToy.

Im Folgenden finden Sie die GLSL Interpretation ich getan habe:

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

ich es von Anhang B von Kapiteln übersetzt 2 von Ken Perlin Noise Hardware an dieser Quelle:

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

Hier ist ein öffentlicher Schatten ich auf Shader-Spielzeug habe, den die gesendeten Rauschfunktion verwendet:

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

Einige andere gute Quellen, die ich zum Thema Lärm bei meinen Recherchen gefunden sind:

https://thebookofshaders.com/11/

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

ich das Buch von Shadern sehr empfehlen, da es nicht nur eine große interaktive Erklärung von Lärm bietet, aber auch andere Shader-Konzepte als auch.

EDIT:

könnten in der Lage sein, den übersetzten Code zu optimieren, indem einige der Hardware-beschleunigte Funktionen in GLSL verwenden. Wird diesen Beitrag aktualisieren, wenn ich das am Ende tut.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top