@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/graph.js
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
import { ShardError } from "@aethervtt/shard-core";
|
|
2
|
+
import { MAX_OCTAVES, nodeDef } from "./nodes.js";
|
|
3
|
+
function pointer(segment) {
|
|
4
|
+
return segment.replaceAll("~", "~0").replaceAll("/", "~1");
|
|
5
|
+
}
|
|
6
|
+
const fail = (code, path, message, hint) => new ShardError(code, message, { path, ...hint ? { hint } : {} });
|
|
7
|
+
function isObject(v) {
|
|
8
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
9
|
+
}
|
|
10
|
+
function parseGraph(json) {
|
|
11
|
+
const errors = [];
|
|
12
|
+
if (!isObject(json)) {
|
|
13
|
+
errors.push(
|
|
14
|
+
new ShardError("noise/invalid-graph", "A noise graph is a JSON object", {
|
|
15
|
+
path: "",
|
|
16
|
+
hint: 'Start from { "output": "height", "nodes": { \u2026 } }.'
|
|
17
|
+
})
|
|
18
|
+
);
|
|
19
|
+
return { errors };
|
|
20
|
+
}
|
|
21
|
+
for (const key of Object.keys(json)) {
|
|
22
|
+
if (!["$schema", "output", "nodes", "dimensions", "extent", "description"].includes(key)) {
|
|
23
|
+
errors.push(
|
|
24
|
+
fail(
|
|
25
|
+
"noise/invalid-graph",
|
|
26
|
+
`/${pointer(key)}`,
|
|
27
|
+
`Unknown graph field "${key}"`,
|
|
28
|
+
"Graph fields: output, nodes, dimensions, extent, description."
|
|
29
|
+
)
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const dimensions = json.dimensions ?? 3;
|
|
34
|
+
if (dimensions !== 2 && dimensions !== 3 && dimensions !== 4) {
|
|
35
|
+
errors.push(fail("noise/invalid-graph", "/dimensions", '"dimensions" must be 2, 3, or 4'));
|
|
36
|
+
}
|
|
37
|
+
const dims = dimensions === 2 || dimensions === 4 ? dimensions : 3;
|
|
38
|
+
const extent = json.extent;
|
|
39
|
+
if (extent !== void 0 && (typeof extent !== "number" || !(extent > 0))) {
|
|
40
|
+
errors.push(
|
|
41
|
+
fail("noise/invalid-graph", "/extent", '"extent" must be a positive number of units')
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
if (json.description !== void 0 && typeof json.description !== "string") {
|
|
45
|
+
errors.push(fail("noise/invalid-graph", "/description", '"description" must be a string'));
|
|
46
|
+
}
|
|
47
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
48
|
+
if (!isObject(json.nodes) || Object.keys(json.nodes).length === 0) {
|
|
49
|
+
errors.push(
|
|
50
|
+
fail(
|
|
51
|
+
"noise/invalid-graph",
|
|
52
|
+
"/nodes",
|
|
53
|
+
'A graph needs a "nodes" object with at least one node',
|
|
54
|
+
'Add "nodes": { "height": { "fbm": { "octaves": 5 } } }.'
|
|
55
|
+
)
|
|
56
|
+
);
|
|
57
|
+
} else {
|
|
58
|
+
for (const [name, body] of Object.entries(json.nodes)) {
|
|
59
|
+
const node = parseNode(body, `/nodes/${pointer(name)}`, dims, errors);
|
|
60
|
+
if (node) nodes.set(name, node);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const output = json.output;
|
|
64
|
+
if (typeof output !== "string") {
|
|
65
|
+
errors.push(
|
|
66
|
+
fail("noise/invalid-graph", "/output", '"output" must name the node the graph returns')
|
|
67
|
+
);
|
|
68
|
+
} else if (isObject(json.nodes) && !(output in json.nodes)) {
|
|
69
|
+
errors.push(
|
|
70
|
+
fail(
|
|
71
|
+
"noise/unknown-node",
|
|
72
|
+
"/output",
|
|
73
|
+
`"output" names "${output}", which isn't a node`,
|
|
74
|
+
hintFor(output, json.nodes)
|
|
75
|
+
)
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
if (isObject(json.nodes)) {
|
|
79
|
+
for (const node of nodes.values()) checkRefs(node, json.nodes, errors);
|
|
80
|
+
checkCycles(nodes, errors);
|
|
81
|
+
}
|
|
82
|
+
if (errors.length > 0) return { errors };
|
|
83
|
+
return {
|
|
84
|
+
graph: {
|
|
85
|
+
output,
|
|
86
|
+
dimensions: dims,
|
|
87
|
+
extent,
|
|
88
|
+
description: json.description,
|
|
89
|
+
nodes
|
|
90
|
+
},
|
|
91
|
+
errors
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function hintFor(_name, nodes) {
|
|
95
|
+
const names = Object.keys(nodes);
|
|
96
|
+
return names.length > 0 ? `Nodes in this graph: ${names.join(", ")}.` : 'Add the node under "nodes".';
|
|
97
|
+
}
|
|
98
|
+
function parseInput(v, path, dims, errors) {
|
|
99
|
+
if (typeof v === "number") {
|
|
100
|
+
if (!Number.isFinite(v)) {
|
|
101
|
+
errors.push(
|
|
102
|
+
new ShardError("noise/invalid-param", "Numbers must be finite", {
|
|
103
|
+
path,
|
|
104
|
+
hint: "Check the parameter against .shard/schemas/noise.schema.json."
|
|
105
|
+
})
|
|
106
|
+
);
|
|
107
|
+
return void 0;
|
|
108
|
+
}
|
|
109
|
+
return { kind: "const", value: v };
|
|
110
|
+
}
|
|
111
|
+
if (typeof v === "string") return { kind: "ref", name: v, path };
|
|
112
|
+
if (isObject(v)) {
|
|
113
|
+
const node = parseNode(v, path, dims, errors);
|
|
114
|
+
return node ? { kind: "node", node } : void 0;
|
|
115
|
+
}
|
|
116
|
+
errors.push(
|
|
117
|
+
fail("noise/invalid-param", path, "An input is a node name, an inline node, or a number")
|
|
118
|
+
);
|
|
119
|
+
return void 0;
|
|
120
|
+
}
|
|
121
|
+
function parseNode(body, path, dims, errors) {
|
|
122
|
+
if (typeof body === "number") {
|
|
123
|
+
const def2 = nodeDef("constant");
|
|
124
|
+
return { type: "constant", def: def2, params: { value: body }, path };
|
|
125
|
+
}
|
|
126
|
+
if (!isObject(body) || Object.keys(body).length !== 1) {
|
|
127
|
+
errors.push(
|
|
128
|
+
new ShardError("noise/invalid-node", "A node is an object with exactly one key: its type", {
|
|
129
|
+
path,
|
|
130
|
+
hint: 'For example { "fbm": { "octaves": 5 } }.'
|
|
131
|
+
})
|
|
132
|
+
);
|
|
133
|
+
return void 0;
|
|
134
|
+
}
|
|
135
|
+
const [type, raw] = Object.entries(body)[0];
|
|
136
|
+
const def = nodeDef(type);
|
|
137
|
+
const at = `${path}/${pointer(type)}`;
|
|
138
|
+
if (!def) {
|
|
139
|
+
errors.push(
|
|
140
|
+
new ShardError("noise/unknown-type", `Unknown node type "${type}"`, {
|
|
141
|
+
path: at,
|
|
142
|
+
hint: "Types: value, perlin, simplex, cellular, fbm, ridged, billow, add, multiply, min, max, lerp, select, remap, clamp, curve, terrace, abs, power, constant, warp, scale, translate."
|
|
143
|
+
})
|
|
144
|
+
);
|
|
145
|
+
return void 0;
|
|
146
|
+
}
|
|
147
|
+
if (def.form === "value") {
|
|
148
|
+
if (typeof raw !== "number" || !Number.isFinite(raw)) {
|
|
149
|
+
errors.push(fail("noise/invalid-param", at, `"${type}" takes a number`));
|
|
150
|
+
return void 0;
|
|
151
|
+
}
|
|
152
|
+
return { type, def, params: { value: raw }, path: at };
|
|
153
|
+
}
|
|
154
|
+
if (def.form === "list") {
|
|
155
|
+
if (!Array.isArray(raw) || raw.length < 2) {
|
|
156
|
+
errors.push(
|
|
157
|
+
new ShardError("noise/arity", `"${type}" takes an array of two or more inputs`, {
|
|
158
|
+
path: at,
|
|
159
|
+
hint: 'Give it two or more inputs: node names, inline nodes, or numbers, e.g. ["a", "b"].'
|
|
160
|
+
})
|
|
161
|
+
);
|
|
162
|
+
return void 0;
|
|
163
|
+
}
|
|
164
|
+
const inputs = [];
|
|
165
|
+
raw.forEach((v, i) => {
|
|
166
|
+
const input = parseInput(v, `${at}/${i}`, dims, errors);
|
|
167
|
+
if (input) inputs.push(input);
|
|
168
|
+
});
|
|
169
|
+
return { type, def, params: { inputs }, path: at };
|
|
170
|
+
}
|
|
171
|
+
let fields;
|
|
172
|
+
if (def.form === "unary" && !isObject(raw)) fields = { input: raw };
|
|
173
|
+
else if (def.form === "unary" && isObject(raw) && !("input" in raw)) fields = { input: raw };
|
|
174
|
+
else if (isObject(raw)) fields = raw;
|
|
175
|
+
else {
|
|
176
|
+
errors.push(
|
|
177
|
+
fail(
|
|
178
|
+
"noise/invalid-node",
|
|
179
|
+
at,
|
|
180
|
+
`"${type}" takes an object of parameters`,
|
|
181
|
+
`Parameters: ${Object.keys(def.params).join(", ")}.`
|
|
182
|
+
)
|
|
183
|
+
);
|
|
184
|
+
return void 0;
|
|
185
|
+
}
|
|
186
|
+
const params = {};
|
|
187
|
+
for (const key of Object.keys(fields)) {
|
|
188
|
+
if (!(key in def.params)) {
|
|
189
|
+
errors.push(
|
|
190
|
+
fail(
|
|
191
|
+
"noise/invalid-param",
|
|
192
|
+
`${at}/${pointer(key)}`,
|
|
193
|
+
`"${type}" has no parameter "${key}"`,
|
|
194
|
+
`Parameters: ${Object.keys(def.params).join(", ")}.`
|
|
195
|
+
)
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
for (const [key, p] of Object.entries(def.params)) {
|
|
200
|
+
const value = parseParam(p, fields[key], `${at}/${pointer(key)}`, type, key, dims, errors);
|
|
201
|
+
if (value !== void 0) params[key] = value;
|
|
202
|
+
}
|
|
203
|
+
return { type, def, params, path: at };
|
|
204
|
+
}
|
|
205
|
+
function parseParam(p, v, path, type, key, dims, errors) {
|
|
206
|
+
const bad = (what) => {
|
|
207
|
+
errors.push(fail("noise/invalid-param", path, `"${type}.${key}" ${what}`, p.description));
|
|
208
|
+
return void 0;
|
|
209
|
+
};
|
|
210
|
+
if (v === void 0) {
|
|
211
|
+
if (p.type === "input") {
|
|
212
|
+
errors.push(fail("noise/arity", path, `"${type}" needs "${key}"`, p.description));
|
|
213
|
+
return void 0;
|
|
214
|
+
}
|
|
215
|
+
if (p.type === "points") {
|
|
216
|
+
errors.push(fail("noise/arity", path, `"${type}" needs "${key}"`, p.description));
|
|
217
|
+
return void 0;
|
|
218
|
+
}
|
|
219
|
+
if ("default" in p && p.default !== void 0) {
|
|
220
|
+
if (key === "dims" && dims === 2) return 2;
|
|
221
|
+
return p.default;
|
|
222
|
+
}
|
|
223
|
+
return void 0;
|
|
224
|
+
}
|
|
225
|
+
switch (p.type) {
|
|
226
|
+
case "input":
|
|
227
|
+
return parseInput(v, path, dims, errors);
|
|
228
|
+
case "number": {
|
|
229
|
+
if (typeof v !== "number" || !Number.isFinite(v)) return bad("must be a number");
|
|
230
|
+
if (p.positive && !(v > 0)) return bad("must be greater than 0");
|
|
231
|
+
if (p.min !== void 0 && v < p.min) return bad(`must be at least ${p.min}`);
|
|
232
|
+
if (p.max !== void 0 && v > p.max) return bad(`must be at most ${p.max}`);
|
|
233
|
+
return v;
|
|
234
|
+
}
|
|
235
|
+
case "integer": {
|
|
236
|
+
if (typeof v !== "number" || !Number.isInteger(v)) return bad("must be an integer");
|
|
237
|
+
if (key === "octaves" && v > MAX_OCTAVES) {
|
|
238
|
+
errors.push(
|
|
239
|
+
new ShardError(
|
|
240
|
+
"noise/too-many-octaves",
|
|
241
|
+
`"${type}" has ${v} octaves; the most is ${MAX_OCTAVES}`,
|
|
242
|
+
{
|
|
243
|
+
path,
|
|
244
|
+
hint: "Past 16 octaves the extra detail is below a pixel anywhere; raise frequency instead."
|
|
245
|
+
}
|
|
246
|
+
)
|
|
247
|
+
);
|
|
248
|
+
return void 0;
|
|
249
|
+
}
|
|
250
|
+
if (p.min !== void 0 && v < p.min) return bad(`must be at least ${p.min}`);
|
|
251
|
+
if (p.max !== void 0 && v > p.max) return bad(`must be at most ${p.max}`);
|
|
252
|
+
return v;
|
|
253
|
+
}
|
|
254
|
+
case "boolean":
|
|
255
|
+
return typeof v === "boolean" ? v : bad("must be true or false");
|
|
256
|
+
case "enum": {
|
|
257
|
+
if (!p.values.includes(v))
|
|
258
|
+
return bad(`must be one of ${p.values.join(", ")}`);
|
|
259
|
+
if (key === "dims" && v === 4 && dims !== 4) {
|
|
260
|
+
errors.push(
|
|
261
|
+
new ShardError("noise/domain-mismatch", `"${type}" is 4D but the graph is ${dims}D`, {
|
|
262
|
+
path,
|
|
263
|
+
hint: 'Set "dimensions": 4 on the graph and sample it with a w coordinate, or use dims 3.'
|
|
264
|
+
})
|
|
265
|
+
);
|
|
266
|
+
return void 0;
|
|
267
|
+
}
|
|
268
|
+
return v;
|
|
269
|
+
}
|
|
270
|
+
case "pair": {
|
|
271
|
+
if (!Array.isArray(v) || v.length !== 2 || !v.every((x) => typeof x === "number" && Number.isFinite(x))) {
|
|
272
|
+
return bad("must be [a, b]");
|
|
273
|
+
}
|
|
274
|
+
return v;
|
|
275
|
+
}
|
|
276
|
+
case "vec": {
|
|
277
|
+
if (typeof v === "number" && Number.isFinite(v)) return [v, v, v, v];
|
|
278
|
+
if (!Array.isArray(v) || v.length < 2 || v.length > 4 || !v.every((x) => typeof x === "number" && Number.isFinite(x))) {
|
|
279
|
+
return bad("must be a number or [x, y, z]");
|
|
280
|
+
}
|
|
281
|
+
const fill = key === "by" && type === "scale" ? 1 : 0;
|
|
282
|
+
return [v[0], v[1], v[2] ?? fill, v[3] ?? fill];
|
|
283
|
+
}
|
|
284
|
+
case "points": {
|
|
285
|
+
if (!Array.isArray(v) || v.length < 2) {
|
|
286
|
+
errors.push(
|
|
287
|
+
fail("noise/arity", path, `"${type}.${key}" needs at least two points`, p.description)
|
|
288
|
+
);
|
|
289
|
+
return void 0;
|
|
290
|
+
}
|
|
291
|
+
let last = -Infinity;
|
|
292
|
+
for (let i = 0; i < v.length; i++) {
|
|
293
|
+
const pt = v[i];
|
|
294
|
+
if (!Array.isArray(pt) || pt.length !== 2 || !pt.every((x) => typeof x === "number" && Number.isFinite(x))) {
|
|
295
|
+
errors.push(fail("noise/invalid-param", `${path}/${i}`, "A point is [x, y]"));
|
|
296
|
+
return void 0;
|
|
297
|
+
}
|
|
298
|
+
if (pt[0] <= last) {
|
|
299
|
+
errors.push(fail("noise/invalid-param", `${path}/${i}`, "Curve points need increasing x"));
|
|
300
|
+
return void 0;
|
|
301
|
+
}
|
|
302
|
+
last = pt[0];
|
|
303
|
+
}
|
|
304
|
+
return v;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
function eachInput(node, f) {
|
|
309
|
+
for (const value of Object.values(node.params)) {
|
|
310
|
+
if (Array.isArray(value)) {
|
|
311
|
+
for (const v of value) if (isInput(v)) f(v);
|
|
312
|
+
} else if (isInput(value)) f(value);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function isInput(v) {
|
|
316
|
+
return isObject(v) && (v.kind === "ref" || v.kind === "node" || v.kind === "const");
|
|
317
|
+
}
|
|
318
|
+
function forEachInput(node, f) {
|
|
319
|
+
eachInput(node, f);
|
|
320
|
+
}
|
|
321
|
+
function checkRefs(node, names, errors) {
|
|
322
|
+
eachInput(node, (input) => {
|
|
323
|
+
if (input.kind === "ref" && !(input.name in names)) {
|
|
324
|
+
errors.push(
|
|
325
|
+
// Hint for the docs: name a node under "nodes", or add it there.
|
|
326
|
+
new ShardError("noise/unknown-node", `"${input.name}" isn't a node in this graph`, {
|
|
327
|
+
path: input.path,
|
|
328
|
+
hint: hintFor(input.name, names)
|
|
329
|
+
})
|
|
330
|
+
);
|
|
331
|
+
} else if (input.kind === "node") checkRefs(input.node, names, errors);
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
function checkCycles(nodes, errors) {
|
|
335
|
+
const state = /* @__PURE__ */ new Map();
|
|
336
|
+
const reported = /* @__PURE__ */ new Set();
|
|
337
|
+
const visit = (name, trail) => {
|
|
338
|
+
const s = state.get(name);
|
|
339
|
+
if (s === "done") return;
|
|
340
|
+
if (s === "visiting") {
|
|
341
|
+
const loop = trail.slice(trail.indexOf(name));
|
|
342
|
+
const key = [...loop].sort().join(">");
|
|
343
|
+
if (!reported.has(key)) {
|
|
344
|
+
reported.add(key);
|
|
345
|
+
errors.push(
|
|
346
|
+
new ShardError("noise/cycle", `Nodes form a cycle: ${[...loop, name].join(" \u2192 ")}`, {
|
|
347
|
+
path: `/nodes/${pointer(name)}`,
|
|
348
|
+
hint: "A node can\u2019t depend on itself; break the loop with a separate node."
|
|
349
|
+
})
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
const node = nodes.get(name);
|
|
355
|
+
if (!node) return;
|
|
356
|
+
state.set(name, "visiting");
|
|
357
|
+
const walk = (n) => eachInput(n, (input) => {
|
|
358
|
+
if (input.kind === "ref") visit(input.name, [...trail, name]);
|
|
359
|
+
else if (input.kind === "node") walk(input.node);
|
|
360
|
+
});
|
|
361
|
+
walk(node);
|
|
362
|
+
state.set(name, "done");
|
|
363
|
+
};
|
|
364
|
+
for (const name of nodes.keys()) visit(name, []);
|
|
365
|
+
}
|
|
366
|
+
export {
|
|
367
|
+
forEachInput,
|
|
368
|
+
parseGraph,
|
|
369
|
+
pointer
|
|
370
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { compileGraph, FRACTAL, type NoiseProgram, OP, POSITION_REGS, SKEW, WIDTH, } from './compile.js';
|
|
2
|
+
export { NOISE_LIBRARY_PATH, registerNoiseGraph, registerNoiseLibrary } from './gpu.js';
|
|
3
|
+
export { forEachInput, type GraphInput, type GraphNode, type ParamValue, type ParsedGraph, parseGraph, pointer, } from './graph.js';
|
|
4
|
+
export { BLOCK, computeOrigins, directionToFace, faceToDirection, gridOrigin, gridPoints, ORIGIN_WORDS, type OriginTerms, patchOrigin, patchPoints, } from './kernel.js';
|
|
5
|
+
export { loadNoiseKernel, type NoiseKernel, noiseKernel, simdSupported, useNoiseKernel, } from './loader.js';
|
|
6
|
+
export { MAX_SAMPLE_POINTS, noiseMethods, resolveGraph } from './methods.js';
|
|
7
|
+
export { CELL_DISTANCES, CELL_RETURNS, MAX_OCTAVES, NODE_DEFS, type NodeCategory, type NodeDef, nodeDef, type ParamDef, SOURCE_KINDS, type SourceKind, } from './nodes.js';
|
|
8
|
+
export { NoiseGraph, type NoiseGraphArtifact, NoiseGraphAssetType, NoiseGraphImporter, NoiseGraphStore, NoiseGraphs, noiseNames, type ProgramJson, } from './noise-graph.js';
|
|
9
|
+
export { noisePlugin } from './plugin.js';
|
|
10
|
+
export { type AsyncOptions, type Grid2d, type GridParams, noiseOrigins, normalizeGrid, poolTiming, type SpherePatch, sampleGrid2d, sampleGrid2dAsync, sampleNoise, sampleNoiseAsync, sampleNoiseGradient, sampleOffset, sampleSpherePatch, sampleSpherePatchAsync, } from './sample.js';
|
|
11
|
+
export { noiseJsonSchema } from './schema.js';
|
|
12
|
+
export { type NoiseDomain, type NoisePreviewOptions, type NoiseStats, noiseStats, previewNoise, } from './stats.js';
|
|
13
|
+
export { generateWgsl, NOISE_LIBRARY, type WgslOptions } from './wgsl.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import {
|
|
2
|
+
compileGraph,
|
|
3
|
+
FRACTAL,
|
|
4
|
+
OP,
|
|
5
|
+
POSITION_REGS,
|
|
6
|
+
SKEW,
|
|
7
|
+
WIDTH
|
|
8
|
+
} from "./compile.js";
|
|
9
|
+
import { NOISE_LIBRARY_PATH, registerNoiseGraph, registerNoiseLibrary } from "./gpu.js";
|
|
10
|
+
import {
|
|
11
|
+
forEachInput,
|
|
12
|
+
parseGraph,
|
|
13
|
+
pointer
|
|
14
|
+
} from "./graph.js";
|
|
15
|
+
import {
|
|
16
|
+
BLOCK,
|
|
17
|
+
computeOrigins,
|
|
18
|
+
directionToFace,
|
|
19
|
+
faceToDirection,
|
|
20
|
+
gridOrigin,
|
|
21
|
+
gridPoints,
|
|
22
|
+
ORIGIN_WORDS,
|
|
23
|
+
patchOrigin,
|
|
24
|
+
patchPoints
|
|
25
|
+
} from "./kernel.js";
|
|
26
|
+
import {
|
|
27
|
+
loadNoiseKernel,
|
|
28
|
+
noiseKernel,
|
|
29
|
+
simdSupported,
|
|
30
|
+
useNoiseKernel
|
|
31
|
+
} from "./loader.js";
|
|
32
|
+
import { MAX_SAMPLE_POINTS, noiseMethods, resolveGraph } from "./methods.js";
|
|
33
|
+
import {
|
|
34
|
+
CELL_DISTANCES,
|
|
35
|
+
CELL_RETURNS,
|
|
36
|
+
MAX_OCTAVES,
|
|
37
|
+
NODE_DEFS,
|
|
38
|
+
nodeDef,
|
|
39
|
+
SOURCE_KINDS
|
|
40
|
+
} from "./nodes.js";
|
|
41
|
+
import {
|
|
42
|
+
NoiseGraph,
|
|
43
|
+
NoiseGraphAssetType,
|
|
44
|
+
NoiseGraphImporter,
|
|
45
|
+
NoiseGraphStore,
|
|
46
|
+
NoiseGraphs,
|
|
47
|
+
noiseNames
|
|
48
|
+
} from "./noise-graph.js";
|
|
49
|
+
import { noisePlugin } from "./plugin.js";
|
|
50
|
+
import {
|
|
51
|
+
noiseOrigins,
|
|
52
|
+
normalizeGrid,
|
|
53
|
+
poolTiming,
|
|
54
|
+
sampleGrid2d,
|
|
55
|
+
sampleGrid2dAsync,
|
|
56
|
+
sampleNoise,
|
|
57
|
+
sampleNoiseAsync,
|
|
58
|
+
sampleNoiseGradient,
|
|
59
|
+
sampleOffset,
|
|
60
|
+
sampleSpherePatch,
|
|
61
|
+
sampleSpherePatchAsync
|
|
62
|
+
} from "./sample.js";
|
|
63
|
+
import { noiseJsonSchema } from "./schema.js";
|
|
64
|
+
import {
|
|
65
|
+
noiseStats,
|
|
66
|
+
previewNoise
|
|
67
|
+
} from "./stats.js";
|
|
68
|
+
import { generateWgsl, NOISE_LIBRARY } from "./wgsl.js";
|
|
69
|
+
export {
|
|
70
|
+
BLOCK,
|
|
71
|
+
CELL_DISTANCES,
|
|
72
|
+
CELL_RETURNS,
|
|
73
|
+
FRACTAL,
|
|
74
|
+
MAX_OCTAVES,
|
|
75
|
+
MAX_SAMPLE_POINTS,
|
|
76
|
+
NODE_DEFS,
|
|
77
|
+
NOISE_LIBRARY,
|
|
78
|
+
NOISE_LIBRARY_PATH,
|
|
79
|
+
NoiseGraph,
|
|
80
|
+
NoiseGraphAssetType,
|
|
81
|
+
NoiseGraphImporter,
|
|
82
|
+
NoiseGraphStore,
|
|
83
|
+
NoiseGraphs,
|
|
84
|
+
OP,
|
|
85
|
+
ORIGIN_WORDS,
|
|
86
|
+
POSITION_REGS,
|
|
87
|
+
SKEW,
|
|
88
|
+
SOURCE_KINDS,
|
|
89
|
+
WIDTH,
|
|
90
|
+
compileGraph,
|
|
91
|
+
computeOrigins,
|
|
92
|
+
directionToFace,
|
|
93
|
+
faceToDirection,
|
|
94
|
+
forEachInput,
|
|
95
|
+
generateWgsl,
|
|
96
|
+
gridOrigin,
|
|
97
|
+
gridPoints,
|
|
98
|
+
loadNoiseKernel,
|
|
99
|
+
nodeDef,
|
|
100
|
+
noiseJsonSchema,
|
|
101
|
+
noiseKernel,
|
|
102
|
+
noiseMethods,
|
|
103
|
+
noiseNames,
|
|
104
|
+
noiseOrigins,
|
|
105
|
+
noisePlugin,
|
|
106
|
+
noiseStats,
|
|
107
|
+
normalizeGrid,
|
|
108
|
+
parseGraph,
|
|
109
|
+
patchOrigin,
|
|
110
|
+
patchPoints,
|
|
111
|
+
pointer,
|
|
112
|
+
poolTiming,
|
|
113
|
+
previewNoise,
|
|
114
|
+
registerNoiseGraph,
|
|
115
|
+
registerNoiseLibrary,
|
|
116
|
+
resolveGraph,
|
|
117
|
+
sampleGrid2d,
|
|
118
|
+
sampleGrid2dAsync,
|
|
119
|
+
sampleNoise,
|
|
120
|
+
sampleNoiseAsync,
|
|
121
|
+
sampleNoiseGradient,
|
|
122
|
+
sampleOffset,
|
|
123
|
+
sampleSpherePatch,
|
|
124
|
+
sampleSpherePatchAsync,
|
|
125
|
+
simdSupported,
|
|
126
|
+
useNoiseKernel
|
|
127
|
+
};
|
package/dist/kernel.d.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Types for kernel.js (plain JavaScript so worker threads can import it without a loader).
|
|
2
|
+
|
|
3
|
+
export declare const BLOCK: number
|
|
4
|
+
export declare const ORIGIN_WORDS: number
|
|
5
|
+
|
|
6
|
+
/** How each source octave's lattice position depends on the sample origin. */
|
|
7
|
+
export interface OriginTerms {
|
|
8
|
+
/** Per term, xyzw: frequency × domain scale (f32 values). */
|
|
9
|
+
readonly a: Float64Array
|
|
10
|
+
/** Per term, xyzw: frequency × domain offset (f64). */
|
|
11
|
+
readonly b: Float64Array
|
|
12
|
+
/** Per term: 0 (none), 2, 3, or 4 (the simplex skew for that many dimensions). */
|
|
13
|
+
readonly skew: Uint8Array
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** What `evalProgram` needs from a compiled program. */
|
|
17
|
+
export interface ProgramData {
|
|
18
|
+
readonly code: Int32Array
|
|
19
|
+
readonly consts: Float32Array
|
|
20
|
+
readonly registers: number
|
|
21
|
+
readonly result: number
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface KernelState {
|
|
25
|
+
readonly memory: WebAssembly.Memory
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface SpherePatch {
|
|
29
|
+
/** Cube face: 0 +X, 1 −X, 2 +Y, 3 −Y, 4 +Z, 5 −Z. */
|
|
30
|
+
readonly face: number
|
|
31
|
+
/** Lower corner in face coordinates, [-1, 1]. */
|
|
32
|
+
readonly x0: number
|
|
33
|
+
readonly y0: number
|
|
34
|
+
/** Side length in face coordinates (2 is the whole face). */
|
|
35
|
+
readonly extent: number
|
|
36
|
+
/** Vertices per side, edges included. */
|
|
37
|
+
readonly resolution: number
|
|
38
|
+
readonly radius: number
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface Grid2d {
|
|
42
|
+
/** Lower corner. */
|
|
43
|
+
readonly origin: readonly [number, number]
|
|
44
|
+
readonly size: readonly [number, number]
|
|
45
|
+
/** Samples per side, edges included. */
|
|
46
|
+
readonly resolution: readonly [number, number]
|
|
47
|
+
/** The plane's z. Default 0. */
|
|
48
|
+
readonly z?: number
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export declare function computeOrigins(
|
|
52
|
+
terms: OriginTerms,
|
|
53
|
+
origin: ArrayLike<number>,
|
|
54
|
+
out: Int32Array,
|
|
55
|
+
): Int32Array
|
|
56
|
+
export declare function instantiate(
|
|
57
|
+
module: WebAssembly.Module,
|
|
58
|
+
instance?: WebAssembly.Instance,
|
|
59
|
+
): KernelState
|
|
60
|
+
export declare function evalProgram(
|
|
61
|
+
state: KernelState,
|
|
62
|
+
program: ProgramData,
|
|
63
|
+
seed: number,
|
|
64
|
+
origins: Int32Array,
|
|
65
|
+
pts: ArrayLike<number>,
|
|
66
|
+
stride: number,
|
|
67
|
+
count: number,
|
|
68
|
+
out: Float32Array,
|
|
69
|
+
outOffset?: number,
|
|
70
|
+
): void
|
|
71
|
+
export declare function faceToDirection<T extends { [i: number]: number }>(
|
|
72
|
+
face: number,
|
|
73
|
+
u: number,
|
|
74
|
+
v: number,
|
|
75
|
+
out: T,
|
|
76
|
+
offset?: number,
|
|
77
|
+
): T
|
|
78
|
+
export declare function directionToFace(
|
|
79
|
+
x: number,
|
|
80
|
+
y: number,
|
|
81
|
+
z: number,
|
|
82
|
+
out: { [i: number]: number },
|
|
83
|
+
): number
|
|
84
|
+
export declare function patchOrigin(p: SpherePatch, out: Float64Array): Float64Array
|
|
85
|
+
export declare function patchPoints(
|
|
86
|
+
p: SpherePatch,
|
|
87
|
+
origin: ArrayLike<number>,
|
|
88
|
+
row0: number,
|
|
89
|
+
row1: number,
|
|
90
|
+
out: Float32Array,
|
|
91
|
+
): Float32Array
|
|
92
|
+
export declare function gridOrigin(g: Grid2d, out: Float64Array): Float64Array
|
|
93
|
+
export declare function gridPoints(
|
|
94
|
+
g: Grid2d,
|
|
95
|
+
origin: ArrayLike<number>,
|
|
96
|
+
row0: number,
|
|
97
|
+
row1: number,
|
|
98
|
+
out: Float32Array,
|
|
99
|
+
): Float32Array
|