@doki-land/live2d-renderer 0.0.0 → 0.0.11

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/README.md CHANGED
@@ -1,3 +1,3 @@
1
1
  # @doki-land/live2d-renderer
2
2
 
3
- Placeholder package (0.0.0). Reserved for doki-land/live2d.ts.
3
+ live2d.ts package 0.0.11.
@@ -0,0 +1,540 @@
1
+ import { ParameterProgram, ModelProgram, ModelInstance, FrameSnapshot, ModelFormat, ModelSettings, AssetResolver, InternalModel } from '@doki-land/live2d-core';
2
+ export { detectModelSettingsFormat } from '@doki-land/live2d-core';
3
+
4
+ /** Implemented renderer kinds. */
5
+ type RendererKind = "webgpu" | "webgl2" | "canvas2d";
6
+ /** Blend modes for Live2D drawable compositing. */
7
+ declare const BlendMode: {
8
+ readonly Normal: 0;
9
+ readonly Additive: 1;
10
+ readonly Multiplicative: 2;
11
+ };
12
+ type BlendMode = (typeof BlendMode)[keyof typeof BlendMode];
13
+ /** A single drawable mesh submitted to the GPU backend. */
14
+ interface DrawableMesh {
15
+ index: number;
16
+ textureIndex: number;
17
+ vertexPositions: Float32Array;
18
+ uvs: Float32Array;
19
+ indices: Uint16Array;
20
+ opacity: number;
21
+ blendMode: BlendMode;
22
+ invertedMask: boolean;
23
+ renderOrder: number;
24
+ dynamicFlag: boolean;
25
+ maskIndices: number[];
26
+ visible: boolean;
27
+ }
28
+ interface TextureData {
29
+ index: number;
30
+ image: HTMLImageElement | ImageBitmap;
31
+ width: number;
32
+ height: number;
33
+ }
34
+ interface ModelDrawPass {
35
+ setTextures(textures: TextureData[]): void;
36
+ draw(drawables: DrawableMesh[], modelMatrix: Float32Array): void;
37
+ destroy(): void;
38
+ }
39
+ /** Top-level renderer bound to a canvas. */
40
+ interface Renderer {
41
+ readonly kind: RendererKind;
42
+ initialize(canvas: HTMLCanvasElement): Promise<void>;
43
+ createModelDrawPass(): ModelDrawPass;
44
+ beginFrame(): void;
45
+ endFrame(): void;
46
+ resize(width: number, height: number): void;
47
+ destroy(): void;
48
+ }
49
+ interface WebGpuRenderer extends Renderer {
50
+ readonly kind: "webgpu";
51
+ getDevice(): GPUDevice | null;
52
+ }
53
+ interface WebGl2Renderer extends Renderer {
54
+ readonly kind: "webgl2";
55
+ getGL(): WebGL2RenderingContext | null;
56
+ }
57
+
58
+ interface Canvas2DRendererOptions {
59
+ /** Fill color for deformed triangles (CSS). */
60
+ fill?: string;
61
+ stroke?: string;
62
+ }
63
+ /** Canvas2D soft renderer — CPU FrameSnapshot preview without WebGPU/WebGL. */
64
+ declare class Canvas2DRendererImpl implements Renderer {
65
+ #private;
66
+ readonly kind: "canvas2d";
67
+ constructor(options?: Canvas2DRendererOptions);
68
+ initialize(canvas: HTMLCanvasElement): Promise<void>;
69
+ createModelDrawPass(): ModelDrawPass;
70
+ beginFrame(): void;
71
+ endFrame(): void;
72
+ resize(width: number, height: number): void;
73
+ destroy(): void;
74
+ }
75
+ declare function createCanvas2DRenderer(options?: Canvas2DRendererOptions): Renderer;
76
+ declare function isCanvas2DAvailable(): boolean;
77
+
78
+ /**
79
+ * WebGL2 renderer with soft clipping-mask support.
80
+ *
81
+ * Mask path: render mask meshes into an offscreen FBO (NDC→UV 1:1), then
82
+ * multiply drawable alpha by the mask (or 1−mask when inverted).
83
+ */
84
+
85
+ interface WebGl2RendererOptions {
86
+ antialias?: boolean;
87
+ alpha?: boolean;
88
+ /**
89
+ * Keep color buffer after present so `canvas.toDataURL` / `toBlob` work.
90
+ * Default true (preview / gallery capture). Set false for max FPS if unused.
91
+ */
92
+ preserveDrawingBuffer?: boolean;
93
+ }
94
+ /** WebGL2 renderer. */
95
+ declare class WebGl2RendererImpl implements WebGl2Renderer {
96
+ #private;
97
+ readonly kind: "webgl2";
98
+ constructor(options?: WebGl2RendererOptions);
99
+ initialize(canvas: HTMLCanvasElement): Promise<void>;
100
+ createModelDrawPass(): ModelDrawPass;
101
+ beginFrame(): void;
102
+ endFrame(): void;
103
+ resize(width: number, height: number): void;
104
+ getGL(): WebGL2RenderingContext | null;
105
+ destroy(): void;
106
+ }
107
+ declare function createWebGl2Renderer(options?: WebGl2RendererOptions): WebGl2Renderer;
108
+ declare function isWebGl2Available(): boolean;
109
+
110
+ /**
111
+ * WebGPU renderer with soft clipping-mask support (parity with WebGL2).
112
+ *
113
+ * Frame flow: beginFrame creates an encoder; drawMeshes writes all mask
114
+ * contexts into one atlas texture, then one color pass samples per-drawable
115
+ * atlas layout; endFrame submits.
116
+ */
117
+
118
+ interface WebGpuRendererOptions {
119
+ /** Prefer high-performance adapter when available. */
120
+ powerPreference?: GPUPowerPreference;
121
+ }
122
+ /** WebGPU renderer. */
123
+ declare class WebGpuRendererImpl implements WebGpuRenderer {
124
+ #private;
125
+ readonly kind: "webgpu";
126
+ constructor(options?: WebGpuRendererOptions);
127
+ initialize(canvas: HTMLCanvasElement): Promise<void>;
128
+ setTextures(textures: TextureData[]): void;
129
+ createModelDrawPass(): ModelDrawPass;
130
+ beginFrame(): void;
131
+ drawMeshes(drawables: DrawableMesh[]): void;
132
+ endFrame(): void;
133
+ resize(width: number, height: number): void;
134
+ getDevice(): GPUDevice | null;
135
+ destroy(): void;
136
+ }
137
+ declare function createWebGpuRenderer(options?: WebGpuRendererOptions): WebGpuRenderer;
138
+ declare function isWebGpuAvailable(): boolean;
139
+
140
+ /**
141
+ * Map Live2D blend modes to WebGL / Canvas compositing.
142
+ */
143
+
144
+ /** Apply premultiplied-friendly Live2D blend factors on a WebGL2 context. */
145
+ declare function applyWebGl2BlendMode(gl: WebGL2RenderingContext, mode: BlendMode): void;
146
+ /** Canvas2D globalCompositeOperation for Live2D blend modes. */
147
+ declare function canvasCompositeForBlendMode(mode: BlendMode): GlobalCompositeOperation;
148
+ /** WebGPU blend state for Live2D modes (straight alpha draw path). */
149
+ declare function webGpuBlendState(mode: BlendMode): GPUBlendState;
150
+
151
+ /**
152
+ * Clipping-mask context grouping + mask atlas layout.
153
+ *
154
+ * Two packing modes:
155
+ * - `uv-grid`: √N UV cells, alpha channel only (Canvas2D / simple path)
156
+ * - `rgba`: Cubism-style channel × UV packing (≤4 → full UV on R/G/B/A)
157
+ */
158
+ interface ClippingDrawableRef {
159
+ readonly index: number;
160
+ readonly maskIndices: readonly number[];
161
+ readonly invertedMask: boolean;
162
+ }
163
+ interface ClippingContext {
164
+ /** Stable key: invert flag + sorted mask drawable indices. */
165
+ readonly key: string;
166
+ readonly maskIndices: readonly number[];
167
+ readonly clippedIndices: readonly number[];
168
+ readonly invertedMask: boolean;
169
+ }
170
+ /** UV-space rectangle inside the shared mask atlas (0..1). */
171
+ interface MaskLayoutRect {
172
+ readonly x: number;
173
+ readonly y: number;
174
+ readonly width: number;
175
+ readonly height: number;
176
+ }
177
+ /** R/G/B/A write/sample selector (Cubism channelFlag). */
178
+ type MaskChannelFlag = readonly [number, number, number, number];
179
+ declare const MASK_CHANNEL_FLAGS: readonly MaskChannelFlag[];
180
+ type MaskAtlasMode = "uv-grid" | "rgba";
181
+ interface MaskAtlasOptions {
182
+ /** Packing strategy. Default `rgba` (Cubism density). */
183
+ readonly mode?: MaskAtlasMode;
184
+ /** Cell inset for `uv-grid` only (reduces neighbour bleed). */
185
+ readonly inset?: number;
186
+ /** Render-texture count for `rgba` (default 1 → max 36). */
187
+ readonly renderTextureCount?: number;
188
+ }
189
+ interface LaidOutClippingContext extends ClippingContext {
190
+ readonly layout: MaskLayoutRect;
191
+ /** 0=R … 3=A. `uv-grid` always uses A (3). */
192
+ readonly channelIndex: number;
193
+ readonly channelFlag: MaskChannelFlag;
194
+ /** Cubism multi-RT buffer index; currently always 0. */
195
+ readonly bufferIndex: number;
196
+ /**
197
+ * Expanded AABB of clipped drawables in vertex/NDC space.
198
+ * Mask write/sample map this rect into `layout` (Cubism bounds-fit).
199
+ * Default before `fitClippingContexts`: full NDC (-1..1)².
200
+ */
201
+ readonly modelBounds: MaskLayoutRect;
202
+ }
203
+ /** Full clip-space quad used when no valid clipped bounds exist. */
204
+ declare const FULL_NDC_BOUNDS: MaskLayoutRect;
205
+ interface ClippingPartition {
206
+ readonly contexts: readonly LaidOutClippingContext[];
207
+ /** Drawables that consume a mask (drawn after mask pass). */
208
+ readonly clipped: ReadonlySet<number>;
209
+ /** Drawables used as masks (mask buffer only, not color target). */
210
+ readonly maskOnly: ReadonlySet<number>;
211
+ }
212
+ /**
213
+ * Group drawables that consume clipping masks into shared contexts.
214
+ * Drawables with empty maskIndices are omitted.
215
+ */
216
+ declare function buildClippingContexts(drawables: readonly ClippingDrawableRef[]): ClippingContext[];
217
+ /**
218
+ * Pack clipping contexts into a square-ish UV grid on one atlas (alpha only).
219
+ */
220
+ declare function layoutMaskAtlasUvGrid(contexts: readonly ClippingContext[], options?: {
221
+ inset?: number;
222
+ }): LaidOutClippingContext[];
223
+ /**
224
+ * Cubism `setupLayoutBounds`: pack across R/G/B/A then UV cells.
225
+ * Single RT → max 36 (4×9); multi-RT → 32 per sheet.
226
+ */
227
+ declare function layoutMaskAtlasRgba(contexts: readonly ClippingContext[], options?: {
228
+ renderTextureCount?: number;
229
+ }): LaidOutClippingContext[];
230
+ /** Pack clipping contexts (default: Cubism RGBA density). */
231
+ declare function layoutMaskAtlas(contexts: readonly ClippingContext[], options?: MaskAtlasOptions): LaidOutClippingContext[];
232
+ /** Partition drawables and assign atlas layouts. */
233
+ declare function partitionForClipping(drawables: readonly ClippingDrawableRef[], options?: MaskAtlasOptions): ClippingPartition;
234
+ /** Axis-aligned bounds of interleaved xy vertex positions. */
235
+ declare function calcVertexBounds(positions: Float32Array): MaskLayoutRect | null;
236
+ /** Expand bounds by a relative margin on each axis (Cubism uses 0.05). */
237
+ declare function expandBounds(bounds: MaskLayoutRect, margin?: number): MaskLayoutRect;
238
+ interface MaskBoundsMeshRef {
239
+ readonly index: number;
240
+ readonly vertexPositions: Float32Array;
241
+ }
242
+ /**
243
+ * Union AABB of clipped drawables, expanded by margin (Cubism
244
+ * `calcClippedDrawableTotalBounds` + 0.05 expand).
245
+ */
246
+ declare function calcClippedDrawableBounds(clippedIndices: readonly number[], byIndex: ReadonlyMap<number, MaskBoundsMeshRef>, margin?: number): MaskLayoutRect;
247
+ /**
248
+ * Attach per-context `modelBounds` so mask write/sample fit the clipped
249
+ * drawable AABB into the atlas cell (higher mask texel density).
250
+ */
251
+ declare function fitClippingContexts(contexts: readonly LaidOutClippingContext[], byIndex: ReadonlyMap<number, MaskBoundsMeshRef>, margin?: number): LaidOutClippingContext[];
252
+ /** Flatten layout to `[x, y, w, h]` for GPU uniforms. */
253
+ declare function maskLayoutVec4(layout: MaskLayoutRect): Float32Array;
254
+ /** Flatten channel flag to `[r, g, b, a]` for GPU uniforms. */
255
+ declare function maskChannelVec4(flag: MaskChannelFlag): Float32Array;
256
+
257
+ declare const CPU_PROGRAM_KIND: "cpu-program";
258
+ interface CpuProgramFile {
259
+ readonly kind: typeof CPU_PROGRAM_KIND;
260
+ readonly version: 1;
261
+ readonly program: {
262
+ readonly format: "moc2" | "moc3";
263
+ readonly parameters: readonly ParameterProgram[];
264
+ readonly drawables: readonly {
265
+ readonly index: number;
266
+ readonly textureIndex: number;
267
+ readonly positions: number[];
268
+ readonly uvs: number[];
269
+ readonly indices: number[];
270
+ readonly opacity: number;
271
+ readonly renderOrder: number;
272
+ readonly blendMode?: number;
273
+ readonly invertedMask?: boolean;
274
+ readonly maskIndices?: number[];
275
+ readonly visible?: boolean;
276
+ readonly deformParamIndex: number;
277
+ readonly deformDeltas: number[] | null;
278
+ }[];
279
+ };
280
+ }
281
+ /** Build a minimal one-quad CPU program for fixtures / homepage. */
282
+ declare function createQuadProgram(options?: {
283
+ parameterId?: string;
284
+ /** Delta applied to top-right vertex at param max (x,y). */
285
+ topRightDelta?: readonly [number, number];
286
+ }): ModelProgram;
287
+ /** Serialize a CPU ModelProgram to UTF-8 JSON bytes. */
288
+ declare function serializeCpuProgram(program: ModelProgram): ArrayBuffer;
289
+ declare function isCpuProgramBytes(bytes: ArrayBuffer): boolean;
290
+ /** Parse CPU program JSON bytes into a ModelProgram. */
291
+ declare function parseCpuProgram(bytes: ArrayBuffer): ModelProgram;
292
+
293
+ /** Create a runtime instance with default parameter values. */
294
+ declare function createModelInstance(program: ModelProgram): ModelInstance;
295
+ declare function setParameterValue(instance: ModelInstance, parameterId: string, value: number): void;
296
+ /** CPU deform 鈫?FrameSnapshot. */
297
+ declare function evaluateFrame(instance: ModelInstance): FrameSnapshot;
298
+ /** Stable fingerprint for golden tests (positions + topology). */
299
+ declare function fingerprintSnapshot(snapshot: FrameSnapshot): string;
300
+
301
+ interface CreateRendererOptions {
302
+ /**
303
+ * Backend try order at initialize time.
304
+ * Default: `["webgpu", "webgl2", "canvas2d"]`.
305
+ */
306
+ prefer?: RendererKind[];
307
+ webgpu?: WebGpuRendererOptions;
308
+ webgl2?: WebGl2RendererOptions;
309
+ canvas2d?: Canvas2DRendererOptions;
310
+ }
311
+ /**
312
+ * Create a renderer provider. Actual backend is chosen on `initialize`
313
+ * (WebGPU → WebGL2 → Canvas2D by default).
314
+ */
315
+ declare function createRenderer(options?: CreateRendererOptions): Renderer;
316
+
317
+ /**
318
+ * moc binary format peek. Settings JSON detection lives in live2d-core
319
+ * (`detectModelSettingsFormat`) so loader and renderer share one helper.
320
+ */
321
+
322
+ /** Peek moc2 vs moc3 from magic bytes. */
323
+ declare function detectMocBinaryFormat(bytes: ArrayBuffer): ModelFormat | null;
324
+
325
+ /**
326
+ * moc binary decode: ArrayBuffer → CPU ModelProgram.
327
+ */
328
+
329
+ interface DecodedMoc2 {
330
+ readonly format: "moc2";
331
+ readonly program: ModelProgram;
332
+ }
333
+ interface DecodedMoc3 {
334
+ readonly format: "moc3";
335
+ readonly program: ModelProgram;
336
+ }
337
+ /** Decode official moc2 (`.moc`) bytes into a default-pose ModelProgram. */
338
+ declare function decodeMoc2(bytes: ArrayBuffer): Promise<DecodedMoc2>;
339
+ /**
340
+ * Decode official moc3 bytes into a ModelProgram.
341
+ * Applies keyform blending + warp/rotation deformer chains at the given pose
342
+ * (defaults when called via decodeMoc3).
343
+ */
344
+ declare function decodeMoc3(bytes: ArrayBuffer): Promise<DecodedMoc3>;
345
+
346
+ /**
347
+ * Shared moc2/moc3 drawable constant-flag decode → blend / invert-mask.
348
+ */
349
+ /** Cubism Core constant drawable flag bits (moc3 art_mesh.drawable_flags). */
350
+ declare const Moc3DrawableFlag: {
351
+ readonly BlendAdditive: number;
352
+ readonly BlendMultiplicative: number;
353
+ readonly IsDoubleSided: number;
354
+ readonly IsInvertedMask: number;
355
+ };
356
+ /** Decode moc3 constant flags into blend + invert-mask. */
357
+ declare function decodeMoc3DrawableFlags(flags: number): {
358
+ blendMode: number;
359
+ invertedMask: boolean;
360
+ doubleSided: boolean;
361
+ };
362
+ /**
363
+ * Decode moc2 color-composition enum (after optionFlags bit0).
364
+ * 0 normal, 1 additive, 2 multiplicative.
365
+ */
366
+ declare function decodeMoc2ColorComposition(composition: number): number;
367
+
368
+ /**
369
+ * Model-format runtime contract (moc2 / moc3 / cpu-program).
370
+ * Not a graphics backend — those live under `backends/`.
371
+ */
372
+ interface ModelBackendOptions {
373
+ /** Bound graphics renderer, if the runtime needs GPU handles. */
374
+ renderer?: Renderer | null;
375
+ /** Asset resolver for moc / textures. */
376
+ resolver?: AssetResolver;
377
+ /** Preloaded moc bytes (tests). */
378
+ mocBytes?: ArrayBuffer;
379
+ }
380
+ /** Live parameter binding for inspectors / playground. */
381
+ interface ParameterBinding {
382
+ readonly id: string;
383
+ readonly min: number;
384
+ readonly max: number;
385
+ readonly defaultValue: number;
386
+ readonly value: number;
387
+ }
388
+ /** moc2 / moc3 model runtime. */
389
+ interface ModelBackend {
390
+ readonly format: ModelFormat;
391
+ canHandle(json: unknown): boolean;
392
+ createModel(settings: ModelSettings, options?: ModelBackendOptions): Promise<InternalModel>;
393
+ updateModel(model: InternalModel, deltaTimeSeconds: number): void;
394
+ getDrawables(model: InternalModel): DrawableMesh[];
395
+ hitTest(model: InternalModel, x: number, y: number): string | null;
396
+ destroyModel(model: InternalModel): void;
397
+ /** Optional CPU snapshot (moc3 CPU path). */
398
+ captureFrame?(model: InternalModel): FrameSnapshot | null;
399
+ setParameter?(model: InternalModel, id: string, value: number): void;
400
+ /** Optional PartOpacity override (moc3 parts / pose / motion). */
401
+ setPartOpacity?(model: InternalModel, id: string, value: number): void;
402
+ listParameters?(model: InternalModel): readonly ParameterBinding[];
403
+ }
404
+ declare function selectModelBackend(backends: ModelBackend[], json: unknown): ModelBackend;
405
+
406
+ /** moc2 (`.moc`) model backend — pure-TS decode → CPU evaluate. */
407
+ declare class Moc2Backend implements ModelBackend {
408
+ readonly format: "moc2";
409
+ canHandle(json: unknown): boolean;
410
+ createModel(settings: ModelSettings, options?: ModelBackendOptions): Promise<InternalModel>;
411
+ updateModel(model: InternalModel, deltaTimeSeconds: number): void;
412
+ getDrawables(model: InternalModel): DrawableMesh[];
413
+ captureFrame(model: InternalModel): FrameSnapshot | null;
414
+ setParameter(model: InternalModel, id: string, value: number): void;
415
+ listParameters(model: InternalModel): readonly ParameterBinding[];
416
+ hitTest(_model: InternalModel, _x: number, _y: number): string | null;
417
+ destroyModel(model: InternalModel): void;
418
+ }
419
+ declare function createMoc2Backend(): Moc2Backend;
420
+
421
+ /** moc3 model backend — official `.moc3` or CPU `.program.json` fixture. */
422
+ declare class Moc3Backend implements ModelBackend {
423
+ readonly format: "moc3";
424
+ canHandle(json: unknown): boolean;
425
+ createModel(settings: ModelSettings, options?: ModelBackendOptions): Promise<InternalModel>;
426
+ updateModel(model: InternalModel, deltaTimeSeconds: number): void;
427
+ getDrawables(model: InternalModel): DrawableMesh[];
428
+ captureFrame(model: InternalModel): FrameSnapshot | null;
429
+ setParameter(model: InternalModel, id: string, value: number): void;
430
+ setPartOpacity(model: InternalModel, id: string, value: number): void;
431
+ listParameters(model: InternalModel): readonly ParameterBinding[];
432
+ hitTest(_model: InternalModel, _x: number, _y: number): string | null;
433
+ destroyModel(model: InternalModel): void;
434
+ }
435
+ declare function createMoc3Backend(): Moc3Backend;
436
+
437
+ /**
438
+ * moc3 keyform binding bands → multilinear blend weights.
439
+ *
440
+ * A drawable/deformer references a binding band; the band lists parameter
441
+ * bindings; each binding has an ordered key table. Keyforms are laid out as
442
+ * the cartesian product of those bindings (same structure as moc2 pivots).
443
+ */
444
+ interface Moc3KeyTables {
445
+ readonly bindingIndex: Int32Array;
446
+ readonly bandBegin: Int32Array;
447
+ readonly bandCount: Int32Array;
448
+ readonly keysBegin: Int32Array;
449
+ readonly keysCount: Int32Array;
450
+ readonly keys: Float32Array;
451
+ /** parameterIndex → bindings owned by that parameter */
452
+ readonly paramBindingBegin: Int32Array;
453
+ readonly paramBindingCount: Int32Array;
454
+ readonly paramCount: number;
455
+ }
456
+
457
+ /**
458
+ * Parse official MOC3 bytes into typed section tables (no deform evaluation).
459
+ */
460
+ interface Moc3CanvasInfo {
461
+ readonly pixelsPerUnit: number;
462
+ readonly originX: number;
463
+ readonly originY: number;
464
+ readonly canvasWidth: number;
465
+ readonly canvasHeight: number;
466
+ readonly flags: number;
467
+ }
468
+ interface Moc3Document {
469
+ readonly version: number;
470
+ readonly littleEndian: boolean;
471
+ readonly counts: Int32Array;
472
+ readonly canvas: Moc3CanvasInfo;
473
+ readonly sections: ReadonlyMap<string, unknown>;
474
+ }
475
+
476
+ /**
477
+ * moc3 Glue: pull paired vertices on art meshes A/B together.
478
+ *
479
+ * Layout (observed on Mao): `glue_info.position_indices` and `.weights` are
480
+ * interleaved pairs `(idxA, idxB)` / `(weightA, weightB)` with weightA+weightB≈1.
481
+ * Keyform `intensities` are Cubism "compatibility" (0..1).
482
+ *
483
+ * target = wA·posA + wB·posB
484
+ * posA' = lerp(posA, target, intensity)
485
+ * posB' = lerp(posB, target, intensity)
486
+ */
487
+
488
+ interface Moc3GluePair {
489
+ readonly indexA: number;
490
+ readonly indexB: number;
491
+ readonly weightA: number;
492
+ readonly weightB: number;
493
+ }
494
+ interface Moc3GlueDef {
495
+ readonly meshA: number;
496
+ readonly meshB: number;
497
+ readonly pairs: readonly Moc3GluePair[];
498
+ readonly band: number;
499
+ readonly keyformBegin: number;
500
+ readonly keyformCount: number;
501
+ }
502
+ /** Parse glue tables from a MOC3 document (empty when model has no glues). */
503
+ declare function loadMoc3Glues(doc: Moc3Document): Moc3GlueDef[];
504
+ /**
505
+ * Apply all glues in-place to world-space per-mesh position buffers
506
+ * (length = vertexCount * 2). Missing meshes are skipped.
507
+ */
508
+ declare function applyMoc3Glues(positionsByMesh: Map<number, Float32Array>, glues: readonly Moc3GlueDef[], keyTables: Moc3KeyTables, getParamByIndex: (index: number) => number, intensities: Float32Array): void;
509
+ /** Mean Euclidean distance between glued vertex pairs (for tests). */
510
+ declare function meanGlueSeamDistance(positionsByMesh: ReadonlyMap<number, Float32Array>, glue: Moc3GlueDef): number;
511
+
512
+ /** Shared untextured preview colors (Canvas2D / WebGL2 / WebGPU parity). */
513
+ declare const PREVIEW_FILL: {
514
+ readonly r: number;
515
+ readonly g: number;
516
+ readonly b: number;
517
+ readonly a: 1;
518
+ };
519
+ declare const PREVIEW_STROKE: {
520
+ readonly r: number;
521
+ readonly g: number;
522
+ readonly b: number;
523
+ readonly a: 1;
524
+ };
525
+ /** Expand triangle indices into a line-list (each edge twice-wound). */
526
+ declare function triangleEdgesToLineList(indices: Uint16Array): Uint16Array;
527
+
528
+ /**
529
+ * `@doki-land/live2d-renderer`
530
+ *
531
+ * Layout:
532
+ * - `backends/` — graphics only (webgpu / webgl2 / canvas2d)
533
+ * - `moc/` — moc2 / moc3 decode + model runtimes (not graphics backends)
534
+ * - `cpu/` — CPU evaluate + cpu-program fixture codec
535
+ * - `tests/` — all vitest suites (package root)
536
+ */
537
+
538
+ declare const LIVE2D_RENDERER_VERSION: "0.0.0";
539
+
540
+ export { BlendMode, CPU_PROGRAM_KIND, Canvas2DRendererImpl, type Canvas2DRendererOptions, type ClippingContext, type ClippingDrawableRef, type ClippingPartition, type CpuProgramFile, type CreateRendererOptions, type DecodedMoc2, type DecodedMoc3, type DrawableMesh, FULL_NDC_BOUNDS, LIVE2D_RENDERER_VERSION, type LaidOutClippingContext, MASK_CHANNEL_FLAGS, type MaskAtlasMode, type MaskAtlasOptions, type MaskChannelFlag, type MaskLayoutRect, Moc2Backend, Moc3Backend, Moc3DrawableFlag, type Moc3GlueDef, type Moc3GluePair, type ModelBackend, type ModelBackendOptions, type ModelDrawPass, PREVIEW_FILL, PREVIEW_STROKE, type ParameterBinding, type Renderer, type RendererKind, type TextureData, type WebGl2Renderer, WebGl2RendererImpl, type WebGl2RendererOptions, type WebGpuRenderer, WebGpuRendererImpl, type WebGpuRendererOptions, applyMoc3Glues, applyWebGl2BlendMode, buildClippingContexts, calcClippedDrawableBounds, calcVertexBounds, canvasCompositeForBlendMode, createCanvas2DRenderer, createMoc2Backend, createMoc3Backend, createModelInstance, createQuadProgram, createRenderer, createWebGl2Renderer, createWebGpuRenderer, decodeMoc2, decodeMoc2ColorComposition, decodeMoc3, decodeMoc3DrawableFlags, detectMocBinaryFormat, evaluateFrame, expandBounds, fingerprintSnapshot, fitClippingContexts, isCanvas2DAvailable, isCpuProgramBytes, isWebGl2Available, isWebGpuAvailable, layoutMaskAtlas, layoutMaskAtlasRgba, layoutMaskAtlasUvGrid, loadMoc3Glues, maskChannelVec4, maskLayoutVec4, meanGlueSeamDistance, parseCpuProgram, partitionForClipping, selectModelBackend, serializeCpuProgram, setParameterValue, triangleEdgesToLineList, webGpuBlendState };