@aethervtt/shard-noise 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +3 -0
- package/dist/compile.d.ts +61 -0
- package/dist/compile.js +375 -0
- package/dist/gpu.d.ts +11 -0
- package/dist/gpu.js +15 -0
- package/dist/graph.d.ts +44 -0
- package/dist/graph.js +370 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +127 -0
- package/dist/kernel.d.ts +99 -0
- package/dist/kernel.js +263 -0
- package/dist/loader.d.ts +25 -0
- package/dist/loader.js +108 -0
- package/dist/methods.d.ts +9 -0
- package/dist/methods.js +119 -0
- package/dist/nodes.d.ts +74 -0
- package/dist/nodes.js +366 -0
- package/dist/noise-graph.d.ts +80 -0
- package/dist/noise-graph.js +258 -0
- package/dist/planet.d.ts +44 -0
- package/dist/planet.js +15 -0
- package/dist/plugin.d.ts +2 -0
- package/dist/plugin.js +18 -0
- package/dist/reference.d.ts +9 -0
- package/dist/reference.js +97 -0
- package/dist/sample.d.ts +67 -0
- package/dist/sample.js +232 -0
- package/dist/schema.d.ts +2 -0
- package/dist/schema.js +132 -0
- package/dist/stats.d.ts +58 -0
- package/dist/stats.js +164 -0
- package/dist/wgsl.d.ts +17 -0
- package/dist/wgsl.js +641 -0
- package/dist/worker.js +58 -0
- package/package.json +39 -0
- package/wasm/shard_noise.wasm +0 -0
- package/wasm/shard_noise_simd.wasm +0 -0
package/dist/stats.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { ShardError } from "@aethervtt/shard-core";
|
|
2
|
+
import { sampleGrid2d, sampleOffset, sampleSpherePatch } from "./sample.js";
|
|
3
|
+
const HISTOGRAM_BINS = 16;
|
|
4
|
+
function noiseStats(graph, seed, domain = {}, options = {}) {
|
|
5
|
+
const { values, weights } = sampleDomain(graph, seed, domain, options.node);
|
|
6
|
+
let min = Infinity;
|
|
7
|
+
let max = -Infinity;
|
|
8
|
+
let total = 0;
|
|
9
|
+
let sum = 0;
|
|
10
|
+
for (let i = 0; i < values.length; i++) {
|
|
11
|
+
const v = values[i];
|
|
12
|
+
const w = weights ? weights[i] : 1;
|
|
13
|
+
if (v < min) min = v;
|
|
14
|
+
if (v > max) max = v;
|
|
15
|
+
total += w;
|
|
16
|
+
sum += v * w;
|
|
17
|
+
}
|
|
18
|
+
const mean = sum / total;
|
|
19
|
+
let variance = 0;
|
|
20
|
+
for (let i = 0; i < values.length; i++) {
|
|
21
|
+
const d = values[i] - mean;
|
|
22
|
+
variance += d * d * (weights ? weights[i] : 1);
|
|
23
|
+
}
|
|
24
|
+
const bins = new Array(HISTOGRAM_BINS).fill(0);
|
|
25
|
+
const span = max - min || 1;
|
|
26
|
+
const thresholds = options.thresholds ?? [];
|
|
27
|
+
const below = thresholds.map(() => 0);
|
|
28
|
+
for (let i = 0; i < values.length; i++) {
|
|
29
|
+
const v = values[i];
|
|
30
|
+
const w = weights ? weights[i] : 1;
|
|
31
|
+
bins[Math.min(HISTOGRAM_BINS - 1, Math.floor((v - min) / span * HISTOGRAM_BINS))] += w;
|
|
32
|
+
for (let t = 0; t < thresholds.length; t++) if (v < thresholds[t]) below[t] += w;
|
|
33
|
+
}
|
|
34
|
+
const r = (x) => Math.round(x * 1e6) / 1e6;
|
|
35
|
+
return {
|
|
36
|
+
samples: values.length,
|
|
37
|
+
min: r(min),
|
|
38
|
+
max: r(max),
|
|
39
|
+
mean: r(mean),
|
|
40
|
+
stdDev: r(Math.sqrt(variance / total)),
|
|
41
|
+
histogram: { from: r(min), to: r(max), bins: bins.map((b) => r(b / total)) },
|
|
42
|
+
below: thresholds.map((threshold, t) => ({ threshold, fraction: r(below[t] / total) }))
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function sampleDomain(graph, seed, domain, node) {
|
|
46
|
+
if (graph.program.dimensions === 4) {
|
|
47
|
+
throw new ShardError("noise/domain-mismatch", "Stats sample 3D domains; this graph is 4D", {
|
|
48
|
+
hint: "Use noise.sample with xyzw points for 4D graphs."
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
const extent = graph.graph.extent;
|
|
52
|
+
if ((domain.kind ?? "plane") === "plane") {
|
|
53
|
+
const size = domain.size ?? (extent ? extent * 2 : 4);
|
|
54
|
+
const n2 = domain.resolution ?? 256;
|
|
55
|
+
const values2 = new Float32Array(n2 * n2);
|
|
56
|
+
sampleGrid2d(graph, seed, { origin: [-size / 2, -size / 2], size, resolution: n2 }, values2, node);
|
|
57
|
+
return { values: values2 };
|
|
58
|
+
}
|
|
59
|
+
const radius = domain.radius ?? extent ?? 1;
|
|
60
|
+
const n = domain.resolution ?? 105;
|
|
61
|
+
const values = new Float32Array(6 * n * n);
|
|
62
|
+
const weights = new Float64Array(6 * n * n);
|
|
63
|
+
const face = new Float32Array(n * n);
|
|
64
|
+
const step = 2 / n;
|
|
65
|
+
for (let f = 0; f < 6; f++) {
|
|
66
|
+
const x0 = -1 + step / 2;
|
|
67
|
+
const extentUv = step * (n - 1);
|
|
68
|
+
sampleSpherePatch(
|
|
69
|
+
graph,
|
|
70
|
+
seed,
|
|
71
|
+
{ face: f, x0, y0: x0, extent: extentUv, resolution: n, radius },
|
|
72
|
+
face,
|
|
73
|
+
node
|
|
74
|
+
);
|
|
75
|
+
values.set(face, f * n * n);
|
|
76
|
+
for (let j = 0; j < n; j++) {
|
|
77
|
+
const tv = Math.tan(Math.PI / 4 * (x0 + j * step));
|
|
78
|
+
for (let i = 0; i < n; i++) {
|
|
79
|
+
const tu = Math.tan(Math.PI / 4 * (x0 + i * step));
|
|
80
|
+
weights[f * n * n + j * n + i] = (1 + tu * tu) * (1 + tv * tv) * (1 + tu * tu + tv * tv) ** -1.5;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return { values, weights };
|
|
85
|
+
}
|
|
86
|
+
function previewNoise(graph, width, height, options = {}) {
|
|
87
|
+
if (options.size) {
|
|
88
|
+
width = options.size;
|
|
89
|
+
height = options.size;
|
|
90
|
+
}
|
|
91
|
+
const seed = options.seed ?? 0;
|
|
92
|
+
const extent = graph.graph.extent;
|
|
93
|
+
const values = new Float32Array(width * height);
|
|
94
|
+
const inside = new Uint8Array(width * height).fill(1);
|
|
95
|
+
if ((options.domain ?? "plane") === "plane") {
|
|
96
|
+
const size = options.span ?? (extent ? extent * 2 : 4);
|
|
97
|
+
const aspect = height / width;
|
|
98
|
+
sampleGrid2d(
|
|
99
|
+
graph,
|
|
100
|
+
seed,
|
|
101
|
+
{
|
|
102
|
+
origin: [-size / 2, -size * aspect / 2],
|
|
103
|
+
size: [size, size * aspect],
|
|
104
|
+
resolution: [width, height]
|
|
105
|
+
},
|
|
106
|
+
values,
|
|
107
|
+
options.node
|
|
108
|
+
);
|
|
109
|
+
const row = new Float32Array(width);
|
|
110
|
+
for (let j = 0; j < height >> 1; j++) {
|
|
111
|
+
const a = j * width;
|
|
112
|
+
const b = (height - 1 - j) * width;
|
|
113
|
+
row.set(values.subarray(a, a + width));
|
|
114
|
+
values.copyWithin(a, b, b + width);
|
|
115
|
+
values.set(row, b);
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
const radius = options.span ?? extent ?? 1;
|
|
119
|
+
const origin = [0, 0, radius];
|
|
120
|
+
const local = new Float32Array(width * height * 3);
|
|
121
|
+
const d = new Float64Array(3);
|
|
122
|
+
for (let j = 0; j < height; j++) {
|
|
123
|
+
for (let i = 0; i < width; i++) {
|
|
124
|
+
const x = (i + 0.5) / width * 2 - 1;
|
|
125
|
+
const y = 1 - (j + 0.5) / height * 2;
|
|
126
|
+
const r2 = x * x + y * y;
|
|
127
|
+
const k = j * width + i;
|
|
128
|
+
if (r2 > 1) {
|
|
129
|
+
inside[k] = 0;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
d[0] = x;
|
|
133
|
+
d[1] = y;
|
|
134
|
+
d[2] = Math.sqrt(1 - r2);
|
|
135
|
+
local[k * 3] = d[0] * radius;
|
|
136
|
+
local[k * 3 + 1] = d[1] * radius;
|
|
137
|
+
local[k * 3 + 2] = d[2] * radius - radius;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
sampleOffset(graph, seed, origin, local, values, options.node);
|
|
141
|
+
}
|
|
142
|
+
let min = Infinity;
|
|
143
|
+
let max = -Infinity;
|
|
144
|
+
for (let k = 0; k < values.length; k++) {
|
|
145
|
+
if (!inside[k]) continue;
|
|
146
|
+
min = Math.min(min, values[k]);
|
|
147
|
+
max = Math.max(max, values[k]);
|
|
148
|
+
}
|
|
149
|
+
const scale = max > min ? 255 / (max - min) : 0;
|
|
150
|
+
const data = new Uint8Array(width * height * 4);
|
|
151
|
+
for (let k = 0; k < values.length; k++) {
|
|
152
|
+
if (!inside[k]) continue;
|
|
153
|
+
const g = Math.round((values[k] - min) * scale);
|
|
154
|
+
data[k * 4] = g;
|
|
155
|
+
data[k * 4 + 1] = g;
|
|
156
|
+
data[k * 4 + 2] = g;
|
|
157
|
+
data[k * 4 + 3] = 255;
|
|
158
|
+
}
|
|
159
|
+
return { width, height, data, min, max };
|
|
160
|
+
}
|
|
161
|
+
export {
|
|
162
|
+
noiseStats,
|
|
163
|
+
previewNoise
|
|
164
|
+
};
|
package/dist/wgsl.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type NoiseProgram } from './compile.js';
|
|
2
|
+
/**
|
|
3
|
+
* `shard::noise`: the sources and helpers, mirroring `crates/shard-noise` operation for operation
|
|
4
|
+
* (same constants, same evaluation order) so GPU results match the CPU within the tolerance.
|
|
5
|
+
*/
|
|
6
|
+
export declare const NOISE_LIBRARY = "\nconst PX: u32 = 501125321u;\nconst PY: u32 = 1136930381u;\nconst PZ: u32 = 1720413743u;\nconst PW: u32 = 1066037191u;\nconst SEED_FLIP_3D: u32 = 0x52d547b3u;\nconst SQRT_2: f32 = 1.4142135623730951;\nconst LN_2: f32 = 0.6931471805599453;\nconst G2: f32 = 0.2113248654051871;\nconst G4: f32 = 0.1381966011250105;\nconst F2: f32 = 0.3660254037844386;\nconst F4: f32 = 0.3090169943749474;\nconst TWO_THIRDS: f32 = 2.0 / 3.0;\nconst PERLIN2_SCALE: f32 = 1.0;\nconst PERLIN3_SCALE: f32 = 1.0;\nconst SIMPLEX2_SCALE: f32 = 70.0;\nconst SIMPLEX3_SCALE: f32 = 32.0;\nconst SIMPLEX4_SCALE: f32 = 27.0;\n\n/** One source octave's lattice origin: the integer cell and the fraction (from the CPU, in f64). */\nstruct NoiseOrigin {\n cell: vec4i,\n frac: vec4f,\n}\n\nfn mix32(x: u32) -> u32 {\n var h = x ^ (x >> 16u);\n h = h * 0x7feb352du;\n h = h ^ (h >> 15u);\n h = h * 0x846ca68bu;\n return h ^ (h >> 16u);\n}\n\nfn fnv(h: u32, b: u32) -> u32 {\n return (h ^ b) * 0x01000193u;\n}\n\n/** hashSeed(seed, label) from @aethervtt/shard-core, for a numeric label. */\nfn hash_seed(seed: u32, label: u32) -> u32 {\n var h = 0x811c9dc5u;\n h = fnv(h, label & 0xffu);\n h = fnv(h, (label >> 8u) & 0xffu);\n h = fnv(h, (label >> 16u) & 0xffu);\n h = fnv(h, label >> 24u);\n return ((seed ^ h) * 0x9e3779b1u) ^ fnv(h, 0x23u);\n}\n\nfn hash2(seed: u32, x: u32, y: u32) -> u32 { return mix32(seed ^ x ^ y); }\nfn hash3(seed: u32, x: u32, y: u32, z: u32) -> u32 { return mix32(seed ^ x ^ y ^ z); }\nfn hash4(seed: u32, x: u32, y: u32, z: u32, w: u32) -> u32 { return mix32(seed ^ x ^ y ^ z ^ w); }\n\nfn to_value(h: u32) -> f32 {\n return f32(h >> 8u) * (2.0 / 16777215.0) - 1.0;\n}\n\nfn flip(x: f32, s: u32) -> f32 {\n return bitcast<f32>(bitcast<u32>(x) ^ s);\n}\n\nfn fade(t: f32) -> f32 {\n return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);\n}\n\nfn lerp(a: f32, b: f32, t: f32) -> f32 {\n return a + t * (b - a);\n}\n\nfn grad_hash2(seed: u32, x: u32, y: u32) -> u32 { return ((seed ^ x ^ y) * 0x27d4eb2du) >> 29u; }\nfn grad_hash3(seed: u32, x: u32, y: u32, z: u32) -> u32 { return ((seed ^ x ^ y ^ z) * 0x27d4eb2du) >> 28u; }\nfn grad_hash4(seed: u32, x: u32, y: u32, z: u32, w: u32) -> u32 { return ((seed ^ x ^ y ^ z ^ w) * 0x27d4eb2du) >> 27u; }\n\nfn grad2(h: u32, x: f32, y: f32) -> f32 {\n let s0 = h << 31u;\n let s1 = (h & 2u) << 30u;\n let diag = flip(x, s0) + flip(y, s1);\n let axis = flip(select(y, x, (h & 2u) == 0u), s0) * SQRT_2;\n return select(axis, diag, h < 4u);\n}\n\nfn grad3(g: u32, x: f32, y: f32, z: f32) -> f32 {\n let drop = g >> 2u;\n let a = select(x, y, drop == 0u);\n let b = select(z, y, drop == 2u);\n return flip(a, g << 31u) + flip(b, (g & 2u) << 30u);\n}\n\nfn grad4(h: u32, x: f32, y: f32, z: f32, w: f32) -> f32 {\n let axis = h >> 3u;\n let a = select(x, y, axis == 0u);\n let b = select(y, z, axis < 2u);\n let d = select(z, w, axis < 3u);\n return flip(a, h << 31u) + flip(b, (h & 2u) << 30u) + flip(d, (h & 4u) << 29u);\n}\n\nfn unit(v: f32) -> f32 {\n return clamp(v, -1.0, 1.0);\n}\n\nfn value2(seed: u32, ix: i32, iy: i32, px: f32, py: f32) -> f32 {\n let fx = floor(px);\n let fy = floor(py);\n let x0 = bitcast<u32>(ix + i32(fx)) * PX;\n let y0 = bitcast<u32>(iy + i32(fy)) * PY;\n let x1 = x0 + PX;\n let y1 = y0 + PY;\n let u = fade(px - fx);\n let v = fade(py - fy);\n let a = lerp(to_value(hash2(seed, x0, y0)), to_value(hash2(seed, x1, y0)), u);\n let b = lerp(to_value(hash2(seed, x0, y1)), to_value(hash2(seed, x1, y1)), u);\n return lerp(a, b, v);\n}\n\nfn value3(seed: u32, ix: i32, iy: i32, iz: i32, px: f32, py: f32, pz: f32) -> f32 {\n let fx = floor(px);\n let fy = floor(py);\n let fz = floor(pz);\n let x0 = bitcast<u32>(ix + i32(fx)) * PX;\n let y0 = bitcast<u32>(iy + i32(fy)) * PY;\n let z0 = bitcast<u32>(iz + i32(fz)) * PZ;\n let x1 = x0 + PX;\n let y1 = y0 + PY;\n let z1 = z0 + PZ;\n let u = fade(px - fx);\n let v = fade(py - fy);\n let w = fade(pz - fz);\n let a = lerp(to_value(hash3(seed, x0, y0, z0)), to_value(hash3(seed, x1, y0, z0)), u);\n let b = lerp(to_value(hash3(seed, x0, y1, z0)), to_value(hash3(seed, x1, y1, z0)), u);\n let d = lerp(to_value(hash3(seed, x0, y0, z1)), to_value(hash3(seed, x1, y0, z1)), u);\n let e = lerp(to_value(hash3(seed, x0, y1, z1)), to_value(hash3(seed, x1, y1, z1)), u);\n return lerp(lerp(a, b, v), lerp(d, e, v), w);\n}\n\nfn perlin2(seed: u32, ix: i32, iy: i32, px: f32, py: f32) -> f32 {\n let fx = floor(px);\n let fy = floor(py);\n let tx = px - fx;\n let ty = py - fy;\n let x0 = bitcast<u32>(ix + i32(fx)) * PX;\n let y0 = bitcast<u32>(iy + i32(fy)) * PY;\n let x1 = x0 + PX;\n let y1 = y0 + PY;\n let tx1 = tx - 1.0;\n let ty1 = ty - 1.0;\n let u = fade(tx);\n let v = fade(ty);\n let a = lerp(grad2(grad_hash2(seed, x0, y0), tx, ty), grad2(grad_hash2(seed, x1, y0), tx1, ty), u);\n let b = lerp(grad2(grad_hash2(seed, x0, y1), tx, ty1), grad2(grad_hash2(seed, x1, y1), tx1, ty1), u);\n return unit(lerp(a, b, v) * PERLIN2_SCALE);\n}\n\nfn perlin3(seed: u32, ix: i32, iy: i32, iz: i32, px: f32, py: f32, pz: f32) -> f32 {\n let fx = floor(px);\n let fy = floor(py);\n let fz = floor(pz);\n let tx = px - fx;\n let ty = py - fy;\n let tz = pz - fz;\n let x0 = bitcast<u32>(ix + i32(fx)) * PX;\n let y0 = bitcast<u32>(iy + i32(fy)) * PY;\n let z0 = bitcast<u32>(iz + i32(fz)) * PZ;\n let x1 = x0 + PX;\n let y1 = y0 + PY;\n let z1 = z0 + PZ;\n let tx1 = tx - 1.0;\n let ty1 = ty - 1.0;\n let tz1 = tz - 1.0;\n let u = fade(tx);\n let v = fade(ty);\n let w = fade(tz);\n let a = lerp(grad3(grad_hash3(seed, x0, y0, z0), tx, ty, tz), grad3(grad_hash3(seed, x1, y0, z0), tx1, ty, tz), u);\n let b = lerp(grad3(grad_hash3(seed, x0, y1, z0), tx, ty1, tz), grad3(grad_hash3(seed, x1, y1, z0), tx1, ty1, tz), u);\n let d = lerp(grad3(grad_hash3(seed, x0, y0, z1), tx, ty, tz1), grad3(grad_hash3(seed, x1, y0, z1), tx1, ty, tz1), u);\n let e = lerp(grad3(grad_hash3(seed, x0, y1, z1), tx, ty1, tz1), grad3(grad_hash3(seed, x1, y1, z1), tx1, ty1, tz1), u);\n return unit(lerp(lerp(a, b, v), lerp(d, e, v), w) * PERLIN3_SCALE);\n}\n\nfn falloff(r2: f32, d2: f32) -> f32 {\n let a = max(r2 - d2, 0.0);\n let a2 = a * a;\n return a2 * a2;\n}\n\nfn simplex2(seed: u32, ix: i32, iy: i32, px: f32, py: f32) -> f32 {\n let fx = floor(px);\n let fy = floor(py);\n let xi = px - fx;\n let yi = py - fy;\n let t = (xi + yi) * G2;\n let x0 = xi - t;\n let y0 = yi - t;\n let xb = bitcast<u32>(ix + i32(fx)) * PX;\n let yb = bitcast<u32>(iy + i32(fy)) * PY;\n let lower = y0 < x0;\n let i1 = select(0.0, 1.0, lower);\n let j1 = 1.0 - i1;\n let x1 = x0 - i1 + G2;\n let y1 = y0 - j1 + G2;\n let x2 = x0 - 1.0 + 2.0 * G2;\n let y2 = y0 - 1.0 + 2.0 * G2;\n let h0 = grad_hash2(seed, xb, yb);\n let h1 = grad_hash2(seed, xb + select(0u, PX, lower), yb + select(PY, 0u, lower));\n let h2 = grad_hash2(seed, xb + PX, yb + PY);\n let n0 = falloff(0.5, x0 * x0 + y0 * y0) * grad2(h0, x0, y0);\n let n1 = falloff(0.5, x1 * x1 + y1 * y1) * grad2(h1, x1, y1);\n let n2 = falloff(0.5, x2 * x2 + y2 * y2) * grad2(h2, x2, y2);\n return unit((n0 + n1 + n2) * SIMPLEX2_SCALE);\n}\n\nfn simplex3(seed: u32, ix: i32, iy: i32, iz: i32, px: f32, py: f32, pz: f32) -> f32 {\n let rx = round(px);\n let ry = round(py);\n let rz = round(pz);\n var xb = bitcast<u32>(ix + i32(rx)) * PX;\n var yb = bitcast<u32>(iy + i32(ry)) * PY;\n var zb = bitcast<u32>(iz + i32(rz)) * PZ;\n var xr = px - rx;\n var yr = py - ry;\n var zr = pz - rz;\n var xs = select(-1, 1, xr < 0.0);\n var ys = select(-1, 1, yr < 0.0);\n var zs = select(-1, 1, zr < 0.0);\n var ax = abs(xr);\n var ay = abs(yr);\n var az = abs(zr);\n var a = (0.6 - xr * xr) - (yr * yr + zr * zr);\n var s = seed;\n var value = 0.0;\n for (var l = 0; l < 2; l++) {\n let a0 = max(a, 0.0);\n let a2 = a0 * a0;\n value = value + a2 * a2 * grad3(grad_hash3(s, xb, yb, zb), xr, yr, zr);\n let mx = ax >= ay && ax >= az;\n let my = !mx && ay >= az;\n let mz = !(mx || my);\n let am = select(select(az, ay, my), ax, mx);\n let b0 = max(a + am + am - 1.0, 0.0);\n let b2 = b0 * b0;\n let hx = xb - select(0u, bitcast<u32>(xs) * PX, mx);\n let hy = yb - select(0u, bitcast<u32>(ys) * PY, my);\n let hz = zb - select(0u, bitcast<u32>(zs) * PZ, mz);\n let ox = xr + select(0.0, f32(xs), mx);\n let oy = yr + select(0.0, f32(ys), my);\n let oz = zr + select(0.0, f32(zs), mz);\n value = value + b2 * b2 * grad3(grad_hash3(s, hx, hy, hz), ox, oy, oz);\n if (l == 1) { break; }\n ax = 0.5 - ax;\n ay = 0.5 - ay;\n az = 0.5 - az;\n xr = f32(xs) * ax;\n yr = f32(ys) * ay;\n zr = f32(zs) * az;\n a = a + ((0.75 - ax) - (ay + az));\n xb = xb + select(0u, PX, xs == -1);\n yb = yb + select(0u, PY, ys == -1);\n zb = zb + select(0u, PZ, zs == -1);\n xs = -xs;\n ys = -ys;\n zs = -zs;\n s = s ^ SEED_FLIP_3D;\n }\n return unit(value * SIMPLEX3_SCALE);\n}\n\nfn simplex4(seed: u32, ix: i32, iy: i32, iz: i32, iw: i32, px: f32, py: f32, pz: f32, pw: f32) -> f32 {\n let fx = floor(px);\n let fy = floor(py);\n let fz = floor(pz);\n let fw = floor(pw);\n let xi = px - fx;\n let yi = py - fy;\n let zi = pz - fz;\n let wi = pw - fw;\n let t = (xi + yi + zi + wi) * G4;\n let x0 = xi - t;\n let y0 = yi - t;\n let z0 = zi - t;\n let w0 = wi - t;\n var rx = 0;\n var ry = 0;\n var rz = 0;\n var rw = 0;\n if (y0 < x0) { rx += 1; } else { ry += 1; }\n if (z0 < x0) { rx += 1; } else { rz += 1; }\n if (w0 < x0) { rx += 1; } else { rw += 1; }\n if (z0 < y0) { ry += 1; } else { rz += 1; }\n if (w0 < y0) { ry += 1; } else { rw += 1; }\n if (w0 < z0) { rz += 1; } else { rw += 1; }\n let xb = bitcast<u32>(ix + i32(fx)) * PX;\n let yb = bitcast<u32>(iy + i32(fy)) * PY;\n let zb = bitcast<u32>(iz + i32(fz)) * PZ;\n let wb = bitcast<u32>(iw + i32(fw)) * PW;\n var value = 0.0;\n for (var k = 0; k < 5; k++) {\n let at = 4 - k;\n let sx = rx >= at;\n let sy = ry >= at;\n let sz = rz >= at;\n let sw = rw >= at;\n let off = f32(k) * G4;\n let x = x0 - select(0.0, 1.0, sx) + off;\n let y = y0 - select(0.0, 1.0, sy) + off;\n let z = z0 - select(0.0, 1.0, sz) + off;\n let w = w0 - select(0.0, 1.0, sw) + off;\n let h = grad_hash4(seed, xb + select(0u, PX, sx), yb + select(0u, PY, sy), zb + select(0u, PZ, sz), wb + select(0u, PW, sw));\n value = value + falloff(0.6, x * x + y * y + z * z + w * w) * grad4(h, x, y, z, w);\n }\n return unit(value * SIMPLEX4_SCALE);\n}\n\nfn jitter_of(h: u32, shift: u32) -> f32 {\n return f32((h >> shift) & 1023u) * (1.0 / 1023.0) - 0.5;\n}\n\nfn cell_result(ret: i32, metric: i32, b1: f32, b2: f32, bh: u32) -> f32 {\n var d1 = b1;\n var d2 = b2;\n if (metric == 0) {\n d1 = sqrt(b1);\n d2 = sqrt(b2);\n }\n if (ret == 0) { return d1; }\n if (ret == 1) { return d2; }\n if (ret == 2) { return d2 - d1; }\n return to_value(mix32(bh));\n}\n\nfn cell_distance(metric: i32, fx: f32, fy: f32, fz: f32) -> f32 {\n if (metric == 1) { return abs(fx) + abs(fy) + abs(fz); }\n if (metric == 2) { return max(max(abs(fx), abs(fy)), abs(fz)); }\n return fx * fx + fy * fy + fz * fz;\n}\n\nfn cellular2(seed: u32, ix: i32, iy: i32, px: f32, py: f32, jitter: f32, metric: i32, ret: i32) -> f32 {\n let fx0 = floor(px);\n let fy0 = floor(py);\n let tx = px - fx0;\n let ty = py - fy0;\n let xb = bitcast<u32>(ix + i32(fx0)) * PX;\n let yb = bitcast<u32>(iy + i32(fy0)) * PY;\n var b1 = 1e10;\n var b2 = 1e10;\n var bh = 0u;\n for (var dy = -1; dy <= 1; dy++) {\n for (var dx = -1; dx <= 1; dx++) {\n let h = hash2(seed, xb + bitcast<u32>(dx) * PX, yb + bitcast<u32>(dy) * PY);\n let fx = f32(dx) + 0.5 + jitter * jitter_of(h, 0u) - tx;\n let fy = f32(dy) + 0.5 + jitter * jitter_of(h, 10u) - ty;\n var d = fx * fx + fy * fy;\n if (metric == 1) { d = abs(fx) + abs(fy); }\n if (metric == 2) { d = max(abs(fx), abs(fy)); }\n let m = d < b1;\n b2 = select(min(b2, d), b1, m);\n bh = select(bh, h, m);\n b1 = select(b1, d, m);\n }\n }\n return cell_result(ret, metric, b1, b2, bh);\n}\n\nfn cellular3(seed: u32, ix: i32, iy: i32, iz: i32, px: f32, py: f32, pz: f32, jitter: f32, metric: i32, ret: i32) -> f32 {\n let fx0 = floor(px);\n let fy0 = floor(py);\n let fz0 = floor(pz);\n let tx = px - fx0;\n let ty = py - fy0;\n let tz = pz - fz0;\n let xb = bitcast<u32>(ix + i32(fx0)) * PX;\n let yb = bitcast<u32>(iy + i32(fy0)) * PY;\n let zb = bitcast<u32>(iz + i32(fz0)) * PZ;\n var b1 = 1e10;\n var b2 = 1e10;\n var bh = 0u;\n for (var dz = -1; dz <= 1; dz++) {\n for (var dy = -1; dy <= 1; dy++) {\n for (var dx = -1; dx <= 1; dx++) {\n let h = hash3(seed, xb + bitcast<u32>(dx) * PX, yb + bitcast<u32>(dy) * PY, zb + bitcast<u32>(dz) * PZ);\n let fx = f32(dx) + 0.5 + jitter * jitter_of(h, 0u) - tx;\n let fy = f32(dy) + 0.5 + jitter * jitter_of(h, 10u) - ty;\n let fz = f32(dz) + 0.5 + jitter * jitter_of(h, 20u) - tz;\n let d = cell_distance(metric, fx, fy, fz);\n let m = d < b1;\n b2 = select(min(b2, d), b1, m);\n bh = select(bh, h, m);\n b1 = select(b1, d, m);\n }\n }\n }\n return cell_result(ret, metric, b1, b2, bh);\n}\n\nfn nlog2(x: f32) -> f32 {\n let bits = bitcast<i32>(x);\n let big0 = bitcast<f32>((bits & 0x007fffff) | 0x3f800000);\n let big = big0 > SQRT_2;\n let m = select(big0, big0 * 0.5, big);\n let e = f32(((bits >> 23u) & 0xff) - 127 + select(0, 1, big));\n let s = (m - 1.0) / (m + 1.0);\n let s2 = s * s;\n var p = 1.0 / 9.0;\n p = 1.0 / 7.0 + s2 * p;\n p = 1.0 / 5.0 + s2 * p;\n p = 1.0 / 3.0 + s2 * p;\n p = 1.0 + s2 * p;\n return e + s * p * (2.0 / LN_2);\n}\n\nfn nexp2(y0: f32) -> f32 {\n let y = clamp(y0, -126.0, 126.0);\n let n = floor(y + 0.5);\n let t = (y - n) * LN_2;\n var p = 1.0 / 720.0;\n p = 1.0 / 120.0 + t * p;\n p = 1.0 / 24.0 + t * p;\n p = 1.0 / 6.0 + t * p;\n p = 0.5 + t * p;\n p = 1.0 + t * p;\n p = 1.0 + t * p;\n return p * bitcast<f32>((i32(n) + 127) << 23u);\n}\n\n/** sign(x) \u00D7 |x|^e, and 0 for |x| below 1e-30 (the kernel's power). */\nfn pow_signed(x: f32, e: f32) -> f32 {\n let a = abs(x);\n let v = select(nexp2(e * nlog2(max(a, 1e-30))), 0.0, a < 1e-30);\n return flip(v, bitcast<u32>(x) & 0x80000000u);\n}\n";
|
|
7
|
+
export interface WgslOptions {
|
|
8
|
+
/** Function name: `noise_<name>`. */
|
|
9
|
+
readonly name: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Generates the graph's WGSL: straight-line code, one `let` per instruction in program order, with
|
|
13
|
+
* every constant inlined. Exports `noise_<name>(p, seed)` for positions near the origin and
|
|
14
|
+
* `noise_<name>_at(origin, local, seed)`, which reads per-octave origin records
|
|
15
|
+
* (`noiseOrigins(graph, origin)` on the CPU) so precision doesn't depend on where `local` is.
|
|
16
|
+
*/
|
|
17
|
+
export declare function generateWgsl(program: NoiseProgram, options: WgslOptions): string;
|