reze-engine 0.68.6 → 0.68.8

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.
@@ -216,36 +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, scale bounce (both eyes)
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 squash, 0, clock, shine [5] the right's
223
- struct ObjectLight { layers: vec4u, ambient: vec4f, sh: array<vec4f, 9>, fill: vec4f, jelly: array<vec4f, 6> }
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
- /** What the glints need to know about a fragment of the eye render class. */
227
- struct RzJelly {
228
- /** Where in the iris this fragment is, in iris radii. */
229
- src: vec2f,
230
- /** 1 inside the iris, easing to 0 at its rim (0 everywhere when off). */
231
- w: f32,
232
- closure: f32,
233
- shine: f32,
234
- /** Scene seconds (wrapped), for the twinkles. */
235
- clock: f32,
236
- };
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
+ }
237
239
 
238
240
  /**
239
241
  * Where the jelly puts an iris vertex. The iris is the part of the eye the eye
240
242
  * bones carry, so it is moved as a whole, in bind space before skinning:
241
- * shrunk about its centre while a lid moves, a little more down than across,
242
- * grown past rest as it springs back, and swelling as a turn or her motion
243
- * knocks it — scale only, in place, inside the white, which stays where it is. Vertices take it by
244
- * their weight on the eye bones (jelly[2].w, jelly[3].w), so nothing else on
245
- * the face moves.
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.
246
250
  */
247
251
  fn rzJellyVertex(p: vec3f, joints: vec4<u32>, nw: vec4f) -> vec3f {
248
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));
249
256
  var out = p;
250
257
  for (var e = 0u; e < 2u; e++) {
251
258
  let bone = j[2u + e].w;
@@ -257,134 +264,33 @@ fn rzJellyVertex(p: vec3f, joints: vec4<u32>, nw: vec4f) -> vec3f {
257
264
  // A rig that carries both eyes on one bone: each vertex follows its own side.
258
265
  if (j[2].w == j[3].w && e == 0u && distance(p.xy, j[1].xy) < distance(p.xy, j[0].xy)) { continue; }
259
266
  if (j[2].w == j[3].w && e == 1u && distance(p.xy, j[0].xy) <= distance(p.xy, j[1].xy)) { continue; }
260
- let st = j[4u + e];
261
- // The squash, nearly round: it shrinks both ways, a little more down than
262
- // across, so the iris keeps its circle and only leans oval; and the bounce
263
- // both eyes share (jelly[1].w). Held under 1.08 so a swell cannot rise
264
- // past the upper lid.
265
- let k = clamp(vec2f(1.0 - 0.8 * st.x, 1.0 - st.x) + j[1].w, vec2f(0.78, 0.75), vec2f(1.08, 1.08));
266
- let moved = c.xy + (p.xy - c.xy) * k;
267
- out = vec3f(mix(p.xy, moved, w), p.z);
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);
268
290
  }
269
291
  return out;
270
292
  }
271
293
 
272
- /**
273
- * The glints' frame for an eye fragment: its place in the iris in iris radii,
274
- * from the bind-space position, which the jelly moved the iris with — so the
275
- * glints ride the sloshing iris. Strength 0 gives w 0, which turns them off.
276
- */
277
- fn rzJellyEye(rp: vec3f) -> RzJelly {
278
- let j = objectLight.jelly;
279
- let qL = (rp.xy - j[0].xy) / max(j[2].xy, vec2f(1e-4));
280
- let qR = (rp.xy - j[1].xy) / max(j[3].xy, vec2f(1e-4));
281
- let right = dot(qR, qR) < dot(qL, qL);
282
- let a = select(qL, qR, right);
283
- let st = select(j[4], j[5], right);
284
- let w = (1.0 - smoothstep(0.85, 1.0, length(a))) * select(0.0, 1.0, j[0].w > 0.0);
285
- return RzJelly(a, w, select(j[2].z, j[3].z, right), st.w, j[4].z);
286
- }
287
-
288
- /**
289
- * The jelly shine, added after the graph: two hard glints where the light
290
- * would catch a bead — placed by the half vector in the head's frame, so they
291
- * hold still while the iris turns under them — and the eye brightening while
292
- * it wobbles. Flat, cel discs rather than a gradient lobe; HDR, so bloom
293
- * takes them. Shut eyes catch nothing.
294
- */
295
- fn rzJellyGlow(jj: RzJelly, tex: vec3f, alpha: f32, v: vec3f, l: vec3f, sun: vec3f, shadow: f32) -> vec3f {
296
- let strength = objectLight.jelly[0].w;
297
- var right = vec3f(1.0, 0.0, 0.0);
298
- var up = vec3f(0.0, 1.0, 0.0);
299
- var fwd = vec3f(0.0, 0.0, -1.0);
300
- if (material.headBoneIndex >= 0.0) {
301
- let hm = skinMats[u32(material.headBoneIndex)];
302
- right = normalize(hm[0].xyz);
303
- up = normalize(hm[1].xyz);
304
- fwd = -normalize(hm[2].xyz);
305
- }
306
- let h = normalize(l + v);
307
- // Held in the middle and lower iris: the top of an iris sits under the upper
308
- // lid, and a glint there — or its bloom halo — pokes out over it.
309
- var g = vec2f(dot(h, right), dot(h, up)) * 0.6;
310
- g = g * min(1.0, 0.25 / max(length(g), 1e-6)) - vec2f(0.0, 0.1);
311
- g.y = min(g.y, 0.0);
312
- let aa = max(length(fwidth(jj.src)), 1e-4);
313
- // A star, not only a disc: the disc with two thin rays through it, the
314
- // anime sparkle.
315
- let dg = jj.src - g;
316
- let rays = max(0.0, 1.0 - abs(dg.y) / 0.018) * (1.0 - smoothstep(0.0, 0.34, abs(dg.x)))
317
- + max(0.0, 1.0 - abs(dg.x) / 0.018) * (1.0 - smoothstep(0.0, 0.26, abs(dg.y)));
318
- let glint = max(1.0 - smoothstep(0.13 - aa, 0.13 + aa, length(dg)), rays * 0.8);
319
- let second = 1.0 - smoothstep(0.07 - aa, 0.07 + aa, distance(jj.src, -0.55 * g + vec2f(0.1, -0.12)));
320
- let facing = saturate(dot(fwd, v) * 2.0);
321
- let key = clamp(dot(sun, vec3f(0.2126, 0.7152, 0.0722)), 0.3, 2.0);
322
- let lit = facing * key * (0.35 + 0.65 * shadow);
323
- // HDR, well past 1, so bloom takes them as the hard sparkle of a gem.
324
- // Bright enough for bloom to catch, not so bright its halo spreads past the
325
- // iris onto the lid.
326
- let glints = (glint + 0.8 * second) * lit * (1.8 + 0.8 * jj.shine);
327
- // Gone as the lid starts down, not only once shut: a half-closed smile puts
328
- // the lid right over where the glint sits.
329
- let open = 1.0 - smoothstep(0.1, 0.45, jj.closure);
330
- // Only where the eye's own picture is (its alpha), never on the iris's top
331
- // rim, and gone as the lid comes down.
332
- let solid = smoothstep(0.5, 0.9, alpha);
333
- let onEye = solid * (1.0 - smoothstep(0.05, 0.35, jj.src.y));
334
- // Light through the jelly: the light enters where the glint is and comes out
335
- // the far side, so the iris glows in its own colour in a crescent opposite
336
- // the glint — the lit-from-within look of a gem, or a jelly.
337
- let r = length(jj.src);
338
- // Out the LOWER iris, always — the anime gem's bright underside — leaning
339
- // away from the glint; never up, where its bloom would spill on the lid.
340
- let away = normalize(vec2f(-g.x * 0.6, -1.0));
341
- let crescent = smoothstep(0.15, 0.7, dot(jj.src, away)) * (1.0 - smoothstep(0.8, 1.0, r));
342
- let through = tex * crescent * (2.2 + 1.0 * jj.shine) * lit;
343
- // And the colour runs deeper: the iris's own hue pushed, never its greys.
344
- let lum = dot(tex, vec3f(0.2126, 0.7152, 0.0722));
345
- let vivid = max(tex - vec3f(lum), vec3f(0.0)) * 1.2;
346
- // The glass over it: a broad soft sheen across the upper iris, under the
347
- // lid line, the dome of a bead catching the room.
348
- 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;
349
- // Everything that blooms keeps to the lower iris, so no halo reaches the lid.
350
- let lower = 1.0 - smoothstep(-0.05, 0.3, jj.src.y);
351
- // The cut: soft facets fanning across the lower iris, light split as a cut
352
- // stone splits it, turning slowly.
353
- let ang = atan2(jj.src.y, jj.src.x);
354
- let facets = pow(0.5 + 0.5 * cos(ang * 7.0 + jj.clock * 0.35), 6.0)
355
- * smoothstep(0.3, 0.75, r) * (1.0 - smoothstep(0.82, 0.97, r)) * lower;
356
- // The rim: a band of its own colour just inside the iris edge, HDR, which
357
- // bloom spreads into a glow around the stone.
358
- let rim = smoothstep(0.7, 0.84, r) * (1.0 - smoothstep(0.86, 0.97, r)) * lower;
359
- // Twinkles: three specks in the lower iris, each flashing now and then on
360
- // the scene clock.
361
- var twinkle = 0.0;
362
- for (var i = 0; i < 3; i++) {
363
- let fi = f32(i);
364
- let at = vec2f(0.42 * cos(3.6 + fi * 1.1), -0.25 - 0.18 * fi + 0.1 * sin(fi * 2.3));
365
- let flash = pow(max(0.0, sin(jj.clock * (1.3 + 0.37 * fi) + fi * 2.1)), 12.0);
366
- twinkle += (1.0 - smoothstep(0.0, 0.05 + aa, distance(jj.src, at))) * flash;
367
- }
368
- let sparkle = (vec3f(glints + twinkle * 2.0) * onEye
369
- + tex * facets * 2.5 * lit * solid * (1.0 + 0.6 * jj.shine));
370
- // The soft light (sheen, glow through, colour) needs only the eye's picture.
371
- let gem = (sparkle + (vec3f(dome) + through + vivid) * solid) * open * jj.w;
372
- // The edge, which jj.w (fading out from 0.85) would hide: the glowing rim
373
- // band, and a thin glossy line right at the border — light running round
374
- // the stone's edge — all the way round, bright below and dim above, where a
375
- // halo would reach the lid. Up to the mesh's edge and no further.
376
- let on = select(0.0, 1.0, strength > 0.0) * (1.0 - smoothstep(1.0 - aa, 1.0, r));
377
- let edgeLine = smoothstep(0.92, 0.955, r) * (1.0 - smoothstep(0.965, 0.995, r));
378
- let edgeLit = mix(0.3, 1.0, lower) * lit * (1.0 + 0.6 * jj.shine);
379
- let edge = (tex * rim * 2.0 + vec3f(rim * 0.25)) * lit * (1.0 + 0.6 * jj.shine)
380
- + (vec3f(0.55) + tex * 0.8) * edgeLine * edgeLit;
381
- let border = edge * solid * open * on;
382
- // The whole eye shines a little brighter, more while it wobbles — not just
383
- // the iris, so this one is not held to it (jj.w).
384
- let lift = tex * (0.25 + 0.35 * jj.shine) * select(0.0, 1.0, strength > 0.0);
385
- return (gem + border + lift) * min(strength, 1.0);
386
- }
387
-
388
294
  /** The light arriving at a surface of this object facing n: its own ambient
389
295
  * where loaded data gave it one (a stage's probes, a character's), else the
390
296
  * world's. The same polynomial rzWorldAmbient evaluates. */
@@ -1 +1 @@
1
- {"version":3,"file":"outline.d.ts","sourceRoot":"","sources":["../../../src/shaders/passes/outline.ts"],"names":[],"mappings":"AAqBA;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,KAAK,CAAA;AAC5C;yCACyC;AACzC,eAAO,MAAM,uBAAuB,KAAK,CAAA;AACzC;mEACmE;AACnE,eAAO,MAAM,uBAAuB,KAAK,CAAA;AACzC;;yCAEyC;AACzC,eAAO,MAAM,0BAA0B,KAAK,CAAA;AAC5C,eAAO,MAAM,wBAAwB,KAAK,CAAA;AAC1C,uCAAuC;AACvC,eAAO,MAAM,yBAAyB,KAAK,CAAA;AAE3C,wBAAgB,iBAAiB,IAAI,MAAM,CAgP1C"}
1
+ {"version":3,"file":"outline.d.ts","sourceRoot":"","sources":["../../../src/shaders/passes/outline.ts"],"names":[],"mappings":"AAqBA;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,KAAK,CAAA;AAC5C;yCACyC;AACzC,eAAO,MAAM,uBAAuB,KAAK,CAAA;AACzC;mEACmE;AACnE,eAAO,MAAM,uBAAuB,KAAK,CAAA;AACzC;;yCAEyC;AACzC,eAAO,MAAM,0BAA0B,KAAK,CAAA;AAC5C,eAAO,MAAM,wBAAwB,KAAK,CAAA;AAC1C,uCAAuC;AACvC,eAAO,MAAM,yBAAyB,KAAK,CAAA;AAE3C,wBAAgB,iBAAiB,IAAI,MAAM,CA2P1C"}
@@ -193,12 +193,22 @@ fn safe_normal2(v: vec2f) -> vec2f {
193
193
  let w = max(clipPos.w, 1e-4);
194
194
  var ndc: vec2f;
195
195
  var coverage = 1.0;
196
+ // The scene's width dial splits around 1×. Above it, it widens the line
197
+ // before the minimum, as it always has. Below it, it thins the line AFTER
198
+ // the minimum: a line held at the minimum is drawn that wide and faded, and
199
+ // it still writes depth across all of it — so a dial at 0.1× or at 0.0001×
200
+ // left the same 1.5 px ring for whatever drew or read depth after it, and
201
+ // the dial did nothing visible. Thinned past the minimum instead, the hull
202
+ // is genuinely sub-pixel, the multisampling covers only what it covers, and
203
+ // the line fades with the dial and claims depth only where it is.
204
+ let widen = max(material.widthScale, 1.0);
205
+ let thin = min(material.widthScale, 1.0);
196
206
  if (material.textured > 0.5) {
197
207
  // The game's: a view-space offset of edgeSize world units along the view
198
208
  // normal, projected, then each axis held between 1.2 px and 1.2 px ×
199
209
  // (1 + _OutlineMaxOffsetMultiplier, 1.5) of a 1920-wide frame; a line the
200
210
  // minimum had to push fades by how far it was pushed.
201
- let off = viewNormal.xy * material.edgeSize * material.widthScale * outlineNormal.w;
211
+ let off = viewNormal.xy * material.edgeSize * widen * outlineNormal.w;
202
212
  let d1 = vec2f(off.x * camera.projection[0][0], off.y * camera.projection[1][1]) / w;
203
213
  // the minimum along the push direction (the game's dir · 2/screen · 1.2)
204
214
  let pxNdc = 2.0 / refViewport * 1.2 * safe_normal2(viewNormal.xy);
@@ -210,7 +220,7 @@ fn safe_normal2(v: vec2f) -> vec2f {
210
220
  ndc = o * select(vec2f(1.0), sign(d1), abs(d1) > vec2f(0.0));
211
221
  } else {
212
222
  let breakDepth = RZ_OUTLINE_FULL_FIGURE * camera.projection[1][1];
213
- let nearNdc = viewNormal.xy * (material.edgeSize * material.widthScale * outlineNormal.w * 4.0 / refViewport);
223
+ let nearNdc = viewNormal.xy * (material.edgeSize * widen * outlineNormal.w * 4.0 / refViewport);
214
224
  ndc = nearNdc * (min(w, breakDepth) / w);
215
225
 
216
226
  // Antialiased minimum (the game's _OutlineAntialias): held at the minimum
@@ -224,6 +234,7 @@ fn safe_normal2(v: vec2f) -> vec2f {
224
234
  ndc = select(vec2f(0.0), ndc * (minPx / px), px > 1e-6);
225
235
  }
226
236
  }
237
+ ndc *= thin;
227
238
  output.normal = worldNormal;
228
239
  output.coverage = coverage;
229
240
  output.position = vec4f(clipPos.xy + ndc * w, clipPos.z, clipPos.w);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reze-engine",
3
- "version": "0.68.6",
3
+ "version": "0.68.8",
4
4
  "description": "A lightweight WebGPU engine for real-time 3D MMD/PMX model rendering",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
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
- { binding: 1, visibility: GPUShaderStage.FRAGMENT, buffer: { type: "uniform" } },
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, and shine like a gem — two hard
13801
- * glints, light glowing through the iris, deeper colour. MMD's 果冻眼, on any
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, 24)
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(72)
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({
@@ -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
- ${renderClass === "eye" ? EYE_JELLY_SAMPLE : PLAIN_SAMPLE} // MMD alpha semantics: material alpha × texture alpha.
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${renderClass === "eye" ? " + rz_jelly_glow" : ""}`
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