|
@@ -0,0 +1,607 @@
|
|
|
+import { code, fn } from '../../../Nodes.js';
|
|
|
+
|
|
|
+// Original shader code from:
|
|
|
+// https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/stdlib/genglsl/lib/mx_noise.glsl
|
|
|
+
|
|
|
+export const mx_noise = code( `float mx_select(bool b, float t, float f)
|
|
|
+{
|
|
|
+ return b ? t : f;
|
|
|
+}
|
|
|
+
|
|
|
+float mx_negate_if(float val, bool b)
|
|
|
+{
|
|
|
+ return b ? -val : val;
|
|
|
+}
|
|
|
+
|
|
|
+int mx_floor(float x)
|
|
|
+{
|
|
|
+ return int(floor(x));
|
|
|
+}
|
|
|
+
|
|
|
+// return mx_floor as well as the fractional remainder
|
|
|
+float mx_floorfrac(float x, out int i)
|
|
|
+{
|
|
|
+ i = mx_floor(x);
|
|
|
+ return x - float(i);
|
|
|
+}
|
|
|
+
|
|
|
+float mx_bilerp(float v0, float v1, float v2, float v3, float s, float t)
|
|
|
+{
|
|
|
+ float s1 = 1.0 - s;
|
|
|
+ return (1.0 - t) * (v0*s1 + v1*s) + t * (v2*s1 + v3*s);
|
|
|
+}
|
|
|
+vec3 mx_bilerp(vec3 v0, vec3 v1, vec3 v2, vec3 v3, float s, float t)
|
|
|
+{
|
|
|
+ float s1 = 1.0 - s;
|
|
|
+ return (1.0 - t) * (v0*s1 + v1*s) + t * (v2*s1 + v3*s);
|
|
|
+}
|
|
|
+float mx_trilerp(float v0, float v1, float v2, float v3, float v4, float v5, float v6, float v7, float s, float t, float r)
|
|
|
+{
|
|
|
+ float s1 = 1.0 - s;
|
|
|
+ float t1 = 1.0 - t;
|
|
|
+ float r1 = 1.0 - r;
|
|
|
+ return (r1*(t1*(v0*s1 + v1*s) + t*(v2*s1 + v3*s)) +
|
|
|
+ r*(t1*(v4*s1 + v5*s) + t*(v6*s1 + v7*s)));
|
|
|
+}
|
|
|
+vec3 mx_trilerp(vec3 v0, vec3 v1, vec3 v2, vec3 v3, vec3 v4, vec3 v5, vec3 v6, vec3 v7, float s, float t, float r)
|
|
|
+{
|
|
|
+ float s1 = 1.0 - s;
|
|
|
+ float t1 = 1.0 - t;
|
|
|
+ float r1 = 1.0 - r;
|
|
|
+ return (r1*(t1*(v0*s1 + v1*s) + t*(v2*s1 + v3*s)) +
|
|
|
+ r*(t1*(v4*s1 + v5*s) + t*(v6*s1 + v7*s)));
|
|
|
+}
|
|
|
+
|
|
|
+// 2 and 3 dimensional gradient functions - perform a dot product against a
|
|
|
+// randomly chosen vector. Note that the gradient vector is not normalized, but
|
|
|
+// this only affects the overal "scale" of the result, so we simply account for
|
|
|
+// the scale by multiplying in the corresponding "perlin" function.
|
|
|
+float mx_gradient_float(uint hash, float x, float y)
|
|
|
+{
|
|
|
+ // 8 possible directions (+-1,+-2) and (+-2,+-1)
|
|
|
+ uint h = hash & 7u;
|
|
|
+ float u = mx_select(h<4u, x, y);
|
|
|
+ float v = 2.0 * mx_select(h<4u, y, x);
|
|
|
+ // compute the dot product with (x,y).
|
|
|
+ return mx_negate_if(u, bool(h&1u)) + mx_negate_if(v, bool(h&2u));
|
|
|
+}
|
|
|
+float mx_gradient_float(uint hash, float x, float y, float z)
|
|
|
+{
|
|
|
+ // use vectors pointing to the edges of the cube
|
|
|
+ uint h = hash & 15u;
|
|
|
+ float u = mx_select(h<8u, x, y);
|
|
|
+ float v = mx_select(h<4u, y, mx_select((h==12u)||(h==14u), x, z));
|
|
|
+ return mx_negate_if(u, bool(h&1u)) + mx_negate_if(v, bool(h&2u));
|
|
|
+}
|
|
|
+vec3 mx_gradient_vec3(uvec3 hash, float x, float y)
|
|
|
+{
|
|
|
+ return vec3(mx_gradient_float(hash.x, x, y), mx_gradient_float(hash.y, x, y), mx_gradient_float(hash.z, x, y));
|
|
|
+}
|
|
|
+vec3 mx_gradient_vec3(uvec3 hash, float x, float y, float z)
|
|
|
+{
|
|
|
+ return vec3(mx_gradient_float(hash.x, x, y, z), mx_gradient_float(hash.y, x, y, z), mx_gradient_float(hash.z, x, y, z));
|
|
|
+}
|
|
|
+// Scaling factors to normalize the result of gradients above.
|
|
|
+// These factors were experimentally calculated to be:
|
|
|
+// 2D: 0.6616
|
|
|
+// 3D: 0.9820
|
|
|
+float mx_gradient_scale2d(float v) { return 0.6616 * v; }
|
|
|
+float mx_gradient_scale3d(float v) { return 0.9820 * v; }
|
|
|
+vec3 mx_gradient_scale2d(vec3 v) { return 0.6616 * v; }
|
|
|
+vec3 mx_gradient_scale3d(vec3 v) { return 0.9820 * v; }
|
|
|
+
|
|
|
+/// Bitwise circular rotation left by k bits (for 32 bit unsigned integers)
|
|
|
+uint mx_rotl32(uint x, int k)
|
|
|
+{
|
|
|
+ return (x<<k) | (x>>(32-k));
|
|
|
+}
|
|
|
+
|
|
|
+void mx_bjmix(inout uint a, inout uint b, inout uint c)
|
|
|
+{
|
|
|
+ a -= c; a ^= mx_rotl32(c, 4); c += b;
|
|
|
+ b -= a; b ^= mx_rotl32(a, 6); a += c;
|
|
|
+ c -= b; c ^= mx_rotl32(b, 8); b += a;
|
|
|
+ a -= c; a ^= mx_rotl32(c,16); c += b;
|
|
|
+ b -= a; b ^= mx_rotl32(a,19); a += c;
|
|
|
+ c -= b; c ^= mx_rotl32(b, 4); b += a;
|
|
|
+}
|
|
|
+
|
|
|
+// Mix up and combine the bits of a, b, and c (doesn't change them, but
|
|
|
+// returns a hash of those three original values).
|
|
|
+uint mx_bjfinal(uint a, uint b, uint c)
|
|
|
+{
|
|
|
+ c ^= b; c -= mx_rotl32(b,14);
|
|
|
+ a ^= c; a -= mx_rotl32(c,11);
|
|
|
+ b ^= a; b -= mx_rotl32(a,25);
|
|
|
+ c ^= b; c -= mx_rotl32(b,16);
|
|
|
+ a ^= c; a -= mx_rotl32(c,4);
|
|
|
+ b ^= a; b -= mx_rotl32(a,14);
|
|
|
+ c ^= b; c -= mx_rotl32(b,24);
|
|
|
+ return c;
|
|
|
+}
|
|
|
+
|
|
|
+// Convert a 32 bit integer into a floating point number in [0,1]
|
|
|
+float mx_bits_to_01(uint bits)
|
|
|
+{
|
|
|
+ return float(bits) / float(uint(0xffffffff));
|
|
|
+}
|
|
|
+
|
|
|
+float mx_fade(float t)
|
|
|
+{
|
|
|
+ return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
|
|
|
+}
|
|
|
+
|
|
|
+uint mx_hash_int(int x)
|
|
|
+{
|
|
|
+ uint len = 1u;
|
|
|
+ uint seed = uint(0xdeadbeef) + (len << 2u) + 13u;
|
|
|
+ return mx_bjfinal(seed+uint(x), seed, seed);
|
|
|
+}
|
|
|
+
|
|
|
+uint mx_hash_int(int x, int y)
|
|
|
+{
|
|
|
+ uint len = 2u;
|
|
|
+ uint a, b, c;
|
|
|
+ a = b = c = uint(0xdeadbeef) + (len << 2u) + 13u;
|
|
|
+ a += uint(x);
|
|
|
+ b += uint(y);
|
|
|
+ return mx_bjfinal(a, b, c);
|
|
|
+}
|
|
|
+
|
|
|
+uint mx_hash_int(int x, int y, int z)
|
|
|
+{
|
|
|
+ uint len = 3u;
|
|
|
+ uint a, b, c;
|
|
|
+ a = b = c = uint(0xdeadbeef) + (len << 2u) + 13u;
|
|
|
+ a += uint(x);
|
|
|
+ b += uint(y);
|
|
|
+ c += uint(z);
|
|
|
+ return mx_bjfinal(a, b, c);
|
|
|
+}
|
|
|
+
|
|
|
+uint mx_hash_int(int x, int y, int z, int xx)
|
|
|
+{
|
|
|
+ uint len = 4u;
|
|
|
+ uint a, b, c;
|
|
|
+ a = b = c = uint(0xdeadbeef) + (len << 2u) + 13u;
|
|
|
+ a += uint(x);
|
|
|
+ b += uint(y);
|
|
|
+ c += uint(z);
|
|
|
+ mx_bjmix(a, b, c);
|
|
|
+ a += uint(xx);
|
|
|
+ return mx_bjfinal(a, b, c);
|
|
|
+}
|
|
|
+
|
|
|
+uint mx_hash_int(int x, int y, int z, int xx, int yy)
|
|
|
+{
|
|
|
+ uint len = 5u;
|
|
|
+ uint a, b, c;
|
|
|
+ a = b = c = uint(0xdeadbeef) + (len << 2u) + 13u;
|
|
|
+ a += uint(x);
|
|
|
+ b += uint(y);
|
|
|
+ c += uint(z);
|
|
|
+ mx_bjmix(a, b, c);
|
|
|
+ a += uint(xx);
|
|
|
+ b += uint(yy);
|
|
|
+ return mx_bjfinal(a, b, c);
|
|
|
+}
|
|
|
+
|
|
|
+uvec3 mx_hash_vec3(int x, int y)
|
|
|
+{
|
|
|
+ uint h = mx_hash_int(x, y);
|
|
|
+ // we only need the low-order bits to be random, so split out
|
|
|
+ // the 32 bit result into 3 parts for each channel
|
|
|
+ uvec3 result;
|
|
|
+ result.x = (h ) & 0xFFu;
|
|
|
+ result.y = (h >> 8 ) & 0xFFu;
|
|
|
+ result.z = (h >> 16) & 0xFFu;
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+uvec3 mx_hash_vec3(int x, int y, int z)
|
|
|
+{
|
|
|
+ uint h = mx_hash_int(x, y, z);
|
|
|
+ // we only need the low-order bits to be random, so split out
|
|
|
+ // the 32 bit result into 3 parts for each channel
|
|
|
+ uvec3 result;
|
|
|
+ result.x = (h ) & 0xFFu;
|
|
|
+ result.y = (h >> 8 ) & 0xFFu;
|
|
|
+ result.z = (h >> 16) & 0xFFu;
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+float mx_perlin_noise_float(vec2 p)
|
|
|
+{
|
|
|
+ int X, Y;
|
|
|
+ float fx = mx_floorfrac(p.x, X);
|
|
|
+ float fy = mx_floorfrac(p.y, Y);
|
|
|
+ float u = mx_fade(fx);
|
|
|
+ float v = mx_fade(fy);
|
|
|
+ float result = mx_bilerp(
|
|
|
+ mx_gradient_float(mx_hash_int(X , Y ), fx , fy ),
|
|
|
+ mx_gradient_float(mx_hash_int(X+1, Y ), fx-1.0, fy ),
|
|
|
+ mx_gradient_float(mx_hash_int(X , Y+1), fx , fy-1.0),
|
|
|
+ mx_gradient_float(mx_hash_int(X+1, Y+1), fx-1.0, fy-1.0),
|
|
|
+ u, v);
|
|
|
+ return mx_gradient_scale2d(result);
|
|
|
+}
|
|
|
+
|
|
|
+float mx_perlin_noise_float(vec3 p)
|
|
|
+{
|
|
|
+ int X, Y, Z;
|
|
|
+ float fx = mx_floorfrac(p.x, X);
|
|
|
+ float fy = mx_floorfrac(p.y, Y);
|
|
|
+ float fz = mx_floorfrac(p.z, Z);
|
|
|
+ float u = mx_fade(fx);
|
|
|
+ float v = mx_fade(fy);
|
|
|
+ float w = mx_fade(fz);
|
|
|
+ float result = mx_trilerp(
|
|
|
+ mx_gradient_float(mx_hash_int(X , Y , Z ), fx , fy , fz ),
|
|
|
+ mx_gradient_float(mx_hash_int(X+1, Y , Z ), fx-1.0, fy , fz ),
|
|
|
+ mx_gradient_float(mx_hash_int(X , Y+1, Z ), fx , fy-1.0, fz ),
|
|
|
+ mx_gradient_float(mx_hash_int(X+1, Y+1, Z ), fx-1.0, fy-1.0, fz ),
|
|
|
+ mx_gradient_float(mx_hash_int(X , Y , Z+1), fx , fy , fz-1.0),
|
|
|
+ mx_gradient_float(mx_hash_int(X+1, Y , Z+1), fx-1.0, fy , fz-1.0),
|
|
|
+ mx_gradient_float(mx_hash_int(X , Y+1, Z+1), fx , fy-1.0, fz-1.0),
|
|
|
+ mx_gradient_float(mx_hash_int(X+1, Y+1, Z+1), fx-1.0, fy-1.0, fz-1.0),
|
|
|
+ u, v, w);
|
|
|
+ return mx_gradient_scale3d(result);
|
|
|
+}
|
|
|
+
|
|
|
+vec3 mx_perlin_noise_vec3(vec2 p)
|
|
|
+{
|
|
|
+ int X, Y;
|
|
|
+ float fx = mx_floorfrac(p.x, X);
|
|
|
+ float fy = mx_floorfrac(p.y, Y);
|
|
|
+ float u = mx_fade(fx);
|
|
|
+ float v = mx_fade(fy);
|
|
|
+ vec3 result = mx_bilerp(
|
|
|
+ mx_gradient_vec3(mx_hash_vec3(X , Y ), fx , fy ),
|
|
|
+ mx_gradient_vec3(mx_hash_vec3(X+1, Y ), fx-1.0, fy ),
|
|
|
+ mx_gradient_vec3(mx_hash_vec3(X , Y+1), fx , fy-1.0),
|
|
|
+ mx_gradient_vec3(mx_hash_vec3(X+1, Y+1), fx-1.0, fy-1.0),
|
|
|
+ u, v);
|
|
|
+ return mx_gradient_scale2d(result);
|
|
|
+}
|
|
|
+
|
|
|
+vec3 mx_perlin_noise_vec3(vec3 p)
|
|
|
+{
|
|
|
+ int X, Y, Z;
|
|
|
+ float fx = mx_floorfrac(p.x, X);
|
|
|
+ float fy = mx_floorfrac(p.y, Y);
|
|
|
+ float fz = mx_floorfrac(p.z, Z);
|
|
|
+ float u = mx_fade(fx);
|
|
|
+ float v = mx_fade(fy);
|
|
|
+ float w = mx_fade(fz);
|
|
|
+ vec3 result = mx_trilerp(
|
|
|
+ mx_gradient_vec3(mx_hash_vec3(X , Y , Z ), fx , fy , fz ),
|
|
|
+ mx_gradient_vec3(mx_hash_vec3(X+1, Y , Z ), fx-1.0, fy , fz ),
|
|
|
+ mx_gradient_vec3(mx_hash_vec3(X , Y+1, Z ), fx , fy-1.0, fz ),
|
|
|
+ mx_gradient_vec3(mx_hash_vec3(X+1, Y+1, Z ), fx-1.0, fy-1.0, fz ),
|
|
|
+ mx_gradient_vec3(mx_hash_vec3(X , Y , Z+1), fx , fy , fz-1.0),
|
|
|
+ mx_gradient_vec3(mx_hash_vec3(X+1, Y , Z+1), fx-1.0, fy , fz-1.0),
|
|
|
+ mx_gradient_vec3(mx_hash_vec3(X , Y+1, Z+1), fx , fy-1.0, fz-1.0),
|
|
|
+ mx_gradient_vec3(mx_hash_vec3(X+1, Y+1, Z+1), fx-1.0, fy-1.0, fz-1.0),
|
|
|
+ u, v, w);
|
|
|
+ return mx_gradient_scale3d(result);
|
|
|
+}
|
|
|
+
|
|
|
+float mx_cell_noise_float(float p)
|
|
|
+{
|
|
|
+ int ix = mx_floor(p);
|
|
|
+ return mx_bits_to_01(mx_hash_int(ix));
|
|
|
+}
|
|
|
+
|
|
|
+float mx_cell_noise_float(vec2 p)
|
|
|
+{
|
|
|
+ int ix = mx_floor(p.x);
|
|
|
+ int iy = mx_floor(p.y);
|
|
|
+ return mx_bits_to_01(mx_hash_int(ix, iy));
|
|
|
+}
|
|
|
+
|
|
|
+float mx_cell_noise_float(vec3 p)
|
|
|
+{
|
|
|
+ int ix = mx_floor(p.x);
|
|
|
+ int iy = mx_floor(p.y);
|
|
|
+ int iz = mx_floor(p.z);
|
|
|
+ return mx_bits_to_01(mx_hash_int(ix, iy, iz));
|
|
|
+}
|
|
|
+
|
|
|
+float mx_cell_noise_float(vec4 p)
|
|
|
+{
|
|
|
+ int ix = mx_floor(p.x);
|
|
|
+ int iy = mx_floor(p.y);
|
|
|
+ int iz = mx_floor(p.z);
|
|
|
+ int iw = mx_floor(p.w);
|
|
|
+ return mx_bits_to_01(mx_hash_int(ix, iy, iz, iw));
|
|
|
+}
|
|
|
+
|
|
|
+vec3 mx_cell_noise_vec3(float p)
|
|
|
+{
|
|
|
+ int ix = mx_floor(p);
|
|
|
+ return vec3(
|
|
|
+ mx_bits_to_01(mx_hash_int(ix, 0)),
|
|
|
+ mx_bits_to_01(mx_hash_int(ix, 1)),
|
|
|
+ mx_bits_to_01(mx_hash_int(ix, 2))
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+vec3 mx_cell_noise_vec3(vec2 p)
|
|
|
+{
|
|
|
+ int ix = mx_floor(p.x);
|
|
|
+ int iy = mx_floor(p.y);
|
|
|
+ return vec3(
|
|
|
+ mx_bits_to_01(mx_hash_int(ix, iy, 0)),
|
|
|
+ mx_bits_to_01(mx_hash_int(ix, iy, 1)),
|
|
|
+ mx_bits_to_01(mx_hash_int(ix, iy, 2))
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+vec3 mx_cell_noise_vec3(vec3 p)
|
|
|
+{
|
|
|
+ int ix = mx_floor(p.x);
|
|
|
+ int iy = mx_floor(p.y);
|
|
|
+ int iz = mx_floor(p.z);
|
|
|
+ return vec3(
|
|
|
+ mx_bits_to_01(mx_hash_int(ix, iy, iz, 0)),
|
|
|
+ mx_bits_to_01(mx_hash_int(ix, iy, iz, 1)),
|
|
|
+ mx_bits_to_01(mx_hash_int(ix, iy, iz, 2))
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+vec3 mx_cell_noise_vec3(vec4 p)
|
|
|
+{
|
|
|
+ int ix = mx_floor(p.x);
|
|
|
+ int iy = mx_floor(p.y);
|
|
|
+ int iz = mx_floor(p.z);
|
|
|
+ int iw = mx_floor(p.w);
|
|
|
+ return vec3(
|
|
|
+ mx_bits_to_01(mx_hash_int(ix, iy, iz, iw, 0)),
|
|
|
+ mx_bits_to_01(mx_hash_int(ix, iy, iz, iw, 1)),
|
|
|
+ mx_bits_to_01(mx_hash_int(ix, iy, iz, iw, 2))
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+float mx_fractal_noise_float(vec3 p, int octaves, float lacunarity, float diminish)
|
|
|
+{
|
|
|
+ float result = 0.0;
|
|
|
+ float amplitude = 1.0;
|
|
|
+ for (int i = 0; i < octaves; ++i)
|
|
|
+ {
|
|
|
+ result += amplitude * mx_perlin_noise_float(p);
|
|
|
+ amplitude *= diminish;
|
|
|
+ p *= lacunarity;
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+vec3 mx_fractal_noise_vec3(vec3 p, int octaves, float lacunarity, float diminish)
|
|
|
+{
|
|
|
+ vec3 result = vec3(0.0);
|
|
|
+ float amplitude = 1.0;
|
|
|
+ for (int i = 0; i < octaves; ++i)
|
|
|
+ {
|
|
|
+ result += amplitude * mx_perlin_noise_vec3(p);
|
|
|
+ amplitude *= diminish;
|
|
|
+ p *= lacunarity;
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+vec2 mx_fractal_noise_vec2(vec3 p, int octaves, float lacunarity, float diminish)
|
|
|
+{
|
|
|
+ return vec2(mx_fractal_noise_float(p, octaves, lacunarity, diminish),
|
|
|
+ mx_fractal_noise_float(p+vec3(19, 193, 17), octaves, lacunarity, diminish));
|
|
|
+}
|
|
|
+
|
|
|
+vec4 mx_fractal_noise_vec4(vec3 p, int octaves, float lacunarity, float diminish)
|
|
|
+{
|
|
|
+ vec3 c = mx_fractal_noise_vec3(p, octaves, lacunarity, diminish);
|
|
|
+ float f = mx_fractal_noise_float(p+vec3(19, 193, 17), octaves, lacunarity, diminish);
|
|
|
+ return vec4(c, f);
|
|
|
+}
|
|
|
+
|
|
|
+float mx_worley_distance(vec2 p, int x, int y, int xoff, int yoff, float jitter, int metric)
|
|
|
+{
|
|
|
+ vec3 tmp = mx_cell_noise_vec3(vec2(x+xoff, y+yoff));
|
|
|
+ vec2 off = vec2(tmp.x, tmp.y);
|
|
|
+
|
|
|
+ off -= 0.5f;
|
|
|
+ off *= jitter;
|
|
|
+ off += 0.5f;
|
|
|
+
|
|
|
+ vec2 cellpos = vec2(float(x), float(y)) + off;
|
|
|
+ vec2 diff = cellpos - p;
|
|
|
+ if (metric == 2)
|
|
|
+ return abs(diff.x) + abs(diff.y); // Manhattan distance
|
|
|
+ if (metric == 3)
|
|
|
+ return max(abs(diff.x), abs(diff.y)); // Chebyshev distance
|
|
|
+ // Either Euclidian or Distance^2
|
|
|
+ return dot(diff, diff);
|
|
|
+}
|
|
|
+
|
|
|
+float mx_worley_distance(vec3 p, int x, int y, int z, int xoff, int yoff, int zoff, float jitter, int metric)
|
|
|
+{
|
|
|
+ vec3 off = mx_cell_noise_vec3(vec3(x+xoff, y+yoff, z+zoff));
|
|
|
+
|
|
|
+ off -= 0.5f;
|
|
|
+ off *= jitter;
|
|
|
+ off += 0.5f;
|
|
|
+
|
|
|
+ vec3 cellpos = vec3(float(x), float(y), float(z)) + off;
|
|
|
+ vec3 diff = cellpos - p;
|
|
|
+ if (metric == 2)
|
|
|
+ return abs(diff.x) + abs(diff.y) + abs(diff.z); // Manhattan distance
|
|
|
+ if (metric == 3)
|
|
|
+ return max(max(abs(diff.x), abs(diff.y)), abs(diff.z)); // Chebyshev distance
|
|
|
+ // Either Euclidian or Distance^2
|
|
|
+ return dot(diff, diff);
|
|
|
+}
|
|
|
+
|
|
|
+float mx_worley_noise_float(vec2 p, float jitter, int metric)
|
|
|
+{
|
|
|
+ int X, Y;
|
|
|
+ vec2 localpos = vec2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y));
|
|
|
+ float sqdist = 1e6f; // Some big number for jitter > 1 (not all GPUs may be IEEE)
|
|
|
+ for (int x = -1; x <= 1; ++x)
|
|
|
+ {
|
|
|
+ for (int y = -1; y <= 1; ++y)
|
|
|
+ {
|
|
|
+ float dist = mx_worley_distance(localpos, x, y, X, Y, jitter, metric);
|
|
|
+ sqdist = min(sqdist, dist);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (metric == 0)
|
|
|
+ sqdist = sqrt(sqdist);
|
|
|
+ return sqdist;
|
|
|
+}
|
|
|
+
|
|
|
+vec2 mx_worley_noise_vec2(vec2 p, float jitter, int metric)
|
|
|
+{
|
|
|
+ int X, Y;
|
|
|
+ vec2 localpos = vec2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y));
|
|
|
+ vec2 sqdist = vec2(1e6f, 1e6f);
|
|
|
+ for (int x = -1; x <= 1; ++x)
|
|
|
+ {
|
|
|
+ for (int y = -1; y <= 1; ++y)
|
|
|
+ {
|
|
|
+ float dist = mx_worley_distance(localpos, x, y, X, Y, jitter, metric);
|
|
|
+ if (dist < sqdist.x)
|
|
|
+ {
|
|
|
+ sqdist.y = sqdist.x;
|
|
|
+ sqdist.x = dist;
|
|
|
+ }
|
|
|
+ else if (dist < sqdist.y)
|
|
|
+ {
|
|
|
+ sqdist.y = dist;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (metric == 0)
|
|
|
+ sqdist = sqrt(sqdist);
|
|
|
+ return sqdist;
|
|
|
+}
|
|
|
+
|
|
|
+vec3 mx_worley_noise_vec3(vec2 p, float jitter, int metric)
|
|
|
+{
|
|
|
+ int X, Y;
|
|
|
+ vec2 localpos = vec2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y));
|
|
|
+ vec3 sqdist = vec3(1e6f, 1e6f, 1e6f);
|
|
|
+ for (int x = -1; x <= 1; ++x)
|
|
|
+ {
|
|
|
+ for (int y = -1; y <= 1; ++y)
|
|
|
+ {
|
|
|
+ float dist = mx_worley_distance(localpos, x, y, X, Y, jitter, metric);
|
|
|
+ if (dist < sqdist.x)
|
|
|
+ {
|
|
|
+ sqdist.z = sqdist.y;
|
|
|
+ sqdist.y = sqdist.x;
|
|
|
+ sqdist.x = dist;
|
|
|
+ }
|
|
|
+ else if (dist < sqdist.y)
|
|
|
+ {
|
|
|
+ sqdist.z = sqdist.y;
|
|
|
+ sqdist.y = dist;
|
|
|
+ }
|
|
|
+ else if (dist < sqdist.z)
|
|
|
+ {
|
|
|
+ sqdist.z = dist;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (metric == 0)
|
|
|
+ sqdist = sqrt(sqdist);
|
|
|
+ return sqdist;
|
|
|
+}
|
|
|
+
|
|
|
+float mx_worley_noise_float(vec3 p, float jitter, int metric)
|
|
|
+{
|
|
|
+ int X, Y, Z;
|
|
|
+ vec3 localpos = vec3(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z));
|
|
|
+ float sqdist = 1e6f;
|
|
|
+ for (int x = -1; x <= 1; ++x)
|
|
|
+ {
|
|
|
+ for (int y = -1; y <= 1; ++y)
|
|
|
+ {
|
|
|
+ for (int z = -1; z <= 1; ++z)
|
|
|
+ {
|
|
|
+ float dist = mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric);
|
|
|
+ sqdist = min(sqdist, dist);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (metric == 0)
|
|
|
+ sqdist = sqrt(sqdist);
|
|
|
+ return sqdist;
|
|
|
+}
|
|
|
+
|
|
|
+vec2 mx_worley_noise_vec2(vec3 p, float jitter, int metric)
|
|
|
+{
|
|
|
+ int X, Y, Z;
|
|
|
+ vec3 localpos = vec3(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z));
|
|
|
+ vec2 sqdist = vec2(1e6f, 1e6f);
|
|
|
+ for (int x = -1; x <= 1; ++x)
|
|
|
+ {
|
|
|
+ for (int y = -1; y <= 1; ++y)
|
|
|
+ {
|
|
|
+ for (int z = -1; z <= 1; ++z)
|
|
|
+ {
|
|
|
+ float dist = mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric);
|
|
|
+ if (dist < sqdist.x)
|
|
|
+ {
|
|
|
+ sqdist.y = sqdist.x;
|
|
|
+ sqdist.x = dist;
|
|
|
+ }
|
|
|
+ else if (dist < sqdist.y)
|
|
|
+ {
|
|
|
+ sqdist.y = dist;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (metric == 0)
|
|
|
+ sqdist = sqrt(sqdist);
|
|
|
+ return sqdist;
|
|
|
+}
|
|
|
+
|
|
|
+vec3 mx_worley_noise_vec3(vec3 p, float jitter, int metric)
|
|
|
+{
|
|
|
+ int X, Y, Z;
|
|
|
+ vec3 localpos = vec3(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z));
|
|
|
+ vec3 sqdist = vec3(1e6f, 1e6f, 1e6f);
|
|
|
+ for (int x = -1; x <= 1; ++x)
|
|
|
+ {
|
|
|
+ for (int y = -1; y <= 1; ++y)
|
|
|
+ {
|
|
|
+ for (int z = -1; z <= 1; ++z)
|
|
|
+ {
|
|
|
+ float dist = mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric);
|
|
|
+ if (dist < sqdist.x)
|
|
|
+ {
|
|
|
+ sqdist.z = sqdist.y;
|
|
|
+ sqdist.y = sqdist.x;
|
|
|
+ sqdist.x = dist;
|
|
|
+ }
|
|
|
+ else if (dist < sqdist.y)
|
|
|
+ {
|
|
|
+ sqdist.z = sqdist.y;
|
|
|
+ sqdist.y = dist;
|
|
|
+ }
|
|
|
+ else if (dist < sqdist.z)
|
|
|
+ {
|
|
|
+ sqdist.z = dist;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (metric == 0)
|
|
|
+ sqdist = sqrt(sqdist);
|
|
|
+ return sqdist;
|
|
|
+}` );
|
|
|
+
|
|
|
+const includes = [ mx_noise ];
|
|
|
+
|
|
|
+export const mx_perlin_noise_float = fn( 'float mx_perlin_noise_float( vec3 p )', includes );
|
|
|
+export const mx_cell_noise_float = fn( 'float mx_cell_noise_float( vec3 p )', includes );
|
|
|
+export const mx_worley_noise_float = fn( 'float mx_worley_noise_float( vec3 p, float jitter, int metric )', includes );
|
|
|
+export const mx_fractal_noise_float = fn( 'float mx_fractal_noise_float( vec3 p, int octaves, float lacunarity, float diminish )', includes );
|