(60 lines)
1 #define TAU 6.2831853071795864769252867665590057683943387987502116419492 #define PHI 1.6180339887498948482045868343656381177203091798057628621353 #define LOG_PHI 0.4812118250596034474977589134243684231351843343856605196604 #define SQRT5 2.2360679774997896964091736687312762354406183596115257242705 #define MAX_RESOLUTION 646 extern int resolution;7 extern float sigma;8 extern float amplitudes[MAX_RESOLUTION];9 extern vec3 offsets[MAX_RESOLUTION];10 extern float z;11 extern vec2 range_min, range_max;13 float cdf(float x) {14 return .5 + .5*sign(x)*sqrt(1.-exp(-4./TAU * x*x));15 }17 // https://www.graphics.rwth-aachen.de/media/papers/jgt.pdf18 float noise3d(vec3 pos) {19 // Find the biggest fibonacci number F_n such that F_n < RESOLUTION20 int n = int(log((float(resolution)-1.)*SQRT5 + .5)/LOG_PHI);21 int dec = int(.5 + pow(PHI,n)/SQRT5); // F_n, using closed form Fibonacci22 int inc = int(.5 + dec/PHI); // F_(n-1)24 float noise = 0.;25 for (int i=0, j=0; i<resolution; ++i) {26 if (j >= dec) {27 j -= dec;28 } else {29 j += inc;30 if (j >= resolution)31 j -= dec;32 }33 // Convert golden ratio sequence into polar coordinate unit vector34 float phi = mod(float(i)*PHI,1.)*TAU;35 float theta = acos(mix(-1.,1.,mod(float(j)*PHI,1.)));36 // Make an orthonormal basis, where n1 is from polar phi/theta,37 // n2 is roated 90 degrees along phi, and n3 is the cross product of the two38 vec3 n1 = vec3(sin(phi)*cos(theta), sin(phi)*sin(theta), cos(phi));39 vec3 n2 = vec3(sin(phi+TAU/4.)*cos(theta), sin(phi+TAU/4.)*sin(theta), cos(phi+TAU/4.));40 vec3 n3 = cross(n1,n2);41 // Convert pos from x/y/z coordinates to n1/n2/n3 coordinates42 float u = dot(n1, pos);43 float v = dot(n2, pos);44 float w = dot(n3, pos);45 // Pull the amplitude from the shuffled array index ("j"), not "i",46 // otherwise neighboring unit vectors will have similar amplitudes!47 float a = amplitudes[j];48 //float a = pow(mod(float(i+1)*(PHI-1.), 1.), .3);49 // Noise is the average of cosine of distance along each axis, shifted by offsets and scaled by amplitude.50 noise += a*(cos(u/a + offsets[i].x) + cos(v/a + offsets[i].y) + cos(w/a + offsets[i].z))/3.;51 }52 return cdf(noise/sigma);53 }55 vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords)56 {57 vec3 coords = vec3(mix(range_min,range_max,texture_coords), z);58 float n = noise3d(coords);59 return vec4(n,n,n,1.);60 }