@framefields/node-lut 2.0.2
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/.turbo/turbo-build.log +20 -0
- package/CHANGELOG.md +23 -0
- package/LICENCE +202 -0
- package/dist/index.d.mts +30 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +23 -0
- package/dist/index.mjs.map +1 -0
- package/dist/renderer.d.mts +7 -0
- package/dist/renderer.d.mts.map +1 -0
- package/dist/renderer.mjs +3 -0
- package/dist/renderers-kmnMKizc.mjs +372 -0
- package/dist/renderers-kmnMKizc.mjs.map +1 -0
- package/package.json +46 -0
- package/src/index.ts +2 -0
- package/src/renderers/index.ts +6 -0
- package/src/renderers/webgpu-renderer.ts +536 -0
- package/src/shared/config.ts +30 -0
- package/src/shared/index.ts +1 -0
- package/tsconfig.json +12 -0
- package/tsdown.config.ts +13 -0
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import { defineRenderer } from "@framefields/node-sdk/renderer";
|
|
2
|
+
import { lutStore, signalRegistry } from "@framefields/webgpu-renderers";
|
|
3
|
+
|
|
4
|
+
//#region src/renderers/webgpu-renderer.ts
|
|
5
|
+
const LUT_3D_SHADER = `
|
|
6
|
+
struct LutUniforms {
|
|
7
|
+
intensity : f32,
|
|
8
|
+
lutSize : f32,
|
|
9
|
+
hasSignal : f32,
|
|
10
|
+
pad : f32,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
@group(0) @binding(0) var<uniform> u : LutUniforms;
|
|
14
|
+
@group(1) @binding(0) var tex : texture_2d<f32>;
|
|
15
|
+
@group(1) @binding(1) var samp : sampler;
|
|
16
|
+
@group(2) @binding(0) var lutTex : texture_3d<f32>;
|
|
17
|
+
@group(2) @binding(1) var lutSamp : sampler;
|
|
18
|
+
@group(3) @binding(0) var signalTex : texture_2d<f32>;
|
|
19
|
+
@group(3) @binding(1) var signalSamp : sampler;
|
|
20
|
+
|
|
21
|
+
struct VSOut {
|
|
22
|
+
@builtin(position) pos : vec4<f32>,
|
|
23
|
+
@location(0) uv : vec2<f32>,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
@vertex fn vs(@builtin(vertex_index) vi: u32) -> VSOut {
|
|
27
|
+
var pos = array<vec2<f32>, 4>(
|
|
28
|
+
vec2<f32>(-1.0, 1.0),
|
|
29
|
+
vec2<f32>(1.0, 1.0),
|
|
30
|
+
vec2<f32>(-1.0, -1.0),
|
|
31
|
+
vec2<f32>(1.0, -1.0)
|
|
32
|
+
);
|
|
33
|
+
var uv = array<vec2<f32>, 4>(
|
|
34
|
+
vec2<f32>(0.0, 0.0),
|
|
35
|
+
vec2<f32>(1.0, 0.0),
|
|
36
|
+
vec2<f32>(0.0, 1.0),
|
|
37
|
+
vec2<f32>(1.0, 1.0)
|
|
38
|
+
);
|
|
39
|
+
return VSOut(vec4<f32>(pos[vi], 0.0, 1.0), uv[vi]);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@fragment fn fs(in : VSOut) -> @location(0) vec4<f32> {
|
|
43
|
+
let inputColor = textureSampleLevel(tex, samp, in.uv, 0.0);
|
|
44
|
+
|
|
45
|
+
// Coordinate adjustment to sample from texel centers
|
|
46
|
+
let uvw = inputColor.rgb * ((u.lutSize - 1.0) / u.lutSize) + vec3<f32>(0.5 / u.lutSize);
|
|
47
|
+
let mappedColor = textureSampleLevel(lutTex, lutSamp, uvw, 0.0);
|
|
48
|
+
|
|
49
|
+
var activeIntensity = u.intensity;
|
|
50
|
+
if (u.hasSignal > 0.5) {
|
|
51
|
+
activeIntensity = textureSampleLevel(signalTex, signalSamp, in.uv, 0.0).r;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let finalRgb = inputColor.rgb + activeIntensity * (mappedColor.rgb - inputColor.rgb);
|
|
55
|
+
return vec4<f32>(finalRgb * inputColor.a, inputColor.a);
|
|
56
|
+
}
|
|
57
|
+
`;
|
|
58
|
+
const LUT_1D_SHADER = `
|
|
59
|
+
struct LutUniforms {
|
|
60
|
+
intensity : f32,
|
|
61
|
+
lutSize : f32,
|
|
62
|
+
hasSignal : f32,
|
|
63
|
+
pad : f32,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
@group(0) @binding(0) var<uniform> u : LutUniforms;
|
|
67
|
+
@group(1) @binding(0) var tex : texture_2d<f32>;
|
|
68
|
+
@group(1) @binding(1) var samp : sampler;
|
|
69
|
+
@group(2) @binding(0) var lutTex : texture_1d<f32>;
|
|
70
|
+
@group(2) @binding(1) var lutSamp : sampler;
|
|
71
|
+
@group(3) @binding(0) var signalTex : texture_2d<f32>;
|
|
72
|
+
@group(3) @binding(1) var signalSamp : sampler;
|
|
73
|
+
|
|
74
|
+
struct VSOut {
|
|
75
|
+
@builtin(position) pos : vec4<f32>,
|
|
76
|
+
@location(0) uv : vec2<f32>,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
@vertex fn vs(@builtin(vertex_index) vi: u32) -> VSOut {
|
|
80
|
+
var pos = array<vec2<f32>, 4>(
|
|
81
|
+
vec2<f32>(-1.0, 1.0),
|
|
82
|
+
vec2<f32>(1.0, 1.0),
|
|
83
|
+
vec2<f32>(-1.0, -1.0),
|
|
84
|
+
vec2<f32>(1.0, -1.0)
|
|
85
|
+
);
|
|
86
|
+
var uv = array<vec2<f32>, 4>(
|
|
87
|
+
vec2<f32>(0.0, 0.0),
|
|
88
|
+
vec2<f32>(1.0, 0.0),
|
|
89
|
+
vec2<f32>(0.0, 1.0),
|
|
90
|
+
vec2<f32>(1.0, 1.0)
|
|
91
|
+
);
|
|
92
|
+
return VSOut(vec4<f32>(pos[vi], 0.0, 1.0), uv[vi]);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@fragment fn fs(in : VSOut) -> @location(0) vec4<f32> {
|
|
96
|
+
let inputColor = textureSampleLevel(tex, samp, in.uv, 0.0);
|
|
97
|
+
|
|
98
|
+
let rCoord = inputColor.r * ((u.lutSize - 1.0) / u.lutSize) + (0.5 / u.lutSize);
|
|
99
|
+
let gCoord = inputColor.g * ((u.lutSize - 1.0) / u.lutSize) + (0.5 / u.lutSize);
|
|
100
|
+
let bCoord = inputColor.b * ((u.lutSize - 1.0) / u.lutSize) + (0.5 / u.lutSize);
|
|
101
|
+
|
|
102
|
+
let mappedR = textureSampleLevel(lutTex, lutSamp, rCoord, 0.0).r;
|
|
103
|
+
let mappedG = textureSampleLevel(lutTex, lutSamp, gCoord, 0.0).g;
|
|
104
|
+
let mappedB = textureSampleLevel(lutTex, lutSamp, bCoord, 0.0).b;
|
|
105
|
+
|
|
106
|
+
var activeIntensity = u.intensity;
|
|
107
|
+
if (u.hasSignal > 0.5) {
|
|
108
|
+
activeIntensity = textureSampleLevel(signalTex, signalSamp, in.uv, 0.0).r;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
let finalRgb = inputColor.rgb + activeIntensity * (vec3<f32>(mappedR, mappedG, mappedB) - inputColor.rgb);
|
|
112
|
+
return vec4<f32>(finalRgb * inputColor.a, inputColor.a);
|
|
113
|
+
}
|
|
114
|
+
`;
|
|
115
|
+
const deviceResourceCache = /* @__PURE__ */ new WeakMap();
|
|
116
|
+
const lutUniformData = new Float32Array(4);
|
|
117
|
+
function getDeviceLayouts(device) {
|
|
118
|
+
let res = deviceResourceCache.get(device);
|
|
119
|
+
if (res) return res;
|
|
120
|
+
res = {
|
|
121
|
+
lutUniformLayout: device.createBindGroupLayout({ entries: [{
|
|
122
|
+
binding: 0,
|
|
123
|
+
visibility: GPUShaderStage.FRAGMENT,
|
|
124
|
+
buffer: { type: "uniform" }
|
|
125
|
+
}] }),
|
|
126
|
+
singleTextureLayout: device.createBindGroupLayout({ entries: [{
|
|
127
|
+
binding: 0,
|
|
128
|
+
visibility: GPUShaderStage.FRAGMENT,
|
|
129
|
+
texture: { sampleType: "float" }
|
|
130
|
+
}, {
|
|
131
|
+
binding: 1,
|
|
132
|
+
visibility: GPUShaderStage.FRAGMENT,
|
|
133
|
+
sampler: { type: "filtering" }
|
|
134
|
+
}] }),
|
|
135
|
+
lutTextureLayout3D: device.createBindGroupLayout({ entries: [{
|
|
136
|
+
binding: 0,
|
|
137
|
+
visibility: GPUShaderStage.FRAGMENT,
|
|
138
|
+
texture: {
|
|
139
|
+
viewDimension: "3d",
|
|
140
|
+
sampleType: "float"
|
|
141
|
+
}
|
|
142
|
+
}, {
|
|
143
|
+
binding: 1,
|
|
144
|
+
visibility: GPUShaderStage.FRAGMENT,
|
|
145
|
+
sampler: { type: "filtering" }
|
|
146
|
+
}] }),
|
|
147
|
+
lutTextureLayout1D: device.createBindGroupLayout({ entries: [{
|
|
148
|
+
binding: 0,
|
|
149
|
+
visibility: GPUShaderStage.FRAGMENT,
|
|
150
|
+
texture: {
|
|
151
|
+
viewDimension: "1d",
|
|
152
|
+
sampleType: "float"
|
|
153
|
+
}
|
|
154
|
+
}, {
|
|
155
|
+
binding: 1,
|
|
156
|
+
visibility: GPUShaderStage.FRAGMENT,
|
|
157
|
+
sampler: { type: "filtering" }
|
|
158
|
+
}] }),
|
|
159
|
+
signalTextureLayout: device.createBindGroupLayout({ entries: [{
|
|
160
|
+
binding: 0,
|
|
161
|
+
visibility: GPUShaderStage.FRAGMENT,
|
|
162
|
+
texture: { sampleType: "float" }
|
|
163
|
+
}, {
|
|
164
|
+
binding: 1,
|
|
165
|
+
visibility: GPUShaderStage.FRAGMENT,
|
|
166
|
+
sampler: { type: "filtering" }
|
|
167
|
+
}] }),
|
|
168
|
+
pipelineCache: /* @__PURE__ */ new Map()
|
|
169
|
+
};
|
|
170
|
+
deviceResourceCache.set(device, res);
|
|
171
|
+
return res;
|
|
172
|
+
}
|
|
173
|
+
function getLutResources(device, format, type) {
|
|
174
|
+
const layouts = getDeviceLayouts(device);
|
|
175
|
+
const cacheKey = `lut_${type}_${format}`;
|
|
176
|
+
let pipeline = layouts.pipelineCache.get(cacheKey);
|
|
177
|
+
if (!pipeline) {
|
|
178
|
+
const shaderCode = type === "3D" ? LUT_3D_SHADER : LUT_1D_SHADER;
|
|
179
|
+
const lutModule = device.createShaderModule({
|
|
180
|
+
label: `lut_${type.toLowerCase()}_${format}.wgsl`,
|
|
181
|
+
code: shaderCode
|
|
182
|
+
});
|
|
183
|
+
const currentLutLayout = type === "3D" ? layouts.lutTextureLayout3D : layouts.lutTextureLayout1D;
|
|
184
|
+
pipeline = device.createRenderPipeline({
|
|
185
|
+
label: `LutPipeline_${type}_${format}`,
|
|
186
|
+
layout: device.createPipelineLayout({ bindGroupLayouts: [
|
|
187
|
+
layouts.lutUniformLayout,
|
|
188
|
+
layouts.singleTextureLayout,
|
|
189
|
+
currentLutLayout,
|
|
190
|
+
layouts.signalTextureLayout
|
|
191
|
+
] }),
|
|
192
|
+
vertex: {
|
|
193
|
+
module: lutModule,
|
|
194
|
+
entryPoint: "vs"
|
|
195
|
+
},
|
|
196
|
+
fragment: {
|
|
197
|
+
module: lutModule,
|
|
198
|
+
entryPoint: "fs",
|
|
199
|
+
targets: [{ format }]
|
|
200
|
+
},
|
|
201
|
+
primitive: { topology: "triangle-strip" }
|
|
202
|
+
});
|
|
203
|
+
layouts.pipelineCache.set(cacheKey, pipeline);
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
lutPipeline: pipeline,
|
|
207
|
+
lutUniformLayout: layouts.lutUniformLayout,
|
|
208
|
+
singleTextureLayout: layouts.singleTextureLayout,
|
|
209
|
+
lutTextureLayout: type === "3D" ? layouts.lutTextureLayout3D : layouts.lutTextureLayout1D,
|
|
210
|
+
signalTextureLayout: layouts.signalTextureLayout
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
const LutWebGPURenderer = async (args) => {
|
|
214
|
+
const { ctx, encoder, pass, targetView, targetTexture, targetWidth, targetHeight, props, drawChild } = args;
|
|
215
|
+
const frame = props.frame ?? 0;
|
|
216
|
+
const fps = props.fps || 30;
|
|
217
|
+
const op = props.virtualMedia?.operation;
|
|
218
|
+
if (op?.op !== "ApplyLUT" || !op) return;
|
|
219
|
+
const childMedia = props.virtualMedia.children?.[0];
|
|
220
|
+
if (!childMedia) return;
|
|
221
|
+
const lutUrl = op.lutUrl;
|
|
222
|
+
if (!lutUrl) return;
|
|
223
|
+
pass.end();
|
|
224
|
+
const width = targetWidth;
|
|
225
|
+
const height = targetHeight;
|
|
226
|
+
const intensityInput = op.intensityHandleId ? op.inputs?.[op.intensityHandleId] : null;
|
|
227
|
+
const hasSignal = !!(intensityInput?.connectionValid && intensityInput.outputItem?.type === "Signal");
|
|
228
|
+
const sd = hasSignal ? intensityInput?.outputItem?.data : null;
|
|
229
|
+
let intensity = 1;
|
|
230
|
+
let hasStaticSignal = false;
|
|
231
|
+
if (!hasSignal) if (intensityInput?.connectionValid && intensityInput.outputItem?.type === "Number") intensity = Number(intensityInput.outputItem.data ?? 1);
|
|
232
|
+
else intensity = Number(op.intensity ?? 1);
|
|
233
|
+
else if (sd && typeof sd === "object") {
|
|
234
|
+
intensity = Number(sd.offset ?? 1);
|
|
235
|
+
hasStaticSignal = true;
|
|
236
|
+
}
|
|
237
|
+
intensity = Math.max(0, Math.min(10, intensity));
|
|
238
|
+
let lut = lutStore.get(lutUrl, ctx.device);
|
|
239
|
+
if (!lut) {
|
|
240
|
+
if ((props.isHeadless ?? (typeof window === "undefined" || globalThis.__IS_HEADLESS_RENDERER__)) || props.forceWait) try {
|
|
241
|
+
lut = await lutStore.getOrLoad(lutUrl, ctx.device);
|
|
242
|
+
} catch (err) {
|
|
243
|
+
if (!(err instanceof DOMException && err.name === "AbortError") && !(err && typeof err === "object" && "name" in err && err.name === "AbortError")) console.error("[ApplyLUT] Failed to load LUT synchronously:", err);
|
|
244
|
+
}
|
|
245
|
+
else lutStore.getOrLoad(lutUrl, ctx.device).catch((err) => {
|
|
246
|
+
if (err instanceof DOMException && err.name === "AbortError" || err && typeof err === "object" && "name" in err && err.name === "AbortError") return;
|
|
247
|
+
console.error("[ApplyLUT] Failed to load LUT in background:", err);
|
|
248
|
+
});
|
|
249
|
+
if (!lut && lutUrl.startsWith("runtime://lut/")) {
|
|
250
|
+
const prefix = lutUrl.substring(0, lutUrl.lastIndexOf("-") + 1);
|
|
251
|
+
if (prefix) lut = lutStore.getAnyMatching(prefix, ctx.device);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
const tmpTex = ctx.renderer.getTemporaryTexture(width, height, [...props.excludeTextures || [], targetTexture]);
|
|
255
|
+
const tmpView = tmpTex.createView();
|
|
256
|
+
ctx.renderer.beginFrame(encoder, tmpView, {
|
|
257
|
+
r: 0,
|
|
258
|
+
g: 0,
|
|
259
|
+
b: 0,
|
|
260
|
+
a: 0
|
|
261
|
+
}, width, height, "clear").end();
|
|
262
|
+
ctx.renderer.pushScissor({
|
|
263
|
+
x: 0,
|
|
264
|
+
y: 0,
|
|
265
|
+
width,
|
|
266
|
+
height
|
|
267
|
+
});
|
|
268
|
+
ctx.renderer.pushIdentity();
|
|
269
|
+
await drawChild(childMedia, {
|
|
270
|
+
...props,
|
|
271
|
+
virtualMedia: childMedia
|
|
272
|
+
}, tmpView, tmpTex, width, height);
|
|
273
|
+
ctx.renderer.popTransform();
|
|
274
|
+
ctx.renderer.popScissor();
|
|
275
|
+
if (!lut) {
|
|
276
|
+
const finalPass$1 = ctx.renderer.beginFrame(encoder, targetView, {
|
|
277
|
+
r: 0,
|
|
278
|
+
g: 0,
|
|
279
|
+
b: 0,
|
|
280
|
+
a: 0
|
|
281
|
+
}, targetWidth, targetHeight, "load");
|
|
282
|
+
ctx.renderer.drawTexture(finalPass$1, tmpTex, {
|
|
283
|
+
x: 0,
|
|
284
|
+
y: 0,
|
|
285
|
+
width: targetWidth,
|
|
286
|
+
height: targetHeight
|
|
287
|
+
}, { opacity: op.opacity ?? 1 });
|
|
288
|
+
args.pass = finalPass$1;
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
const { lutPipeline: pipeline, lutUniformLayout: uLayout, singleTextureLayout: tLayout, lutTextureLayout: lLayout, signalTextureLayout: sigLayout } = getLutResources(ctx.device, ctx.renderer.format, lut.type);
|
|
292
|
+
const sampler = ctx.renderer.samplerCache.getSampler(ctx.device);
|
|
293
|
+
const outTex = ctx.renderer.getTemporaryTexture(width, height, [
|
|
294
|
+
tmpTex,
|
|
295
|
+
targetTexture,
|
|
296
|
+
...props.excludeTextures || []
|
|
297
|
+
]);
|
|
298
|
+
let signalView;
|
|
299
|
+
if (hasStaticSignal) {
|
|
300
|
+
const elapsedSeconds = props.elapsedMs !== void 0 ? props.elapsedMs / 1e3 : frame / fps;
|
|
301
|
+
const durationSeconds = props.virtualMedia?.metadata?.durationMs ? props.virtualMedia.metadata.durationMs / 1e3 : props.durationMs !== void 0 ? props.durationMs / 1e3 : 0;
|
|
302
|
+
signalView = signalRegistry.getOrCreate2DTextureView(ctx.device, encoder, sd.nodeId ?? "lut_intensity_sig", elapsedSeconds, durationSeconds, sd, width, height, props.renderId, frame, fps);
|
|
303
|
+
} else signalView = signalRegistry.getDummy1x1TextureView(ctx.device);
|
|
304
|
+
lutUniformData[0] = intensity;
|
|
305
|
+
lutUniformData[1] = lut.size;
|
|
306
|
+
lutUniformData[2] = hasStaticSignal ? 1 : 0;
|
|
307
|
+
lutUniformData[3] = 0;
|
|
308
|
+
const uniformBuffer = ctx.renderer.getTemporaryBuffer(lutUniformData);
|
|
309
|
+
const renderPass = encoder.beginRenderPass({ colorAttachments: [{
|
|
310
|
+
view: outTex.createView(),
|
|
311
|
+
loadOp: "clear",
|
|
312
|
+
storeOp: "store",
|
|
313
|
+
clearValue: {
|
|
314
|
+
r: 0,
|
|
315
|
+
g: 0,
|
|
316
|
+
b: 0,
|
|
317
|
+
a: 0
|
|
318
|
+
}
|
|
319
|
+
}] });
|
|
320
|
+
renderPass.setPipeline(pipeline);
|
|
321
|
+
renderPass.setBindGroup(0, ctx.device.createBindGroup({
|
|
322
|
+
layout: uLayout,
|
|
323
|
+
entries: [{
|
|
324
|
+
binding: 0,
|
|
325
|
+
resource: { buffer: uniformBuffer }
|
|
326
|
+
}]
|
|
327
|
+
}));
|
|
328
|
+
renderPass.setBindGroup(1, ctx.renderer.bindGroupCache.getBindGroup(ctx.device, tLayout, tmpTex, sampler));
|
|
329
|
+
renderPass.setBindGroup(2, ctx.device.createBindGroup({
|
|
330
|
+
layout: lLayout,
|
|
331
|
+
entries: [{
|
|
332
|
+
binding: 0,
|
|
333
|
+
resource: lut.texture.createView()
|
|
334
|
+
}, {
|
|
335
|
+
binding: 1,
|
|
336
|
+
resource: sampler
|
|
337
|
+
}]
|
|
338
|
+
}));
|
|
339
|
+
renderPass.setBindGroup(3, ctx.device.createBindGroup({
|
|
340
|
+
layout: sigLayout,
|
|
341
|
+
entries: [{
|
|
342
|
+
binding: 0,
|
|
343
|
+
resource: signalView
|
|
344
|
+
}, {
|
|
345
|
+
binding: 1,
|
|
346
|
+
resource: sampler
|
|
347
|
+
}]
|
|
348
|
+
}));
|
|
349
|
+
renderPass.draw(4);
|
|
350
|
+
renderPass.end();
|
|
351
|
+
const finalPass = ctx.renderer.beginFrame(encoder, targetView, {
|
|
352
|
+
r: 0,
|
|
353
|
+
g: 0,
|
|
354
|
+
b: 0,
|
|
355
|
+
a: 0
|
|
356
|
+
}, targetWidth, targetHeight, "load");
|
|
357
|
+
ctx.renderer.drawTexture(finalPass, outTex, {
|
|
358
|
+
x: 0,
|
|
359
|
+
y: 0,
|
|
360
|
+
width: targetWidth,
|
|
361
|
+
height: targetHeight
|
|
362
|
+
}, { opacity: op.opacity ?? 1 });
|
|
363
|
+
args.pass = finalPass;
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
//#endregion
|
|
367
|
+
//#region src/renderers/index.ts
|
|
368
|
+
var renderers_default = defineRenderer({ WebGPURenderer: LutWebGPURenderer });
|
|
369
|
+
|
|
370
|
+
//#endregion
|
|
371
|
+
export { renderers_default as t };
|
|
372
|
+
//# sourceMappingURL=renderers-kmnMKizc.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderers-kmnMKizc.mjs","names":["finalPass"],"sources":["../src/renderers/webgpu-renderer.ts","../src/renderers/index.ts"],"sourcesContent":["/// <reference types=\"webgpu\" />\nimport type { WebGPUNodeRenderer } from \"@framefields/node-sdk\";\nimport { lutStore, signalRegistry } from \"@framefields/webgpu-renderers\";\n\nexport const LUT_3D_SHADER = `\nstruct LutUniforms {\n\tintensity : f32,\n\tlutSize : f32,\n\thasSignal : f32,\n\tpad : f32,\n};\n\n@group(0) @binding(0) var<uniform> u : LutUniforms;\n@group(1) @binding(0) var tex : texture_2d<f32>;\n@group(1) @binding(1) var samp : sampler;\n@group(2) @binding(0) var lutTex : texture_3d<f32>;\n@group(2) @binding(1) var lutSamp : sampler;\n@group(3) @binding(0) var signalTex : texture_2d<f32>;\n@group(3) @binding(1) var signalSamp : sampler;\n\nstruct VSOut {\n\t@builtin(position) pos : vec4<f32>,\n\t@location(0) uv : vec2<f32>,\n};\n\n@vertex fn vs(@builtin(vertex_index) vi: u32) -> VSOut {\n\tvar pos = array<vec2<f32>, 4>(\n\t\tvec2<f32>(-1.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0),\n\t\tvec2<f32>(-1.0, -1.0),\n\t\tvec2<f32>(1.0, -1.0)\n\t);\n\tvar uv = array<vec2<f32>, 4>(\n\t\tvec2<f32>(0.0, 0.0),\n\t\tvec2<f32>(1.0, 0.0),\n\t\tvec2<f32>(0.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0)\n\t);\n\treturn VSOut(vec4<f32>(pos[vi], 0.0, 1.0), uv[vi]);\n}\n\n@fragment fn fs(in : VSOut) -> @location(0) vec4<f32> {\n\tlet inputColor = textureSampleLevel(tex, samp, in.uv, 0.0);\n\t\n\t// Coordinate adjustment to sample from texel centers\n\tlet uvw = inputColor.rgb * ((u.lutSize - 1.0) / u.lutSize) + vec3<f32>(0.5 / u.lutSize);\n\tlet mappedColor = textureSampleLevel(lutTex, lutSamp, uvw, 0.0);\n\t\n\tvar activeIntensity = u.intensity;\n\tif (u.hasSignal > 0.5) {\n\t\tactiveIntensity = textureSampleLevel(signalTex, signalSamp, in.uv, 0.0).r;\n\t}\n\t\n\tlet finalRgb = inputColor.rgb + activeIntensity * (mappedColor.rgb - inputColor.rgb);\n\treturn vec4<f32>(finalRgb * inputColor.a, inputColor.a);\n}\n`;\n\nexport const LUT_1D_SHADER = `\nstruct LutUniforms {\n\tintensity : f32,\n\tlutSize : f32,\n\thasSignal : f32,\n\tpad : f32,\n};\n\n@group(0) @binding(0) var<uniform> u : LutUniforms;\n@group(1) @binding(0) var tex : texture_2d<f32>;\n@group(1) @binding(1) var samp : sampler;\n@group(2) @binding(0) var lutTex : texture_1d<f32>;\n@group(2) @binding(1) var lutSamp : sampler;\n@group(3) @binding(0) var signalTex : texture_2d<f32>;\n@group(3) @binding(1) var signalSamp : sampler;\n\nstruct VSOut {\n\t@builtin(position) pos : vec4<f32>,\n\t@location(0) uv : vec2<f32>,\n};\n\n@vertex fn vs(@builtin(vertex_index) vi: u32) -> VSOut {\n\tvar pos = array<vec2<f32>, 4>(\n\t\tvec2<f32>(-1.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0),\n\t\tvec2<f32>(-1.0, -1.0),\n\t\tvec2<f32>(1.0, -1.0)\n\t);\n\tvar uv = array<vec2<f32>, 4>(\n\t\tvec2<f32>(0.0, 0.0),\n\t\tvec2<f32>(1.0, 0.0),\n\t\tvec2<f32>(0.0, 1.0),\n\t\tvec2<f32>(1.0, 1.0)\n\t);\n\treturn VSOut(vec4<f32>(pos[vi], 0.0, 1.0), uv[vi]);\n}\n\n@fragment fn fs(in : VSOut) -> @location(0) vec4<f32> {\n\tlet inputColor = textureSampleLevel(tex, samp, in.uv, 0.0);\n\t\n\tlet rCoord = inputColor.r * ((u.lutSize - 1.0) / u.lutSize) + (0.5 / u.lutSize);\n\tlet gCoord = inputColor.g * ((u.lutSize - 1.0) / u.lutSize) + (0.5 / u.lutSize);\n\tlet bCoord = inputColor.b * ((u.lutSize - 1.0) / u.lutSize) + (0.5 / u.lutSize);\n\t\n\tlet mappedR = textureSampleLevel(lutTex, lutSamp, rCoord, 0.0).r;\n\tlet mappedG = textureSampleLevel(lutTex, lutSamp, gCoord, 0.0).g;\n\tlet mappedB = textureSampleLevel(lutTex, lutSamp, bCoord, 0.0).b;\n\t\n\tvar activeIntensity = u.intensity;\n\tif (u.hasSignal > 0.5) {\n\t\tactiveIntensity = textureSampleLevel(signalTex, signalSamp, in.uv, 0.0).r;\n\t}\n\t\n\tlet finalRgb = inputColor.rgb + activeIntensity * (vec3<f32>(mappedR, mappedG, mappedB) - inputColor.rgb);\n\treturn vec4<f32>(finalRgb * inputColor.a, inputColor.a);\n}\n`;\n\ninterface DeviceLutLayouts {\n\tlutUniformLayout: GPUBindGroupLayout;\n\tsingleTextureLayout: GPUBindGroupLayout;\n\tlutTextureLayout3D: GPUBindGroupLayout;\n\tlutTextureLayout1D: GPUBindGroupLayout;\n\tsignalTextureLayout: GPUBindGroupLayout;\n\tpipelineCache: Map<string, GPURenderPipeline>;\n}\n\nconst deviceResourceCache = new WeakMap<GPUDevice, DeviceLutLayouts>();\nconst lutUniformData = new Float32Array(4);\n\nfunction getDeviceLayouts(device: GPUDevice): DeviceLutLayouts {\n\tlet res = deviceResourceCache.get(device);\n\tif (res) return res;\n\n\tconst lutUniformLayout = device.createBindGroupLayout({\n\t\tentries: [\n\t\t\t{\n\t\t\t\tbinding: 0,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\tbuffer: { type: \"uniform\" },\n\t\t\t},\n\t\t],\n\t});\n\tconst singleTextureLayout = device.createBindGroupLayout({\n\t\tentries: [\n\t\t\t{\n\t\t\t\tbinding: 0,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\ttexture: { sampleType: \"float\" },\n\t\t\t},\n\t\t\t{\n\t\t\t\tbinding: 1,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\tsampler: { type: \"filtering\" },\n\t\t\t},\n\t\t],\n\t});\n\tconst lutTextureLayout3D = device.createBindGroupLayout({\n\t\tentries: [\n\t\t\t{\n\t\t\t\tbinding: 0,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\ttexture: { viewDimension: \"3d\", sampleType: \"float\" },\n\t\t\t},\n\t\t\t{\n\t\t\t\tbinding: 1,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\tsampler: { type: \"filtering\" },\n\t\t\t},\n\t\t],\n\t});\n\tconst lutTextureLayout1D = device.createBindGroupLayout({\n\t\tentries: [\n\t\t\t{\n\t\t\t\tbinding: 0,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\ttexture: { viewDimension: \"1d\", sampleType: \"float\" },\n\t\t\t},\n\t\t\t{\n\t\t\t\tbinding: 1,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\tsampler: { type: \"filtering\" },\n\t\t\t},\n\t\t],\n\t});\n\tconst signalTextureLayout = device.createBindGroupLayout({\n\t\tentries: [\n\t\t\t{\n\t\t\t\tbinding: 0,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\ttexture: { sampleType: \"float\" },\n\t\t\t},\n\t\t\t{\n\t\t\t\tbinding: 1,\n\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\tsampler: { type: \"filtering\" },\n\t\t\t},\n\t\t],\n\t});\n\n\tres = {\n\t\tlutUniformLayout,\n\t\tsingleTextureLayout,\n\t\tlutTextureLayout3D,\n\t\tlutTextureLayout1D,\n\t\tsignalTextureLayout,\n\t\tpipelineCache: new Map(),\n\t};\n\tdeviceResourceCache.set(device, res);\n\treturn res;\n}\n\nfunction getLutResources(\n\tdevice: GPUDevice,\n\tformat: GPUTextureFormat,\n\ttype: \"1D\" | \"3D\",\n) {\n\tconst layouts = getDeviceLayouts(device);\n\tconst cacheKey = `lut_${type}_${format}`;\n\tlet pipeline = layouts.pipelineCache.get(cacheKey);\n\tif (!pipeline) {\n\t\tconst shaderCode = type === \"3D\" ? LUT_3D_SHADER : LUT_1D_SHADER;\n\t\tconst lutModule = device.createShaderModule({\n\t\t\tlabel: `lut_${type.toLowerCase()}_${format}.wgsl`,\n\t\t\tcode: shaderCode,\n\t\t});\n\t\tconst currentLutLayout =\n\t\t\ttype === \"3D\" ? layouts.lutTextureLayout3D : layouts.lutTextureLayout1D;\n\t\tpipeline = device.createRenderPipeline({\n\t\t\tlabel: `LutPipeline_${type}_${format}`,\n\t\t\tlayout: device.createPipelineLayout({\n\t\t\t\tbindGroupLayouts: [\n\t\t\t\t\tlayouts.lutUniformLayout,\n\t\t\t\t\tlayouts.singleTextureLayout,\n\t\t\t\t\tcurrentLutLayout,\n\t\t\t\t\tlayouts.signalTextureLayout,\n\t\t\t\t],\n\t\t\t}),\n\t\t\tvertex: { module: lutModule, entryPoint: \"vs\" },\n\t\t\tfragment: {\n\t\t\t\tmodule: lutModule,\n\t\t\t\tentryPoint: \"fs\",\n\t\t\t\ttargets: [{ format }],\n\t\t\t},\n\t\t\tprimitive: { topology: \"triangle-strip\" },\n\t\t});\n\t\tlayouts.pipelineCache.set(cacheKey, pipeline);\n\t}\n\n\treturn {\n\t\tlutPipeline: pipeline,\n\t\tlutUniformLayout: layouts.lutUniformLayout,\n\t\tsingleTextureLayout: layouts.singleTextureLayout,\n\t\tlutTextureLayout:\n\t\t\ttype === \"3D\" ? layouts.lutTextureLayout3D : layouts.lutTextureLayout1D,\n\t\tsignalTextureLayout: layouts.signalTextureLayout,\n\t};\n}\n\nexport const LutWebGPURenderer: WebGPUNodeRenderer = async (args) => {\n\tconst {\n\t\tctx,\n\t\tencoder,\n\t\tpass,\n\t\ttargetView,\n\t\ttargetTexture,\n\t\ttargetWidth,\n\t\ttargetHeight,\n\t\tprops,\n\t\tdrawChild,\n\t} = args;\n\tconst frame = props.frame ?? 0;\n\tconst fps = props.fps || 30;\n\tconst op = props.virtualMedia?.operation as any;\n\tif (op?.op !== \"ApplyLUT\" || !op) return;\n\tconst childMedia = props.virtualMedia.children?.[0];\n\tif (!childMedia) return;\n\n\tconst lutUrl = op.lutUrl;\n\tif (!lutUrl) return;\n\n\t// End the active pass\n\tpass.end();\n\n\tconst width = targetWidth;\n\tconst height = targetHeight;\n\n\t// Resolve the intensity signal\n\tconst intensityInput = op.intensityHandleId\n\t\t? op.inputs?.[op.intensityHandleId]\n\t\t: null;\n\tconst hasSignal = !!(\n\t\tintensityInput?.connectionValid &&\n\t\tintensityInput.outputItem?.type === \"Signal\"\n\t);\n\tconst sd = hasSignal ? intensityInput?.outputItem?.data : null;\n\n\tlet intensity = 1.0;\n\tlet hasStaticSignal = false;\n\n\tif (!hasSignal) {\n\t\tif (\n\t\t\tintensityInput?.connectionValid &&\n\t\t\tintensityInput.outputItem?.type === \"Number\"\n\t\t) {\n\t\t\tintensity = Number(intensityInput.outputItem.data ?? 1.0);\n\t\t} else {\n\t\t\tintensity = Number(op.intensity ?? 1.0);\n\t\t}\n\t} else if (sd && typeof sd === \"object\") {\n\t\tintensity = Number((sd as any).offset ?? 1.0);\n\t\thasStaticSignal = true;\n\t}\n\tintensity = Math.max(0, Math.min(10, intensity));\n\n\t// Load the GPU LUT resource without blocking the rendering pipeline.\n\tlet lut = lutStore.get(lutUrl, ctx.device);\n\tif (!lut) {\n\t\tconst isHeadless =\n\t\t\tprops.isHeadless ??\n\t\t\t(typeof window === \"undefined\" ||\n\t\t\t\t(globalThis as any).__IS_HEADLESS_RENDERER__);\n\n\t\tif (isHeadless || props.forceWait) {\n\t\t\ttry {\n\t\t\t\tlut = await lutStore.getOrLoad(lutUrl, ctx.device);\n\t\t\t} catch (err) {\n\t\t\t\tif (\n\t\t\t\t\t!(err instanceof DOMException && err.name === \"AbortError\") &&\n\t\t\t\t\t!(\n\t\t\t\t\t\terr &&\n\t\t\t\t\t\ttypeof err === \"object\" &&\n\t\t\t\t\t\t\"name\" in err &&\n\t\t\t\t\t\terr.name === \"AbortError\"\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tconsole.error(\"[ApplyLUT] Failed to load LUT synchronously:\", err);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Trigger background load\n\t\t\tlutStore.getOrLoad(lutUrl, ctx.device).catch((err) => {\n\t\t\t\tif (\n\t\t\t\t\t(err instanceof DOMException && err.name === \"AbortError\") ||\n\t\t\t\t\t(err &&\n\t\t\t\t\t\ttypeof err === \"object\" &&\n\t\t\t\t\t\t\"name\" in err &&\n\t\t\t\t\t\terr.name === \"AbortError\")\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconsole.error(\"[ApplyLUT] Failed to load LUT in background:\", err);\n\t\t\t});\n\t\t}\n\n\t\t// Fallback to any matching cached LUT for the same node\n\t\tif (!lut && lutUrl.startsWith(\"runtime://lut/\")) {\n\t\t\tconst prefix = lutUrl.substring(0, lutUrl.lastIndexOf(\"-\") + 1);\n\t\t\tif (prefix) {\n\t\t\t\tlut = lutStore.getAnyMatching(prefix, ctx.device);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst tmpTex = ctx.renderer.getTemporaryTexture(width, height, [\n\t\t...(props.excludeTextures || []),\n\t\ttargetTexture,\n\t]);\n\tconst tmpView = tmpTex.createView();\n\n\t// Clear temporary texture\n\tconst childPass = ctx.renderer.beginFrame(\n\t\tencoder,\n\t\ttmpView,\n\t\t{ r: 0, g: 0, b: 0, a: 0 },\n\t\twidth,\n\t\theight,\n\t\t\"clear\",\n\t);\n\tchildPass.end();\n\n\t// Draw child frame into tmpTex\n\tctx.renderer.pushScissor({ x: 0, y: 0, width, height });\n\tctx.renderer.pushIdentity();\n\tawait drawChild(\n\t\tchildMedia,\n\t\t{ ...props, virtualMedia: childMedia },\n\t\ttmpView,\n\t\ttmpTex,\n\t\twidth,\n\t\theight,\n\t);\n\tctx.renderer.popTransform();\n\tctx.renderer.popScissor();\n\n\t// If no LUT is ready (and no fallback is available), draw the child frame directly as a passthrough\n\tif (!lut) {\n\t\tconst finalPass = ctx.renderer.beginFrame(\n\t\t\tencoder,\n\t\t\ttargetView,\n\t\t\t{ r: 0, g: 0, b: 0, a: 0 },\n\t\t\ttargetWidth,\n\t\t\ttargetHeight,\n\t\t\t\"load\",\n\t\t);\n\n\t\tctx.renderer.drawTexture(\n\t\t\tfinalPass,\n\t\t\ttmpTex,\n\t\t\t{ x: 0, y: 0, width: targetWidth, height: targetHeight },\n\t\t\t{ opacity: op.opacity ?? 1 },\n\t\t);\n\t\targs.pass = finalPass;\n\t\treturn;\n\t}\n\n\t// Fetch pipeline and layouts\n\tconst {\n\t\tlutPipeline: pipeline,\n\t\tlutUniformLayout: uLayout,\n\t\tsingleTextureLayout: tLayout,\n\t\tlutTextureLayout: lLayout,\n\t\tsignalTextureLayout: sigLayout,\n\t} = getLutResources(ctx.device, ctx.renderer.format, lut.type);\n\n\tconst sampler = ctx.renderer.samplerCache.getSampler(ctx.device);\n\n\t// Setup intermediate output texture\n\tconst outTex = ctx.renderer.getTemporaryTexture(width, height, [\n\t\ttmpTex,\n\t\ttargetTexture,\n\t\t...(props.excludeTextures || []),\n\t]);\n\n\t// Fetch dynamic intensity signal texture view\n\tlet signalView: GPUTextureView;\n\tif (hasStaticSignal) {\n\t\tconst elapsedSeconds =\n\t\t\tprops.elapsedMs !== undefined ? props.elapsedMs / 1000 : frame / fps;\n\t\tconst durationSeconds = props.virtualMedia?.metadata?.durationMs\n\t\t\t? props.virtualMedia.metadata.durationMs / 1000\n\t\t\t: props.durationMs !== undefined\n\t\t\t\t? props.durationMs / 1000\n\t\t\t\t: 0;\n\t\tsignalView = signalRegistry.getOrCreate2DTextureView(\n\t\t\tctx.device,\n\t\t\tencoder,\n\t\t\tsd.nodeId ?? \"lut_intensity_sig\",\n\t\t\telapsedSeconds,\n\t\t\tdurationSeconds,\n\t\t\tsd,\n\t\t\twidth,\n\t\t\theight,\n\t\t\tprops.renderId,\n\t\t\tframe,\n\t\t\tfps,\n\t\t);\n\t} else {\n\t\tsignalView = signalRegistry.getDummy1x1TextureView(ctx.device);\n\t}\n\n\t// Prepare uniforms\n\tlutUniformData[0] = intensity;\n\tlutUniformData[1] = lut.size;\n\tlutUniformData[2] = hasStaticSignal ? 1 : 0;\n\tlutUniformData[3] = 0; // padding\n\n\tconst uniformBuffer = ctx.renderer.getTemporaryBuffer(lutUniformData);\n\n\tconst renderPass = encoder.beginRenderPass({\n\t\tcolorAttachments: [\n\t\t\t{\n\t\t\t\tview: outTex.createView(),\n\t\t\t\tloadOp: \"clear\",\n\t\t\t\tstoreOp: \"store\",\n\t\t\t\tclearValue: { r: 0, g: 0, b: 0, a: 0 },\n\t\t\t},\n\t\t],\n\t});\n\n\trenderPass.setPipeline(pipeline!);\n\trenderPass.setBindGroup(\n\t\t0,\n\t\tctx.device.createBindGroup({\n\t\t\tlayout: uLayout!,\n\t\t\tentries: [{ binding: 0, resource: { buffer: uniformBuffer } }],\n\t\t}),\n\t);\n\trenderPass.setBindGroup(\n\t\t1,\n\t\tctx.renderer.bindGroupCache.getBindGroup(\n\t\t\tctx.device,\n\t\t\ttLayout!,\n\t\t\ttmpTex,\n\t\t\tsampler,\n\t\t),\n\t);\n\trenderPass.setBindGroup(\n\t\t2,\n\t\tctx.device.createBindGroup({\n\t\t\tlayout: lLayout!,\n\t\t\tentries: [\n\t\t\t\t{ binding: 0, resource: lut.texture.createView() },\n\t\t\t\t{ binding: 1, resource: sampler },\n\t\t\t],\n\t\t}),\n\t);\n\trenderPass.setBindGroup(\n\t\t3,\n\t\tctx.device.createBindGroup({\n\t\t\tlayout: sigLayout!,\n\t\t\tentries: [\n\t\t\t\t{ binding: 0, resource: signalView },\n\t\t\t\t{ binding: 1, resource: sampler },\n\t\t\t],\n\t\t}),\n\t);\n\trenderPass.draw(4);\n\trenderPass.end();\n\n\t// Blending/opacity draw to the targetView\n\tconst finalPass = ctx.renderer.beginFrame(\n\t\tencoder,\n\t\ttargetView,\n\t\t{ r: 0, g: 0, b: 0, a: 0 },\n\t\ttargetWidth,\n\t\ttargetHeight,\n\t\t\"load\",\n\t);\n\n\tctx.renderer.drawTexture(\n\t\tfinalPass,\n\t\toutTex,\n\t\t{ x: 0, y: 0, width: targetWidth, height: targetHeight },\n\t\t{ opacity: op.opacity ?? 1 },\n\t);\n\targs.pass = finalPass;\n};\n","import { defineRenderer } from \"@framefields/node-sdk/renderer\";\nimport { LutWebGPURenderer } from \"./webgpu-renderer.js\";\n\nexport default defineRenderer({\n\tWebGPURenderer: LutWebGPURenderer,\n});\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@framefields/node-lut",
|
|
3
|
+
"version": "2.0.2",
|
|
4
|
+
"private": false,
|
|
5
|
+
"framefields": {
|
|
6
|
+
"type": "ApplyLUT",
|
|
7
|
+
"kind": "effect"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"license": "Apache-2.0",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.mts",
|
|
14
|
+
"development": "./src/index.ts",
|
|
15
|
+
"import": "./dist/index.mjs",
|
|
16
|
+
"default": "./dist/index.mjs"
|
|
17
|
+
},
|
|
18
|
+
"./renderer": {
|
|
19
|
+
"types": "./dist/renderer.d.mts",
|
|
20
|
+
"development": "./src/renderers/index.ts",
|
|
21
|
+
"import": "./dist/renderer.mjs",
|
|
22
|
+
"default": "./dist/renderer.mjs"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"zod": "^4.3.6",
|
|
27
|
+
"@framefields/core": "2.0.2",
|
|
28
|
+
"@framefields/webgpu-renderers": "2.0.2",
|
|
29
|
+
"@framefields/node-sdk": "2.0.2"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^24.1.0",
|
|
33
|
+
"tsdown": "^0.19.0",
|
|
34
|
+
"typescript": "^5.8.3",
|
|
35
|
+
"webgpu": "^0.4.0",
|
|
36
|
+
"@framefields/tsconfig": "2.0.2"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsdown",
|
|
43
|
+
"dev": "tsdown --watch",
|
|
44
|
+
"clean": "rm -rf dist .turbo"
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/index.ts
ADDED