@yali-engine/tsl 0.0.0-stage → 0.4.0
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/bin/compile.mjs +68 -0
- package/dist/builders.d.ts +64 -0
- package/dist/builders.js +99 -0
- package/dist/builders.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/material.d.ts +65 -0
- package/dist/material.js +164 -0
- package/dist/material.js.map +1 -0
- package/dist/node.d.ts +61 -0
- package/dist/node.js +199 -0
- package/dist/node.js.map +1 -0
- package/package.json +31 -3
- package/README.md +0 -3
package/bin/compile.mjs
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// The `materials` build step (ADR-0064): compiles every `*.material.ts` under <dir> (its default
|
|
3
|
+
// export, named after the file; or its named exports, named after them) to WGSL, and writes
|
|
4
|
+
// one module of plain data (`MaterialShader`s) for the app to register. A production build
|
|
5
|
+
// ships this output, not @yali-engine/tsl's compiler.
|
|
6
|
+
//
|
|
7
|
+
// node --experimental-strip-types bin/compile.mjs <dir> <out.ts> [--check]
|
|
8
|
+
//
|
|
9
|
+
// --check exits 1 when <out.ts> is stale (CI). Output is deterministic: files and exports in
|
|
10
|
+
// sorted order, each material's WGSL as compileMaterial gives it.
|
|
11
|
+
import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
12
|
+
import { join, relative, resolve } from 'node:path';
|
|
13
|
+
import { pathToFileURL } from 'node:url';
|
|
14
|
+
|
|
15
|
+
const [dirArg, outArg] = process.argv.slice(2).filter((a) => !a.startsWith('--'));
|
|
16
|
+
if (!dirArg || !outArg) {
|
|
17
|
+
console.error('usage: compile.mjs <materials dir> <out.ts> [--check]');
|
|
18
|
+
process.exit(2);
|
|
19
|
+
}
|
|
20
|
+
const dir = resolve(dirArg);
|
|
21
|
+
const out = resolve(outArg);
|
|
22
|
+
// In the workspace: the TypeScript source; published (no src): the built JS.
|
|
23
|
+
const source = new URL('../src/index.ts', import.meta.url);
|
|
24
|
+
const { compileMaterial } = await import((existsSync(source) ? source : new URL('../dist/index.js', import.meta.url)).href);
|
|
25
|
+
|
|
26
|
+
const files = [];
|
|
27
|
+
const walk = (d) => {
|
|
28
|
+
for (const e of readdirSync(d).sort()) {
|
|
29
|
+
const p = join(d, e);
|
|
30
|
+
if (statSync(p).isDirectory()) walk(p);
|
|
31
|
+
else if (e.endsWith('.material.ts')) files.push(p);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
if (existsSync(dir)) walk(dir);
|
|
35
|
+
|
|
36
|
+
const compiled = [];
|
|
37
|
+
for (const f of files) {
|
|
38
|
+
const mod = await import(pathToFileURL(f).href);
|
|
39
|
+
const base = f.split(/[\\/]/).pop().replace(/\.material\.ts$/, '');
|
|
40
|
+
for (const key of Object.keys(mod).sort()) {
|
|
41
|
+
const name = key === 'default' ? base.replace(/[^a-zA-Z0-9_]/g, '_') : key;
|
|
42
|
+
if (!mod[key] || !Array.isArray(mod[key].outputs)) continue;
|
|
43
|
+
if (compiled.some((c) => c.name === name)) throw new Error(`Two node materials are named "${name}" (${relative(process.cwd(), f)}).`);
|
|
44
|
+
compiled.push(compileMaterial(name, mod[key]));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const rel = relative(process.cwd(), dir).split('\\').join('/');
|
|
49
|
+
const text = [
|
|
50
|
+
`// GENERATED by @yali-engine/tsl (bin/compile.mjs) from ${rel}/**/*.material.ts. Do not edit.`,
|
|
51
|
+
'// Register with render.materials.registerShader(shader); ADR-0064.',
|
|
52
|
+
'',
|
|
53
|
+
...compiled.map((c) => `export const ${c.name} = ${JSON.stringify({ name: c.name, entry: c.entry, hash: c.hash, params: c.params, textures: c.textures, wgsl: c.wgsl }, null, 2)} as const;\n`),
|
|
54
|
+
`export const all = [${compiled.map((c) => c.name).join(', ')}] as const;`,
|
|
55
|
+
'',
|
|
56
|
+
].join('\n');
|
|
57
|
+
|
|
58
|
+
const current = existsSync(out) ? readFileSync(out, 'utf8') : '';
|
|
59
|
+
if (process.argv.includes('--check')) {
|
|
60
|
+
if (current !== text) {
|
|
61
|
+
console.error(JSON.stringify({ tsl: 'stale', out: relative(process.cwd(), out), fix: `node --experimental-strip-types packages/tsl/bin/compile.mjs ${dirArg} ${outArg}` }));
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
console.log(JSON.stringify({ tsl: 'up-to-date', materials: compiled.map((c) => c.name) }));
|
|
65
|
+
} else {
|
|
66
|
+
if (current !== text) writeFileSync(out, text);
|
|
67
|
+
console.log(JSON.stringify({ tsl: current === text ? 'up-to-date' : 'written', materials: compiled.map((c) => ({ name: c.name, hash: c.hash, params: c.params.length, textures: c.textures })) }));
|
|
68
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Node, type NodeLike } from './node.ts';
|
|
2
|
+
/** A float node (`float(0.5)`, or a node converted to a float). */
|
|
3
|
+
export declare const float: (v: NodeLike) => Node;
|
|
4
|
+
export declare const vec2: (...p: NodeLike[]) => Node;
|
|
5
|
+
export declare const vec3: (...p: NodeLike[]) => Node;
|
|
6
|
+
export declare const vec4: (...p: NodeLike[]) => Node;
|
|
7
|
+
/** A colour as a vec3: `color(0xff8800)` (sRGB hex, converted to linear) or `color(r, g, b)` (linear). */
|
|
8
|
+
export declare function color(r: number, g?: number, b?: number): Node;
|
|
9
|
+
/** The mesh's first UV set (`uv()`). */
|
|
10
|
+
export declare const uv: () => Node;
|
|
11
|
+
/** The interpolated world-space normal, normalized. */
|
|
12
|
+
export declare const normalWorld: Node;
|
|
13
|
+
/** The fragment's position, world space but camera-relative (ADR-0008: the camera is the origin). */
|
|
14
|
+
export declare const positionWorld: Node;
|
|
15
|
+
/** Unit vector from the fragment towards the camera. */
|
|
16
|
+
export declare const viewDirection: Node;
|
|
17
|
+
/** The instance's `render.Mesh.color`, linear RGB. */
|
|
18
|
+
export declare const instanceColor: Node;
|
|
19
|
+
/** Seconds since the app started (the render plugin's clock). */
|
|
20
|
+
export declare const time: Node;
|
|
21
|
+
/**
|
|
22
|
+
* A material parameter: a named value each material made from this shader may set
|
|
23
|
+
* (`materials.add({ shader, params: { tint: [1, 0, 0] } })`), stored in the material's record
|
|
24
|
+
* (ADR-0064), so changing it never recompiles. `value` is its default.
|
|
25
|
+
*/
|
|
26
|
+
export declare function uniform(value: number | readonly number[], name: string): Node;
|
|
27
|
+
/** Texture slots a material record holds (ADR-0060): colour slots are sRGB, data slots linear. */
|
|
28
|
+
export type TextureSlot = 'baseColor' | 'normal' | 'orm' | 'emissive';
|
|
29
|
+
/**
|
|
30
|
+
* Samples one of the material's texture slots (`texture('baseColor', uv())`), as RGBA: white
|
|
31
|
+
* when the material has no texture there, the magenta checker when it failed to load.
|
|
32
|
+
*/
|
|
33
|
+
export declare function texture(slot: TextureSlot, coords?: Node): Node;
|
|
34
|
+
/** `cond ? a : b`, without a branch (TSL `select`; WGSL `select(b, a, cond)`). */
|
|
35
|
+
export declare function select(cond: Node, a: NodeLike, b: NodeLike): Node;
|
|
36
|
+
export declare const abs: (a: NodeLike) => Node;
|
|
37
|
+
export declare const sin: (a: NodeLike) => Node;
|
|
38
|
+
export declare const cos: (a: NodeLike) => Node;
|
|
39
|
+
export declare const floor: (a: NodeLike) => Node;
|
|
40
|
+
export declare const fract: (a: NodeLike) => Node;
|
|
41
|
+
export declare const sqrt: (a: NodeLike) => Node;
|
|
42
|
+
export declare const exp: (a: NodeLike) => Node;
|
|
43
|
+
export declare const normalize: (a: NodeLike) => Node;
|
|
44
|
+
export declare const length: (a: NodeLike) => Node;
|
|
45
|
+
export declare const saturate: (a: NodeLike) => Node;
|
|
46
|
+
export declare const min: (a: NodeLike, b: NodeLike) => Node;
|
|
47
|
+
export declare const max: (a: NodeLike, b: NodeLike) => Node;
|
|
48
|
+
export declare const pow: (a: NodeLike, b: NodeLike) => Node;
|
|
49
|
+
export declare const step: (edge: NodeLike, x: NodeLike) => Node;
|
|
50
|
+
export declare const dot: (a: NodeLike, b: NodeLike) => Node;
|
|
51
|
+
export declare const cross: (a: NodeLike, b: NodeLike) => Node;
|
|
52
|
+
export declare const reflect: (a: NodeLike, n: NodeLike) => Node;
|
|
53
|
+
export declare const clamp: (x: NodeLike, lo: NodeLike, hi: NodeLike) => Node;
|
|
54
|
+
export declare const mix: (a: NodeLike, b: NodeLike, t: NodeLike) => Node;
|
|
55
|
+
export declare const smoothstep: (lo: NodeLike, hi: NodeLike, x: NodeLike) => Node;
|
|
56
|
+
/**
|
|
57
|
+
* A reusable graph function, as TSL's `Fn`: called with nodes, it returns the node its body
|
|
58
|
+
* builds. Expanded inline (the code generator shares identical subgraphs), so it costs nothing.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* const fresnel = Fn(([power]: Node[]) => float(1).sub(normalWorld.dot(viewDirection).saturate()).pow(power));
|
|
62
|
+
* emissiveNode: color(0x3366ff).mul(fresnel(float(3)))
|
|
63
|
+
*/
|
|
64
|
+
export declare function Fn<A extends Node[]>(body: (args: A) => Node): (...args: A) => Node;
|
package/dist/builders.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { YaliError } from '@yali-engine/core';
|
|
2
|
+
import { call, construct, Node, nodeOf } from "./node.js";
|
|
3
|
+
// Constructors (three.js TSL names).
|
|
4
|
+
/** A float node (`float(0.5)`, or a node converted to a float). */
|
|
5
|
+
export const float = (v) => nodeOf(v);
|
|
6
|
+
export const vec2 = (...p) => construct('vec2f', p);
|
|
7
|
+
export const vec3 = (...p) => construct('vec3f', p);
|
|
8
|
+
export const vec4 = (...p) => construct('vec4f', p);
|
|
9
|
+
/** A colour as a vec3: `color(0xff8800)` (sRGB hex, converted to linear) or `color(r, g, b)` (linear). */
|
|
10
|
+
export function color(r, g, b) {
|
|
11
|
+
if (g === undefined) {
|
|
12
|
+
const lin = (c) => (c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4);
|
|
13
|
+
return vec3(lin(((r >> 16) & 255) / 255), lin(((r >> 8) & 255) / 255), lin((r & 255) / 255));
|
|
14
|
+
}
|
|
15
|
+
return vec3(r, g, b ?? 0);
|
|
16
|
+
}
|
|
17
|
+
// Inputs the surface stage provides (named as in three.js TSL).
|
|
18
|
+
const input = (name, type) => new Node('input', type, [], name);
|
|
19
|
+
/** The mesh's first UV set (`uv()`). */
|
|
20
|
+
export const uv = () => input('uv', 'vec2f');
|
|
21
|
+
/** The interpolated world-space normal, normalized. */
|
|
22
|
+
export const normalWorld = input('normal_world', 'vec3f');
|
|
23
|
+
/** The fragment's position, world space but camera-relative (ADR-0008: the camera is the origin). */
|
|
24
|
+
export const positionWorld = input('position_world', 'vec3f');
|
|
25
|
+
/** Unit vector from the fragment towards the camera. */
|
|
26
|
+
export const viewDirection = input('view_dir', 'vec3f');
|
|
27
|
+
/** The instance's `render.Mesh.color`, linear RGB. */
|
|
28
|
+
export const instanceColor = input('instance_color', 'vec3f');
|
|
29
|
+
/** Seconds since the app started (the render plugin's clock). */
|
|
30
|
+
export const time = input('time', 'f32');
|
|
31
|
+
/**
|
|
32
|
+
* A material parameter: a named value each material made from this shader may set
|
|
33
|
+
* (`materials.add({ shader, params: { tint: [1, 0, 0] } })`), stored in the material's record
|
|
34
|
+
* (ADR-0064), so changing it never recompiles. `value` is its default.
|
|
35
|
+
*/
|
|
36
|
+
export function uniform(value, name) {
|
|
37
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name))
|
|
38
|
+
throw new YaliError('TSL_UNIFORM', `"${name}" is not a valid uniform name.`, 'Use letters, digits and _, starting with a letter.');
|
|
39
|
+
const v = typeof value === 'number' ? [value] : [...value];
|
|
40
|
+
if (v.length < 1 || v.length > 4 || v.some((x) => !Number.isFinite(x)))
|
|
41
|
+
throw new YaliError('TSL_UNIFORM', `Uniform "${name}" needs 1–4 finite numbers.`, 'Pass a number or an array of up to four.');
|
|
42
|
+
const type = ['f32', 'vec2f', 'vec3f', 'vec4f'][v.length - 1];
|
|
43
|
+
return new Node('uniform', type, [], [name, ...v.map(String)].join('|'));
|
|
44
|
+
}
|
|
45
|
+
const SLOTS = ['baseColor', 'normal', 'orm', 'emissive'];
|
|
46
|
+
/**
|
|
47
|
+
* Samples one of the material's texture slots (`texture('baseColor', uv())`), as RGBA: white
|
|
48
|
+
* when the material has no texture there, the magenta checker when it failed to load.
|
|
49
|
+
*/
|
|
50
|
+
export function texture(slot, coords = uv()) {
|
|
51
|
+
if (!SLOTS.includes(slot))
|
|
52
|
+
throw new YaliError('TSL_TEXTURE', `"${slot}" is not a texture slot.`, `Use one of: ${SLOTS.join(', ')}.`);
|
|
53
|
+
if (coords.type !== 'vec2f')
|
|
54
|
+
throw new YaliError('TSL_TYPE', `texture() needs vec2 coordinates, not ${coords.type}.`, 'Pass uv() or a vec2 node.');
|
|
55
|
+
return new Node('texture', 'vec4f', [coords], slot);
|
|
56
|
+
}
|
|
57
|
+
/** `cond ? a : b`, without a branch (TSL `select`; WGSL `select(b, a, cond)`). */
|
|
58
|
+
export function select(cond, a, b) {
|
|
59
|
+
const [x, y] = [nodeOf(a), nodeOf(b)];
|
|
60
|
+
if (cond.type !== 'bool')
|
|
61
|
+
throw new YaliError('TSL_TYPE', `select() needs a bool condition, not ${cond.type}.`, 'Use a comparison: a.lessThan(b).');
|
|
62
|
+
const type = x.type === y.type ? x.type : x.type === 'f32' ? y.type : y.type === 'f32' ? x.type : null;
|
|
63
|
+
if (!type)
|
|
64
|
+
throw new YaliError('TSL_TYPE', `select() branches are ${x.type} and ${y.type}.`, 'Make both branches the same type.');
|
|
65
|
+
return new Node('select', type, [cond, x.type === type ? x : construct(type, [x]), y.type === type ? y : construct(type, [y])], 'select');
|
|
66
|
+
}
|
|
67
|
+
// Functions (WGSL built-ins under their TSL names).
|
|
68
|
+
export const abs = (a) => call('abs', [a]);
|
|
69
|
+
export const sin = (a) => call('sin', [a]);
|
|
70
|
+
export const cos = (a) => call('cos', [a]);
|
|
71
|
+
export const floor = (a) => call('floor', [a]);
|
|
72
|
+
export const fract = (a) => call('fract', [a]);
|
|
73
|
+
export const sqrt = (a) => call('sqrt', [a]);
|
|
74
|
+
export const exp = (a) => call('exp', [a]);
|
|
75
|
+
export const normalize = (a) => call('normalize', [a]);
|
|
76
|
+
export const length = (a) => call('length', [a]);
|
|
77
|
+
export const saturate = (a) => call('saturate', [a]);
|
|
78
|
+
export const min = (a, b) => call('min', [a, b]);
|
|
79
|
+
export const max = (a, b) => call('max', [a, b]);
|
|
80
|
+
export const pow = (a, b) => call('pow', [a, b]);
|
|
81
|
+
export const step = (edge, x) => call('step', [edge, x]);
|
|
82
|
+
export const dot = (a, b) => call('dot', [a, b]);
|
|
83
|
+
export const cross = (a, b) => call('cross', [a, b]);
|
|
84
|
+
export const reflect = (a, n) => call('reflect', [a, n]);
|
|
85
|
+
export const clamp = (x, lo, hi) => call('clamp', [x, lo, hi]);
|
|
86
|
+
export const mix = (a, b, t) => call('mix', [a, b, t]);
|
|
87
|
+
export const smoothstep = (lo, hi, x) => call('smoothstep', [lo, hi, x]);
|
|
88
|
+
/**
|
|
89
|
+
* A reusable graph function, as TSL's `Fn`: called with nodes, it returns the node its body
|
|
90
|
+
* builds. Expanded inline (the code generator shares identical subgraphs), so it costs nothing.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* const fresnel = Fn(([power]: Node[]) => float(1).sub(normalWorld.dot(viewDirection).saturate()).pow(power));
|
|
94
|
+
* emissiveNode: color(0x3366ff).mul(fresnel(float(3)))
|
|
95
|
+
*/
|
|
96
|
+
export function Fn(body) {
|
|
97
|
+
return (...args) => body(args);
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=builders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builders.js","sourceRoot":"","sources":["../src/builders.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@yali-engine/tsl`: materials as node graphs with three.js TSL's names (ADR-0007, ADR-0064).
|
|
3
|
+
* Graphs are plain data; `compileMaterial` turns one into a WGSL function the scene's draw
|
|
4
|
+
* shader calls, and the `materials` build step does that for every `*.material.ts` file, so a
|
|
5
|
+
* production build ships WGSL, not this compiler.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* // src/materials/lava.material.ts
|
|
9
|
+
* import { color, mix, nodeMaterial, sin, time, uniform, uv } from '@yali-engine/tsl';
|
|
10
|
+
* export default nodeMaterial({
|
|
11
|
+
* colorNode: mix(color(0x220000), color(0xff5500), sin(time.mul(2).add(uv().x.mul(9))).mul(0.5).add(0.5)),
|
|
12
|
+
* emissiveNode: color(0xff3300).mul(uniform(1.5, 'glow')),
|
|
13
|
+
* });
|
|
14
|
+
*/
|
|
15
|
+
export * from './builders.ts';
|
|
16
|
+
export { type CompiledMaterial, compileMaterial, type MaterialParam, type NodeMaterial, type NodeMaterialDef, nodeMaterial, PARAM_FLOATS } from './material.ts';
|
|
17
|
+
export { call, construct, lanesOf, Node, type NodeLike, nodeOf, type NodeType } from './node.ts';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@yali-engine/tsl`: materials as node graphs with three.js TSL's names (ADR-0007, ADR-0064).
|
|
3
|
+
* Graphs are plain data; `compileMaterial` turns one into a WGSL function the scene's draw
|
|
4
|
+
* shader calls, and the `materials` build step does that for every `*.material.ts` file, so a
|
|
5
|
+
* production build ships WGSL, not this compiler.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* // src/materials/lava.material.ts
|
|
9
|
+
* import { color, mix, nodeMaterial, sin, time, uniform, uv } from '@yali-engine/tsl';
|
|
10
|
+
* export default nodeMaterial({
|
|
11
|
+
* colorNode: mix(color(0x220000), color(0xff5500), sin(time.mul(2).add(uv().x.mul(9))).mul(0.5).add(0.5)),
|
|
12
|
+
* emissiveNode: color(0xff3300).mul(uniform(1.5, 'glow')),
|
|
13
|
+
* });
|
|
14
|
+
*/
|
|
15
|
+
export * from "./builders.js";
|
|
16
|
+
export { compileMaterial, nodeMaterial, PARAM_FLOATS } from "./material.js";
|
|
17
|
+
export { call, construct, lanesOf, Node, nodeOf } from "./node.js";
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAyB,eAAe,EAA+D,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAChK,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAiB,MAAM,EAAiB,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { type TextureSlot } from './builders.ts';
|
|
2
|
+
import { type Node, type NodeLike } from './node.ts';
|
|
3
|
+
/** A material's surface outputs, named as three.js's MeshStandardNodeMaterial properties. */
|
|
4
|
+
export interface NodeMaterialDef {
|
|
5
|
+
/** Linear base colour (vec3). Default: the instance's colour. */
|
|
6
|
+
readonly colorNode?: NodeLike;
|
|
7
|
+
/** 0–1. Default 1. */
|
|
8
|
+
readonly opacityNode?: NodeLike;
|
|
9
|
+
/** 0–1. Default 0. */
|
|
10
|
+
readonly metalnessNode?: NodeLike;
|
|
11
|
+
/** 0–1. Default 1. */
|
|
12
|
+
readonly roughnessNode?: NodeLike;
|
|
13
|
+
/** Linear emitted colour (vec3). Default black. */
|
|
14
|
+
readonly emissiveNode?: NodeLike;
|
|
15
|
+
/** World-space shading normal (vec3, normalized by the lighting). Default: the mesh's. */
|
|
16
|
+
readonly normalNode?: NodeLike;
|
|
17
|
+
/** Ambient occlusion 0–1. Default 1. */
|
|
18
|
+
readonly aoNode?: NodeLike;
|
|
19
|
+
}
|
|
20
|
+
/** Floats of per-material parameters in a material record (two vec4s; ADR-0064). */
|
|
21
|
+
export declare const PARAM_FLOATS = 8;
|
|
22
|
+
/** One material parameter's place in the record. */
|
|
23
|
+
export interface MaterialParam {
|
|
24
|
+
readonly name: string;
|
|
25
|
+
readonly lanes: number;
|
|
26
|
+
/** Float index in the record's parameter block (0–7). */
|
|
27
|
+
readonly offset: number;
|
|
28
|
+
readonly default: readonly number[];
|
|
29
|
+
}
|
|
30
|
+
/** A material compiled to WGSL (what `materials.gen.ts` holds; ADR-0064). */
|
|
31
|
+
export interface CompiledMaterial {
|
|
32
|
+
readonly name: string;
|
|
33
|
+
/** The WGSL function's name: `material_<name>`. */
|
|
34
|
+
readonly entry: string;
|
|
35
|
+
/** The function, `fn material_<name>(in: SurfaceInput, p: array<vec4f, 2>) -> Surface`. */
|
|
36
|
+
readonly wgsl: string;
|
|
37
|
+
/** FNV-1a of `wgsl`, hex: equal materials share a shader. */
|
|
38
|
+
readonly hash: string;
|
|
39
|
+
readonly params: readonly MaterialParam[];
|
|
40
|
+
/** Texture slots it samples. */
|
|
41
|
+
readonly textures: readonly TextureSlot[];
|
|
42
|
+
}
|
|
43
|
+
/** A material graph: its outputs, ready to compile. */
|
|
44
|
+
export interface NodeMaterial {
|
|
45
|
+
readonly outputs: readonly Node[];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Declares a node material from its outputs, as three.js's `MeshStandardNodeMaterial`
|
|
49
|
+
* properties name them. Compile it with `compileMaterial` (the `materials` build step does).
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* export const lava = nodeMaterial({
|
|
53
|
+
* colorNode: mix(color(0x220000), color(0xff5500), sin(time.mul(2).add(uv().x.mul(9))).mul(0.5).add(0.5)),
|
|
54
|
+
* emissiveNode: color(0xff3300).mul(uniform(1.5, 'glow')),
|
|
55
|
+
* roughnessNode: float(0.6),
|
|
56
|
+
* });
|
|
57
|
+
*/
|
|
58
|
+
export declare function nodeMaterial(def: NodeMaterialDef): NodeMaterial;
|
|
59
|
+
/**
|
|
60
|
+
* Compiles a node material to a WGSL function (ADR-0064). Identical subgraphs are computed
|
|
61
|
+
* once; variables are numbered in a fixed post-order from the outputs, so the same graph
|
|
62
|
+
* always gives the same text. Material parameters (`uniform`) are packed into the record's
|
|
63
|
+
* 8 floats without crossing a vec4; more is an error.
|
|
64
|
+
*/
|
|
65
|
+
export declare function compileMaterial(name: string, material: NodeMaterial): CompiledMaterial;
|
package/dist/material.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { YaliError } from '@yali-engine/core';
|
|
2
|
+
import { instanceColor, normalWorld } from "./builders.js";
|
|
3
|
+
import { lanesOf, nodeOf } from "./node.js";
|
|
4
|
+
/** The outputs in the order the generated `Surface` takes them, with their types and defaults. */
|
|
5
|
+
const OUTPUTS = [
|
|
6
|
+
{ key: 'colorNode', field: 'base_color', type: 'vec3f', fallback: () => instanceColor },
|
|
7
|
+
{ key: 'opacityNode', field: 'opacity', type: 'f32', fallback: () => nodeOf(1) },
|
|
8
|
+
{ key: 'metalnessNode', field: 'metalness', type: 'f32', fallback: () => nodeOf(0) },
|
|
9
|
+
{ key: 'roughnessNode', field: 'roughness', type: 'f32', fallback: () => nodeOf(1) },
|
|
10
|
+
{ key: 'emissiveNode', field: 'emissive', type: 'vec3f', fallback: () => nodeOf(0) },
|
|
11
|
+
{ key: 'normalNode', field: 'normal', type: 'vec3f', fallback: () => normalWorld },
|
|
12
|
+
{ key: 'aoNode', field: 'occlusion', type: 'f32', fallback: () => nodeOf(1) },
|
|
13
|
+
];
|
|
14
|
+
/** Floats of per-material parameters in a material record (two vec4s; ADR-0064). */
|
|
15
|
+
export const PARAM_FLOATS = 8;
|
|
16
|
+
/**
|
|
17
|
+
* Declares a node material from its outputs, as three.js's `MeshStandardNodeMaterial`
|
|
18
|
+
* properties name them. Compile it with `compileMaterial` (the `materials` build step does).
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* export const lava = nodeMaterial({
|
|
22
|
+
* colorNode: mix(color(0x220000), color(0xff5500), sin(time.mul(2).add(uv().x.mul(9))).mul(0.5).add(0.5)),
|
|
23
|
+
* emissiveNode: color(0xff3300).mul(uniform(1.5, 'glow')),
|
|
24
|
+
* roughnessNode: float(0.6),
|
|
25
|
+
* });
|
|
26
|
+
*/
|
|
27
|
+
export function nodeMaterial(def) {
|
|
28
|
+
const outputs = OUTPUTS.map((o) => {
|
|
29
|
+
const v = def[o.key];
|
|
30
|
+
const n = v === undefined ? o.fallback() : nodeOf(v);
|
|
31
|
+
if (n.type === o.type)
|
|
32
|
+
return n;
|
|
33
|
+
if (n.type === 'f32' && o.type !== 'f32')
|
|
34
|
+
return n; // splatted by the generator
|
|
35
|
+
throw new YaliError('TSL_OUTPUT', `${o.key} is ${n.type}; it must be ${o.type === 'f32' ? 'a float' : 'a vec3'}.`, `Swizzle or build a ${o.type} (e.g. vec3(x) or v.xyz).`);
|
|
36
|
+
});
|
|
37
|
+
return { outputs };
|
|
38
|
+
}
|
|
39
|
+
const GRAD_INPUT = 'uv';
|
|
40
|
+
/**
|
|
41
|
+
* Compiles a node material to a WGSL function (ADR-0064). Identical subgraphs are computed
|
|
42
|
+
* once; variables are numbered in a fixed post-order from the outputs, so the same graph
|
|
43
|
+
* always gives the same text. Material parameters (`uniform`) are packed into the record's
|
|
44
|
+
* 8 floats without crossing a vec4; more is an error.
|
|
45
|
+
*/
|
|
46
|
+
export function compileMaterial(name, material) {
|
|
47
|
+
if (!/^[a-zA-Z][a-zA-Z0-9_]*$/.test(name))
|
|
48
|
+
throw new YaliError('TSL_NAME', `"${name}" is not a valid material name.`, 'Use letters, digits and _, starting with a letter.');
|
|
49
|
+
const lines = [];
|
|
50
|
+
const names = new Map();
|
|
51
|
+
const params = [];
|
|
52
|
+
const textures = new Set();
|
|
53
|
+
let next = 0;
|
|
54
|
+
const param = (n) => {
|
|
55
|
+
const [pname, ...vals] = String(n.value).split('|');
|
|
56
|
+
const existing = params.find((p) => p.name === pname);
|
|
57
|
+
if (existing) {
|
|
58
|
+
if (existing.lanes !== lanesOf(n.type))
|
|
59
|
+
throw new YaliError('TSL_UNIFORM', `Uniform "${pname}" is used with two sizes.`, 'Give each uniform one type.');
|
|
60
|
+
return existing;
|
|
61
|
+
}
|
|
62
|
+
const lanes = lanesOf(n.type);
|
|
63
|
+
let at = params.reduce((o, p) => Math.max(o, p.offset + p.lanes), 0);
|
|
64
|
+
if ((at % 4) + lanes > 4)
|
|
65
|
+
at = Math.ceil(at / 4) * 4;
|
|
66
|
+
if (at + lanes > PARAM_FLOATS) {
|
|
67
|
+
throw new YaliError('TSL_UNIFORMS', `Material "${name}" needs more than ${PARAM_FLOATS} uniform floats.`, 'Pack uniforms (a vec4 for four floats) or bake constants: a material record holds 8.');
|
|
68
|
+
}
|
|
69
|
+
const p = { name: pname, lanes, offset: at, default: vals.map(Number) };
|
|
70
|
+
params.push(p);
|
|
71
|
+
return p;
|
|
72
|
+
};
|
|
73
|
+
const lit = (v, type) => {
|
|
74
|
+
const f = (x) => (Number.isInteger(x) ? `${x}.0` : String(x));
|
|
75
|
+
return type === 'f32' ? f(v[0]) : `${type}(${v.map(f).join(', ')})`;
|
|
76
|
+
};
|
|
77
|
+
/** Gradients for texture coordinates: the UV set's, scaled when the coordinates are a tiled uv(). */
|
|
78
|
+
const gradients = (coords) => {
|
|
79
|
+
if (coords.kind === 'input' && coords.value === GRAD_INPUT)
|
|
80
|
+
return ['in.ddx', 'in.ddy'];
|
|
81
|
+
if (coords.kind === 'op' && (coords.value === '*' || coords.value === '+' || coords.value === '-')) {
|
|
82
|
+
const [a, b] = coords.args;
|
|
83
|
+
const uvSide = [a, b].findIndex((x) => x.kind === 'input' && x.value === GRAD_INPUT);
|
|
84
|
+
if (uvSide >= 0) {
|
|
85
|
+
if (coords.value !== '*')
|
|
86
|
+
return ['in.ddx', 'in.ddy'];
|
|
87
|
+
const k = emit(coords.args[1 - uvSide]);
|
|
88
|
+
return [`in.ddx * ${k}`, `in.ddy * ${k}`];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return ['in.ddx', 'in.ddy'];
|
|
92
|
+
};
|
|
93
|
+
const emit = (n) => {
|
|
94
|
+
const known = names.get(n.key);
|
|
95
|
+
if (known)
|
|
96
|
+
return known;
|
|
97
|
+
let expr;
|
|
98
|
+
switch (n.kind) {
|
|
99
|
+
case 'const':
|
|
100
|
+
return lit(n.value, n.type); // inline, never a variable
|
|
101
|
+
case 'input':
|
|
102
|
+
return `in.${n.value}`;
|
|
103
|
+
case 'uniform': {
|
|
104
|
+
const p = param(n);
|
|
105
|
+
const comps = 'xyzw'.slice(p.offset % 4, (p.offset % 4) + p.lanes);
|
|
106
|
+
expr = `p[${Math.floor(p.offset / 4)}].${comps}`;
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
case 'op': {
|
|
110
|
+
if (n.value === 'neg')
|
|
111
|
+
expr = `-(${emit(n.args[0])})`;
|
|
112
|
+
else
|
|
113
|
+
expr = `(${emit(n.args[0])} ${n.value} ${emit(n.args[1])})`;
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
case 'call':
|
|
117
|
+
expr = `${n.value}(${n.args.map(emit).join(', ')})`;
|
|
118
|
+
break;
|
|
119
|
+
case 'swizzle':
|
|
120
|
+
expr = `${emit(n.args[0])}.${n.value}`;
|
|
121
|
+
break;
|
|
122
|
+
case 'construct':
|
|
123
|
+
expr = `${n.type}(${n.args.map(emit).join(', ')})`;
|
|
124
|
+
break;
|
|
125
|
+
case 'select':
|
|
126
|
+
expr = `select(${emit(n.args[2])}, ${emit(n.args[1])}, ${emit(n.args[0])})`;
|
|
127
|
+
break;
|
|
128
|
+
case 'texture': {
|
|
129
|
+
const slot = n.value;
|
|
130
|
+
textures.add(slot);
|
|
131
|
+
const [dx, dy] = gradients(n.args[0]);
|
|
132
|
+
const lane = { baseColor: 'x', normal: 'y', orm: 'z', emissive: 'w' }[slot];
|
|
133
|
+
const fn = slot === 'baseColor' || slot === 'emissive' ? 'sample_srgb' : 'sample_linear';
|
|
134
|
+
expr = `${fn}(in.maps.${lane}, ${emit(n.args[0])}, ${dx}, ${dy})`;
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const v = `v${next++}`;
|
|
139
|
+
lines.push(` let ${v}: ${n.type} = ${expr};`);
|
|
140
|
+
names.set(n.key, v);
|
|
141
|
+
return v;
|
|
142
|
+
};
|
|
143
|
+
const outs = material.outputs.map((n, i) => {
|
|
144
|
+
const e = emit(n);
|
|
145
|
+
return OUTPUTS[i].type !== 'f32' && n.type === 'f32' ? `vec3f(${e})` : e;
|
|
146
|
+
});
|
|
147
|
+
const entry = `material_${name}`;
|
|
148
|
+
const wgsl = [
|
|
149
|
+
`fn ${entry}(in: SurfaceInput, p: array<vec4f, 2>) -> Surface {`,
|
|
150
|
+
...lines,
|
|
151
|
+
` return Surface(${outs.join(', ')});`,
|
|
152
|
+
'}',
|
|
153
|
+
].join('\n');
|
|
154
|
+
return { name, entry, wgsl, hash: fnv1a(wgsl), params, textures: [...textures].sort() };
|
|
155
|
+
}
|
|
156
|
+
function fnv1a(s) {
|
|
157
|
+
let h = 0x811c9dc5;
|
|
158
|
+
for (let i = 0; i < s.length; i++) {
|
|
159
|
+
h ^= s.charCodeAt(i);
|
|
160
|
+
h = Math.imul(h, 0x01000193);
|
|
161
|
+
}
|
|
162
|
+
return (h >>> 0).toString(16).padStart(8, '0');
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=material.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"material.js","sourceRoot":"","sources":["../src/material.ts"],"names":[],"mappings":"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"}
|
package/dist/node.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/** Value types a node can have (WGSL's names). */
|
|
2
|
+
export type NodeType = 'f32' | 'vec2f' | 'vec3f' | 'vec4f' | 'bool' | 'u32';
|
|
3
|
+
/** Lanes of a type (1 for scalars). */
|
|
4
|
+
export declare const lanesOf: (t: NodeType) => number;
|
|
5
|
+
/**
|
|
6
|
+
* One node of a material graph (ADR-0064): plain data (`kind`, `type`, `args`, a `value` for
|
|
7
|
+
* constants and inputs), so a graph serialises, diffs and edits like any data; the methods
|
|
8
|
+
* only build new nodes, mirroring three.js TSL (`a.mul(b).add(c)`, `v.xyz`).
|
|
9
|
+
*/
|
|
10
|
+
export declare class Node {
|
|
11
|
+
#private;
|
|
12
|
+
readonly kind: 'const' | 'input' | 'uniform' | 'op' | 'call' | 'swizzle' | 'construct' | 'texture' | 'select';
|
|
13
|
+
readonly type: NodeType;
|
|
14
|
+
readonly args: readonly Node[];
|
|
15
|
+
/** Constant values, an input's or uniform's name, a call's function, a swizzle mask. */
|
|
16
|
+
readonly value: string | readonly number[];
|
|
17
|
+
constructor(kind: Node['kind'], type: NodeType, args: readonly Node[], value: Node['value']);
|
|
18
|
+
/** A structural key: equal graphs have equal keys (the code generator shares them). */
|
|
19
|
+
get key(): string;
|
|
20
|
+
add(o: NodeLike): Node;
|
|
21
|
+
sub(o: NodeLike): Node;
|
|
22
|
+
mul(o: NodeLike): Node;
|
|
23
|
+
div(o: NodeLike): Node;
|
|
24
|
+
negate(): Node;
|
|
25
|
+
lessThan(o: NodeLike): Node;
|
|
26
|
+
greaterThan(o: NodeLike): Node;
|
|
27
|
+
lessThanEqual(o: NodeLike): Node;
|
|
28
|
+
greaterThanEqual(o: NodeLike): Node;
|
|
29
|
+
normalize(): Node;
|
|
30
|
+
length(): Node;
|
|
31
|
+
abs(): Node;
|
|
32
|
+
sin(): Node;
|
|
33
|
+
cos(): Node;
|
|
34
|
+
fract(): Node;
|
|
35
|
+
saturate(): Node;
|
|
36
|
+
clamp(lo: NodeLike, hi: NodeLike): Node;
|
|
37
|
+
pow(e: NodeLike): Node;
|
|
38
|
+
dot(o: NodeLike): Node;
|
|
39
|
+
mix(b: NodeLike, t: NodeLike): Node;
|
|
40
|
+
get x(): Node;
|
|
41
|
+
get y(): Node;
|
|
42
|
+
get z(): Node;
|
|
43
|
+
get w(): Node;
|
|
44
|
+
get xy(): Node;
|
|
45
|
+
get xyz(): Node;
|
|
46
|
+
get rgb(): Node;
|
|
47
|
+
get r(): Node;
|
|
48
|
+
get g(): Node;
|
|
49
|
+
get b(): Node;
|
|
50
|
+
get a(): Node;
|
|
51
|
+
/** Components by mask (`xyz`, `rgba`, `yx`…). */
|
|
52
|
+
swizzle(mask: string): Node;
|
|
53
|
+
}
|
|
54
|
+
/** What a builder accepts: a node or a plain number (a float constant). */
|
|
55
|
+
export type NodeLike = Node | number;
|
|
56
|
+
/** A node from a node or a number. */
|
|
57
|
+
export declare function nodeOf(v: NodeLike): Node;
|
|
58
|
+
/** A call of a WGSL built-in (`call('mix', [a, b, t])`). Scalars broadcast to the vector argument's type. */
|
|
59
|
+
export declare function call(fn: string, args: readonly NodeLike[]): Node;
|
|
60
|
+
/** A typed vector or scalar from components (`vec3(1, 0, 0)`, `vec4(rgb, 1)`, `vec3(0.5)` splats). */
|
|
61
|
+
export declare function construct(type: NodeType, parts: readonly NodeLike[]): Node;
|
package/dist/node.js
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { YaliError } from '@yali-engine/core';
|
|
2
|
+
const LANES = { f32: 1, vec2f: 2, vec3f: 3, vec4f: 4, bool: 1, u32: 1 };
|
|
3
|
+
const VEC = ['f32', 'f32', 'vec2f', 'vec3f', 'vec4f'];
|
|
4
|
+
/** Lanes of a type (1 for scalars). */
|
|
5
|
+
export const lanesOf = (t) => LANES[t];
|
|
6
|
+
/**
|
|
7
|
+
* One node of a material graph (ADR-0064): plain data (`kind`, `type`, `args`, a `value` for
|
|
8
|
+
* constants and inputs), so a graph serialises, diffs and edits like any data; the methods
|
|
9
|
+
* only build new nodes, mirroring three.js TSL (`a.mul(b).add(c)`, `v.xyz`).
|
|
10
|
+
*/
|
|
11
|
+
export class Node {
|
|
12
|
+
kind;
|
|
13
|
+
type;
|
|
14
|
+
args;
|
|
15
|
+
/** Constant values, an input's or uniform's name, a call's function, a swizzle mask. */
|
|
16
|
+
value;
|
|
17
|
+
#key = null;
|
|
18
|
+
constructor(kind, type, args, value) {
|
|
19
|
+
this.kind = kind;
|
|
20
|
+
this.type = type;
|
|
21
|
+
this.args = args;
|
|
22
|
+
this.value = value;
|
|
23
|
+
}
|
|
24
|
+
/** A structural key: equal graphs have equal keys (the code generator shares them). */
|
|
25
|
+
get key() {
|
|
26
|
+
this.#key ??= `${this.kind}:${this.type}:${JSON.stringify(this.value)}(${this.args.map((a) => a.key).join(',')})`;
|
|
27
|
+
return this.#key;
|
|
28
|
+
}
|
|
29
|
+
add(o) {
|
|
30
|
+
return binary('+', this, o);
|
|
31
|
+
}
|
|
32
|
+
sub(o) {
|
|
33
|
+
return binary('-', this, o);
|
|
34
|
+
}
|
|
35
|
+
mul(o) {
|
|
36
|
+
return binary('*', this, o);
|
|
37
|
+
}
|
|
38
|
+
div(o) {
|
|
39
|
+
return binary('/', this, o);
|
|
40
|
+
}
|
|
41
|
+
negate() {
|
|
42
|
+
return new Node('op', this.type, [this], 'neg');
|
|
43
|
+
}
|
|
44
|
+
lessThan(o) {
|
|
45
|
+
return compare('<', this, o);
|
|
46
|
+
}
|
|
47
|
+
greaterThan(o) {
|
|
48
|
+
return compare('>', this, o);
|
|
49
|
+
}
|
|
50
|
+
lessThanEqual(o) {
|
|
51
|
+
return compare('<=', this, o);
|
|
52
|
+
}
|
|
53
|
+
greaterThanEqual(o) {
|
|
54
|
+
return compare('>=', this, o);
|
|
55
|
+
}
|
|
56
|
+
// Common functions as methods, as TSL allows (`v.normalize()`, `t.clamp(0, 1)`).
|
|
57
|
+
normalize() {
|
|
58
|
+
return call('normalize', [this]);
|
|
59
|
+
}
|
|
60
|
+
length() {
|
|
61
|
+
return call('length', [this]);
|
|
62
|
+
}
|
|
63
|
+
abs() {
|
|
64
|
+
return call('abs', [this]);
|
|
65
|
+
}
|
|
66
|
+
sin() {
|
|
67
|
+
return call('sin', [this]);
|
|
68
|
+
}
|
|
69
|
+
cos() {
|
|
70
|
+
return call('cos', [this]);
|
|
71
|
+
}
|
|
72
|
+
fract() {
|
|
73
|
+
return call('fract', [this]);
|
|
74
|
+
}
|
|
75
|
+
saturate() {
|
|
76
|
+
return call('saturate', [this]);
|
|
77
|
+
}
|
|
78
|
+
clamp(lo, hi) {
|
|
79
|
+
return call('clamp', [this, lo, hi]);
|
|
80
|
+
}
|
|
81
|
+
pow(e) {
|
|
82
|
+
return call('pow', [this, e]);
|
|
83
|
+
}
|
|
84
|
+
dot(o) {
|
|
85
|
+
return call('dot', [this, o]);
|
|
86
|
+
}
|
|
87
|
+
mix(b, t) {
|
|
88
|
+
return call('mix', [this, b, t]);
|
|
89
|
+
}
|
|
90
|
+
// Swizzles (the common ones; any mask through `swizzle`).
|
|
91
|
+
get x() {
|
|
92
|
+
return this.swizzle('x');
|
|
93
|
+
}
|
|
94
|
+
get y() {
|
|
95
|
+
return this.swizzle('y');
|
|
96
|
+
}
|
|
97
|
+
get z() {
|
|
98
|
+
return this.swizzle('z');
|
|
99
|
+
}
|
|
100
|
+
get w() {
|
|
101
|
+
return this.swizzle('w');
|
|
102
|
+
}
|
|
103
|
+
get xy() {
|
|
104
|
+
return this.swizzle('xy');
|
|
105
|
+
}
|
|
106
|
+
get xyz() {
|
|
107
|
+
return this.swizzle('xyz');
|
|
108
|
+
}
|
|
109
|
+
get rgb() {
|
|
110
|
+
return this.swizzle('xyz');
|
|
111
|
+
}
|
|
112
|
+
get r() {
|
|
113
|
+
return this.swizzle('x');
|
|
114
|
+
}
|
|
115
|
+
get g() {
|
|
116
|
+
return this.swizzle('y');
|
|
117
|
+
}
|
|
118
|
+
get b() {
|
|
119
|
+
return this.swizzle('z');
|
|
120
|
+
}
|
|
121
|
+
get a() {
|
|
122
|
+
return this.swizzle('w');
|
|
123
|
+
}
|
|
124
|
+
/** Components by mask (`xyz`, `rgba`, `yx`…). */
|
|
125
|
+
swizzle(mask) {
|
|
126
|
+
const m = mask.replace(/[rgba]/g, (c) => ({ r: 'x', g: 'y', b: 'z', a: 'w' })[c]);
|
|
127
|
+
const n = lanesOf(this.type);
|
|
128
|
+
if (!/^[xyzw]{1,4}$/.test(m) || [...m].some((c) => 'xyzw'.indexOf(c) >= n) || this.type === 'bool' || this.type === 'u32') {
|
|
129
|
+
throw new YaliError('TSL_SWIZZLE', `.${mask} does not apply to a ${this.type}.`, 'Swizzle vectors only, with components the vector has.');
|
|
130
|
+
}
|
|
131
|
+
return new Node('swizzle', VEC[m.length], [this], m);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/** A node from a node or a number. */
|
|
135
|
+
export function nodeOf(v) {
|
|
136
|
+
if (v instanceof Node)
|
|
137
|
+
return v;
|
|
138
|
+
if (typeof v === 'number' && Number.isFinite(v))
|
|
139
|
+
return new Node('const', 'f32', [], [v]);
|
|
140
|
+
throw new YaliError('TSL_VALUE', `${String(v)} is not a node or a finite number.`, 'Pass a node (float(), vec3(), uniform()…) or a finite number.');
|
|
141
|
+
}
|
|
142
|
+
function binary(op, a, b) {
|
|
143
|
+
const [x, y] = [nodeOf(a), nodeOf(b)];
|
|
144
|
+
return new Node('op', resultOf(op, x.type, y.type), [x, y], op);
|
|
145
|
+
}
|
|
146
|
+
function compare(op, a, b) {
|
|
147
|
+
const [x, y] = [nodeOf(a), nodeOf(b)];
|
|
148
|
+
if (x.type !== 'f32' || y.type !== 'f32')
|
|
149
|
+
throw new YaliError('TSL_TYPE', `Comparison ${op} takes two floats, not ${x.type} and ${y.type}.`, 'Compare components (`.x`) or lengths.');
|
|
150
|
+
return new Node('op', 'bool', [x, y], op);
|
|
151
|
+
}
|
|
152
|
+
/** The type of `a op b`: equal types, or a vector with a scalar (WGSL broadcasts). */
|
|
153
|
+
function resultOf(op, a, b) {
|
|
154
|
+
if (a === b && a !== 'bool')
|
|
155
|
+
return a;
|
|
156
|
+
if (a === 'f32' && b.startsWith('vec'))
|
|
157
|
+
return b;
|
|
158
|
+
if (b === 'f32' && a.startsWith('vec'))
|
|
159
|
+
return a;
|
|
160
|
+
throw new YaliError('TSL_TYPE', `${a} ${op} ${b} has no type.`, 'Combine equal types, or a vector with a float.');
|
|
161
|
+
}
|
|
162
|
+
/** WGSL built-in functions the DSL exposes, with how their result type follows the arguments. */
|
|
163
|
+
const FUNCTIONS = {
|
|
164
|
+
...Object.fromEntries(['abs', 'sin', 'cos', 'tan', 'floor', 'ceil', 'fract', 'sqrt', 'exp', 'exp2', 'log', 'log2', 'normalize', 'saturate', 'sign'].map((f) => [f, (a) => a[0]])),
|
|
165
|
+
...Object.fromEntries(['min', 'max', 'pow', 'step', 'reflect'].map((f) => [f, (a) => a.find((t) => t !== 'f32') ?? 'f32'])),
|
|
166
|
+
...Object.fromEntries(['clamp', 'mix', 'smoothstep'].map((f) => [f, (a) => a.find((t) => t !== 'f32') ?? 'f32'])),
|
|
167
|
+
dot: () => 'f32',
|
|
168
|
+
length: () => 'f32',
|
|
169
|
+
distance: () => 'f32',
|
|
170
|
+
cross: () => 'vec3f',
|
|
171
|
+
};
|
|
172
|
+
/** A call of a WGSL built-in (`call('mix', [a, b, t])`). Scalars broadcast to the vector argument's type. */
|
|
173
|
+
export function call(fn, args) {
|
|
174
|
+
const rule = FUNCTIONS[fn];
|
|
175
|
+
if (!rule)
|
|
176
|
+
throw new YaliError('TSL_FUNCTION', `${fn} is not a function @yali-engine/tsl knows.`, `Use one of: ${Object.keys(FUNCTIONS).join(', ')}.`);
|
|
177
|
+
let nodes = args.map(nodeOf);
|
|
178
|
+
const type = rule(nodes.map((n) => n.type));
|
|
179
|
+
// WGSL wants every argument of a vector call to be that vector type; only mix may take a
|
|
180
|
+
// scalar blend factor. Splat the other scalar operands.
|
|
181
|
+
if (type.startsWith('vec'))
|
|
182
|
+
nodes = nodes.map((n, i) => (n.type === 'f32' && !(fn === 'mix' && i === 2) ? construct(type, [n]) : n));
|
|
183
|
+
return new Node('call', type, nodes, fn);
|
|
184
|
+
}
|
|
185
|
+
/** A typed vector or scalar from components (`vec3(1, 0, 0)`, `vec4(rgb, 1)`, `vec3(0.5)` splats). */
|
|
186
|
+
export function construct(type, parts) {
|
|
187
|
+
const nodes = parts.map(nodeOf);
|
|
188
|
+
const want = lanesOf(type);
|
|
189
|
+
const have = nodes.reduce((n, p) => n + lanesOf(p.type), 0);
|
|
190
|
+
if (!(have === want || (nodes.length === 1 && nodes[0].type === 'f32'))) {
|
|
191
|
+
throw new YaliError('TSL_CONSTRUCT', `${type}(…) got ${have} components; it needs ${want} (or one float to splat).`, 'Pass the right number of components.');
|
|
192
|
+
}
|
|
193
|
+
if (nodes.every((n) => n.kind === 'const')) {
|
|
194
|
+
const flat = nodes.flatMap((n) => n.value);
|
|
195
|
+
return new Node('const', type, [], flat.length === 1 ? Array(want).fill(flat[0]) : flat);
|
|
196
|
+
}
|
|
197
|
+
return new Node('construct', type, nodes, type);
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=node.js.map
|
package/dist/node.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yali-engine/tsl",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Yali's material DSL: three.js TSL names, a node graph as plain data, compiled to WGSL at build time (ADR-0007, ADR-0064).",
|
|
5
|
+
"license": "MIT OR Apache-2.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"bin": {
|
|
18
|
+
"yali-tsl": "./bin/compile.mjs"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"bin"
|
|
23
|
+
],
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@yali-engine/core": "0.4.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@webgpu/types": "^0.1.60"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"typecheck": "tsc -p tsconfig.json",
|
|
32
|
+
"test": "node --experimental-strip-types --no-warnings --test \"test/*.test.ts\""
|
|
33
|
+
}
|
|
6
34
|
}
|
package/README.md
DELETED