|
|
|
WebGPU/WGSL Tutorials and Articles
Graphics and Compute ... |
|
|
|
| Noise Categories - Managing the Madness! | |
Their seems to be so many noise functions - their are hundreds if not thousands of noise algorithms - each with their own name and characteristics.
However, we try and categories the noise functions - group them together - so that we have a handful of types of noises.
Elaboration on an earlier article which was collecting noise functions ( LINK). In this article, we sort of try and organise things - and take things further. Each noise function is linked to an interactive example - so you can click on it and see a hacky version of the noise. Send me a quick email if you find a bug or think of a tidier version/better version :)
Out of the 60 example noise functions - we'll group them into 7 main categories (given below).
Noise Function Categories
Base Noise
1. Random Noise
2. Value Noise
3. Gradient Noise
4. White Noise
5. Uniform Noise
6. Blue Noise
7. Pink Noise
8. Gaussian Noise
Complex & Layered Noise
9. Fractal Noise
10. Octave Noise
11. Fractional Brownian Motion (FBM)
12. Turbulence Noise
13. Layered Noise
14. Perlin Noise
15. Fractal Cellular Noise
16. Noise Blending
17. Domain Warping
Directional Noise
18. Flow Noise
19. Anisotropic Noise
20. Gradient Squared Noise
21. Angular Gradient Noise
22. Spiral Noise
23. Stripe Noise
24. Stripe Gradient Noise
25. Directional Voronoi
Cellular Noise
26. Voronoi Noise
27. Worley Noise
28. Cellular Noise
29. Fractal Voronoi
30. Spiral Voronoi
31. Noisy Voronoi
Patterned Noise
32. Ring Noise
33. Radial Noise
34. Ripple Noise
35. Polygonal Grid Noise
36. Crosshatch Noise
37. Starburst Noise
38. Circular Wave Noise
39. Spiral Gradient Noise
40. Plasma Noise
41. Interference Noise
42. Checkerboard Noise
43. Hexagonal Noise
Animated/Temporal Noise
44. Offset Noise
45. Warped Noise
46. Seamless Noise
47. Texture Distortion Noise
48. Dynamic Noise
49. Time-Varying Voronoi
50. Animated Gradient Noise
Specialized Noise
51. Tileable Noise
52. Gradient Ridge Noise
53. Multiscale Noise
54. Spectral Noise
55. Blob Noise
56. Point Cluster Noise
57. Crystal Noise
58. Wavelet Noise
59. Ridged FBM Noise
60. Sparse Convolution Noise
The following give a small description of each example noise function from above - in addition to a mockup code implementation in WGSL (WebGPU Shader Language).
| Base Noise | |
1. Random Noise
Generates uncorrelated random values across the domain.
fn random(uv: vec2<f32>) -> f32 { return fract(sin(dot(uv, vec2<f32>(12.9898, 78.233))) * 43758.5453); }
2. Value Noise
Interpolates random values to create smooth transitions.
fn valueNoise(uv: vec2<f32>) -> f32 { let cell = floor(uv); let frac = fract(uv); let randomValues = vec2<f32>(random(cell), random(cell + vec2<f32>(1.0, 0.0))); return mix(randomValues.x, randomValues.y, frac.x); }
3. Gradient Noise
Utilizes gradient vectors to interpolate smooth noise.
fn gradientNoise(uv: vec2<f32>) -> f32 { let cell = floor(uv); let grad = fract(sin(vec2<f32>(dot(cell, vec2<f32>(127.1, 311.7)), dot(cell + vec2<f32>(1.0, 0.0), vec2<f32>(269.5, 183.3)))) * 43758.5453); return dot(grad, fract(uv)); }
4. White Noise
Produces uncorrelated, high-frequency noise.
fn whiteNoise(uv: vec2<f32>) -> f32 { return random(uv); }
5. Uniform Noise
Generates noise with uniform distribution.
fn uniformNoise(uv: vec2<f32>) -> f32 { return step(0.5, random(uv)); }
6. Blue Noise
Low-frequency noise optimized for dithering.
fn blueNoise(uv: vec2<f32>) -> f32 { return smoothstep(0.2, 0.8, random(uv)); }
7. Pink Noise
Lower frequency noise useful in audio synthesis.
fn pinkNoise(uv: vec2<f32>) -> f32 { return pow(random(uv), 1.0 / 3.0); }
8. Gaussian Noise
Generates noise with a Gaussian distribution.
fn gaussianNoise(uv: vec2<f32>) -> f32 { let rand1 = random(uv); let rand2 = random(uv + vec2<f32>(1.0, 1.0)); return sqrt(-2.0 * log(rand1)) * cos(6.283185 * rand2); }
| Complex/Layered Noise | |
9. Fractal Noise
Combines multiple layers of noise at different scales.
fn fractalNoise(uv: vec2<f32>, octaves: i32) -> f32 { var value = 0.0; var frequency = 1.0; var amplitude = 1.0; for (var i: i32 = 0; i < octaves; i = i + 1) { value += fbm(uv * frequency) * amplitude; frequency *= 2.0; amplitude *= 0.5; } return value; }
10. Octave Noise
A simpler layering of multiple frequencies of noise.
fn octaveNoise(uv: vec2<f32>, octaves: i32) -> f32 { var result = 0.0; for (var i: i32 = 0; i < octaves; i = i + 1) { result += fbm(uv * pow(2.0, f32(i))) / pow(2.0, f32(i)); } return result; }
11. Fractional Brownian Motion (FBM)
A widely-used method for natural-looking noise patterns.
fn fbm(uv: vec2<f32>) -> f32 { var value = 0.0; var frequency = 1.0; var amplitude = 0.5; for (var i: i32 = 0; i < 5; i = i + 1) { value += gradientNoise(uv * frequency) * amplitude; frequency *= 2.0; amplitude *= 0.5; } return value; }
12. Turbulence Noise
A variant of FBM using absolute values for sharper textures.
fn turbulence(uv: vec2<f32>) -> f32 { var value = 0.0; var frequency = 1.0; for (var i: i32 = 0; i < 5; i = i + 1) { value += abs(gradientNoise(uv * frequency)); frequency *= 2.0; } return value; }
13. Layered Noise
Stacks noise layers for texture complexity.
fn layeredNoise(uv: vec2<f32>, layers: i32) -> f32 { var result = 0.0; for (var i: i32 = 0; i < layers; i = i + 1) { result += gradientNoise(uv * pow(2.0, f32(i))) / pow(2.0, f32(i)); } return result; }
14. Perlin Noise
A classic noise function used in procedural generation.
fn perlinNoise(uv: vec2<f32>) -> f32 { let cell = floor(uv); let grad = fract(sin(vec2<f32>(dot(cell, vec2<f32>(127.1, 311.7)), dot(cell + vec2<f32>(1.0, 0.0), vec2<f32>(269.5, 183.3)))) * 43758.5453); return dot(grad, fract(uv)); }
15. Fractal Cellular Noise
Combines cellular noise with fractal layers.
fn fractalCellularNoise(uv: vec2<f32>, layers: i32) -> f32 { var result = 0.0; for (var i: i32 = 0; i < layers; i = i + 1) { result += voronoiNoise(uv * pow(2.0, f32(i))) / pow(2.0, f32(i)); } return result; }
16. Noise Blending
Interpolates between multiple noise types.
fn noiseBlending(uv: vec2<f32>, weight: f32) -> f32 { return mix(gradientNoise(uv), voronoiNoise(uv), weight); }
17. Domain Warping
Applies noise to distort its own domain.
fn domainWarping(uv: vec2<f32>) -> f32 { let warp = fbm(uv); return fbm(uv + warp); }
| Directional Noise | |
18. Flow Noise
Produces smoothly flowing patterns, ideal for fluid effects.
fn flowNoise(uv: vec2<f32>, time: f32) -> f32 { let warpedUV = uv + vec2<f32>(sin(time), cos(time)); return fbm(warpedUV); }
19. Anisotropic Noise
Stretches noise along a specific axis for directional effects.
fn anisotropicNoise(uv: vec2<f32>, direction: vec2<f32>) -> f32 { let stretchUV = uv * direction; return gradientNoise(stretchUV); }
20. Gradient Squared Noise
Amplifies directional gradients for sharp features.
fn gradientSquaredNoise(uv: vec2<f32>) -> f32 { let grad = gradientNoise(uv); return grad * grad; }
21. Angular Gradient Noise
Creates angular patterns for circular or star-like effects.
fn angularGradientNoise(uv: vec2<f32>) -> f32 { let angle = atan2(uv.y, uv.x) * 0.5 / 3.14159; return abs(fract(angle) - 0.5); }
22. Spiral Noise
Generates spiraling patterns.
fn spiralNoise(uv: vec2<f32>, twists: f32) -> f32 { let angle = atan2(uv.y, uv.x); return abs(sin(angle * twists + length(uv))); }
23. Stripe Noise
Produces parallel line patterns.
fn stripeNoise(uv: vec2<f32>, frequency: f32) -> f32 { return abs(sin(uv.x * frequency)); }
24. Stripe Gradient Noise
Adds a gradient effect to stripe noise.
fn stripeGradientNoise(uv: vec2<f32>, frequency: f32, minValue: f32, maxValue: f32) -> f32 { return mix(minValue, maxValue, abs(sin(uv.x * frequency))); }
25. Directional Voronoi
Orients Voronoi noise in a specific direction.
fn directionalVoronoi(uv: vec2<f32>, direction: vec2<f32>) -> f32 { let dirUV = uv + direction; return voronoiNoise(dirUV); }
| Cellular Noise | |
26. Voronoi Noise
Generates cell-like patterns with varying sizes.
fn voronoiNoise(uv: vec2<f32>) -> f32 { let cell = floor(uv); let frac = fract(uv); var minDist = 1.0; for (var y: i32 = -1; y <= 1; y = y + 1) { for (var x: i32 = -1; x <= 1; x = x + 1) { let neighbor = cell + vec2<f32>(f32(x), f32(y)); let point = neighbor + random(neighbor); let dist = length(frac - (point - cell)); minDist = min(minDist, dist); } } return minDist; }
27. Worley Noise
Computes distances to nearest neighbors for texture variety.
fn worleyNoise(uv: vec2<f32>) -> f32 { var minDist: f32 = 1e9; var featurePoint: vec2<f32>; // Generate feature points and calculate distance for (var i: i32 = -1; i <= 1; i = i + 1) { for (var j: i32 = -1; j <= 1; j = j + 1) { featurePoint = floor(uv) + vec2<f32>(f32(i), f32(j)) + fract(sin(vec2<f32>(dot(floor(uv) + vec2<f32>(f32(i), f32(j)), vec2<f32>(12.9898, 78.233))) * 43758.5453)); var dist: f32 = length(uv - featurePoint); if (dist < minDist) { minDist = dist; } } } return minDist; }
28. Cellular Noise
Combines cellular techniques for organic looks.
fn cellularNoise(uv: vec2<f32>) -> f32 { return worleyNoise(uv) - voronoiNoise(uv); // or another combination of functions }
29. Fractal Voronoi
Layers Voronoi noise for fractal patterns.
fn fractalVoronoi(uv: vec2<f32>, octaves: i32) -> f32 { var result = 0.0; for (var i: i32 = 0; i < octaves; i = i + 1) { result += voronoiNoise(uv * pow(2.0, f32(i))) / pow(2.0, f32(i)); } return result; }
30. Spiral Voronoi
Twists Voronoi cells into spirals.
fn spiralVoronoi(uv: vec2<f32>, twists: f32) -> f32 { return voronoiNoise(uv + vec2<f32>(sin(twists), cos(twists))); }
31. Noisy Voronoi
Adds randomness to Voronoi cells.
fn noisyVoronoi(uv: vec2<f32>) -> f32 { return voronoiNoise(uv) * random(uv); }
| Patterned Noise | |
32. Ring Noise
Produces concentric rings.
fn ringNoise(uv: vec2<f32>) -> f32 { return abs(sin(length(uv) * 10.0)); }
33. Radial Noise
Creates circular, radial patterns.
fn radialNoise(uv: vec2<f32>) -> f32 { return fract(length(uv) * 5.0); }
34. Ripple Noise
Mimics ripples in water.
fn rippleNoise(uv: vec2<f32>) -> f32 { return sin(length(uv) * 10.0) * 0.5 + 0.5; }
35. Polygonal Grid Noise
Creates a grid of polygons like hexagons.
fn polygonalGridNoise(uv: vec2<f32>, sides: f32) -> f32 { let angle = atan2(uv.y, uv.x) + 3.14159; let segment = floor(angle / (6.28318 / sides)); return fract(segment + random(uv)); }
36. Crosshatch Noise
Produces crosshatching patterns.
fn crosshatchNoise(uv: vec2<f32>, frequency: f32) -> f32 { let lineX = step(0.5, sin(uv.x * frequency) * 0.5 + 0.5); let lineY = step(0.5, sin(uv.y * frequency) * 0.5 + 0.5); return lineX * lineY; }
37. Starburst Noise
Radiates lines from a central point.
fn starburstNoise(uv: vec2<f32>) -> f32 { return abs(sin(atan2(uv.y, uv.x) * 10.0)); }
38. Circular Wave Noise
Produces expanding concentric waves.
fn circularWaveNoise(uv: vec2<f32>, time: f32) -> f32 { return sin(length(uv) * 10.0 - time); }
39. Spiral Gradient Noise
Generates a gradient that spirals outward.
fn spiralGradientNoise(uv: vec2<f32>, frequency: f32, amplitude: f32) -> f32 { let angle = atan2(uv.y, uv.x); let dist = length(uv); // Create a spiral pattern with frequency and amplitude controls let spiral = sin(angle * frequency + dist * amplitude); // Blend the spiral pattern with noise let noise = random(uv); // Fade the effect based on distance let fade = smoothstep(0.0, 1.0, dist); // Combine the spiral and noise with the fade return mix(noise, spiral, fade); }
40. Plasma Noise
Produces a plasma-like, colorful pattern resource.
fn plasmaNoise(uvin: vec2<f32>) -> f32 { var scale:f32 = 0.1; var time: f32 = 0.5; var uv = uvin*scale; let layer1 = sin(uv.x * 10.0 + time) * cos(uv.y * 10.0 + time); let layer2 = sin(uv.x * 20.0 + uv.y * 20.0 + time * 2.0) * 0.5; let layer3 = cos(uv.x * 40.0 - uv.y * 40.0 + time * 4.0) * 0.25; let noise = layer1 + layer2 + layer3; return noise * 0.5 + 0.5; // Normalize to range [0, 1] }
41. Interference Noise
Simulates wave interference.
fn interferenceNoise(uv: vec2<f32>) -> f32 { return sin(uv.x * 5.0) + cos(uv.y * 5.0); }
42. Checkerboard Noise
Produces a checkerboard pattern.
fn checkerboardNoise(uv: vec2<f32>) -> f32 { let check = floor(uv.x) + floor(uv.y); return fract(sin(check) * 43758.5453); }
43. Hexagonal Noise
Creates a hexagonal tiling pattern.
fn hexagonalNoise(uv: vec2<f32>) -> f32 { // Constants to define hexagonal grid let k = vec2<f32>( sqrt(3.0), 1.0); // Transform UV coordinates to hexagonal grid space let uv_hex = vec2<f32>( uv.x * k.x + uv.y * k.y, uv.y * k.x - uv.x * k.y ); // Calculate hexagonal cell coordinates let cell = floor(uv_hex); let f = fract(uv_hex); // Calculate noise values for the corners of the hexagon let corners = array<vec2<f32>, 6>( vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 0.0), vec2<f32>(0.5, 0.866), vec2<f32>(-0.5, 0.866), vec2<f32>(-1.0, 0.0), vec2<f32>(-0.5, -0.866) ); var noise_value: f32 = 0.0; var min_distance: f32 = 1e10; for (var i: u32 = 0u; i < 6u; i = i + 1u) { let corner = cell + corners[i]; let dist = distance(uv_hex, corner); if (dist < min_distance) { min_distance = dist; noise_value = fract(sin(dot(corner, vec2<f32>(12.9898, 78.233))) * 43758.5453); } } return noise_value; }
| Animated/Temporal Noise | |
44. Offset Noise
Introduces an offset effect, often used for animation.
fn offsetNoise(uv: vec2<f32>, time: f32) -> f32 { return random(uv + time); }
45. Warped Noise
Distorts the noise field over time to create dynamic effects.
fn warpedNoise(uv: vec2<f32>, time: f32) -> f32 { let warpedUV = uv + sin(time + uv) * 0.5; return random(warpedUV); }
46. Seamless Noise
Creates a continuous, looping noise pattern, typically used in textures.
fn seamlessNoise(uv: vec2<f32>) -> f32 { let repeatUV = fract(uv); return random(repeatUV); }
47. Texture Distortion Noise
Distorts texture coordinates for dynamic texture animation.
fn textureDistortionNoise(uv: vec2<f32>, time: f32) -> f32 { let distortedUV = uv + sin(uv + time) * 0.1; return random(distortedUV); }
48. Dynamic Noise
Changes its characteristics over time for evolving patterns.
fn dynamicNoise(uv: vec2<f32>, time: f32) -> f32 { let dynamicUV = uv + time * 0.1; return random(dynamicUV); }
49. Time-Varying Voronoi
Modifies the Voronoi cells over time for moving patterns.
fn timeVaryingVoronoi(uv: vec2<f32>, time: f32) -> f32 { let timeShiftedUV = uv + time * 0.1; return voronoiNoise(timeShiftedUV); }
50. Animated Gradient Noise
Creates animated gradients by adjusting the direction over time.
fn animatedGradientNoise(uv: vec2<f32>, time: f32) -> f32 { let angle = time + atan2(uv.y, uv.x); let gradient = vec2<f32>(cos(angle), sin(angle)); return dot(uv, gradient); }
| Specialized Noise | |
51. Tileable Noise
Generates repeating noise patterns, typically used for textures.
fn tileableNoise(uv: vec2<f32>) -> f32 { return random(fract(uv)); }
52. Gradient Ridge Noise
Adds ridges to gradient noise for more pronounced features.
fn gradientRidgeNoise(uv: vec2<f32>) -> f32 { let gradient = gradientNoise(uv); return abs(gradient) * 2.0 - 1.0; }
53. Multiscale Noise
Combines multiple noise functions at different scales.
fn multiscaleNoise(uv: vec2<f32>, scales: i32) -> f32 { var result = 0.0; for (var i: i32 = 0; i < scales; i = i + 1) { result += random(uv * pow(2.0, f32(i))) / pow(2.0, f32(i)); } return result; }
54. Spectral Noise
Noise with controlled frequency components, often for sound design.
fn spectralNoise(uv: vec2<f32>, frequency: f32) -> f32 { return random(uv * frequency); }
55. Blob Noise
Creates irregular blob-like structures.
fn blobNoise(uv: vec2<f32>, size: f32) -> f32 { var minDist: f32 = 0.0; // Initialize with a large value for (var y: i32 = -1; y <= 1; y = y + 1) { for (var x: i32 = -1; x <= 1; x = x + 1) { let neighbor = vec2<f32>(f32(x), f32(y)); let point = floor(uv) + neighbor + random(floor(uv) + neighbor); let dist = length(uv - point) * 2.0; if ( dist < 1.5 && minDist==0.0) { minDist = 8.0; } minDist = min(minDist, dist) ; } } return exp(-minDist / size); }
56. Point Cluster Noise
Generates clustered points for dense structures.
fn pointClusterNoise(uv: vec2<f32>) -> f32 { return step(0.5, random(uv)); }
57. Crystal Noise
Creates crystal-like sharp, angular noise patterns.
fn crystalNoise(uv: vec2<f32>) -> f32 { var minDist: f32 = 1.0; // Initialize with a large value var facet: vec2<f32> = vec2<f32>(0.0, 0.0); for (var y: i32 = -1; y <= 1; y = y + 1) { for (var x: i32 = -1; x <= 1; x = x + 1) { let neighbor = vec2<f32>(f32(x), f32(y)); let point = floor(uv) + neighbor + random(floor(uv) + neighbor); let dist = length(uv - point); if (dist < minDist) { minDist = dist; facet = point; } } } let angle = atan2(uv.y - facet.y, uv.x - facet.x); return abs(sin(angle * 10.0)); }
58. Wavelet Noise
Uses wavelets to generate smooth, multi-scale noise.
fn waveletNoise(uv: vec2<f32>, scale: f32) -> f32 { let noise = sin(uv.x * scale + random(uv) * scale) * cos(uv.y * scale + random(uv.yx) * scale); return abs(noise); }
59. Ridged FBM Noise
A variant of FBM that enhances high-frequency features.
fn ridgedFBM(uv: vec2<f32>, octaves: i32) -> f32 { var result = 0.0; var amplitude = 1.0; for (var i: i32 = 0; i < octaves; i = i + 1) { result += amplitude * (1.0 - abs(fbm(uv * pow(2.0, f32(i))))) / pow(2.0, f32(i)); amplitude *= 0.5; } return result; }
60. Sparse Convolution Noise
Noise with sparse, scattered values used for specialized effects.
fn sparseConvolutionNoise(uv: vec2<f32>) -> f32 { var scale: f32 = 2.0; var total: f32 = 0.0; var weight: f32 = 0.0; for (var y: i32 = -1; y <= 1; y = y + 1) { for (var x: i32 = -1; x <= 1; x = x + 1) { let neighbor = vec2<f32>(f32(x), f32(y)); let offset = random(neighbor) * scale; let point = uv + neighbor + offset; let value = random(point); let dist = length(neighbor); let influence = 1.0 / (1.0 + dist); total += value * influence; weight += influence; } } return total / weight; }
| Resources & Links | |
• WebGPU Code Samples/Interactive (LINK)
• Lots of noise functions on a single image (LINK)
• Earlier article when research the and collecting different noise functions (just functions) (LINK)
• Diary/run through of noise (LINK)
|
|
|
|
|
|