summaryrefslogtreecommitdiff
path: root/assets/final/shaders/math/noise.wgsl
blob: 9f99e4a7064d92d37eddf6b4ef68ab68137c8b63 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Random number generation and noise functions for WGSL shaders.
// Collection of hash functions and noise generators.

// ============================================
// Hash Functions (Float Input)
// ============================================

// Hash: f32 -> f32
// Fast fractional hash for floats
fn hash_1f(x: f32) -> f32 {
  var v = fract(x * 0.3351);
  v *= v + 33.33;
  v *= v + v;
  return fract(v);
}

// Hash: vec2<f32> -> f32
// 2D coordinate to single hash value
fn hash_2f(p: vec2<f32>) -> f32 {
  var h = dot(p, vec2<f32>(127.1, 311.7));
  return fract(sin(h) * 43758.5453123);
}

// Hash: vec2<f32> -> vec2<f32>
// 2D coordinate to 2D hash (from Shadertoy 4djSRW)
fn hash_2f_2f(p: vec2<f32>) -> vec2<f32> {
  var p3 = fract(vec3<f32>(p.x, p.y, p.x) * vec3<f32>(0.1021, 0.1013, 0.0977));
  p3 += dot(p3, p3.yzx + 33.33);
  return fract((p3.xx + p3.yz) * p3.zy);
}

// Hash: vec3<f32> -> f32
// 3D coordinate to single hash value
fn hash_3f(p: vec3<f32>) -> f32 {
  var h = dot(p, vec3<f32>(127.1, 311.7, 74.7));
  return fract(sin(h) * 43758.5453123);
}

// Hash: vec3<f32> -> vec3<f32>
// 3D coordinate to 3D hash
fn hash_3f_3f(p: vec3<f32>) -> vec3<f32> {
  var v = fract(p);
  v += dot(v, v.yxz + 32.41);
  return fract((v.xxy + v.yzz) * v.zyx);
}

// ============================================
// Hash Functions (Integer Input)
// ============================================

// Hash: u32 -> f32
// Integer hash with bit operations (high quality)
fn hash_1u(p: u32) -> f32 {
  var P = (p << 13u) ^ p;
  P = P * (P * P * 15731u + 789221u) + 1376312589u;
  return bitcast<f32>((P >> 9u) | 0x3f800000u) - 1.0;
}

// Hash: u32 -> vec2<f32>
fn hash_1u_2f(p: u32) -> vec2<f32> {
  return vec2<f32>(hash_1u(p), hash_1u(p + 1423u));
}

// Hash: u32 -> vec3<f32>
fn hash_1u_3f(p: u32) -> vec3<f32> {
  return vec3<f32>(hash_1u(p), hash_1u(p + 1423u), hash_1u(p + 124453u));
}

// ============================================
// Noise Functions
// ============================================

// Value Noise: 2D
// Interpolated grid noise using smoothstep
fn noise_2d(p: vec2<f32>) -> f32 {
  let i = floor(p);
  let f = fract(p);
  let u = f * f * (3.0 - 2.0 * f);
  let n0 = hash_2f(i + vec2<f32>(0.0, 0.0));
  let n1 = hash_2f(i + vec2<f32>(1.0, 0.0));
  let n2 = hash_2f(i + vec2<f32>(0.0, 1.0));
  let n3 = hash_2f(i + vec2<f32>(1.0, 1.0));
  let ix0 = mix(n0, n1, u.x);
  let ix1 = mix(n2, n3, u.x);
  return mix(ix0, ix1, u.y);
}

// Value Noise: 3D
fn noise_3d(p: vec3<f32>) -> f32 {
  let i = floor(p);
  let f = fract(p);
  let u = f * f * (3.0 - 2.0 * f);
  let n000 = hash_3f(i + vec3<f32>(0.0, 0.0, 0.0));
  let n100 = hash_3f(i + vec3<f32>(1.0, 0.0, 0.0));
  let n010 = hash_3f(i + vec3<f32>(0.0, 1.0, 0.0));
  let n110 = hash_3f(i + vec3<f32>(1.0, 1.0, 0.0));
  let n001 = hash_3f(i + vec3<f32>(0.0, 0.0, 1.0));
  let n101 = hash_3f(i + vec3<f32>(1.0, 0.0, 1.0));
  let n011 = hash_3f(i + vec3<f32>(0.0, 1.0, 1.0));
  let n111 = hash_3f(i + vec3<f32>(1.0, 1.0, 1.0));
  let ix00 = mix(n000, n100, u.x);
  let ix10 = mix(n010, n110, u.x);
  let ix01 = mix(n001, n101, u.x);
  let ix11 = mix(n011, n111, u.x);
  let iy0 = mix(ix00, ix10, u.y);
  let iy1 = mix(ix01, ix11, u.y);
  return mix(iy0, iy1, u.z);
}

// ============================================
// Special Functions
// ============================================

// Gyroid function (periodic triply-orthogonal minimal surface)
// Useful for procedural patterns and cellular structures
fn gyroid(p: vec3<f32>) -> f32 {
  return abs(0.04 + dot(sin(p), cos(p.zxy)));
}

// Fractional Brownian Motion (FBM) 2D
// Multi-octave noise for natural-looking variation
fn fbm_2d(p: vec2<f32>, octaves: i32) -> f32 {
  var value = 0.0;
  var amplitude = 0.5;
  var frequency = 1.0;
  var pos = p;
  for (var i = 0; i < octaves; i++) {
    value += amplitude * noise_2d(pos * frequency);
    frequency *= 2.0;
    amplitude *= 0.5;
  }
  return value;
}

// Fractional Brownian Motion (FBM) 3D
fn fbm_3d(p: vec3<f32>, octaves: i32) -> f32 {
  var value = 0.0;
  var amplitude = 0.5;
  var frequency = 1.0;
  var pos = p;
  for (var i = 0; i < octaves; i++) {
    value += amplitude * noise_3d(pos * frequency);
    frequency *= 2.0;
    amplitude *= 0.5;
  }
  return value;
}