Nodes/Jovi_GLSL/NOISE SIMPLEX (JOV_GL)
ComfyUI Node

NOISE SIMPLEX (JOV_GL)

Simplex noise without the artifacts — the node that's smoother than Perlin

By Amorano·Created 2 years ago·Updated about a year ago· 20
NOISE SIMPLEX (JOV_GL)
  • iRes
  • RGBA
  • RGB
  • MASK
frequency1.00
amplitude1.00
octaves4
lacunarity2.00
persistence0.50
offset0.00
seed0
FRAGMENT// name: NOISE SIMPLEX // desc: Simplex noise, simply // category: NOISE // control: res, seed #ifndef LIB_NOISE_PARAMS #define LIB_NOISE_PARAMS #ifndef MAX_OCTAVES #define MAX_OCTAVES 16 #endif struct NoiseParams { float frequency; // Base frequency multiplier float amplitude; // Base amplitude multiplier int octaves; // Number of octaves float lacunarity; // Frequency multiplier per octave float persistence; // Amplitude multiplier per octave (same as 'gain' in some functions) float offset; // For ridge noise int seed; // Seed }; NoiseParams defaultNoiseParams() { NoiseParams params; params.frequency = 1.0; params.amplitude = 1.0; params.octaves = 4; params.lacunarity = 2.0; params.persistence = 0.5; params.offset = 1.0; params.seed = 0; return params; } #endif #ifndef LIB_NOISE_SIMPLEX #define LIB_NOISE_SIMPLEX #ifndef LIB_NOISE_HASH #define LIB_NOISE_HASH //------------------------------------------------------------------------------ // HASH NOISE //------------------------------------------------------------------------------ float noise_hash(int n) { n = (n << 13) ^ n; return float( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 0x7fffffff; } // Basic 1D hash - maps float to float [0,1] float noise_hash11(float p) { p = fract(p * .1031); p *= p + 33.33; return fract(p * p); } // 2D to 1D hash - maps vec2 to float [0,1] float noise_hash21(vec2 p) { vec3 p3 = fract(vec3(p.xyx) * .1031); p3 += dot(p3, p3.yzx + 33.33); return fract((p3.x + p3.y) * p3.z); } // 3D to 3D hash - maps vec3 to vec3 [0,1] vec3 noise_hash33(vec3 p) { p = fract(p * vec3(443.8975, 397.2973, 491.1871)); p += dot(p.zxy, p.yxz + 19.19); return fract(vec3(p.x * p.y, p.y * p.z, p.z * p.x)); } #endif #ifndef LIB_NOISE_SMOOTH #define LIB_NOISE_SMOOTH //------------------------------------------------------------------------------ // SMOOTH GRADIENT TABLES // Predefined gradient tables for noise generation //------------------------------------------------------------------------------ vec2 noise_smooth(int hash, vec2 p) { const vec2 grad[4] = vec2[]( vec2( 1.0, 1.0), vec2(-1.0, 1.0), vec2( 1.0, -1.0), vec2(-1.0, -1.0) ); return grad[hash & 3]; } vec3 noise_smooth(int hash, vec3 p) { const vec3 grad[12] = vec3[]( vec3( 1.0, 1.0, 0.0), vec3(-1.0, 1.0, 0.0), vec3( 1.0, -1.0, 0.0), vec3(-1.0, -1.0, 0.0), vec3( 1.0, 0.0, 1.0), vec3(-1.0, 0.0, 1.0), vec3( 1.0, 0.0, -1.0), vec3(-1.0, 0.0, -1.0), vec3( 0.0, 1.0, 1.0), vec3( 0.0, -1.0, 1.0), vec3( 0.0, 1.0, -1.0), vec3( 0.0, -1.0, -1.0) ); return grad[hash % 12]; } vec4 noise_smooth(int hash, vec4 p) { const vec4 grad[32] = vec4[]( vec4( 1.0, 1.0, 1.0, 0.0), vec4(-1.0, 1.0, 1.0, 0.0), vec4( 1.0, -1.0, 1.0, 0.0), vec4(-1.0, -1.0, 1.0, 0.0), vec4( 1.0, 1.0, -1.0, 0.0), vec4(-1.0, 1.0, -1.0, 0.0), vec4( 1.0, -1.0, -1.0, 0.0), vec4(-1.0, -1.0, -1.0, 0.0), vec4( 1.0, 1.0, 0.0, 1.0), vec4(-1.0, 1.0, 0.0, 1.0), vec4( 1.0, -1.0, 0.0, 1.0), vec4(-1.0, -1.0, 0.0, 1.0), vec4( 1.0, 0.0, 1.0, 1.0), vec4(-1.0, 0.0, 1.0, 1.0), vec4( 1.0, 0.0, -1.0, 1.0), vec4(-1.0, 0.0, -1.0, 1.0), vec4( 0.0, 1.0, 1.0, 1.0), vec4( 0.0, -1.0, 1.0, 1.0), vec4( 0.0, 1.0, -1.0, 1.0), vec4( 0.0, -1.0, -1.0, 1.0), vec4( 1.0, 1.0, 0.0, -1.0), vec4(-1.0, 1.0, 0.0, -1.0), vec4( 1.0, -1.0, 0.0, -1.0), vec4(-1.0, -1.0, 0.0, -1.0), vec4( 1.0, 0.0, 1.0, -1.0), vec4(-1.0, 0.0, 1.0, -1.0), vec4( 1.0, 0.0, -1.0, -1.0), vec4(-1.0, 0.0, -1.0, -1.0), vec4( 0.0, 1.0, 1.0, -1.0), vec4( 0.0, -1.0, 1.0, -1.0), vec4( 0.0, 1.0, -1.0, -1.0), vec4( 0.0, -1.0, -1.0, -1.0) ); return grad[hash & 31]; } #endif //------------------------------------------------------------------------------ // NOISE SIMPLEX //------------------------------------------------------------------------------ #define MOD289(vec_type) vec_type mod289(const in vec_type x) { \ return x - floor(x * (1. / 289.)) * 289.; \ } MOD289(float) MOD289(vec2) MOD289(vec3) MOD289(vec4) #define PERMUTE(vec_type) vec_type permute(const in vec_type x, int seed) { \ return mod289(((x * 34.0 + noise_hash(seed)) + 1.0) * x); \ } PERMUTE(float) PERMUTE(vec2) PERMUTE(vec3) PERMUTE(vec4) #define TAYLORINVSQRT(vec_type) vec_type taylorInvSqrt(in vec_type r) { \ return 1.79284291400159 - 0.85373472095314 * r; \ } TAYLORINVSQRT(float) TAYLORINVSQRT(vec2) TAYLORINVSQRT(vec3) TAYLORINVSQRT(vec4) vec4 grad4(float j, vec4 ip, int seed) { const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0); vec4 p,s; p.xyz = floor(fract(vec3(j + noise_hash(seed)) * ip.xyz) * 7.0) * ip.z - 1.0; p.w = 1.5 - dot(abs(p.xyz), ones.xyz); s = vec4(lessThan(p, vec4(0.0))); p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www; return p; } float noise_simplex(in vec2 v, int seed) { const vec4 C = vec4(0.211324865405187, 0.366025403784439, // 0.5*(sqrt(3.0)-1.0) -0.577350269189626, // -1.0 + 2.0 * C.x 0.024390243902439); // 1.0 / 41.0 // First corner vec2 i = floor(v + dot(v, C.yy) ); vec2 x0 = v - i + dot(i, C.xx); // Other corners vec2 i1; i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); vec4 x12 = x0.xyxy + C.xxzz; x12.xy -= i1; // Permutations i = mod289(i); // Avoid truncation effects in permutation vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ), seed) + i.x + vec3(0.0, i1.x, 1.0 ), seed); vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0); m = m*m ; m = m*m ; // Gradients: 41 points uniformly over a line, mapped onto a diamond. // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) vec3 x = 2.0 * fract(p * C.www) - 1.0; vec3 h = abs(x) - 0.5; vec3 ox = floor(x + 0.5); vec3 a0 = x - ox; // Normalize gradients implicitly by scaling m // Approximation of: m *= inversesqrt( a0*a0 + h*h ); m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h ); // Compute final noise value at P vec3 g; g.x = a0.x * x0.x + h.x * x0.y; g.yz = a0.yz * x12.xz + h.yz * x12.yw; return 130.0 * dot(m, g); } float noise_simplex(in vec3 v, int seed) { const vec2 C = vec2(1.0/6.0, 1.0/3.0) ; const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); // First corner vec3 i = floor(v + dot(v, C.yyy) ); vec3 x0 = v - i + dot(i, C.xxx) ; // Other corners vec3 g = step(x0.yzx, x0.xyz); vec3 l = 1.0 - g; vec3 i1 = min( g.xyz, l.zxy ); vec3 i2 = max( g.xyz, l.zxy ); vec3 x1 = x0 - i1 + C.xxx; vec3 x2 = x0 - i2 + C.yyy; vec3 x3 = x0 - D.yyy; // Permutations i = mod289(i); vec4 p = permute( permute( permute(i.z + vec4(0.0, i1.z, i2.z, 1.0 ), seed) + i.y + vec4(0.0, i1.y, i2.y, 1.0 ), seed) + i.x + vec4(0.0, i1.x, i2.x, 1.0 ), seed); // Gradients: 7x7 points over a square, mapped onto an octahedron. // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) float n_ = 0.142857142857; vec3 ns = n_ * D.wyz - D.xzx; vec4 j = p - 49.0 * floor(p * ns.z * ns.z); vec4 x_ = floor(j * ns.z); vec4 y_ = floor(j - 7.0 * x_ ); vec4 x = x_ *ns.x + ns.yyyy; vec4 y = y_ *ns.x + ns.yyyy; vec4 h = 1.0 - abs(x) - abs(y); vec4 b0 = vec4( x.xy, y.xy ); vec4 b1 = vec4( x.zw, y.zw ); vec4 s0 = floor(b0)*2.0 + 1.0; vec4 s1 = floor(b1)*2.0 + 1.0; vec4 sh = -step(h, vec4(0.0)); vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ; vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ; vec3 p0 = vec3(a0.xy,h.x); vec3 p1 = vec3(a0.zw,h.y); vec3 p2 = vec3(a1.xy,h.z); vec3 p3 = vec3(a1.zw,h.w); //Normalize gradients vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); p0 *= norm.x; p1 *= norm.y; p2 *= norm.z; p3 *= norm.w; // Mix final noise value vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); m = m * m; return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3) ) ); } float noise_simplex(in vec4 v, int seed) { const vec4 C = vec4( 0.138196601125011, // (5 - sqrt(5))/20 G4 0.276393202250021, // 2 * G4 0.414589803375032, // 3 * G4 -0.447213595499958); // -1 + 4 * G4 // First corner vec4 i = floor(v + dot(v, vec4(.309016994374947451)) ); // (sqrt(5) - 1)/4 vec4 x0 = v - i + dot(i, C.xxxx); // Other corners // Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI) vec4 i0; vec3 isX = step( x0.yzw, x0.xxx ); vec3 isYZ = step( x0.zww, x0.yyz ); i0.x = isX.x + isX.y + isX.z; i0.yzw = 1.0 - isX; i0.y += isYZ.x + isYZ.y; i0.zw += 1.0 - isYZ.xy; i0.z += isYZ.z; i0.w += 1.0 - isYZ.z; // i0 now contains the unique values 0,1,2,3 in each channel vec4 i3 = clamp( i0, 0.0, 1.0 ); vec4 i2 = clamp( i0-1.0, 0.0, 1.0 ); vec4 i1 = clamp( i0-2.0, 0.0, 1.0 ); vec4 x1 = x0 - i1 + C.xxxx; vec4 x2 = x0 - i2 + C.yyyy; vec4 x3 = x0 - i3 + C.zzzz; vec4 x4 = x0 + C.wwww; // Permutations i = mod289(i); float j0 = permute( permute( permute( permute( i.w, seed) + i.z, seed) + i.y, seed) + i.x, seed); vec4 j1 = permute( permute( permute( permute ( i.w + vec4(i1.w, i2.w, i3.w, 1.0 ), seed) + i.z + vec4(i1.z, i2.z, i3.z, 1.0 ), seed) + i.y + vec4(i1.y, i2.y, i3.y, 1.0 ), seed) + i.x + vec4(i1.x, i2.x, i3.x, 1.0 ), seed); // Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope // 7*7*6 = 294, which is close to the ring size 17*17 = 289. vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ; vec4 p0 = grad4(j0, ip, seed); vec4 p1 = grad4(j1.x, ip, seed); vec4 p2 = grad4(j1.y, ip, seed); vec4 p3 = grad4(j1.z, ip, seed); vec4 p4 = grad4(j1.w, ip, seed); // Normalize gradients vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); p0 *= norm.x; p1 *= norm.y; p2 *= norm.z; p3 *= norm.w; p4 *= taylorInvSqrt(dot(p4,p4)); // Mix contributions from the five corners vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0); vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0); m0 = m0 * m0; m1 = m1 * m1; return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 ))) + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ; } //------------------------------------------------------------------------------ // PARAMETERS //------------------------------------------------------------------------------ #define NOISE_SIMPLEX(vec_type) float noise_simplex(vec_type p, NoiseParams params) { \ float value = 0.0; \ float frequency = params.frequency; \ float amplitude = params.amplitude; \ float maxValue = 0.0; \ for(int i = 0; i < min(params.octaves, MAX_OCTAVES); i++) { \ value += amplitude * noise_simplex(p * frequency, params.seed + i * 1337); \ maxValue += amplitude; \ frequency *= params.lacunarity; \ amplitude *= params.persistence; \ } \ return value / maxValue; \ } NOISE_SIMPLEX(vec2) NOISE_SIMPLEX(vec3) NOISE_SIMPLEX(vec4) #endif uniform float frequency; // 1.; 1.; 100.; 0.01 | Base frequency multiplier uniform float amplitude; // 1.; 1.; 100.; 0.01 | Base amplitude multiplier uniform int octaves; // 4; 1; 12; 1 | Number of octaves uniform float lacunarity; // 2.; 0.; 100.; 0.01 | Frequency multiplier per octave uniform float persistence; // 0.5; 0.; 100.; 0.01 | Amplitude multiplier per octave (same as 'gain' in some functions) uniform float offset; // 0.; 0.; 100.; 0.01 | For ridge noise void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv = fragCoord / iResolution.xy; NoiseParams nparam = defaultNoiseParams(); nparam.frequency = frequency; nparam.amplitude = amplitude; nparam.octaves = octaves; nparam.lacunarity = lacunarity; nparam.persistence = persistence; nparam.offset = offset; nparam.seed = iSeed; float simplex = noise_simplex(uv, nparam); fragColor = vec4(simplex, simplex, simplex, 1.); }

Perlin noise is the default, but it has a tell: on axis-aligned patterns you can see the grid. Simplex noise was invented to fix exactly that - same idea, cleaner lattice, fewer visible artifacts, and it's the noise of choice for flow fields and anything where the grid would break the illusion. This node generates it with the full fBm control set, a seed, and GPU speed, and it sits next to the Perlin and Worley generators in the pack's NOISE menu.

How it works

The shader implements simplex gradient noise over a skewed simplex grid instead of a square lattice, then layers it with the standard fractional Brownian motion stack. The inputs are identical in spirit to the Perlin node:

  • frequency (default 1) - base feature scale.
  • amplitude (default 1) - strength of the first octave.
  • octaves (default 4, max 12) - layers of noise summed.
  • lacunarity (default 2) - frequency multiplier per octave.
  • persistence (default 0.5) - amplitude multiplier per octave.
  • offset - a shift on the noise field.
  • seed - drives iSeed for reproducible output.

No image input - pure generator at iRes (default 512×512). Outputs: RGBA, RGB, and MASK of the grayscale field.

Why simplex instead of Perlin?

For most masking work the difference is subtle, and honestly you could use either. Where simplex earns its keep: displacement and warp inputs, where the lattice artifacts of Perlin show up as faint grid-like flows, and anything animated, where simplex's lower anisotropy makes motion look less "digital." If you're making a cloud or smoke mask, reach for simplex first - it just holds up better at higher frequencies.

Install

One-time pack install. Via ComfyUI Manager, search Jovi_GLSL; or:

cd ComfyUI/custom_nodes
git clone https://github.com/Amorano/Jovi_GLSL.git
cd Jovi_GLSL
pip install -r requirements.txt

Restart ComfyUI. Standard pack deps (PyOpenGL, glfw, opencv-contrib-python, cozy_comfyui from git), needs an OpenGL context. No models, no keys. Under JOVI_GLSL 🌈 → NOISE.

Gotchas

Same copy-paste quirk as the Perlin node: the seed tooltip talks about frames and continuous mode - it's just the noise seed, reproducible per value. Keep octaves low (2–3) for smooth flow-field work, and remember the noise is fully deterministic: same seed, same image, every time, which is what you want when you're building a repeatable workflow that shouldn't drift between runs.

CategoryJOV_GL 🌈/NOISE

Inputs (9)

NameTypeDefaultDescription
frequencyoptFLOAT1.001–100Base frequency multiplier
amplitudeoptFLOAT1.001–100Base amplitude multiplier
octavesoptINT41–12Number of octaves
lacunarityoptFLOAT2.000–100Frequency multiplier per octave
persistenceoptFLOAT0.500–100Amplitude multiplier per octave (same as 'gain' in some functions)
offsetoptFLOAT0.000–100For ridge noise
iResoptVEC2INT512,512Width and Height as a Vector2 Integer (x, y)
seedoptINT00–9223372036854776000Number of frames to generate. 0 (continuous mode) means continue from the last queue generating the next single frame based on iFrameRate.
FRAGMENToptSTRING// name: NOISE SIMPLEX // desc: Simplex noise, simply // category: NOISE // control: res, seed #ifndef LIB_NOISE_PARAMS #define LIB_NOISE_PARAMS #ifndef MAX_OCTAVES #define MAX_OCTAVES 16 #endif struct NoiseParams { float frequency; // Base frequency multiplier float amplitude; // Base amplitude multiplier int octaves; // Number of octaves float lacunarity; // Frequency multiplier per octave float persistence; // Amplitude multiplier per octave (same as 'gain' in some functions) float offset; // For ridge noise int seed; // Seed }; NoiseParams defaultNoiseParams() { NoiseParams params; params.frequency = 1.0; params.amplitude = 1.0; params.octaves = 4; params.lacunarity = 2.0; params.persistence = 0.5; params.offset = 1.0; params.seed = 0; return params; } #endif #ifndef LIB_NOISE_SIMPLEX #define LIB_NOISE_SIMPLEX #ifndef LIB_NOISE_HASH #define LIB_NOISE_HASH //------------------------------------------------------------------------------ // HASH NOISE //------------------------------------------------------------------------------ float noise_hash(int n) { n = (n << 13) ^ n; return float( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 0x7fffffff; } // Basic 1D hash - maps float to float [0,1] float noise_hash11(float p) { p = fract(p * .1031); p *= p + 33.33; return fract(p * p); } // 2D to 1D hash - maps vec2 to float [0,1] float noise_hash21(vec2 p) { vec3 p3 = fract(vec3(p.xyx) * .1031); p3 += dot(p3, p3.yzx + 33.33); return fract((p3.x + p3.y) * p3.z); } // 3D to 3D hash - maps vec3 to vec3 [0,1] vec3 noise_hash33(vec3 p) { p = fract(p * vec3(443.8975, 397.2973, 491.1871)); p += dot(p.zxy, p.yxz + 19.19); return fract(vec3(p.x * p.y, p.y * p.z, p.z * p.x)); } #endif #ifndef LIB_NOISE_SMOOTH #define LIB_NOISE_SMOOTH //------------------------------------------------------------------------------ // SMOOTH GRADIENT TABLES // Predefined gradient tables for noise generation //------------------------------------------------------------------------------ vec2 noise_smooth(int hash, vec2 p) { const vec2 grad[4] = vec2[]( vec2( 1.0, 1.0), vec2(-1.0, 1.0), vec2( 1.0, -1.0), vec2(-1.0, -1.0) ); return grad[hash & 3]; } vec3 noise_smooth(int hash, vec3 p) { const vec3 grad[12] = vec3[]( vec3( 1.0, 1.0, 0.0), vec3(-1.0, 1.0, 0.0), vec3( 1.0, -1.0, 0.0), vec3(-1.0, -1.0, 0.0), vec3( 1.0, 0.0, 1.0), vec3(-1.0, 0.0, 1.0), vec3( 1.0, 0.0, -1.0), vec3(-1.0, 0.0, -1.0), vec3( 0.0, 1.0, 1.0), vec3( 0.0, -1.0, 1.0), vec3( 0.0, 1.0, -1.0), vec3( 0.0, -1.0, -1.0) ); return grad[hash % 12]; } vec4 noise_smooth(int hash, vec4 p) { const vec4 grad[32] = vec4[]( vec4( 1.0, 1.0, 1.0, 0.0), vec4(-1.0, 1.0, 1.0, 0.0), vec4( 1.0, -1.0, 1.0, 0.0), vec4(-1.0, -1.0, 1.0, 0.0), vec4( 1.0, 1.0, -1.0, 0.0), vec4(-1.0, 1.0, -1.0, 0.0), vec4( 1.0, -1.0, -1.0, 0.0), vec4(-1.0, -1.0, -1.0, 0.0), vec4( 1.0, 1.0, 0.0, 1.0), vec4(-1.0, 1.0, 0.0, 1.0), vec4( 1.0, -1.0, 0.0, 1.0), vec4(-1.0, -1.0, 0.0, 1.0), vec4( 1.0, 0.0, 1.0, 1.0), vec4(-1.0, 0.0, 1.0, 1.0), vec4( 1.0, 0.0, -1.0, 1.0), vec4(-1.0, 0.0, -1.0, 1.0), vec4( 0.0, 1.0, 1.0, 1.0), vec4( 0.0, -1.0, 1.0, 1.0), vec4( 0.0, 1.0, -1.0, 1.0), vec4( 0.0, -1.0, -1.0, 1.0), vec4( 1.0, 1.0, 0.0, -1.0), vec4(-1.0, 1.0, 0.0, -1.0), vec4( 1.0, -1.0, 0.0, -1.0), vec4(-1.0, -1.0, 0.0, -1.0), vec4( 1.0, 0.0, 1.0, -1.0), vec4(-1.0, 0.0, 1.0, -1.0), vec4( 1.0, 0.0, -1.0, -1.0), vec4(-1.0, 0.0, -1.0, -1.0), vec4( 0.0, 1.0, 1.0, -1.0), vec4( 0.0, -1.0, 1.0, -1.0), vec4( 0.0, 1.0, -1.0, -1.0), vec4( 0.0, -1.0, -1.0, -1.0) ); return grad[hash & 31]; } #endif //------------------------------------------------------------------------------ // NOISE SIMPLEX //------------------------------------------------------------------------------ #define MOD289(vec_type) vec_type mod289(const in vec_type x) { \ return x - floor(x * (1. / 289.)) * 289.; \ } MOD289(float) MOD289(vec2) MOD289(vec3) MOD289(vec4) #define PERMUTE(vec_type) vec_type permute(const in vec_type x, int seed) { \ return mod289(((x * 34.0 + noise_hash(seed)) + 1.0) * x); \ } PERMUTE(float) PERMUTE(vec2) PERMUTE(vec3) PERMUTE(vec4) #define TAYLORINVSQRT(vec_type) vec_type taylorInvSqrt(in vec_type r) { \ return 1.79284291400159 - 0.85373472095314 * r; \ } TAYLORINVSQRT(float) TAYLORINVSQRT(vec2) TAYLORINVSQRT(vec3) TAYLORINVSQRT(vec4) vec4 grad4(float j, vec4 ip, int seed) { const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0); vec4 p,s; p.xyz = floor(fract(vec3(j + noise_hash(seed)) * ip.xyz) * 7.0) * ip.z - 1.0; p.w = 1.5 - dot(abs(p.xyz), ones.xyz); s = vec4(lessThan(p, vec4(0.0))); p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www; return p; } float noise_simplex(in vec2 v, int seed) { const vec4 C = vec4(0.211324865405187, 0.366025403784439, // 0.5*(sqrt(3.0)-1.0) -0.577350269189626, // -1.0 + 2.0 * C.x 0.024390243902439); // 1.0 / 41.0 // First corner vec2 i = floor(v + dot(v, C.yy) ); vec2 x0 = v - i + dot(i, C.xx); // Other corners vec2 i1; i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); vec4 x12 = x0.xyxy + C.xxzz; x12.xy -= i1; // Permutations i = mod289(i); // Avoid truncation effects in permutation vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ), seed) + i.x + vec3(0.0, i1.x, 1.0 ), seed); vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0); m = m*m ; m = m*m ; // Gradients: 41 points uniformly over a line, mapped onto a diamond. // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) vec3 x = 2.0 * fract(p * C.www) - 1.0; vec3 h = abs(x) - 0.5; vec3 ox = floor(x + 0.5); vec3 a0 = x - ox; // Normalize gradients implicitly by scaling m // Approximation of: m *= inversesqrt( a0*a0 + h*h ); m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h ); // Compute final noise value at P vec3 g; g.x = a0.x * x0.x + h.x * x0.y; g.yz = a0.yz * x12.xz + h.yz * x12.yw; return 130.0 * dot(m, g); } float noise_simplex(in vec3 v, int seed) { const vec2 C = vec2(1.0/6.0, 1.0/3.0) ; const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); // First corner vec3 i = floor(v + dot(v, C.yyy) ); vec3 x0 = v - i + dot(i, C.xxx) ; // Other corners vec3 g = step(x0.yzx, x0.xyz); vec3 l = 1.0 - g; vec3 i1 = min( g.xyz, l.zxy ); vec3 i2 = max( g.xyz, l.zxy ); vec3 x1 = x0 - i1 + C.xxx; vec3 x2 = x0 - i2 + C.yyy; vec3 x3 = x0 - D.yyy; // Permutations i = mod289(i); vec4 p = permute( permute( permute(i.z + vec4(0.0, i1.z, i2.z, 1.0 ), seed) + i.y + vec4(0.0, i1.y, i2.y, 1.0 ), seed) + i.x + vec4(0.0, i1.x, i2.x, 1.0 ), seed); // Gradients: 7x7 points over a square, mapped onto an octahedron. // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) float n_ = 0.142857142857; vec3 ns = n_ * D.wyz - D.xzx; vec4 j = p - 49.0 * floor(p * ns.z * ns.z); vec4 x_ = floor(j * ns.z); vec4 y_ = floor(j - 7.0 * x_ ); vec4 x = x_ *ns.x + ns.yyyy; vec4 y = y_ *ns.x + ns.yyyy; vec4 h = 1.0 - abs(x) - abs(y); vec4 b0 = vec4( x.xy, y.xy ); vec4 b1 = vec4( x.zw, y.zw ); vec4 s0 = floor(b0)*2.0 + 1.0; vec4 s1 = floor(b1)*2.0 + 1.0; vec4 sh = -step(h, vec4(0.0)); vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ; vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ; vec3 p0 = vec3(a0.xy,h.x); vec3 p1 = vec3(a0.zw,h.y); vec3 p2 = vec3(a1.xy,h.z); vec3 p3 = vec3(a1.zw,h.w); //Normalize gradients vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); p0 *= norm.x; p1 *= norm.y; p2 *= norm.z; p3 *= norm.w; // Mix final noise value vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); m = m * m; return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3) ) ); } float noise_simplex(in vec4 v, int seed) { const vec4 C = vec4( 0.138196601125011, // (5 - sqrt(5))/20 G4 0.276393202250021, // 2 * G4 0.414589803375032, // 3 * G4 -0.447213595499958); // -1 + 4 * G4 // First corner vec4 i = floor(v + dot(v, vec4(.309016994374947451)) ); // (sqrt(5) - 1)/4 vec4 x0 = v - i + dot(i, C.xxxx); // Other corners // Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI) vec4 i0; vec3 isX = step( x0.yzw, x0.xxx ); vec3 isYZ = step( x0.zww, x0.yyz ); i0.x = isX.x + isX.y + isX.z; i0.yzw = 1.0 - isX; i0.y += isYZ.x + isYZ.y; i0.zw += 1.0 - isYZ.xy; i0.z += isYZ.z; i0.w += 1.0 - isYZ.z; // i0 now contains the unique values 0,1,2,3 in each channel vec4 i3 = clamp( i0, 0.0, 1.0 ); vec4 i2 = clamp( i0-1.0, 0.0, 1.0 ); vec4 i1 = clamp( i0-2.0, 0.0, 1.0 ); vec4 x1 = x0 - i1 + C.xxxx; vec4 x2 = x0 - i2 + C.yyyy; vec4 x3 = x0 - i3 + C.zzzz; vec4 x4 = x0 + C.wwww; // Permutations i = mod289(i); float j0 = permute( permute( permute( permute( i.w, seed) + i.z, seed) + i.y, seed) + i.x, seed); vec4 j1 = permute( permute( permute( permute ( i.w + vec4(i1.w, i2.w, i3.w, 1.0 ), seed) + i.z + vec4(i1.z, i2.z, i3.z, 1.0 ), seed) + i.y + vec4(i1.y, i2.y, i3.y, 1.0 ), seed) + i.x + vec4(i1.x, i2.x, i3.x, 1.0 ), seed); // Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope // 7*7*6 = 294, which is close to the ring size 17*17 = 289. vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ; vec4 p0 = grad4(j0, ip, seed); vec4 p1 = grad4(j1.x, ip, seed); vec4 p2 = grad4(j1.y, ip, seed); vec4 p3 = grad4(j1.z, ip, seed); vec4 p4 = grad4(j1.w, ip, seed); // Normalize gradients vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); p0 *= norm.x; p1 *= norm.y; p2 *= norm.z; p3 *= norm.w; p4 *= taylorInvSqrt(dot(p4,p4)); // Mix contributions from the five corners vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0); vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0); m0 = m0 * m0; m1 = m1 * m1; return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 ))) + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ; } //------------------------------------------------------------------------------ // PARAMETERS //------------------------------------------------------------------------------ #define NOISE_SIMPLEX(vec_type) float noise_simplex(vec_type p, NoiseParams params) { \ float value = 0.0; \ float frequency = params.frequency; \ float amplitude = params.amplitude; \ float maxValue = 0.0; \ for(int i = 0; i < min(params.octaves, MAX_OCTAVES); i++) { \ value += amplitude * noise_simplex(p * frequency, params.seed + i * 1337); \ maxValue += amplitude; \ frequency *= params.lacunarity; \ amplitude *= params.persistence; \ } \ return value / maxValue; \ } NOISE_SIMPLEX(vec2) NOISE_SIMPLEX(vec3) NOISE_SIMPLEX(vec4) #endif uniform float frequency; // 1.; 1.; 100.; 0.01 | Base frequency multiplier uniform float amplitude; // 1.; 1.; 100.; 0.01 | Base amplitude multiplier uniform int octaves; // 4; 1; 12; 1 | Number of octaves uniform float lacunarity; // 2.; 0.; 100.; 0.01 | Frequency multiplier per octave uniform float persistence; // 0.5; 0.; 100.; 0.01 | Amplitude multiplier per octave (same as 'gain' in some functions) uniform float offset; // 0.; 0.; 100.; 0.01 | For ridge noise void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv = fragCoord / iResolution.xy; NoiseParams nparam = defaultNoiseParams(); nparam.frequency = frequency; nparam.amplitude = amplitude; nparam.octaves = octaves; nparam.lacunarity = lacunarity; nparam.persistence = persistence; nparam.offset = offset; nparam.seed = iSeed; float simplex = noise_simplex(uv, nparam); fragColor = vec4(simplex, simplex, simplex, 1.); }

Outputs (3)

NameTypeDescription
RGBAIMAGEFull channel [RGBA] image. If there is an alpha, the image will be masked out with it when using this output.
RGBIMAGEThree channel [RGB] image. There will be no alpha.
MASKMASKSingle channel mask output.