reze-engine 0.68.5 → 0.68.7
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/dist/engine.d.ts +2 -3
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +6 -6
- package/dist/graph/slots.d.ts.map +1 -1
- package/dist/graph/slots.js +2 -10
- package/dist/jelly-eyes.d.ts +9 -3
- package/dist/jelly-eyes.d.ts.map +1 -1
- package/dist/jelly-eyes.js +438 -85
- package/dist/shaders/materials/common.d.ts.map +1 -1
- package/dist/shaders/materials/common.js +49 -104
- package/package.json +1 -1
- package/src/engine.ts +6 -6
- package/src/graph/slots.ts +2 -10
- package/src/jelly-eyes.ts +449 -81
- package/src/shaders/materials/common.ts +49 -104
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/shaders/materials/common.ts"],"names":[],"mappings":"AA4BA,eAAO,MAAM,oBAAoB,
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/shaders/materials/common.ts"],"names":[],"mappings":"AA4BA,eAAO,MAAM,oBAAoB,QA2ThC,CAAC;AAwHF,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAGD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,aAAa,orMAgHzB,CAAA;AAQD,eAAO,MAAM,4BAA4B,QAC6H,CAAA"}
|
|
@@ -216,34 +216,43 @@ fn _rzCastShadow(wp: vec3f) -> f32 {
|
|
|
216
216
|
// jelly its jelly eyes (Engine.setModelJellyEyes, jelly-eyes.ts), not
|
|
217
217
|
// lighting but per-model all the same, so it rides here:
|
|
218
218
|
// [0] left iris centre (bind space), strength — 0 is off
|
|
219
|
-
// [1] right iris centre,
|
|
219
|
+
// [1] right iris centre, the highlight layers' materialIds
|
|
220
|
+
// (a + b·4096, 0 none)
|
|
220
221
|
// [2] left iris half extents, closure, eye bone (−1 none)
|
|
221
222
|
// [3] the right's
|
|
222
|
-
// [4] left
|
|
223
|
-
|
|
223
|
+
// [4] left scale x, y, twist, highlight turn (radians)
|
|
224
|
+
// [5] the right's
|
|
225
|
+
// [6] left drift x, y, highlight's own offset x, y (bind units)
|
|
226
|
+
// [7] the right's
|
|
227
|
+
// [8] left eye bone's head (the roll's pivot), roll (radians)
|
|
228
|
+
// [9] the right's
|
|
229
|
+
// [10] left highlight scale x, y, forward push (bind units), 0
|
|
230
|
+
// [11] the right's
|
|
231
|
+
struct ObjectLight { layers: vec4u, ambient: vec4f, sh: array<vec4f, 9>, fill: vec4f, jelly: array<vec4f, 12> }
|
|
224
232
|
@group(1) @binding(1) var<uniform> objectLight: ObjectLight;
|
|
225
233
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
w: f32,
|
|
232
|
-
closure: f32,
|
|
233
|
-
shine: f32,
|
|
234
|
-
};
|
|
234
|
+
fn _rzJellyTurn(q: vec2f, a: f32) -> vec2f {
|
|
235
|
+
let c = cos(a);
|
|
236
|
+
let s = sin(a);
|
|
237
|
+
return vec2f(c * q.x - s * q.y, s * q.x + c * q.y);
|
|
238
|
+
}
|
|
235
239
|
|
|
236
240
|
/**
|
|
237
241
|
* Where the jelly puts an iris vertex. The iris is the part of the eye the eye
|
|
238
242
|
* bones carry, so it is moved as a whole, in bind space before skinning:
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
* the
|
|
243
|
+
* scaled about its centre (the CPU composes the blink's spring, the lid's
|
|
244
|
+
* press and her motion's knock into one scale), turned and drifted a hair on
|
|
245
|
+
* the spring, brought forward a hair, and rolled about the eye bone with a
|
|
246
|
+
* closing expression — inside the white, which stays where it is. A highlight
|
|
247
|
+
* layer (this draw's material is one of jelly[1].w's) takes the iris's move,
|
|
248
|
+
* then its own scale, turn and tremble, before the roll. Vertices take it by their weight on the eye bones
|
|
249
|
+
* (jelly[2].w, jelly[3].w), so nothing else on the face moves.
|
|
244
250
|
*/
|
|
245
251
|
fn rzJellyVertex(p: vec3f, joints: vec4<u32>, nw: vec4f) -> vec3f {
|
|
246
252
|
let j = objectLight.jelly;
|
|
253
|
+
let ids = u32(j[1].w);
|
|
254
|
+
let mid = u32(material.materialId);
|
|
255
|
+
let hl = mid > 0u && (mid == (ids & 4095u) || mid == (ids >> 12u));
|
|
247
256
|
var out = p;
|
|
248
257
|
for (var e = 0u; e < 2u; e++) {
|
|
249
258
|
let bone = j[2u + e].w;
|
|
@@ -255,97 +264,33 @@ fn rzJellyVertex(p: vec3f, joints: vec4<u32>, nw: vec4f) -> vec3f {
|
|
|
255
264
|
// A rig that carries both eyes on one bone: each vertex follows its own side.
|
|
256
265
|
if (j[2].w == j[3].w && e == 0u && distance(p.xy, j[1].xy) < distance(p.xy, j[0].xy)) { continue; }
|
|
257
266
|
if (j[2].w == j[3].w && e == 1u && distance(p.xy, j[0].xy) <= distance(p.xy, j[1].xy)) { continue; }
|
|
258
|
-
let
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
//
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
267
|
+
let t = j[4u + e];
|
|
268
|
+
let m = j[6u + e];
|
|
269
|
+
let h = j[10u + e];
|
|
270
|
+
var q = _rzJellyTurn((p.xy - c.xy) * t.xy, t.z) + m.xy;
|
|
271
|
+
// Forward is −Z (MMD faces −Z).
|
|
272
|
+
var push = h.z;
|
|
273
|
+
if (hl) {
|
|
274
|
+
// Sliding over the iris's dome on its own, a highlight sheet a hair in
|
|
275
|
+
// front of it would sink into it where the dome bulges more and the two
|
|
276
|
+
// fight for depth; so it comes forward by as far as it slid — a slope of
|
|
277
|
+
// one, steeper than the dome anywhere it draws.
|
|
278
|
+
let before = q;
|
|
279
|
+
q = _rzJellyTurn(q * h.xy, t.w) + m.zw;
|
|
280
|
+
push += length(q - before);
|
|
281
|
+
}
|
|
282
|
+
var moved = vec3f(c.xy + q, p.z - push);
|
|
283
|
+
let roll = j[8u + e];
|
|
284
|
+
if (roll.w != 0.0) {
|
|
285
|
+
let d = moved - roll.xyz;
|
|
286
|
+
let rd = _rzJellyTurn(d.yz, roll.w);
|
|
287
|
+
moved = roll.xyz + vec3f(d.x, rd.x, rd.y);
|
|
288
|
+
}
|
|
289
|
+
out = mix(p, moved, w);
|
|
266
290
|
}
|
|
267
291
|
return out;
|
|
268
292
|
}
|
|
269
293
|
|
|
270
|
-
/**
|
|
271
|
-
* The glints' frame for an eye fragment: its place in the iris in iris radii,
|
|
272
|
-
* from the bind-space position, which the jelly moved the iris with — so the
|
|
273
|
-
* glints ride the sloshing iris. Strength 0 gives w 0, which turns them off.
|
|
274
|
-
*/
|
|
275
|
-
fn rzJellyEye(rp: vec3f) -> RzJelly {
|
|
276
|
-
let j = objectLight.jelly;
|
|
277
|
-
let qL = (rp.xy - j[0].xy) / max(j[2].xy, vec2f(1e-4));
|
|
278
|
-
let qR = (rp.xy - j[1].xy) / max(j[3].xy, vec2f(1e-4));
|
|
279
|
-
let right = dot(qR, qR) < dot(qL, qL);
|
|
280
|
-
let a = select(qL, qR, right);
|
|
281
|
-
let st = select(j[4], j[5], right);
|
|
282
|
-
let w = (1.0 - smoothstep(0.85, 1.0, length(a))) * select(0.0, 1.0, j[0].w > 0.0);
|
|
283
|
-
return RzJelly(a, w, select(j[2].z, j[3].z, right), st.w);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* The jelly shine, added after the graph: two hard glints where the light
|
|
288
|
-
* would catch a bead — placed by the half vector in the head's frame, so they
|
|
289
|
-
* hold still while the iris turns under them — and the eye brightening while
|
|
290
|
-
* it wobbles. Flat, cel discs rather than a gradient lobe; HDR, so bloom
|
|
291
|
-
* takes them. Shut eyes catch nothing.
|
|
292
|
-
*/
|
|
293
|
-
fn rzJellyGlow(jj: RzJelly, tex: vec3f, alpha: f32, v: vec3f, l: vec3f, sun: vec3f, shadow: f32) -> vec3f {
|
|
294
|
-
let strength = objectLight.jelly[0].w;
|
|
295
|
-
var right = vec3f(1.0, 0.0, 0.0);
|
|
296
|
-
var up = vec3f(0.0, 1.0, 0.0);
|
|
297
|
-
var fwd = vec3f(0.0, 0.0, -1.0);
|
|
298
|
-
if (material.headBoneIndex >= 0.0) {
|
|
299
|
-
let hm = skinMats[u32(material.headBoneIndex)];
|
|
300
|
-
right = normalize(hm[0].xyz);
|
|
301
|
-
up = normalize(hm[1].xyz);
|
|
302
|
-
fwd = -normalize(hm[2].xyz);
|
|
303
|
-
}
|
|
304
|
-
let h = normalize(l + v);
|
|
305
|
-
// Held in the middle and lower iris: the top of an iris sits under the upper
|
|
306
|
-
// lid, and a glint there — or its bloom halo — pokes out over it.
|
|
307
|
-
var g = vec2f(dot(h, right), dot(h, up)) * 0.6;
|
|
308
|
-
g = g * min(1.0, 0.25 / max(length(g), 1e-6)) - vec2f(0.0, 0.1);
|
|
309
|
-
g.y = min(g.y, 0.0);
|
|
310
|
-
let aa = max(length(fwidth(jj.src)), 1e-4);
|
|
311
|
-
let glint = 1.0 - smoothstep(0.16 - aa, 0.16 + aa, distance(jj.src, g));
|
|
312
|
-
let second = 1.0 - smoothstep(0.07 - aa, 0.07 + aa, distance(jj.src, -0.55 * g + vec2f(0.1, -0.12)));
|
|
313
|
-
let facing = saturate(dot(fwd, v) * 2.0);
|
|
314
|
-
let key = clamp(dot(sun, vec3f(0.2126, 0.7152, 0.0722)), 0.3, 2.0);
|
|
315
|
-
let lit = facing * key * (0.35 + 0.65 * shadow);
|
|
316
|
-
// HDR, well past 1, so bloom takes them as the hard sparkle of a gem.
|
|
317
|
-
// Bright enough for bloom to catch, not so bright its halo spreads past the
|
|
318
|
-
// iris onto the lid.
|
|
319
|
-
let glints = (glint + 0.8 * second) * lit * (1.8 + 0.8 * jj.shine);
|
|
320
|
-
// Gone as the lid starts down, not only once shut: a half-closed smile puts
|
|
321
|
-
// the lid right over where the glint sits.
|
|
322
|
-
let open = 1.0 - smoothstep(0.1, 0.45, jj.closure);
|
|
323
|
-
// Only where the eye's own picture is (its alpha), never on the iris's top
|
|
324
|
-
// rim, and gone as the lid comes down.
|
|
325
|
-
let solid = smoothstep(0.5, 0.9, alpha);
|
|
326
|
-
let onEye = solid * (1.0 - smoothstep(0.05, 0.35, jj.src.y));
|
|
327
|
-
// Light through the jelly: the light enters where the glint is and comes out
|
|
328
|
-
// the far side, so the iris glows in its own colour in a crescent opposite
|
|
329
|
-
// the glint — the lit-from-within look of a gem, or a jelly.
|
|
330
|
-
let r = length(jj.src);
|
|
331
|
-
let away = -normalize(g + vec2f(0.0, -1e-3));
|
|
332
|
-
let crescent = smoothstep(0.15, 0.7, dot(jj.src, away)) * (1.0 - smoothstep(0.8, 1.0, r));
|
|
333
|
-
let through = tex * crescent * (2.2 + 1.0 * jj.shine) * lit;
|
|
334
|
-
// And the colour runs deeper: the iris's own hue pushed, never its greys.
|
|
335
|
-
let lum = dot(tex, vec3f(0.2126, 0.7152, 0.0722));
|
|
336
|
-
let vivid = max(tex - vec3f(lum), vec3f(0.0)) * 1.2;
|
|
337
|
-
// The glass over it: a broad soft sheen across the upper iris, under the
|
|
338
|
-
// lid line, the dome of a bead catching the room.
|
|
339
|
-
let dome = (1.0 - smoothstep(0.0, 0.5, distance(jj.src * vec2f(0.8, 1.4), vec2f(0.0, 0.2)))) * 0.45 * lit;
|
|
340
|
-
// The glints keep off the iris's top; the soft light (sheen, glow through,
|
|
341
|
-
// colour) has no halo to spill, so it only needs the eye's own picture.
|
|
342
|
-
let gem = (vec3f(glints) * onEye + (vec3f(dome) + through + vivid) * solid) * open * jj.w;
|
|
343
|
-
// The whole eye shines a little brighter, more while it wobbles — not just
|
|
344
|
-
// the iris, so this one is not held to it (jj.w).
|
|
345
|
-
let lift = tex * (0.25 + 0.35 * jj.shine) * select(0.0, 1.0, strength > 0.0);
|
|
346
|
-
return (gem + lift) * min(strength, 1.0);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
294
|
/** The light arriving at a surface of this object facing n: its own ambient
|
|
350
295
|
* where loaded data gave it one (a stage's probes, a character's), else the
|
|
351
296
|
* world's. The same polynomial rzWorldAmbient evaluates. */
|
package/package.json
CHANGED
package/src/engine.ts
CHANGED
|
@@ -8338,7 +8338,8 @@ export class Engine {
|
|
|
8338
8338
|
label: "main per-material bind group layout",
|
|
8339
8339
|
entries: [
|
|
8340
8340
|
{ binding: 0, visibility: GPUShaderStage.FRAGMENT, texture: {} },
|
|
8341
|
-
|
|
8341
|
+
// VERTEX too: jelly eyes tell a highlight layer by its materialId.
|
|
8342
|
+
{ binding: 1, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: { type: "uniform" } },
|
|
8342
8343
|
{ binding: 2, visibility: GPUShaderStage.FRAGMENT, texture: {} },
|
|
8343
8344
|
{ binding: 3, visibility: GPUShaderStage.FRAGMENT, texture: {} },
|
|
8344
8345
|
// StyleUniforms for compiled graph shaders (adjust-tier sliders). Hand-written
|
|
@@ -13797,9 +13798,8 @@ export class Engine {
|
|
|
13797
13798
|
|
|
13798
13799
|
/**
|
|
13799
13800
|
* Jelly eyes: her irises shrink and spring back as her lids move, swell as her
|
|
13800
|
-
* head turns or moves, and wobble back
|
|
13801
|
-
*
|
|
13802
|
-
* PMX and under any eye graph. Null stills them again.
|
|
13801
|
+
* head turns or moves, and wobble back. MMD's 果冻眼, on any PMX and under
|
|
13802
|
+
* any eye graph. Null stills them again.
|
|
13803
13803
|
*
|
|
13804
13804
|
* Driven by her closing morphs (まばたき, the winks) and her head bone, never
|
|
13805
13805
|
* her eyes' own turn, so eye tracking following the camera leaves it still.
|
|
@@ -13902,7 +13902,7 @@ export class Engine {
|
|
|
13902
13902
|
if (inst.jellyEyes) {
|
|
13903
13903
|
inst.jellyEyes.step(deltaTime, inst.model)
|
|
13904
13904
|
inst.jellyEyes.write(inst.objectLight)
|
|
13905
|
-
this.device.queue.writeBuffer(inst.lightBuffer, 48 * 4, inst.objectLight, 48,
|
|
13905
|
+
this.device.queue.writeBuffer(inst.lightBuffer, 48 * 4, inst.objectLight, 48, 48)
|
|
13906
13906
|
}
|
|
13907
13907
|
animMs += performance.now() - tAnim
|
|
13908
13908
|
// Material morphs ride the same weight change as vertex morphs but land in
|
|
@@ -15210,7 +15210,7 @@ export class Engine {
|
|
|
15210
15210
|
// the cast on the character layer as well as the default one. Words:
|
|
15211
15211
|
// layers [0..3], ambient flag [4..7], SH [8..43], fill [44..47], jelly
|
|
15212
15212
|
// eyes [48..71] — see materials/common.ts.
|
|
15213
|
-
const objectLight = new Float32Array(
|
|
15213
|
+
const objectLight = new Float32Array(96)
|
|
15214
15214
|
new Uint32Array(objectLight.buffer)[0] =
|
|
15215
15215
|
isStage || isPlane || isProp ? RENDERING_LAYER_DEFAULT : (RENDERING_LAYER_DEFAULT | RENDERING_LAYER_CHARACTER) >>> 0
|
|
15216
15216
|
const lightBuffer = this.device.createBuffer({
|
package/src/graph/slots.ts
CHANGED
|
@@ -57,15 +57,8 @@ const EYE_REAR_GATE = `
|
|
|
57
57
|
}
|
|
58
58
|
`
|
|
59
59
|
|
|
60
|
-
// Eye's jelly (Engine.setModelJellyEyes): the vertex shader moves the iris
|
|
61
|
-
// itself; the fragment only adds the glints, computed once the lighting context
|
|
62
|
-
// exists and added in the epilogue after the graph. Off, they are zero.
|
|
63
60
|
const PLAIN_SAMPLE = ` let tex_s = textureSample(diffuseTexture, diffuseSampler, input.uv);
|
|
64
61
|
`
|
|
65
|
-
const EYE_JELLY_SAMPLE = ` let rz_jelly = rzJellyEye(input.restPos);
|
|
66
|
-
${PLAIN_SAMPLE}`
|
|
67
|
-
const EYE_JELLY_GLOW = ` let rz_jelly_glow = rzJellyGlow(rz_jelly, tex_color, tex_s.a, v, l, sun, shadow);
|
|
68
|
-
`
|
|
69
62
|
|
|
70
63
|
// ── Adjust-tier uniforms — fixed 16-vec4f block (256 B) shared by the single material
|
|
71
64
|
// bind group layout; non-graph draws bind a zero buffer. ──
|
|
@@ -114,7 +107,7 @@ function prelude(renderClass: RenderClass, alphaMode: AlphaMode, blend: StyleBle
|
|
|
114
107
|
const flip =
|
|
115
108
|
renderClass === "eye" ? "" : "\n n = select(-n, n, dot(n, v) >= 0.0);"
|
|
116
109
|
return `@fragment fn fs(input: VertexOutput) -> FSOut {
|
|
117
|
-
${
|
|
110
|
+
${PLAIN_SAMPLE} // MMD alpha semantics: material alpha × texture alpha.
|
|
118
111
|
let alpha = material.alpha * tex_s.a;
|
|
119
112
|
${discard}
|
|
120
113
|
|
|
@@ -161,7 +154,6 @@ ${gate}
|
|
|
161
154
|
// The normal the lamps' diffuse layer is lit by, for a principled walk to
|
|
162
155
|
// compute it on the way (rzLightsDiffuseOnce). n is final from here on.
|
|
163
156
|
_rzLampN = n;
|
|
164
|
-
${renderClass === "eye" ? EYE_JELLY_GLOW : ""}
|
|
165
157
|
`
|
|
166
158
|
}
|
|
167
159
|
|
|
@@ -214,7 +206,7 @@ function epilogue(renderClass: RenderClass, alphaMode: AlphaMode, hasOpacity: bo
|
|
|
214
206
|
// it is emission, not a surface colour, so nothing may ramp or shadow it. Zero
|
|
215
207
|
// on every fragment of every material that is not dissolving, which is what
|
|
216
208
|
// keeps this out of the way of a scene that never uses it.
|
|
217
|
-
const BURN = ` + RZ_BURN_COLOR * rz_burn
|
|
209
|
+
const BURN = ` + RZ_BURN_COLOR * rz_burn`
|
|
218
210
|
// The scene fog, last, as the game lays it over a lit surface; an
|
|
219
211
|
// emission-only graph takes none (the game's effect shaders have no fog).
|
|
220
212
|
// A premultiplied colour takes its fog premultiplied too: the haze a pane
|