reze-engine 0.64.0 → 0.66.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.
Files changed (173) hide show
  1. package/dist/engine.d.ts +300 -94
  2. package/dist/engine.d.ts.map +1 -1
  3. package/dist/engine.js +1628 -787
  4. package/dist/graph/compile.d.ts.map +1 -1
  5. package/dist/graph/compile.js +5 -0
  6. package/dist/graph/presets/body.d.ts.map +1 -1
  7. package/dist/graph/presets/body.js +26 -24
  8. package/dist/graph/presets/cloth_rough.js +8 -8
  9. package/dist/graph/presets/cloth_smooth.js +8 -8
  10. package/dist/graph/presets/default.js +4 -4
  11. package/dist/graph/presets/eye.js +10 -10
  12. package/dist/graph/presets/face.d.ts.map +1 -1
  13. package/dist/graph/presets/face.js +28 -26
  14. package/dist/graph/presets/hair.js +6 -6
  15. package/dist/graph/presets/metal.js +8 -8
  16. package/dist/graph/presets/stockings.d.ts.map +1 -1
  17. package/dist/graph/presets/stockings.js +4 -11
  18. package/dist/graph/presets/unlit.d.ts.map +1 -1
  19. package/dist/graph/presets/unlit.js +9 -13
  20. package/dist/graph/registry.d.ts.map +1 -1
  21. package/dist/graph/registry.js +128 -157
  22. package/dist/graph/render-class.d.ts +5 -2
  23. package/dist/graph/render-class.d.ts.map +1 -1
  24. package/dist/graph/slots.d.ts.map +1 -1
  25. package/dist/graph/slots.js +12 -2
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/model.d.ts +23 -1
  29. package/dist/model.d.ts.map +1 -1
  30. package/dist/model.js +41 -1
  31. package/dist/outline-normals.d.ts +12 -0
  32. package/dist/outline-normals.d.ts.map +1 -0
  33. package/dist/outline-normals.js +100 -0
  34. package/dist/pmx-loader.d.ts +7 -0
  35. package/dist/pmx-loader.d.ts.map +1 -1
  36. package/dist/pmx-loader.js +17 -3
  37. package/dist/shaders/anchor-table.d.ts +11 -0
  38. package/dist/shaders/anchor-table.d.ts.map +1 -1
  39. package/dist/shaders/anchor-table.js +9 -3
  40. package/dist/shaders/directives.d.ts +42 -5
  41. package/dist/shaders/directives.d.ts.map +1 -1
  42. package/dist/shaders/directives.js +51 -4
  43. package/dist/shaders/lights.d.ts +11 -7
  44. package/dist/shaders/lights.d.ts.map +1 -1
  45. package/dist/shaders/lights.js +315 -271
  46. package/dist/shaders/materials/common.d.ts.map +1 -1
  47. package/dist/shaders/materials/common.js +30 -5
  48. package/dist/shaders/materials/nodes.d.ts +1 -1
  49. package/dist/shaders/materials/nodes.d.ts.map +1 -1
  50. package/dist/shaders/materials/nodes.js +191 -271
  51. package/dist/shaders/passes/bloom.d.ts +4 -3
  52. package/dist/shaders/passes/bloom.d.ts.map +1 -1
  53. package/dist/shaders/passes/bloom.js +58 -87
  54. package/dist/shaders/passes/composite.d.ts +1 -1
  55. package/dist/shaders/passes/composite.d.ts.map +1 -1
  56. package/dist/shaders/passes/composite.js +121 -77
  57. package/dist/shaders/passes/ground.js +1 -1
  58. package/dist/shaders/passes/mirror.d.ts +18 -12
  59. package/dist/shaders/passes/mirror.d.ts.map +1 -1
  60. package/dist/shaders/passes/mirror.js +59 -13
  61. package/dist/shaders/passes/outline.d.ts.map +1 -1
  62. package/dist/shaders/passes/outline.js +71 -14
  63. package/dist/shaders/passes/particles.d.ts.map +1 -1
  64. package/dist/shaders/passes/particles.js +9 -3
  65. package/dist/shaders/passes/probe.d.ts +45 -0
  66. package/dist/shaders/passes/probe.d.ts.map +1 -0
  67. package/dist/shaders/passes/probe.js +230 -0
  68. package/dist/shaders/passes/scene-contract.d.ts +13 -0
  69. package/dist/shaders/passes/scene-contract.d.ts.map +1 -1
  70. package/dist/shaders/passes/scene-contract.js +4 -0
  71. package/dist/shaders/scene-light-api.d.ts.map +1 -1
  72. package/dist/shaders/scene-light-api.js +1 -0
  73. package/dist/unity/globals.d.ts +7 -0
  74. package/dist/unity/globals.d.ts.map +1 -1
  75. package/dist/unity/globals.js +4 -3
  76. package/dist/unity/host.d.ts +18 -0
  77. package/dist/unity/host.d.ts.map +1 -1
  78. package/dist/unity/host.js +144 -70
  79. package/dist/unity/looks.d.ts +47 -0
  80. package/dist/unity/looks.d.ts.map +1 -1
  81. package/dist/unity/looks.js +150 -6
  82. package/dist/unity/skin.d.ts.map +1 -1
  83. package/dist/unity/skin.js +5 -2
  84. package/dist/unity/stage.d.ts +24 -0
  85. package/dist/unity/stage.d.ts.map +1 -1
  86. package/dist/unity/stage.js +59 -7
  87. package/package.json +1 -1
  88. package/src/engine.ts +2010 -1033
  89. package/src/graph/compile.ts +4 -0
  90. package/src/graph/presets/body.ts +26 -24
  91. package/src/graph/presets/cloth_rough.ts +8 -8
  92. package/src/graph/presets/cloth_smooth.ts +8 -8
  93. package/src/graph/presets/default.ts +4 -4
  94. package/src/graph/presets/eye.ts +10 -10
  95. package/src/graph/presets/face.ts +28 -26
  96. package/src/graph/presets/hair.ts +6 -6
  97. package/src/graph/presets/metal.ts +8 -8
  98. package/src/graph/presets/stockings.ts +4 -11
  99. package/src/graph/presets/unlit.ts +9 -13
  100. package/src/graph/registry.ts +133 -158
  101. package/src/graph/render-class.ts +5 -2
  102. package/src/graph/slots.ts +12 -2
  103. package/src/index.ts +1 -0
  104. package/src/model.ts +50 -1
  105. package/src/outline-normals.ts +110 -0
  106. package/src/pmx-loader.ts +18 -3
  107. package/src/shaders/anchor-table.ts +15 -3
  108. package/src/shaders/directives.ts +88 -6
  109. package/src/shaders/lights.ts +464 -415
  110. package/src/shaders/materials/common.ts +30 -5
  111. package/src/shaders/materials/nodes.ts +191 -271
  112. package/src/shaders/passes/bloom.ts +59 -87
  113. package/src/shaders/passes/composite.ts +121 -77
  114. package/src/shaders/passes/ground.ts +1 -1
  115. package/src/shaders/passes/mirror.ts +60 -13
  116. package/src/shaders/passes/outline.ts +71 -14
  117. package/src/shaders/passes/particles.ts +9 -3
  118. package/src/shaders/passes/probe.ts +240 -0
  119. package/src/shaders/passes/scene-contract.ts +17 -0
  120. package/src/shaders/scene-light-api.ts +1 -0
  121. package/src/unity/globals.ts +7 -3
  122. package/src/unity/host.ts +93 -20
  123. package/src/unity/looks.ts +182 -9
  124. package/src/unity/skin.ts +5 -2
  125. package/src/unity/stage.ts +66 -7
  126. package/dist/physics-debug.d.ts +0 -30
  127. package/dist/physics-debug.d.ts.map +0 -1
  128. package/dist/physics-debug.js +0 -526
  129. package/dist/shaders/agx-lut.d.ts +0 -11
  130. package/dist/shaders/agx-lut.d.ts.map +0 -1
  131. package/dist/shaders/agx-lut.js +0 -29
  132. package/dist/shaders/dfg_lut.d.ts +0 -3
  133. package/dist/shaders/dfg_lut.d.ts.map +0 -1
  134. package/dist/shaders/dfg_lut.js +0 -129
  135. package/dist/shaders/ltc_mag_lut.d.ts +0 -3
  136. package/dist/shaders/ltc_mag_lut.d.ts.map +0 -1
  137. package/dist/shaders/ltc_mag_lut.js +0 -1033
  138. package/dist/shaders/materials/body.d.ts +0 -2
  139. package/dist/shaders/materials/body.d.ts.map +0 -1
  140. package/dist/shaders/materials/body.js +0 -95
  141. package/dist/shaders/materials/cloth_rough.d.ts +0 -2
  142. package/dist/shaders/materials/cloth_rough.d.ts.map +0 -1
  143. package/dist/shaders/materials/cloth_rough.js +0 -69
  144. package/dist/shaders/materials/cloth_smooth.d.ts +0 -2
  145. package/dist/shaders/materials/cloth_smooth.d.ts.map +0 -1
  146. package/dist/shaders/materials/cloth_smooth.js +0 -61
  147. package/dist/shaders/materials/default.d.ts +0 -2
  148. package/dist/shaders/materials/default.d.ts.map +0 -1
  149. package/dist/shaders/materials/default.js +0 -43
  150. package/dist/shaders/materials/eye.d.ts +0 -2
  151. package/dist/shaders/materials/eye.d.ts.map +0 -1
  152. package/dist/shaders/materials/eye.js +0 -60
  153. package/dist/shaders/materials/face.d.ts +0 -2
  154. package/dist/shaders/materials/face.d.ts.map +0 -1
  155. package/dist/shaders/materials/face.js +0 -95
  156. package/dist/shaders/materials/hair.d.ts +0 -2
  157. package/dist/shaders/materials/hair.d.ts.map +0 -1
  158. package/dist/shaders/materials/hair.js +0 -90
  159. package/dist/shaders/materials/metal.d.ts +0 -2
  160. package/dist/shaders/materials/metal.d.ts.map +0 -1
  161. package/dist/shaders/materials/metal.js +0 -77
  162. package/dist/shaders/materials/mmd_classic.d.ts +0 -2
  163. package/dist/shaders/materials/mmd_classic.d.ts.map +0 -1
  164. package/dist/shaders/materials/mmd_classic.js +0 -66
  165. package/dist/shaders/materials/stockings.d.ts +0 -2
  166. package/dist/shaders/materials/stockings.d.ts.map +0 -1
  167. package/dist/shaders/materials/stockings.js +0 -122
  168. package/dist/shaders/passes/physics-debug.d.ts +0 -2
  169. package/dist/shaders/passes/physics-debug.d.ts.map +0 -1
  170. package/dist/shaders/passes/physics-debug.js +0 -69
  171. package/src/shaders/agx-lut.ts +0 -30
  172. package/src/shaders/dfg_lut.ts +0 -131
  173. package/src/shaders/ltc_mag_lut.ts +0 -1035
package/src/pmx-loader.ts CHANGED
@@ -36,6 +36,13 @@ export class PmxLoader {
36
36
  private inverseBindMatrices: Float32Array | null = null
37
37
  private joints0: Uint16Array | null = null
38
38
  private weights0: Uint8Array | null = null
39
+ /** The PMX's additional UV channels (1–4), each four floats a vertex. The
40
+ * engine's own shading reads none of them; a native look can name one as
41
+ * the carrier of a game vertex stream (NativeLook.streams). */
42
+ private additionalUvs: Float32Array[] = []
43
+ /** PMX per-vertex edge scale — the outline's width multiplier, as the
44
+ * game's outline takes vertex colour alpha. */
45
+ private edgeScales: Float32Array | null = null
39
46
  private morphs: Morph[] = []
40
47
  private vertexCount: number = 0
41
48
  private rigidbodies: Rigidbody[] = []
@@ -150,6 +157,8 @@ export class PmxLoader {
150
157
  // Prepare skinning arrays (4 influences per vertex)
151
158
  const joints = new Uint16Array(count * 4)
152
159
  const weights = new Uint8Array(count * 4) // UNORM8, will be normalized to 255
160
+ const edgeScales = new Float32Array(count)
161
+ this.additionalUvs = Array.from({ length: this.additionalVec4Count }, () => new Float32Array(count * 4))
153
162
 
154
163
  for (let i = 0; i < count; i++) {
155
164
  const px = this.getFloat32()
@@ -167,7 +176,10 @@ export class PmxLoader {
167
176
  // PMX UVs are in the same orientation as WebGPU sampling; no flip
168
177
  uvs.push(u, v)
169
178
 
170
- this.offset += this.additionalVec4Count * 16
179
+ for (let k = 0; k < this.additionalVec4Count; k++) {
180
+ const a = this.additionalUvs[k]
181
+ for (let c = 0; c < 4; c++) a[i * 4 + c] = this.getFloat32()
182
+ }
171
183
  const type = this.getUint8()
172
184
  const base = i * 4
173
185
  // Initialize defaults
@@ -238,11 +250,12 @@ export class PmxLoader {
238
250
  } else {
239
251
  throw new Error(`Invalid bone weight type: ${type}`)
240
252
  }
241
- this.offset += 4 // edge scale
253
+ edgeScales[i] = this.getFloat32()
242
254
  }
243
255
 
244
256
  this.joints0 = joints
245
257
  this.weights0 = weights
258
+ this.edgeScales = edgeScales
246
259
  return { positions, normals, uvs }
247
260
  }
248
261
 
@@ -1136,7 +1149,9 @@ export class PmxLoader {
1136
1149
  morphing,
1137
1150
  this.rigidbodies,
1138
1151
  this.joints,
1139
- this.warnings
1152
+ this.warnings,
1153
+ this.edgeScales,
1154
+ this.additionalUvs
1140
1155
  )
1141
1156
  }
1142
1157
 
@@ -23,6 +23,12 @@
23
23
  interface AnchorRequest {
24
24
  bone: string
25
25
  trail: boolean
26
+ /** Model units down the bone's own axis (`#anchor ... along d`); absent = 0,
27
+ * the joint itself. */
28
+ along?: number
29
+ /** World units the bone must move before its trail keeps a point
30
+ * (`trail step d`); absent = every 60 Hz tick. */
31
+ step?: number
26
32
  }
27
33
 
28
34
  /** The empty table — a scene with no effect installed asks for no bones. */
@@ -48,6 +54,11 @@ export interface AnchorTable {
48
54
  * Order is first-come, so a single effect gets the identity alias and the whole
49
55
  * mechanism is a no-op until a second effect exists — which is what makes this
50
56
  * safe to land before setEffects does.
57
+ *
58
+ * A point ALONG a bone is a different point: `#anchor 右手首 trail along 0.9`
59
+ * and a bare `#anchor 右手首` are two entries, keyed by bone and distance, since
60
+ * sharing one ring would hand one of them the other's path. So is a trail
61
+ * recorded at a different `step`: its ring keeps different points.
51
62
  */
52
63
  export function buildAnchorTable(requests: AnchorRequest[][], max: number): AnchorTable {
53
64
  const entries: AnchorRequest[] = []
@@ -58,7 +69,8 @@ export function buildAnchorTable(requests: AnchorRequest[][], max: number): Anch
58
69
  for (let e = 0; e < requests.length; e++) {
59
70
  const local: number[] = []
60
71
  for (const req of requests[e]) {
61
- let g = index.get(req.bone)
72
+ const key = req.along || req.step ? `${req.bone}\u0000${req.along ?? 0}\u0000${req.step ?? 0}` : req.bone
73
+ let g = index.get(key)
62
74
  if (g === undefined) {
63
75
  if (entries.length >= max) {
64
76
  // Refused, and the effect still installs: an effect that loses one of
@@ -69,8 +81,8 @@ export function buildAnchorTable(requests: AnchorRequest[][], max: number): Anch
69
81
  continue
70
82
  }
71
83
  g = entries.length
72
- index.set(req.bone, g)
73
- entries.push({ bone: req.bone, trail: req.trail })
84
+ index.set(key, g)
85
+ entries.push({ bone: req.bone, trail: req.trail, ...(req.along ? { along: req.along } : {}), ...(req.step ? { step: req.step } : {}) })
74
86
  } else if (req.trail) {
75
87
  // A later request for the same bone can only ever ADD the trail — the
76
88
  // ring is shared, and turning it on for one reader turns it on for all.
@@ -28,6 +28,30 @@
28
28
  // each directive was, so every diagnostic's line number still points at the
29
29
  // line the author is looking at.
30
30
 
31
+ /**
32
+ * A bone an effect follows: `#anchor <bone> [trail] [along <d>]`.
33
+ *
34
+ * `along` is for an effect that comes off a point ON the bone rather than at its
35
+ * joint — threads leaving the knuckles, not the wrist; a flame at a sword's tip.
36
+ * The point is `d` model units down the bone's own axis: the direction a PMX
37
+ * editor draws the bone pointing (its tail, as an offset or as the bone it
38
+ * points at), turned by the bone's pose, scaled with the model. A left and a
39
+ * right wrist point opposite ways, so one number mirrors itself. A bone with no
40
+ * tail has no axis, and the point stays at the joint.
41
+ *
42
+ * Everything the anchor feeds reads the moved point: rzAnchor, the trail, the
43
+ * ribbon. Two effects naming the same bone at different `along` are two anchors.
44
+ *
45
+ * `trail step d` records the path the way a game's trail does (Unity's
46
+ * minVertexDistance): the newest point follows the bone every frame, and a
47
+ * point is only LEFT BEHIND once the bone is `d` world units from the last one.
48
+ * Sampled on the clock alone, a slowing hand leaves a knot of tiny segments
49
+ * whose directions jitter, and a wide ribbon fans across them into a starburst;
50
+ * a stepped path has no segment shorter than `d`. Ages stay true — each point
51
+ * keeps the time it was left. Different steps are different anchors.
52
+ */
53
+ export type EffectAnchor = { bone: string; trail: boolean; along?: number; step?: number }
54
+
31
55
  /** A knob an effect exposes, for a host to build a control from. */
32
56
  export type EffectParamDecl = {
33
57
  name: string
@@ -40,8 +64,10 @@ export type EffectParamDecl = {
40
64
  }
41
65
 
42
66
  export type EffectDirectives = {
43
- /** Bones this effect follows, in declaration order — slot 0 is the first. */
44
- anchors: { bone: string; trail: boolean }[]
67
+ /** Bones this effect follows, in declaration order — slot 0 is the first.
68
+ * `along` (model units, absent = 0) moves the point down the bone's own
69
+ * axis, its rest tail direction posed with it: see EffectAnchor. */
70
+ anchors: EffectAnchor[]
45
71
  params: EffectParamDecl[]
46
72
  /** Field layer: 0 full, 1 half. Full unless `#halfres` says otherwise. */
47
73
  fieldLayer: 0 | 1
@@ -54,6 +80,16 @@ export type EffectDirectives = {
54
80
  * every real grass renderer does, and the only thing that bounds a dense
55
81
  * lawn's cost by the pixels it covers rather than by how deep it stacks. */
56
82
  particleBlend: "alpha" | "additive" | "cutout"
83
+ /** How RIBBONS land, a separate axis from the particles': additive unless
84
+ * the file says `#blend over`. Ribbons ignored #blend until that keyword,
85
+ * and every shipped ribbon was tuned additive — so the default stays, and
86
+ * `over` is the opt-in. The same line sets particles to plain alpha, which
87
+ * already IS premultiplied over for them. */
88
+ trailBlend: "additive" | "over"
89
+ /** `#depth always`: the particles are drawn over the scene, not depth
90
+ * tested — a game glow its material draws with ZTest Always (a moon's halo
91
+ * in front of the sky dome it sits behind). Depth tested otherwise. */
92
+ depthAlways: boolean
57
93
  particles: number
58
94
  lights: number
59
95
  grid: number
@@ -130,6 +166,7 @@ const SPEC = {
130
166
  halfres: 0,
131
167
  layer: 1,
132
168
  blend: 1,
169
+ depth: 1,
133
170
  particles: 1,
134
171
  lights: 1,
135
172
  grid: 1,
@@ -190,6 +227,8 @@ export function parseDirectives(wgsl: string): DirectiveResult {
190
227
  fieldLayer: 0,
191
228
  additiveLayer: false,
192
229
  particleBlend: "alpha",
230
+ trailBlend: "additive",
231
+ depthAlways: false,
193
232
  particles: 0,
194
233
  lights: 0,
195
234
  grid: 0,
@@ -223,11 +262,40 @@ export function parseDirectives(wgsl: string): DirectiveResult {
223
262
 
224
263
  switch (tag) {
225
264
  case "anchor": {
226
- if (args.length < 1 || args.length > 2 || (args[1] && args[1] !== "trail")) {
227
- errors.push(`${at}: #anchor takes a bone name and optionally the word "trail"`)
265
+ // <bone> [trail [step <d>]] [along <d>], in that order.
266
+ const usage = `${at}: #anchor takes a bone name, optionally "trail" (and "step" with a distance), then optionally "along" and a distance`
267
+ if (args.length < 1) {
268
+ errors.push(usage)
269
+ return
270
+ }
271
+ let k = 1
272
+ const trail = args[k] === "trail"
273
+ if (trail) k++
274
+ let step: number | undefined
275
+ if (trail && args[k] === "step") {
276
+ const v = num(args[k + 1])
277
+ if (v === null || v <= 0) {
278
+ errors.push(`${at}: #anchor ... trail step needs a positive distance in world units, like "step 0.24"`)
279
+ return
280
+ }
281
+ step = v
282
+ k += 2
283
+ }
284
+ let along: number | undefined
285
+ if (args[k] === "along") {
286
+ const v = num(args[k + 1])
287
+ if (v === null) {
288
+ errors.push(`${at}: #anchor ... along needs a distance in model units, like "along 0.9"`)
289
+ return
290
+ }
291
+ along = v
292
+ k += 2
293
+ }
294
+ if (k !== args.length) {
295
+ errors.push(usage)
228
296
  return
229
297
  }
230
- d.anchors.push({ bone: args[0], trail: args[1] === "trail" })
298
+ d.anchors.push({ bone: args[0], trail, ...(step ? { step } : {}), ...(along ? { along } : {}) })
231
299
  return
232
300
  }
233
301
  case "param": {
@@ -284,8 +352,15 @@ export function parseDirectives(wgsl: string): DirectiveResult {
284
352
  d.additiveLayer = true
285
353
  return
286
354
  case "blend":
355
+ // `over` is for ribbons: laid over the scene by their alpha instead of
356
+ // added. For particles it is the default alpha, which is already over.
357
+ if (args[0] === "over") {
358
+ d.trailBlend = "over"
359
+ d.particleBlend = "alpha"
360
+ return
361
+ }
287
362
  if (args[0] !== "additive" && args[0] !== "cutout") {
288
- errors.push(`${at}: #blend takes "additive" or "cutout" — alpha is the default`)
363
+ errors.push(`${at}: #blend takes "additive", "cutout" or "over" — alpha is the default`)
289
364
  return
290
365
  }
291
366
  d.particleBlend = args[0]
@@ -293,6 +368,13 @@ export function parseDirectives(wgsl: string): DirectiveResult {
293
368
  case "bloom":
294
369
  d.bloom = true
295
370
  return
371
+ case "depth":
372
+ if (args[0] !== "always") {
373
+ errors.push(`${at}: #depth takes "always" — depth tested is the default`)
374
+ return
375
+ }
376
+ d.depthAlways = true
377
+ return
296
378
  case "ground": {
297
379
  const m = /^#([0-9a-fA-F]{6})$/.exec(args[0] ?? "")
298
380
  const noise = args[1] === undefined ? 0 : num(args[1])