@doki-land/live2d-renderer 0.0.15 → 0.0.17
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 +186 -1
- package/dist/index.d.ts +9 -6
- package/dist/index.js +8 -8
- package/package.json +2 -2
- package/src/backends/canvas2d.ts +7 -4
- package/src/backends/webgl2.ts +3 -3
- package/src/backends/webgpu.ts +3 -3
- package/src/index.ts +10 -7
- package/src/moc/decode.ts +2 -2
- package/src/moc/drawable-flags.ts +1 -1
- package/src/moc/moc2-deform.ts +1 -1
- package/src/moc/moc2-reader.ts +1 -1
- package/src/moc/moc2.ts +1 -1
- package/src/moc/moc3-deform.ts +1 -1
- package/src/moc/moc3-layout.ts +3 -6
- package/src/moc/moc3-reader.ts +1 -1
- package/src/moc/moc3-to-program.ts +3 -5
- package/src/moc/moc3.ts +3 -3
- package/src/{blend.ts → render/blend.ts} +1 -1
- package/src/{create-renderer.ts → runtime/create-renderer.ts} +4 -4
- package/src/{model-runtime.ts → runtime/model-runtime.ts} +2 -2
- package/src/{shared-compile.ts → runtime/shared-compile.ts} +3 -3
- /package/src/{detect-format.ts → format/detect-format.ts} +0 -0
- /package/src/{clipping.ts → render/clipping.ts} +0 -0
- /package/src/{coords.ts → render/coords.ts} +0 -0
- /package/src/{preview-style.ts → render/preview-style.ts} +0 -0
package/README.md
CHANGED
|
@@ -1,3 +1,188 @@
|
|
|
1
1
|
# @doki-land/live2d-renderer
|
|
2
2
|
|
|
3
|
-
live2d.ts
|
|
3
|
+
Model execution and browser-native rendering backends for `live2d.ts`.
|
|
4
|
+
|
|
5
|
+
This package owns both MOC2/MOC3 runtime behavior and the WebGPU, WebGL2, and Canvas2D graphics implementations.
|
|
6
|
+
Applications should normally use these capabilities through `@doki-land/live2d`.
|
|
7
|
+
|
|
8
|
+
## ✨ Features
|
|
9
|
+
|
|
10
|
+
- Pure TypeScript MOC2 and MOC3 parsing paths.
|
|
11
|
+
- CPU model programs and deterministic frame evaluation.
|
|
12
|
+
- WebGPU rendering.
|
|
13
|
+
- WebGL2 rendering.
|
|
14
|
+
- Canvas2D compatibility rendering.
|
|
15
|
+
- Texture, blend mode, clipping, and mask-atlas support.
|
|
16
|
+
- Parameter bindings for inspectors and interactive hosts.
|
|
17
|
+
- Renderer initialization fallback.
|
|
18
|
+
- Structural and model-fixture tests.
|
|
19
|
+
|
|
20
|
+
## 🧭 Package Role
|
|
21
|
+
|
|
22
|
+
The source tree separates execution concerns:
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
src/backends/ WebGPU, WebGL2, and Canvas2D graphics backends
|
|
26
|
+
src/moc/ MOC2/MOC3 decode, deformation, and ModelBackend implementations
|
|
27
|
+
src/cpu/ model program parsing and CPU frame evaluation
|
|
28
|
+
src/render/ blend modes, clipping, coords, preview styling
|
|
29
|
+
src/runtime/ renderer factory and model-runtime glue
|
|
30
|
+
src/format/ moc binary and settings format peek helpers
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
MOC2 and MOC3 are model formats, not graphics backends. WebGPU, WebGL2, and Canvas2D are graphics backends, not model
|
|
34
|
+
formats.
|
|
35
|
+
|
|
36
|
+
## 📦 Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pnpm add @doki-land/live2d-renderer
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Install this package directly when building renderer tools, conformance tests, custom facades, or specialized host
|
|
43
|
+
pipelines.
|
|
44
|
+
|
|
45
|
+
## 🚀 Creating a Renderer
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import {createRenderer} from "@doki-land/live2d-renderer";
|
|
49
|
+
|
|
50
|
+
const renderer = createRenderer({
|
|
51
|
+
prefer: ["webgpu", "webgl2", "canvas2d"],
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
await renderer.initialize(canvas);
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Fallback occurs during initialization. This matters because browser feature detection alone cannot prove that an
|
|
58
|
+
adapter, device, context, or required capability can be created.
|
|
59
|
+
|
|
60
|
+
## 🖼️ Backend Selection
|
|
61
|
+
|
|
62
|
+
### WebGPU
|
|
63
|
+
|
|
64
|
+
Preferred for modern browsers and explicit GPU resource management. A valid `navigator.gpu` object is not sufficient;
|
|
65
|
+
adapter and device creation can still fail.
|
|
66
|
+
|
|
67
|
+
### WebGL2
|
|
68
|
+
|
|
69
|
+
Primary GPU fallback with broad browser support. Shader compilation, framebuffer allocation, texture limits, and context
|
|
70
|
+
loss remain device-dependent.
|
|
71
|
+
|
|
72
|
+
### Canvas2D
|
|
73
|
+
|
|
74
|
+
Compatibility and diagnostic path using textured triangle approximation. It is useful for fallback rendering and
|
|
75
|
+
CPU-output inspection but is not expected to match GPU throughput for complex models.
|
|
76
|
+
|
|
77
|
+
## 🧠 Model Runtime
|
|
78
|
+
|
|
79
|
+
A `ModelBackend` is responsible for:
|
|
80
|
+
|
|
81
|
+
- determining whether it can handle normalized model settings;
|
|
82
|
+
- creating model state from settings and binary data;
|
|
83
|
+
- updating model time and parameters;
|
|
84
|
+
- producing drawable meshes or CPU frame snapshots;
|
|
85
|
+
- exposing parameter bindings;
|
|
86
|
+
- releasing model-owned state.
|
|
87
|
+
|
|
88
|
+
Model runtimes must not create their own application frame loop or DOM controls.
|
|
89
|
+
|
|
90
|
+
## 🎭 Rendering Semantics
|
|
91
|
+
|
|
92
|
+
The renderer preserves model-defined behavior including:
|
|
93
|
+
|
|
94
|
+
- drawable render order;
|
|
95
|
+
- opacity and visibility;
|
|
96
|
+
- normal, additive, and multiplicative blending where implemented;
|
|
97
|
+
- mask relationships;
|
|
98
|
+
- inverted masks;
|
|
99
|
+
- texture coordinates;
|
|
100
|
+
- model-space orientation.
|
|
101
|
+
|
|
102
|
+
Transparent drawables cannot be freely reordered across characters or masks merely to reduce state changes. Visual
|
|
103
|
+
correctness takes precedence over speculative batching.
|
|
104
|
+
|
|
105
|
+
## 🧭 Coordinate Contract
|
|
106
|
+
|
|
107
|
+
Model geometry uses a consistent model-space convention before reaching a graphics backend. Each backend is responsible
|
|
108
|
+
for exactly one conversion to its target coordinate system.
|
|
109
|
+
|
|
110
|
+
Do not fix orientation problems with CSS canvas transforms. CSS transforms also affect pointer mapping and can hide a
|
|
111
|
+
double conversion instead of correcting the model-to-renderer contract.
|
|
112
|
+
|
|
113
|
+
Orientation changes require a neutral fixture or pixel evidence across the affected backends.
|
|
114
|
+
|
|
115
|
+
## ⚡ Performance Engineering
|
|
116
|
+
|
|
117
|
+
Performance work should target measured costs:
|
|
118
|
+
|
|
119
|
+
- model-program and instance lifetime;
|
|
120
|
+
- per-frame allocations;
|
|
121
|
+
- parameter dirty tracking;
|
|
122
|
+
- affected deformer and drawable evaluation;
|
|
123
|
+
- dynamic vertex upload ranges;
|
|
124
|
+
- mask-pass reuse;
|
|
125
|
+
- texture and pipeline state changes;
|
|
126
|
+
- overdraw and canvas resolution;
|
|
127
|
+
- multi-character scaling.
|
|
128
|
+
|
|
129
|
+
WebAssembly, TypeScript, WebGPU, and WebGL2 are implementation tools, not benchmark results. Comparisons must use
|
|
130
|
+
equivalent visual output and report CPU, GPU, allocation, upload, and memory metrics.
|
|
131
|
+
|
|
132
|
+
## 🧪 Testing
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
pnpm --filter @doki-land/live2d-renderer typecheck
|
|
136
|
+
pnpm --filter @doki-land/live2d-renderer test
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Renderer changes should add the smallest appropriate evidence:
|
|
140
|
+
|
|
141
|
+
- CPU golden snapshots for evaluation changes;
|
|
142
|
+
- structural assertions for format decoding;
|
|
143
|
+
- orientation tests for coordinate changes;
|
|
144
|
+
- mask and blend fixtures for compositing changes;
|
|
145
|
+
- pixel comparisons for graphics parity;
|
|
146
|
+
- browser checks for device-specific behavior.
|
|
147
|
+
|
|
148
|
+
Proprietary models must not be committed without redistribution permission.
|
|
149
|
+
|
|
150
|
+
## 🔌 Extending the Package
|
|
151
|
+
|
|
152
|
+
New model-format support belongs under `src/moc/`. New browser graphics implementations belong under `src/backends/`. Do
|
|
153
|
+
not create a separate published package for every MOC revision or GPU backend unless an independently useful public
|
|
154
|
+
contract justifies it.
|
|
155
|
+
|
|
156
|
+
## 🤝 Contributing
|
|
157
|
+
|
|
158
|
+
### Renderer expectations
|
|
159
|
+
|
|
160
|
+
- Keep hot paths allocation-aware.
|
|
161
|
+
- Preserve deterministic CPU behavior.
|
|
162
|
+
- Document the visual invariant behind renderer changes.
|
|
163
|
+
- Add structural, pixel, or browser evidence appropriate to the change.
|
|
164
|
+
- Rebuild generated bundles from source instead of editing them manually.
|
|
165
|
+
|
|
166
|
+
## 📄 License
|
|
167
|
+
|
|
168
|
+
### Clean-room rendering
|
|
169
|
+
|
|
170
|
+
- WGSL and GLSL shaders, graphics pipelines, mask and blend paths, model execution, Canvas2D mesh rendering, resource
|
|
171
|
+
lifecycle, and GPU submission optimizations are independently designed and handwritten.
|
|
172
|
+
- No implementation is copied, translated, ported, derived from, or linked against an official renderer, Core binary,
|
|
173
|
+
SDK wrapper, shader source, pipeline implementation, or internal API.
|
|
174
|
+
- External format names identify interoperability targets only.
|
|
175
|
+
- The maintainers and contributors are independent and are not employed by, affiliated with, sponsored by, endorsed by,
|
|
176
|
+
or acting on behalf of the official Cubism SDK vendor.
|
|
177
|
+
|
|
178
|
+
### Contribution boundary
|
|
179
|
+
|
|
180
|
+
- Do not submit official SDK or shader source, disassembly-derived implementations, mechanically translated code, or
|
|
181
|
+
dependencies on an official runtime.
|
|
182
|
+
- Support compatibility patches with a public format fact, neutral fixture, reproducible independent observation, or
|
|
183
|
+
independently authored technical rationale.
|
|
184
|
+
|
|
185
|
+
### Terms
|
|
186
|
+
|
|
187
|
+
- See the repository license for source-code terms.
|
|
188
|
+
- Model assets used for local testing may have separate terms.
|
package/dist/index.d.ts
CHANGED
|
@@ -335,10 +335,10 @@ interface DecodedMoc3 {
|
|
|
335
335
|
readonly format: "moc3";
|
|
336
336
|
readonly program: ModelProgram;
|
|
337
337
|
}
|
|
338
|
-
/** Decode
|
|
338
|
+
/** Decode binary moc2 (`.moc`) bytes into a default-pose ModelProgram. */
|
|
339
339
|
declare function decodeMoc2(bytes: ArrayBuffer): Promise<DecodedMoc2>;
|
|
340
340
|
/**
|
|
341
|
-
* Decode
|
|
341
|
+
* Decode binary moc3 bytes into a ModelProgram.
|
|
342
342
|
* Applies keyform blending + warp/rotation deformer chains at the given pose
|
|
343
343
|
* (defaults when called via decodeMoc3).
|
|
344
344
|
*/
|
|
@@ -347,7 +347,7 @@ declare function decodeMoc3(bytes: ArrayBuffer): Promise<DecodedMoc3>;
|
|
|
347
347
|
/**
|
|
348
348
|
* Shared moc2/moc3 drawable constant-flag decode → blend / invert-mask.
|
|
349
349
|
*/
|
|
350
|
-
/**
|
|
350
|
+
/** Drawable flag bits decoded from the supported MOC3 art-mesh records. */
|
|
351
351
|
declare const Moc3DrawableFlag: {
|
|
352
352
|
readonly BlendAdditive: number;
|
|
353
353
|
readonly BlendMultiplicative: number;
|
|
@@ -391,7 +391,7 @@ interface ParameterBinding {
|
|
|
391
391
|
/** Shared read-only decode payload (renderer-internal; set by stage asset cache). */
|
|
392
392
|
interface SharedModelCompile {
|
|
393
393
|
readonly mocBytes: ArrayBuffer;
|
|
394
|
-
/**
|
|
394
|
+
/** Parsed binary `.moc3` document. */
|
|
395
395
|
readonly moc3Doc?: unknown;
|
|
396
396
|
/** moc3 CPU `.program.json` program. */
|
|
397
397
|
readonly cpuProgram?: _doki_land_live2d_core.ModelProgram;
|
|
@@ -431,7 +431,7 @@ declare class Moc2Backend implements ModelBackend {
|
|
|
431
431
|
}
|
|
432
432
|
declare function createMoc2Backend(): Moc2Backend;
|
|
433
433
|
|
|
434
|
-
/** moc3 model backend
|
|
434
|
+
/** moc3 model backend for binary `.moc3` input or CPU `.program.json` fixtures. */
|
|
435
435
|
declare class Moc3Backend implements ModelBackend {
|
|
436
436
|
readonly format: "moc3";
|
|
437
437
|
canHandle(json: unknown): boolean;
|
|
@@ -468,7 +468,7 @@ interface Moc3KeyTables {
|
|
|
468
468
|
}
|
|
469
469
|
|
|
470
470
|
/**
|
|
471
|
-
* Parse
|
|
471
|
+
* Parse binary MOC3 input into typed section tables (no deform evaluation).
|
|
472
472
|
*/
|
|
473
473
|
interface Moc3CanvasInfo {
|
|
474
474
|
readonly pixelsPerUnit: number;
|
|
@@ -548,6 +548,9 @@ declare function compileSharedModelCompile(settings: ModelSettings, mocBytes: Ar
|
|
|
548
548
|
* - `backends/` — graphics only (webgpu / webgl2 / canvas2d)
|
|
549
549
|
* - `moc/` — moc2 / moc3 decode + model runtimes (not graphics backends)
|
|
550
550
|
* - `cpu/` — CPU evaluate + cpu-program fixture codec
|
|
551
|
+
* - `render/` — blend, clipping, coords, preview styling helpers
|
|
552
|
+
* - `runtime/` — renderer factory + model runtime glue
|
|
553
|
+
* - `format/` — moc binary / settings format peek (shared with core)
|
|
551
554
|
* - `tests/` — all vitest suites (package root)
|
|
552
555
|
*/
|
|
553
556
|
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ var BlendMode = {
|
|
|
5
5
|
Multiplicative: 2
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
-
// src/blend.ts
|
|
8
|
+
// src/render/blend.ts
|
|
9
9
|
function applyWebGl2BlendMode(gl, mode) {
|
|
10
10
|
gl.enable(gl.BLEND);
|
|
11
11
|
switch (mode) {
|
|
@@ -84,7 +84,7 @@ function webGpuBlendState(mode) {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
// src/clipping.ts
|
|
87
|
+
// src/render/clipping.ts
|
|
88
88
|
var MASK_CHANNEL_FLAGS = [
|
|
89
89
|
[1, 0, 0, 0],
|
|
90
90
|
[0, 1, 0, 0],
|
|
@@ -329,7 +329,7 @@ function maskChannelVec4(flag) {
|
|
|
329
329
|
return new Float32Array([flag[0], flag[1], flag[2], flag[3]]);
|
|
330
330
|
}
|
|
331
331
|
|
|
332
|
-
// src/coords.ts
|
|
332
|
+
// src/render/coords.ts
|
|
333
333
|
function modelYUpToCanvasPixelY(modelY, canvasHeight) {
|
|
334
334
|
return (1 - modelY) * (canvasHeight / 2);
|
|
335
335
|
}
|
|
@@ -337,7 +337,7 @@ function modelXToCanvasPixelX(modelX, canvasWidth) {
|
|
|
337
337
|
return (modelX + 1) * (canvasWidth / 2);
|
|
338
338
|
}
|
|
339
339
|
|
|
340
|
-
// src/preview-style.ts
|
|
340
|
+
// src/render/preview-style.ts
|
|
341
341
|
var PREVIEW_FILL = {
|
|
342
342
|
r: 91 / 255,
|
|
343
343
|
g: 141 / 255,
|
|
@@ -2620,7 +2620,7 @@ function fingerprintSnapshot(snapshot) {
|
|
|
2620
2620
|
return parts.join("|");
|
|
2621
2621
|
}
|
|
2622
2622
|
|
|
2623
|
-
// src/create-renderer.ts
|
|
2623
|
+
// src/runtime/create-renderer.ts
|
|
2624
2624
|
var DEFAULT_PREFER = ["webgpu", "webgl2", "canvas2d"];
|
|
2625
2625
|
var INIT_TIMEOUT_MS = {
|
|
2626
2626
|
webgpu: 2500,
|
|
@@ -2711,7 +2711,7 @@ function createRenderer(options = {}) {
|
|
|
2711
2711
|
return new FallbackRenderer(prefer, options);
|
|
2712
2712
|
}
|
|
2713
2713
|
|
|
2714
|
-
// src/detect-format.ts
|
|
2714
|
+
// src/format/detect-format.ts
|
|
2715
2715
|
import { detectModelSettingsFormat } from "@doki-land/live2d-core";
|
|
2716
2716
|
function detectMocBinaryFormat(bytes) {
|
|
2717
2717
|
if (bytes.byteLength < 4) return null;
|
|
@@ -5512,7 +5512,7 @@ function createMoc3Backend() {
|
|
|
5512
5512
|
return new Moc3Backend();
|
|
5513
5513
|
}
|
|
5514
5514
|
|
|
5515
|
-
// src/model-runtime.ts
|
|
5515
|
+
// src/runtime/model-runtime.ts
|
|
5516
5516
|
function selectModelBackend(backends, json) {
|
|
5517
5517
|
const hit = backends.find((b) => b.canHandle(json));
|
|
5518
5518
|
if (!hit) {
|
|
@@ -5523,7 +5523,7 @@ function selectModelBackend(backends, json) {
|
|
|
5523
5523
|
return hit;
|
|
5524
5524
|
}
|
|
5525
5525
|
|
|
5526
|
-
// src/shared-compile.ts
|
|
5526
|
+
// src/runtime/shared-compile.ts
|
|
5527
5527
|
function compileSharedModelCompile(settings, mocBytes) {
|
|
5528
5528
|
if (settings.format === "moc2") {
|
|
5529
5529
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@doki-land/live2d-renderer",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"description": "Live2D rendering — moc2/moc3 decode + WebGPU, WebGL2, Canvas2D backends for live2d.ts.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"test": "vitest run"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@doki-land/live2d-core": "0.0.
|
|
48
|
+
"@doki-land/live2d-core": "0.0.17"
|
|
49
49
|
},
|
|
50
50
|
"sideEffects": false
|
|
51
51
|
}
|
package/src/backends/canvas2d.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import { canvasCompositeForBlendMode } from "../blend.js";
|
|
1
|
+
import { canvasCompositeForBlendMode } from "../render/blend.js";
|
|
2
2
|
import {
|
|
3
3
|
fitClippingContexts,
|
|
4
4
|
type MaskLayoutRect,
|
|
5
5
|
partitionForClipping,
|
|
6
|
-
} from "../clipping.js";
|
|
7
|
-
import {
|
|
8
|
-
|
|
6
|
+
} from "../render/clipping.js";
|
|
7
|
+
import {
|
|
8
|
+
modelXToCanvasPixelX,
|
|
9
|
+
modelYUpToCanvasPixelY,
|
|
10
|
+
} from "../render/coords.js";
|
|
11
|
+
import { PREVIEW_FILL, PREVIEW_STROKE } from "../render/preview-style.js";
|
|
9
12
|
import type {
|
|
10
13
|
DrawableMesh,
|
|
11
14
|
ModelDrawPass,
|
package/src/backends/webgl2.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* multiply drawable alpha by the mask (or 1−mask when inverted).
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { applyWebGl2BlendMode } from "../blend.js";
|
|
8
|
+
import { applyWebGl2BlendMode } from "../render/blend.js";
|
|
9
9
|
import {
|
|
10
10
|
fitClippingContexts,
|
|
11
11
|
type LaidOutClippingContext,
|
|
@@ -13,12 +13,12 @@ import {
|
|
|
13
13
|
maskChannelVec4,
|
|
14
14
|
maskLayoutVec4,
|
|
15
15
|
partitionForClipping,
|
|
16
|
-
} from "../clipping.js";
|
|
16
|
+
} from "../render/clipping.js";
|
|
17
17
|
import {
|
|
18
18
|
PREVIEW_FILL,
|
|
19
19
|
PREVIEW_STROKE,
|
|
20
20
|
triangleEdgesToLineList,
|
|
21
|
-
} from "../preview-style.js";
|
|
21
|
+
} from "../render/preview-style.js";
|
|
22
22
|
import type {
|
|
23
23
|
DrawableMesh,
|
|
24
24
|
ModelDrawPass,
|
package/src/backends/webgpu.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* atlas layout; endFrame submits.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { webGpuBlendState } from "../blend.js";
|
|
9
|
+
import { webGpuBlendState } from "../render/blend.js";
|
|
10
10
|
import {
|
|
11
11
|
fitClippingContexts,
|
|
12
12
|
type LaidOutClippingContext,
|
|
@@ -14,12 +14,12 @@ import {
|
|
|
14
14
|
maskChannelVec4,
|
|
15
15
|
maskLayoutVec4,
|
|
16
16
|
partitionForClipping,
|
|
17
|
-
} from "../clipping.js";
|
|
17
|
+
} from "../render/clipping.js";
|
|
18
18
|
import {
|
|
19
19
|
PREVIEW_FILL,
|
|
20
20
|
PREVIEW_STROKE,
|
|
21
21
|
triangleEdgesToLineList,
|
|
22
|
-
} from "../preview-style.js";
|
|
22
|
+
} from "../render/preview-style.js";
|
|
23
23
|
import type {
|
|
24
24
|
DrawableMesh,
|
|
25
25
|
ModelDrawPass,
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
* - `backends/` — graphics only (webgpu / webgl2 / canvas2d)
|
|
6
6
|
* - `moc/` — moc2 / moc3 decode + model runtimes (not graphics backends)
|
|
7
7
|
* - `cpu/` — CPU evaluate + cpu-program fixture codec
|
|
8
|
+
* - `render/` — blend, clipping, coords, preview styling helpers
|
|
9
|
+
* - `runtime/` — renderer factory + model runtime glue
|
|
10
|
+
* - `format/` — moc binary / settings format peek (shared with core)
|
|
8
11
|
* - `tests/` — all vitest suites (package root)
|
|
9
12
|
*/
|
|
10
13
|
|
|
@@ -30,7 +33,7 @@ export {
|
|
|
30
33
|
applyWebGl2BlendMode,
|
|
31
34
|
canvasCompositeForBlendMode,
|
|
32
35
|
webGpuBlendState,
|
|
33
|
-
} from "./blend.js";
|
|
36
|
+
} from "./render/blend.js";
|
|
34
37
|
export {
|
|
35
38
|
buildClippingContexts,
|
|
36
39
|
type ClippingContext,
|
|
@@ -53,7 +56,7 @@ export {
|
|
|
53
56
|
maskChannelVec4,
|
|
54
57
|
maskLayoutVec4,
|
|
55
58
|
partitionForClipping,
|
|
56
|
-
} from "./clipping.js";
|
|
59
|
+
} from "./render/clipping.js";
|
|
57
60
|
export {
|
|
58
61
|
CPU_PROGRAM_KIND,
|
|
59
62
|
type CpuProgramFile,
|
|
@@ -71,11 +74,11 @@ export {
|
|
|
71
74
|
export {
|
|
72
75
|
type CreateRendererOptions,
|
|
73
76
|
createRenderer,
|
|
74
|
-
} from "./create-renderer.js";
|
|
77
|
+
} from "./runtime/create-renderer.js";
|
|
75
78
|
export {
|
|
76
79
|
detectMocBinaryFormat,
|
|
77
80
|
detectModelSettingsFormat,
|
|
78
|
-
} from "./detect-format.js";
|
|
81
|
+
} from "./format/detect-format.js";
|
|
79
82
|
export {
|
|
80
83
|
type DecodedMoc2,
|
|
81
84
|
type DecodedMoc3,
|
|
@@ -102,13 +105,13 @@ export {
|
|
|
102
105
|
type ParameterBinding,
|
|
103
106
|
type SharedModelCompile,
|
|
104
107
|
selectModelBackend,
|
|
105
|
-
} from "./model-runtime.js";
|
|
108
|
+
} from "./runtime/model-runtime.js";
|
|
106
109
|
export {
|
|
107
110
|
PREVIEW_FILL,
|
|
108
111
|
PREVIEW_STROKE,
|
|
109
112
|
triangleEdgesToLineList,
|
|
110
|
-
} from "./preview-style.js";
|
|
111
|
-
export { compileSharedModelCompile } from "./shared-compile.js";
|
|
113
|
+
} from "./render/preview-style.js";
|
|
114
|
+
export { compileSharedModelCompile } from "./runtime/shared-compile.js";
|
|
112
115
|
export {
|
|
113
116
|
BlendMode,
|
|
114
117
|
type DrawableMesh,
|
package/src/moc/decode.ts
CHANGED
|
@@ -23,7 +23,7 @@ function readMagic(bytes: ArrayBuffer): string {
|
|
|
23
23
|
return String.fromCharCode(...new Uint8Array(bytes, 0, 4));
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
/** Decode
|
|
26
|
+
/** Decode binary moc2 (`.moc`) bytes into a default-pose ModelProgram. */
|
|
27
27
|
export async function decodeMoc2(bytes: ArrayBuffer): Promise<DecodedMoc2> {
|
|
28
28
|
if (bytes.byteLength < 4) {
|
|
29
29
|
throw new Error("@doki-land/live2d-renderer: truncated moc2 header");
|
|
@@ -48,7 +48,7 @@ export async function decodeMoc2(bytes: ArrayBuffer): Promise<DecodedMoc2> {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
|
-
* Decode
|
|
51
|
+
* Decode binary moc3 bytes into a ModelProgram.
|
|
52
52
|
* Applies keyform blending + warp/rotation deformer chains at the given pose
|
|
53
53
|
* (defaults when called via decodeMoc3).
|
|
54
54
|
*/
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { FrameBlendMode } from "@doki-land/live2d-core";
|
|
6
6
|
|
|
7
|
-
/**
|
|
7
|
+
/** Drawable flag bits decoded from the supported MOC3 art-mesh records. */
|
|
8
8
|
export const Moc3DrawableFlag = {
|
|
9
9
|
BlendAdditive: 1 << 0,
|
|
10
10
|
BlendMultiplicative: 1 << 1,
|
package/src/moc/moc2-deform.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* moc2 default-pose deformer bake: affine + mesh-warp parent chain.
|
|
3
|
-
*
|
|
3
|
+
* Evaluates the parsed keyform tables into drawable-space positions.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { interpolateKeyforms, resolveKeyformBlend } from "./moc2-keyforms.js";
|
package/src/moc/moc2-reader.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* moc2 binary stream reader (7-bit varints, big-endian ints/floats).
|
|
3
|
-
*
|
|
3
|
+
* Covers the record layout exercised by the repository's supported fixtures.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
export const MOC2_REF_TYPE = 33;
|
package/src/moc/moc2.ts
CHANGED
|
@@ -15,7 +15,7 @@ import type {
|
|
|
15
15
|
ModelBackend,
|
|
16
16
|
ModelBackendOptions,
|
|
17
17
|
ParameterBinding,
|
|
18
|
-
} from "../model-runtime.js";
|
|
18
|
+
} from "../runtime/model-runtime.js";
|
|
19
19
|
import type { BlendMode, DrawableMesh } from "../types.js";
|
|
20
20
|
import { type Moc2ModelImpl, Moc2Parser } from "./moc2-objects.js";
|
|
21
21
|
import {
|
package/src/moc/moc3-deform.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* moc3 deformer bake: warp grids + rotation affines along parent chains.
|
|
3
3
|
*
|
|
4
|
-
* Coordinate contract
|
|
4
|
+
* Coordinate contract covered by the Wanko regression fixture:
|
|
5
5
|
* - Root rotations author scale ≈ 1/pixelsPerUnit; children stay in pixels.
|
|
6
6
|
* - Nested rotation under rotation: mulAffine; origins/children share parent units.
|
|
7
7
|
* - Rotation under warp: origin is warp UV; fold 1/ppu into the local linear
|
package/src/moc/moc3-layout.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Layout order follows public MOC3 memory-map descriptions (OpenL2D hexpat /
|
|
6
|
-
* independent format notes). Deformer evaluation is deferred — default pose
|
|
7
|
-
* uses each art mesh's first keyform only.
|
|
2
|
+
* MOC3 section layout used by the decoder: a 64-byte header, a section-offset
|
|
3
|
+
* table of 160 u32 entries, and the referenced body arrays. Deformer evaluation
|
|
4
|
+
* is deferred; the initial pose uses each art mesh's first keyform.
|
|
8
5
|
*/
|
|
9
6
|
|
|
10
7
|
export const MOC3_MAGIC = "MOC3";
|
package/src/moc/moc3-reader.ts
CHANGED
|
@@ -38,11 +38,9 @@ function normalizePositions(
|
|
|
38
38
|
canvasHeight: number,
|
|
39
39
|
pixelsPerUnit: number,
|
|
40
40
|
): Float32Array {
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
// Y-up NDC (head / bowl toward +Y). Negate Y once here — same contract as
|
|
45
|
-
// moc2 after top-left pixel normalization.
|
|
41
|
+
// Deformer output uses logical canvas/ppu units around the model center.
|
|
42
|
+
// Convert the decoded authoring orientation once into the renderer's shared
|
|
43
|
+
// Y-up NDC contract, matching the moc2 path after top-left normalization.
|
|
46
44
|
const ppu = pixelsPerUnit > 0 ? pixelsPerUnit : 1;
|
|
47
45
|
const hw = canvasWidth > 0 ? (canvasWidth / ppu) * 0.5 : 0.5;
|
|
48
46
|
const hh = canvasHeight > 0 ? (canvasHeight / ppu) * 0.5 : 0.5;
|
package/src/moc/moc3.ts
CHANGED
|
@@ -17,7 +17,7 @@ import type {
|
|
|
17
17
|
ModelBackend,
|
|
18
18
|
ModelBackendOptions,
|
|
19
19
|
ParameterBinding,
|
|
20
|
-
} from "../model-runtime.js";
|
|
20
|
+
} from "../runtime/model-runtime.js";
|
|
21
21
|
import type { BlendMode, DrawableMesh } from "../types.js";
|
|
22
22
|
import { cascadedPartOpacity, readMoc3PartTables } from "./moc3-parts.js";
|
|
23
23
|
import { type Moc3Document, parseMoc3Document } from "./moc3-reader.js";
|
|
@@ -49,7 +49,7 @@ function paramFingerprint(values: ArrayLike<number>): string {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
interface Moc3State {
|
|
52
|
-
/** Present for
|
|
52
|
+
/** Present for binary MOC3 input; null for cpu-program fixtures. */
|
|
53
53
|
doc: Moc3Document | null;
|
|
54
54
|
instance: ModelInstance;
|
|
55
55
|
lastFrame: FrameSnapshot | null;
|
|
@@ -82,7 +82,7 @@ function bakePose(state: Moc3State): void {
|
|
|
82
82
|
state.lastFrame = evaluateFrame(next);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
/** moc3 model backend
|
|
85
|
+
/** moc3 model backend for binary `.moc3` input or CPU `.program.json` fixtures. */
|
|
86
86
|
export class Moc3Backend implements ModelBackend {
|
|
87
87
|
readonly format = "moc3" as const;
|
|
88
88
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Map Live2D blend modes to WebGL / Canvas compositing.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { BlendMode } from "
|
|
5
|
+
import { BlendMode } from "../types.js";
|
|
6
6
|
|
|
7
7
|
/** Apply premultiplied-friendly Live2D blend factors on a WebGL2 context. */
|
|
8
8
|
export function applyWebGl2BlendMode(
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type Canvas2DRendererOptions,
|
|
3
3
|
createCanvas2DRenderer,
|
|
4
|
-
} from "
|
|
4
|
+
} from "../backends/canvas2d.js";
|
|
5
5
|
import {
|
|
6
6
|
createWebGl2Renderer,
|
|
7
7
|
type WebGl2RendererOptions,
|
|
8
|
-
} from "
|
|
8
|
+
} from "../backends/webgl2.js";
|
|
9
9
|
import {
|
|
10
10
|
createWebGpuRenderer,
|
|
11
11
|
type WebGpuRendererOptions,
|
|
12
|
-
} from "
|
|
13
|
-
import type { Renderer, RendererKind } from "
|
|
12
|
+
} from "../backends/webgpu.js";
|
|
13
|
+
import type { Renderer, RendererKind } from "../types.js";
|
|
14
14
|
|
|
15
15
|
export interface CreateRendererOptions {
|
|
16
16
|
/**
|
|
@@ -5,7 +5,7 @@ import type {
|
|
|
5
5
|
ModelFormat,
|
|
6
6
|
ModelSettings,
|
|
7
7
|
} from "@doki-land/live2d-core";
|
|
8
|
-
import type { DrawableMesh, Renderer } from "
|
|
8
|
+
import type { DrawableMesh, Renderer } from "../types.js";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Model-format runtime contract (moc2 / moc3 / cpu-program).
|
|
@@ -34,7 +34,7 @@ export interface ParameterBinding {
|
|
|
34
34
|
/** Shared read-only decode payload (renderer-internal; set by stage asset cache). */
|
|
35
35
|
export interface SharedModelCompile {
|
|
36
36
|
readonly mocBytes: ArrayBuffer;
|
|
37
|
-
/**
|
|
37
|
+
/** Parsed binary `.moc3` document. */
|
|
38
38
|
readonly moc3Doc?: unknown;
|
|
39
39
|
/** moc3 CPU `.program.json` program. */
|
|
40
40
|
readonly cpuProgram?: import("@doki-land/live2d-core").ModelProgram;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ModelProgram, ModelSettings } from "@doki-land/live2d-core";
|
|
2
|
-
import { isCpuProgramBytes, parseCpuProgram } from "
|
|
3
|
-
import { Moc2Parser } from "
|
|
4
|
-
import { parseMoc3Document } from "
|
|
2
|
+
import { isCpuProgramBytes, parseCpuProgram } from "../cpu/cpu-program.js";
|
|
3
|
+
import { Moc2Parser } from "../moc/moc2-objects.js";
|
|
4
|
+
import { parseMoc3Document } from "../moc/moc3-reader.js";
|
|
5
5
|
import type { SharedModelCompile } from "./model-runtime.js";
|
|
6
6
|
|
|
7
7
|
/** One-time decode of moc bytes for stage-level {@link ModelAsset} sharing. */
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|