insomni 0.2.0-alpha.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.
@@ -0,0 +1,470 @@
1
+ import tgpu, { d } from "typegpu";
2
+ //#region src/core/context.ts
3
+ const DEPTH_FORMAT = "depth24plus";
4
+ function safeSize(width, height) {
5
+ return [Math.max(width, 1), Math.max(height, 1)];
6
+ }
7
+ function createBackbuffer(root, width, height, format) {
8
+ const texture = root.device.createTexture({
9
+ label: "insomni-backbuffer",
10
+ size: safeSize(width, height),
11
+ format,
12
+ sampleCount: 1,
13
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_SRC
14
+ });
15
+ return {
16
+ texture,
17
+ view: texture.createView()
18
+ };
19
+ }
20
+ function createDepth(root, width, height, sampleCount) {
21
+ const depthTexture = root.device.createTexture({
22
+ label: "insomni-depth",
23
+ size: safeSize(width, height),
24
+ format: DEPTH_FORMAT,
25
+ sampleCount,
26
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING
27
+ });
28
+ return {
29
+ depthTexture,
30
+ depthView: depthTexture.createView()
31
+ };
32
+ }
33
+ function createMsaaColor(root, width, height, format, sampleCount) {
34
+ if (sampleCount <= 1) return null;
35
+ const texture = root.device.createTexture({
36
+ label: "insomni-color-msaa",
37
+ size: safeSize(width, height),
38
+ format,
39
+ sampleCount,
40
+ usage: GPUTextureUsage.RENDER_ATTACHMENT
41
+ });
42
+ return {
43
+ texture,
44
+ view: texture.createView()
45
+ };
46
+ }
47
+ function createCanvasContext(root, canvas, sampleCount = 1, persistent = false) {
48
+ const format = navigator.gpu.getPreferredCanvasFormat();
49
+ const gpuContext = root.configureContext({
50
+ canvas,
51
+ format,
52
+ alphaMode: "premultiplied",
53
+ ...persistent ? { usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_DST } : {}
54
+ });
55
+ const depth = createDepth(root, canvas.width, canvas.height, sampleCount);
56
+ const msaa = createMsaaColor(root, canvas.width, canvas.height, format, sampleCount);
57
+ const back = persistent ? createBackbuffer(root, canvas.width, canvas.height, format) : null;
58
+ return {
59
+ canvas,
60
+ gpuContext,
61
+ format,
62
+ width: canvas.width,
63
+ height: canvas.height,
64
+ sampleCount,
65
+ colorTexture: msaa?.texture ?? null,
66
+ colorView: msaa?.view ?? null,
67
+ depthTexture: depth.depthTexture,
68
+ depthView: depth.depthView,
69
+ persistent,
70
+ backbuffer: back?.texture ?? null,
71
+ backbufferView: back?.view ?? null
72
+ };
73
+ }
74
+ function resizeCanvas(ctx, root, width, height) {
75
+ const w = Math.max(0, Math.floor(width));
76
+ const h = Math.max(0, Math.floor(height));
77
+ ctx.canvas.width = w;
78
+ ctx.canvas.height = h;
79
+ ctx.width = w;
80
+ ctx.height = h;
81
+ ctx.depthTexture.destroy();
82
+ const depth = createDepth(root, width, height, ctx.sampleCount);
83
+ ctx.depthTexture = depth.depthTexture;
84
+ ctx.depthView = depth.depthView;
85
+ if (ctx.colorTexture) ctx.colorTexture.destroy();
86
+ const msaa = createMsaaColor(root, width, height, ctx.format, ctx.sampleCount);
87
+ ctx.colorTexture = msaa?.texture ?? null;
88
+ ctx.colorView = msaa?.view ?? null;
89
+ if (ctx.persistent) {
90
+ if (ctx.backbuffer) ctx.backbuffer.destroy();
91
+ const back = createBackbuffer(root, width, height, ctx.format);
92
+ ctx.backbuffer = back.texture;
93
+ ctx.backbufferView = back.view;
94
+ }
95
+ }
96
+ //#endregion
97
+ //#region src/math/scalar.ts
98
+ const TAU = Math.PI * 2;
99
+ const PI = Math.PI;
100
+ const HALF_PI = Math.PI / 2;
101
+ const DEG_TO_RAD = Math.PI / 180;
102
+ const RAD_TO_DEG = 180 / Math.PI;
103
+ function clamp(value, min, max) {
104
+ return value < min ? min : value > max ? max : value;
105
+ }
106
+ function clamp01(value) {
107
+ return value < 0 ? 0 : value > 1 ? 1 : value;
108
+ }
109
+ function lerp(a, b, t) {
110
+ return a + (b - a) * t;
111
+ }
112
+ /** Inverse of `lerp`: where does `value` sit between `a` and `b`? */
113
+ function inverseLerp(a, b, value) {
114
+ return a === b ? 0 : (value - a) / (b - a);
115
+ }
116
+ /** Map `value` from `[a0, a1]` to `[b0, b1]` (unclamped). */
117
+ function remap(value, a0, a1, b0, b1) {
118
+ return b0 + (value - a0) * (b1 - b0) / (a1 - a0);
119
+ }
120
+ /** Hermite smoothstep. `t` is clamped to `[edge0, edge1]`. */
121
+ function smoothstep(edge0, edge1, value) {
122
+ const t = clamp01((value - edge0) / (edge1 - edge0));
123
+ return t * t * (3 - 2 * t);
124
+ }
125
+ /** Ken Perlin's 5th-order smoothstep — zero 1st & 2nd derivatives at edges. */
126
+ function smootherstep(edge0, edge1, value) {
127
+ const t = clamp01((value - edge0) / (edge1 - edge0));
128
+ return t * t * t * (t * (t * 6 - 15) + 10);
129
+ }
130
+ function degToRad(deg) {
131
+ return deg * DEG_TO_RAD;
132
+ }
133
+ function radToDeg(rad) {
134
+ return rad * RAD_TO_DEG;
135
+ }
136
+ /** Wraps `value` into `[0, modulus)` (handles negatives, unlike `%`). */
137
+ function wrap(value, modulus) {
138
+ return (value % modulus + modulus) % modulus;
139
+ }
140
+ function sign(value) {
141
+ return value < 0 ? -1 : value > 0 ? 1 : 0;
142
+ }
143
+ function approxEqual(a, b, epsilon = 1e-6) {
144
+ return Math.abs(a - b) <= epsilon;
145
+ }
146
+ //#endregion
147
+ //#region src/shared/pipeline.ts
148
+ const ALPHA_BLEND = {
149
+ color: {
150
+ srcFactor: "one",
151
+ dstFactor: "one-minus-src-alpha",
152
+ operation: "add"
153
+ },
154
+ alpha: {
155
+ srcFactor: "one",
156
+ dstFactor: "one-minus-src-alpha",
157
+ operation: "add"
158
+ }
159
+ };
160
+ const OPAQUE_ALPHA_THRESHOLD = .5;
161
+ /**
162
+ * Depth attachment uses `less` compare. Z is assigned in scene order — lower Z
163
+ * is closer to the camera. Opaque shapes are drawn front-to-back (lowest Z
164
+ * first) with depth write enabled; transparent shapes draw back-to-front with
165
+ * depth write disabled but depth test still rejecting fragments occluded by
166
+ * opaque content.
167
+ */
168
+ const DEPTH_COMPARE = "less";
169
+ const CameraSchema = d.struct({
170
+ vpCol0: d.vec2f,
171
+ vpCol1: d.vec2f,
172
+ vpCol2: d.vec2f,
173
+ viewport: d.vec2f,
174
+ dpr: d.f32,
175
+ _pad: d.f32
176
+ });
177
+ /**
178
+ * Per-draw-call uniform supplying the Z slot range this draw occupies.
179
+ * `baseZ` is the Z value for the shape whose `instance_index === firstInstance`;
180
+ * subsequent instances step by `zStep`. Shader:
181
+ * z = baseZ + zStep * f32(instance_index - firstInstance)
182
+ */
183
+ const DrawSchema = d.struct({
184
+ baseZ: d.f32,
185
+ zStep: d.f32,
186
+ firstInstance: d.u32,
187
+ _pad: d.u32
188
+ });
189
+ /**
190
+ * Per-instance shape record. 32 B, bit-packed. Byte-identical to the CPU-side
191
+ * layout in `pack.ts`:
192
+ * pos @ 0 vec2f
193
+ * sizePacked @ 8 u32 — `pack2x16float(sizeX, sizeY)`
194
+ * fillBits @ 12 u32 — `pack4x8unorm(fill)`
195
+ * strokeBits @ 16 u32
196
+ * rsPacked @ 20 u32 — `pack2x16float(rotation, strokeWidth)`
197
+ * crPacked @ 24 u32 — `pack2x16float(cornerRadius, _)`
198
+ * shapeType @ 28 u32
199
+ *
200
+ * Shaders `unpack4x8unorm` / `unpack2x16float` on access.
201
+ */
202
+ const ShapeSchema = d.struct({
203
+ pos: d.vec2f,
204
+ sizePacked: d.u32,
205
+ fillBits: d.u32,
206
+ strokeBits: d.u32,
207
+ rsPacked: d.u32,
208
+ crPacked: d.u32,
209
+ shapeType: d.u32
210
+ });
211
+ const TriangleSchema = d.struct({
212
+ p1: d.vec2f,
213
+ p2: d.vec2f,
214
+ p3: d.vec2f,
215
+ fill: d.vec4f
216
+ });
217
+ const CameraLayout = tgpu.bindGroupLayout({ camera: {
218
+ uniform: CameraSchema,
219
+ visibility: ["vertex"]
220
+ } });
221
+ const ShapeBufferLayout = tgpu.bindGroupLayout({ shapes: {
222
+ storage: d.arrayOf(ShapeSchema),
223
+ access: "readonly",
224
+ visibility: ["vertex", "fragment"]
225
+ } });
226
+ const TriangleBufferLayout = tgpu.bindGroupLayout({ triangles: {
227
+ storage: d.arrayOf(TriangleSchema),
228
+ access: "readonly",
229
+ visibility: ["vertex"]
230
+ } });
231
+ const DrawLayout = tgpu.bindGroupLayout({ draw: {
232
+ uniform: DrawSchema,
233
+ visibility: ["vertex"]
234
+ } });
235
+ CameraLayout.bound.camera;
236
+ ShapeBufferLayout.bound.shapes;
237
+ TriangleBufferLayout.bound.triangles;
238
+ DrawLayout.bound.draw;
239
+ tgpu.bindGroupLayout({ clearColor: {
240
+ uniform: d.vec4f,
241
+ visibility: ["fragment"]
242
+ } }).bound.clearColor;
243
+ tgpu.fn([d.vec2f, d.f32], d.vec2f)`(v, a) {
244
+ let c = cos(a);
245
+ let s = sin(a);
246
+ return vec2f(c * v.x - s * v.y, s * v.x + c * v.y);
247
+ }`;
248
+ tgpu.fn([
249
+ d.vec2f,
250
+ d.vec2f,
251
+ d.f32
252
+ ], d.f32)`(p, b, r) {
253
+ let q = abs(p) - b + r;
254
+ return length(max(q, vec2f(0.0))) + min(max(q.x, q.y), 0.0) - r;
255
+ }`;
256
+ tgpu.fn([d.vec2f, d.f32], d.f32)`(p, r) {
257
+ return length(p) - r;
258
+ }`;
259
+ tgpu.fn([d.vec2f, d.vec2f], d.f32)`(p, ab) {
260
+ let k1 = length(p / ab);
261
+ let k2 = length(p / (ab * ab));
262
+ return k1 * (k1 - 1.0) / k2;
263
+ }`;
264
+ const SpriteSchema = d.struct({
265
+ pos: d.vec2f,
266
+ size: d.vec2f,
267
+ uvMin: d.vec2f,
268
+ uvMax: d.vec2f,
269
+ tint: d.vec4f,
270
+ anchor: d.vec2f,
271
+ rotation: d.f32,
272
+ _pad: d.f32
273
+ });
274
+ const SpriteBufferLayout = tgpu.bindGroupLayout({ sprites: {
275
+ storage: d.arrayOf(SpriteSchema),
276
+ access: "readonly",
277
+ visibility: ["vertex"]
278
+ } });
279
+ const TextureSamplerLayout = tgpu.bindGroupLayout({
280
+ spriteTexture: {
281
+ texture: "float",
282
+ visibility: ["fragment"]
283
+ },
284
+ spriteSampler: {
285
+ sampler: "filtering",
286
+ visibility: ["fragment"]
287
+ }
288
+ });
289
+ SpriteBufferLayout.bound.sprites;
290
+ TextureSamplerLayout.bound.spriteTexture;
291
+ TextureSamplerLayout.bound.spriteSampler;
292
+ /**
293
+ * Per-instance segment record. 24 B:
294
+ * start: vec2f @ 0
295
+ * end: vec2f @ 8
296
+ * color: u32 @ 16 (unorm8x4)
297
+ * width: f32 @ 20 (layer-local units)
298
+ * Byte-identical to the CPU layout in `pack.ts` (`SEGMENT_FLOATS = 6`).
299
+ */
300
+ const SegmentSchema = d.struct({
301
+ start: d.vec2f,
302
+ end: d.vec2f,
303
+ colorBits: d.u32,
304
+ width: d.f32
305
+ });
306
+ tgpu.bindGroupLayout({ segments: {
307
+ storage: d.arrayOf(SegmentSchema),
308
+ access: "readonly",
309
+ visibility: ["vertex", "fragment"]
310
+ } }).bound.segments;
311
+ /**
312
+ * Per-instance curve record. 48 B, 16-B-aligned for storage buffer arrays:
313
+ * p0: vec2f @ 0
314
+ * p1: vec2f @ 8
315
+ * p2: vec2f @ 16
316
+ * p3: vec2f @ 24
317
+ * colorBits: u32 @ 32 (unorm8x4)
318
+ * widthPacked: u32 @ 36 (pack2x16float(widthStart, widthEnd))
319
+ * flagsBits: u32 @ 40 (cap style in low 2 bits)
320
+ * _pad: u32 @ 44
321
+ * Byte-identical to the CPU layout in `pack.ts` (`CURVE_FLOATS = 12`).
322
+ */
323
+ const CurveSchema = d.struct({
324
+ p0: d.vec2f,
325
+ p1: d.vec2f,
326
+ p2: d.vec2f,
327
+ p3: d.vec2f,
328
+ colorBits: d.u32,
329
+ widthPacked: d.u32,
330
+ flagsBits: d.u32,
331
+ _pad: d.u32
332
+ });
333
+ tgpu.bindGroupLayout({ curves: {
334
+ storage: d.arrayOf(CurveSchema),
335
+ access: "readonly",
336
+ visibility: ["vertex", "fragment"]
337
+ } }).bound.curves;
338
+ tgpu.fn([
339
+ d.f32,
340
+ d.f32,
341
+ d.f32,
342
+ d.f32
343
+ ], d.vec2f)`(c0, c1, c2, c3) {
344
+ var mn = min(c0, c3);
345
+ var mx = max(c0, c3);
346
+ let alpha = -c0 + 3.0 * c1 - 3.0 * c2 + c3;
347
+ let beta = c0 - 2.0 * c1 + c2;
348
+ let gamma = -c0 + c1;
349
+ if (abs(alpha) < 1e-6) {
350
+ if (abs(beta) > 1e-6) {
351
+ let t = -gamma / (2.0 * beta);
352
+ if (t > 0.0 && t < 1.0) {
353
+ let u = 1.0 - t;
354
+ let v = u * u * u * c0 + 3.0 * u * u * t * c1 + 3.0 * u * t * t * c2 + t * t * t * c3;
355
+ mn = min(mn, v);
356
+ mx = max(mx, v);
357
+ }
358
+ }
359
+ } else {
360
+ let disc = beta * beta - alpha * gamma;
361
+ if (disc >= 0.0) {
362
+ let s = sqrt(disc);
363
+ let t1 = (-beta + s) / alpha;
364
+ if (t1 > 0.0 && t1 < 1.0) {
365
+ let u = 1.0 - t1;
366
+ let v = u * u * u * c0 + 3.0 * u * u * t1 * c1 + 3.0 * u * t1 * t1 * c2 + t1 * t1 * t1 * c3;
367
+ mn = min(mn, v);
368
+ mx = max(mx, v);
369
+ }
370
+ let t2 = (-beta - s) / alpha;
371
+ if (t2 > 0.0 && t2 < 1.0) {
372
+ let u = 1.0 - t2;
373
+ let v = u * u * u * c0 + 3.0 * u * u * t2 * c1 + 3.0 * u * t2 * t2 * c2 + t2 * t2 * t2 * c3;
374
+ mn = min(mn, v);
375
+ mx = max(mx, v);
376
+ }
377
+ }
378
+ }
379
+ return vec2f(mn, mx);
380
+ }`;
381
+ /**
382
+ * Per-instance arc record. 32 B (16-B aligned for storage struct arrays):
383
+ * center: vec2f @ 0
384
+ * radius: f32 @ 8
385
+ * theta0: f32 @ 12 start angle (radians)
386
+ * theta1: f32 @ 16 end angle (radians)
387
+ * width: f32 @ 20 stroke thickness (layer-local units)
388
+ * colorBits: u32 @ 24 unorm8x4 RGBA, unpremultiplied
389
+ * _pad: u32 @ 28
390
+ *
391
+ * Arc is the short path from `theta0` to `theta1`; direction is irrelevant
392
+ * to the rendered geometry. CPU normalises so the absolute span is ≤ 2π;
393
+ * spans ≥ 2π render as a full ring. Caps are butt (perpendicular at each
394
+ * endpoint).
395
+ */
396
+ const ArcSchema = d.struct({
397
+ center: d.vec2f,
398
+ radius: d.f32,
399
+ theta0: d.f32,
400
+ theta1: d.f32,
401
+ width: d.f32,
402
+ colorBits: d.u32,
403
+ _pad: d.u32
404
+ });
405
+ tgpu.bindGroupLayout({ arcs: {
406
+ storage: d.arrayOf(ArcSchema),
407
+ access: "readonly",
408
+ visibility: ["vertex", "fragment"]
409
+ } }).bound.arcs;
410
+ tgpu.fn([
411
+ d.f32,
412
+ d.f32,
413
+ d.f32,
414
+ d.f32
415
+ ], d.vec4f)`(r, halfAng, halfW, pad) {
416
+ let outer = r + halfW + pad;
417
+ let innerRaw = r - halfW - pad;
418
+ let inner = select(0.0, innerRaw, innerRaw > 0.0);
419
+ let ch = cos(halfAng);
420
+ let sh = sin(halfAng);
421
+ // +X axis (angle 0) is always inside the wedge → x_max = outer.
422
+ let xMax = outer;
423
+ var xMin: f32;
424
+ var yMax: f32;
425
+ var yMin: f32;
426
+ let PI = 3.141592653589793;
427
+ let HALF_PI = 1.5707963267948966;
428
+ if (halfAng >= PI) {
429
+ xMin = -outer;
430
+ yMax = outer;
431
+ yMin = -outer;
432
+ } else if (halfAng >= HALF_PI) {
433
+ // Wedge crosses ±π/2 → y reaches ±outer; x_min at the wedge boundary.
434
+ yMax = outer;
435
+ yMin = -outer;
436
+ xMin = outer * ch;
437
+ } else {
438
+ // Narrow wedge: y extrema come from the outer-ring endpoints; x_min
439
+ // comes from the inner-ring endpoints.
440
+ yMax = outer * sh;
441
+ yMin = -yMax;
442
+ xMin = inner * ch;
443
+ }
444
+ return vec4f(xMin, yMin, xMax, yMax);
445
+ }`;
446
+ tgpu.fn([
447
+ d.vec2f,
448
+ d.f32,
449
+ d.f32,
450
+ d.f32
451
+ ], d.f32)`(p, r, mid, halfAng) {
452
+ let c = cos(mid);
453
+ let s = sin(mid);
454
+ // Rotate by -mid so the arc spans [-halfAng, halfAng] around +X.
455
+ let q = vec2f(c * p.x + s * p.y, -s * p.x + c * p.y);
456
+ // Reflect to upper half — the arc is symmetric in y.
457
+ let qa = vec2f(q.x, abs(q.y));
458
+ let ch = cos(halfAng);
459
+ let sh = sin(halfAng);
460
+ // qa is outside the wedge (angle > halfAng) iff cross > 0.
461
+ let cross = ch * qa.y - sh * qa.x;
462
+ if (cross <= 0.0) {
463
+ return abs(length(qa) - r);
464
+ }
465
+ // Outside the wedge: nearest point on the arc is the upper endpoint.
466
+ let endpoint = vec2f(r * ch, r * sh);
467
+ return length(qa - endpoint);
468
+ }`;
469
+ //#endregion
470
+ export { DEPTH_FORMAT as A, lerp as C, smootherstep as D, sign as E, resizeCanvas as M, smoothstep as O, inverseLerp as S, remap as T, TAU as _, OPAQUE_ALPHA_THRESHOLD as a, clamp01 as b, SpriteBufferLayout as c, TriangleBufferLayout as d, TriangleSchema as f, RAD_TO_DEG as g, PI as h, DEPTH_COMPARE as i, createCanvasContext as j, wrap as k, SpriteSchema as l, HALF_PI as m, CameraLayout as n, ShapeBufferLayout as o, DEG_TO_RAD as p, CameraSchema as r, ShapeSchema as s, ALPHA_BLEND as t, TextureSamplerLayout as u, approxEqual as v, radToDeg as w, degToRad as x, clamp as y };
@@ -0,0 +1,115 @@
1
+ import * as _$typegpu from "typegpu";
2
+ import { TgpuRoot, d } from "typegpu";
3
+
4
+ //#region src/shared/pipeline.d.ts
5
+ declare const CameraSchema: d.WgslStruct<{
6
+ vpCol0: d.Vec2f;
7
+ vpCol1: d.Vec2f;
8
+ vpCol2: d.Vec2f;
9
+ viewport: d.Vec2f;
10
+ dpr: d.F32;
11
+ _pad: d.F32;
12
+ }>;
13
+ /**
14
+ * Per-instance shape record. 32 B, bit-packed. Byte-identical to the CPU-side
15
+ * layout in `pack.ts`:
16
+ * pos @ 0 vec2f
17
+ * sizePacked @ 8 u32 — `pack2x16float(sizeX, sizeY)`
18
+ * fillBits @ 12 u32 — `pack4x8unorm(fill)`
19
+ * strokeBits @ 16 u32
20
+ * rsPacked @ 20 u32 — `pack2x16float(rotation, strokeWidth)`
21
+ * crPacked @ 24 u32 — `pack2x16float(cornerRadius, _)`
22
+ * shapeType @ 28 u32
23
+ *
24
+ * Shaders `unpack4x8unorm` / `unpack2x16float` on access.
25
+ */
26
+ declare const ShapeSchema: d.WgslStruct<{
27
+ pos: d.Vec2f;
28
+ sizePacked: d.U32;
29
+ fillBits: d.U32;
30
+ strokeBits: d.U32;
31
+ rsPacked: d.U32;
32
+ crPacked: d.U32;
33
+ shapeType: d.U32;
34
+ }>;
35
+ declare const TriangleSchema: d.WgslStruct<{
36
+ p1: d.Vec2f;
37
+ p2: d.Vec2f;
38
+ p3: d.Vec2f;
39
+ fill: d.Vec4f;
40
+ }>;
41
+ declare const CameraLayout: _$typegpu.TgpuBindGroupLayout<{
42
+ camera: {
43
+ uniform: d.WgslStruct<{
44
+ vpCol0: d.Vec2f;
45
+ vpCol1: d.Vec2f;
46
+ vpCol2: d.Vec2f;
47
+ viewport: d.Vec2f;
48
+ dpr: d.F32;
49
+ _pad: d.F32;
50
+ }>;
51
+ visibility: "vertex"[];
52
+ };
53
+ }>;
54
+ declare const ShapeBufferLayout: _$typegpu.TgpuBindGroupLayout<{
55
+ shapes: {
56
+ storage: (elementCount: number) => d.WgslArray<d.WgslStruct<{
57
+ pos: d.Vec2f;
58
+ sizePacked: d.U32;
59
+ fillBits: d.U32;
60
+ strokeBits: d.U32;
61
+ rsPacked: d.U32;
62
+ crPacked: d.U32;
63
+ shapeType: d.U32;
64
+ }>>;
65
+ access: "readonly";
66
+ visibility: ("fragment" | "vertex")[];
67
+ };
68
+ }>;
69
+ declare const TriangleBufferLayout: _$typegpu.TgpuBindGroupLayout<{
70
+ triangles: {
71
+ storage: (elementCount: number) => d.WgslArray<d.WgslStruct<{
72
+ p1: d.Vec2f;
73
+ p2: d.Vec2f;
74
+ p3: d.Vec2f;
75
+ fill: d.Vec4f;
76
+ }>>;
77
+ access: "readonly";
78
+ visibility: "vertex"[];
79
+ };
80
+ }>;
81
+ declare const SpriteSchema: d.WgslStruct<{
82
+ pos: d.Vec2f;
83
+ size: d.Vec2f;
84
+ uvMin: d.Vec2f;
85
+ uvMax: d.Vec2f;
86
+ tint: d.Vec4f;
87
+ anchor: d.Vec2f;
88
+ rotation: d.F32;
89
+ _pad: d.F32;
90
+ }>;
91
+ declare const SpriteBufferLayout: _$typegpu.TgpuBindGroupLayout<{
92
+ sprites: {
93
+ storage: (elementCount: number) => d.WgslArray<d.WgslStruct<{
94
+ pos: d.Vec2f;
95
+ size: d.Vec2f;
96
+ uvMin: d.Vec2f;
97
+ uvMax: d.Vec2f;
98
+ tint: d.Vec4f;
99
+ anchor: d.Vec2f;
100
+ rotation: d.F32;
101
+ _pad: d.F32;
102
+ }>>;
103
+ access: "readonly";
104
+ visibility: "vertex"[];
105
+ };
106
+ }>;
107
+ declare const TextureSamplerLayout: _$typegpu.TgpuBindGroupLayout<{
108
+ spriteTexture: _$typegpu.TgpuLayoutTexture<d.WgslTexture2d<d.F32>>;
109
+ spriteSampler: {
110
+ sampler: "filtering";
111
+ visibility: "fragment"[];
112
+ };
113
+ }>;
114
+ //#endregion
115
+ export { SpriteBufferLayout as a, TriangleBufferLayout as c, ShapeSchema as i, TriangleSchema as l, CameraSchema as n, SpriteSchema as o, ShapeBufferLayout as r, TextureSamplerLayout as s, CameraLayout as t };