@driftengine/core 4.13.6 → 4.14.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 (91) hide show
  1. package/CHANGELOG.json +51 -0
  2. package/README.md +1 -1
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.js +1 -0
  5. package/dist/render/backend/api.d.ts +19 -3
  6. package/dist/render/backend/webgl2/motionTarget.d.ts +39 -0
  7. package/dist/render/backend/webgl2/motionTarget.js +254 -0
  8. package/dist/render/backend/webgl2/pointSkinFeedback.d.ts +13 -3
  9. package/dist/render/backend/webgl2/pointSkinFeedback.js +45 -12
  10. package/dist/render/backend/webgl2/renderer.d.ts +101 -7
  11. package/dist/render/backend/webgl2/renderer.js +337 -9
  12. package/dist/render/backend/webgpu/pointSkinPass.d.ts +16 -3
  13. package/dist/render/backend/webgpu/pointSkinPass.js +79 -21
  14. package/dist/render/backend/webgpu/postPass.d.ts +6 -1
  15. package/dist/render/backend/webgpu/renderer.d.ts +41 -0
  16. package/dist/render/backend/webgpu/renderer.js +143 -5
  17. package/dist/render/baseDecals.d.ts +48 -0
  18. package/dist/render/baseDecals.js +71 -0
  19. package/dist/render/emissiveFlow.d.ts +40 -0
  20. package/dist/render/emissiveFlow.js +51 -0
  21. package/dist/render/fixtureAtlas.d.ts +8 -3
  22. package/dist/render/fixtureAtlas.js +17 -6
  23. package/dist/render/globalMedium.d.ts +17 -0
  24. package/dist/render/globalMedium.js +14 -0
  25. package/dist/render/globalMediumPass.js +3 -2
  26. package/dist/render/iridescentOverlay.d.ts +78 -0
  27. package/dist/render/iridescentOverlay.js +102 -0
  28. package/dist/render/mesh.d.ts +24 -0
  29. package/dist/render/mesh.js +79 -0
  30. package/dist/render/pointSkin.d.ts +18 -0
  31. package/dist/render/pointSkin.js +50 -5
  32. package/dist/render/recon/mover.d.ts +3 -2
  33. package/dist/render/recon/mover.js +3 -2
  34. package/dist/render/sceneTarget.d.ts +2 -0
  35. package/dist/render/sceneTarget.js +1 -1
  36. package/dist/render/shaders/flat/baseDecals.d.ts +17 -0
  37. package/dist/render/shaders/flat/baseDecals.js +71 -0
  38. package/dist/render/shaders/flat/emissiveFlow.d.ts +15 -0
  39. package/dist/render/shaders/flat/emissiveFlow.js +45 -0
  40. package/dist/render/shaders/flat/glassTint.d.ts +1 -1
  41. package/dist/render/shaders/flat/glassTint.js +3 -0
  42. package/dist/render/shaders/flat/index.d.ts +16 -0
  43. package/dist/render/shaders/flat/index.js +9 -0
  44. package/dist/render/shaders/flat/iridescentOverlay.d.ts +15 -0
  45. package/dist/render/shaders/flat/iridescentOverlay.js +65 -0
  46. package/dist/render/shaders/flat/layered.js +4 -4
  47. package/dist/render/shaders/flat/main.d.ts +1 -1
  48. package/dist/render/shaders/flat/main.js +12 -1
  49. package/dist/render/shaders/flat/mapReads.d.ts +1 -1
  50. package/dist/render/shaders/flat/mapReads.js +7 -3
  51. package/dist/render/shaders/flat/worldUv.js +6 -5
  52. package/dist/render/shaders/generated/flat.wgsl.d.ts +480 -16
  53. package/dist/render/shaders/generated/flat.wgsl.js +519 -55
  54. package/dist/render/shaders/generated/temporalResolve.wgsl.d.ts +15 -5
  55. package/dist/render/shaders/generated/temporalResolve.wgsl.js +15 -5
  56. package/dist/render/shaders/temporalResolve.js +25 -9
  57. package/dist/render/surfaceTexture.d.ts +32 -0
  58. package/dist/render/temporalPass.d.ts +3 -1
  59. package/dist/render/temporalPass.js +9 -1
  60. package/package.json +6 -6
  61. package/src/index.ts +3 -0
  62. package/src/render/backend/api.ts +19 -2
  63. package/src/render/backend/webgl2/motionTarget.ts +299 -0
  64. package/src/render/backend/webgl2/pointSkinFeedback.ts +49 -14
  65. package/src/render/backend/webgl2/renderer.ts +411 -9
  66. package/src/render/backend/webgpu/pointSkinPass.ts +90 -23
  67. package/src/render/backend/webgpu/renderer.ts +163 -3
  68. package/src/render/baseDecals.ts +93 -0
  69. package/src/render/emissiveFlow.ts +66 -0
  70. package/src/render/fixtureAtlas.ts +26 -7
  71. package/src/render/globalMedium.ts +31 -0
  72. package/src/render/globalMediumPass.ts +3 -7
  73. package/src/render/iridescentOverlay.ts +177 -0
  74. package/src/render/mesh.ts +82 -0
  75. package/src/render/pointSkin.ts +64 -5
  76. package/src/render/recon/mover.ts +3 -2
  77. package/src/render/sceneTarget.ts +3 -0
  78. package/src/render/shaders/flat/baseDecals.ts +71 -0
  79. package/src/render/shaders/flat/emissiveFlow.ts +45 -0
  80. package/src/render/shaders/flat/glassTint.ts +7 -1
  81. package/src/render/shaders/flat/index.ts +25 -0
  82. package/src/render/shaders/flat/iridescentOverlay.ts +65 -0
  83. package/src/render/shaders/flat/layered.ts +4 -4
  84. package/src/render/shaders/flat/main.ts +12 -1
  85. package/src/render/shaders/flat/mapReads.ts +7 -3
  86. package/src/render/shaders/flat/worldUv.ts +6 -5
  87. package/src/render/shaders/generated/flat.wgsl.ts +519 -55
  88. package/src/render/shaders/generated/temporalResolve.wgsl.ts +15 -5
  89. package/src/render/shaders/temporalResolve.ts +25 -9
  90. package/src/render/surfaceTexture.ts +32 -0
  91. package/src/render/temporalPass.ts +8 -0
@@ -0,0 +1,65 @@
1
+ /**
2
+ * A surface's iridescent overlay on its base colour, before it is lit:
3
+ * `SurfaceMaterial.iridescentOverlay`, packed into `uIridescence` by `iridescentOverlay.ts`, whose
4
+ * `iridescentBase` is this arithmetic on the CPU and says what each term is and what it gives up.
5
+ *
6
+ * **Called once the normal is mapped and turned to the viewer**, so the view term reads the surface
7
+ * a pixel shows, and before any light is added, so the lights below read the colour it makes. The
8
+ * mask is read in uniform control flow, under the lighting branch and this switch's, so its implicit
9
+ * level is legal: AGENTS.md 2026-08-07.
10
+ *
11
+ * **A lit switch, `IRIDESCENT_OVERLAY`**, off until a material first asks, declared after
12
+ * `EMISSIVE_FLOW` so each switch before it keeps its id. Compiled out, its thirty-six vectors are
13
+ * not declared and the call is a constant.
14
+ */
15
+ export function iridescentOverlayGlsl(on: boolean): string {
16
+ if (!on) {
17
+ return /* glsl */ `
18
+ const bool IRIDESCENT_OVERLAY = false; // wgsl:override
19
+ bool iridescent() { return false; }
20
+ vec3 iridescentBase(vec3 base, vec3 n, vec2 uv) { return base; }
21
+ `;
22
+ }
23
+ return /* glsl */ `
24
+ /* Whether this program lays an iridescent overlay. Off but where a material has asked. */
25
+ const bool IRIDESCENT_OVERLAY = true; // wgsl:override
26
+ /*
27
+ * Thirty-six vectors, as iridescentOverlay.ts packs them: the direction toward the sheen and the
28
+ * blend (0); the contrast, the tiling, the weight and 1 for on (1); the mask's array, 0 none, 1 ORM,
29
+ * 2 model, 3 albedo, 4 emissive, its layer and its channel (2); what takes the material's
30
+ * coordinates back to the mesh's own (3); then the ramp, thirty-two colours.
31
+ */
32
+ uniform vec4 uIridescence[36]; // wgsl:material
33
+
34
+ bool iridescent() { return uIridescence[1].w > 0.5; }
35
+
36
+ /* The mask's channel at the material's coordinates; 1 where it names no array. */
37
+ float iridescentMask(vec2 uv) {
38
+ float source = uIridescence[2].x;
39
+ if (source < 0.5) return 1.0;
40
+ vec3 at = vec3(uv, uIridescence[2].y);
41
+ vec4 texel = source < 1.5 ? texture(uOrmMap, at)
42
+ : source < 2.5 ? texture(uModelMap, at)
43
+ : source < 3.5 ? texture(uAlbedo, at)
44
+ : texture(uEmissiveMap, at);
45
+ return texel[int(uIridescence[2].z + 0.5)];
46
+ }
47
+
48
+ vec3 iridescentBase(vec3 base, vec3 n, vec2 uv) {
49
+ vec3 toEye = normalize(uCameraPos - vWorldPos);
50
+ vec3 halfway = toEye + uIridescence[0].xyz;
51
+ float span = length(halfway);
52
+ float nh = span > 0.0 ? dot(n, halfway / span) : 0.0;
53
+ float sheen = nh > 0.0 ? clamp(pow(nh, uIridescence[1].x), 0.0, 1.0) : 0.0;
54
+ float nv = dot(n, toEye);
55
+ vec2 own = vUv.xy * uIridescence[3].xy + uIridescence[3].zw;
56
+ float x = nv + own.x + uIridescence[0].w * (sheen - nv);
57
+ float t = clamp(fract(x * uIridescence[1].y), 0.0, 1.0);
58
+ float at = t * 31.0;
59
+ int below = min(int(floor(at)), 30);
60
+ vec3 o = mix(uIridescence[4 + below].rgb, uIridescence[5 + below].rgb, at - float(below));
61
+ vec3 blended = mix(2.0 * base * o, 1.0 - 2.0 * (1.0 - base) * (1.0 - o), step(0.5, base));
62
+ return base + (blended - base) * (x * iridescentMask(uv) * uIridescence[1].z);
63
+ }
64
+ `;
65
+ }
@@ -41,7 +41,7 @@ vec3 layeredTexel() { return vec3(0.0, 0.0, 1.0); }
41
41
  bool layeredMeshNormal() { return false; }
42
42
  vec3 layeredMeshTexel() { return vec3(0.0, 0.0, 1.0); }
43
43
  bool layeredGlows() { return false; }
44
- vec3 layeredEmissive() { return vec3(0.0); }
44
+ vec3 layeredEmissive(vec2 shift) { return vec3(0.0); }
45
45
  float layeredAmbient() { return 1.0; }
46
46
  float layeredSpecular(float own) { return own; }
47
47
  `;
@@ -254,10 +254,10 @@ bool layeredGlows() {
254
254
  return uLayers[1].z > -0.5;
255
255
  }
256
256
 
257
- /* The emissive map at its layer's place, glowing by that layer's share. */
258
- vec3 layeredEmissive() {
257
+ /* The emissive map at its layer's place, moved by its scroll, glowing by that layer's share. */
258
+ vec3 layeredEmissive(vec2 shift) {
259
259
  int glow = int(uLayers[1].z + 0.5);
260
- return texture(uEmissiveMap, layerAt(glow)).rgb * layerShare(glow);
260
+ return texture(uEmissiveMap, layerAt(glow) + vec3(shift, 0.0)).rgb * layerShare(glow);
261
261
  }
262
262
  `;
263
263
  }
@@ -399,6 +399,8 @@ export const MAIN_GLSL = `void main() {
399
399
  if (backFace) n = -n;
400
400
  /* A blending rim, on the base colour every light below reads: overlay.ts. */
401
401
  if (SURFACE_OVERLAY) albedo = overlayRimBase(albedo, surfaceAt.xy, n);
402
+ /* And a view-turned hue over it, before any light reads it: iridescentOverlay.ts. */
403
+ if (IRIDESCENT_OVERLAY && iridescent()) albedo = iridescentBase(albedo, n, surfaceAt.xy);
402
404
  /*
403
405
  * A model's surface, gathered once, on a branch on the switches alone (models.ts) — and whether
404
406
  * there is one, asked once: every site below is a branch on these two, which a pipeline with no
@@ -407,6 +409,13 @@ export const MAIN_GLSL = `void main() {
407
409
  bool modelled = modelOn();
408
410
  bool modelledBehind = modelSeesBehind();
409
411
  if (modelled) modelSurface(n, albedo, surfaceRoughness, metal, surfaceAt);
412
+ /*
413
+ * The frame's decals laid into the colour light falls on, by the geometric normal, after the
414
+ * model has made its own (baseDecals.ts). The colour a glow takes where the mesh names none is
415
+ * kept from before them: a decal marks what the surface is lit as and leaves what it emits.
416
+ */
417
+ vec3 glowBase = albedo;
418
+ if (BASE_DECALS) albedo = baseDecals(albedo, vWorldPos, normalize(vNormal));
410
419
  /*
411
420
  * Skin's colour half leaves here, with the colour its spread light is multiplied by, and a whole
412
421
  * alpha a multisampled edge resolves to its coverage. A branch on the switches alone, so uniform.
@@ -1988,7 +1997,7 @@ export const MAIN_GLSL = `void main() {
1988
1997
  lit += through * glassGlow * (thin * (1.0 - metal));
1989
1998
  }
1990
1999
  diffuseAlone = lit;
1991
- vec3 emissiveTint = vEmissiveColor.r < 0.0 ? albedo : vEmissiveColor;
2000
+ vec3 emissiveTint = vEmissiveColor.r < 0.0 ? glowBase : vEmissiveColor;
1992
2001
  /*
1993
2002
  * Where the surface glows, from an image, or everywhere if it binds none.
1994
2003
  *
@@ -2008,6 +2017,8 @@ export const MAIN_GLSL = `void main() {
2008
2017
  vec3 emissiveMapped = vec3(1.0);
2009
2018
  if (uMaterialFlags.z != 0) {
2010
2019
  emissiveMapped = emissiveTexel(surfaceAt) * uEmissiveScale;
2020
+ /* Held to where the mask keeps it, at the mesh's own coordinates: emissiveFlow.ts. */
2021
+ if (EMISSIVE_FLOW) emissiveMapped *= emissiveMask();
2011
2022
  }
2012
2023
  /* Pulse, flicker and fade from the layer's effects; exactly 1 where it names none. */
2013
2024
  float fxGlow = fx4.z + fx5.x + fx5.w > 0.0 ? fxEmission(surfaceAt.z) : 1.0;
@@ -30,9 +30,13 @@ vec3 ormTexel(vec3 at) {
30
30
  return texture(uOrmMap, at).rgb;
31
31
  }
32
32
 
33
+ /* The emissive map, moved by its scroll wherever it is read: emissiveFlow.ts. Behind its switch,
34
+ which a WebGPU pipeline built before a material asked has off, so the mask and the scroll come
35
+ on together rather than the scroll a few frames ahead. */
33
36
  vec3 emissiveTexel(vec3 at) {
34
- if (LAYERED && layered() && layeredGlows()) return layeredEmissive();
35
- if (WORLD_UVS && triplanar()) return triplanarEmissive(at.z);
36
- return texture(uEmissiveMap, at).rgb;
37
+ vec2 shift = EMISSIVE_FLOW ? emissiveShift() : vec2(0.0);
38
+ if (LAYERED && layered() && layeredGlows()) return layeredEmissive(shift);
39
+ if (WORLD_UVS && triplanar()) return triplanarEmissive(at.z, shift);
40
+ return texture(uEmissiveMap, vec3(at.xy + shift, at.z)).rgb;
37
41
  }
38
42
  `;
@@ -28,7 +28,7 @@ bool triplanar() { return false; }
28
28
  vec2 planarAt() { return vec2(0.0); }
29
29
  vec4 triplanarAlbedo(float layer) { return vec4(0.0); }
30
30
  vec3 triplanarOrm(float layer) { return vec3(0.0); }
31
- vec3 triplanarEmissive(float layer) { return vec3(0.0); }
31
+ vec3 triplanarEmissive(float layer, vec2 shift) { return vec3(0.0); }
32
32
  vec3 triplanarNormal(vec3 n, float layer) { return n; }
33
33
  `;
34
34
  }
@@ -76,12 +76,13 @@ vec3 triplanarOrm(float layer) {
76
76
  texture(uOrmMap, vec3(p.xz, layer)).rgb * w.y + texture(uOrmMap, vec3(p.xy, layer)).rgb * w.z;
77
77
  }
78
78
 
79
- vec3 triplanarEmissive(float layer) {
79
+ /* The emissive map on the three planes, each moved by the scroll: emissiveFlow.ts. */
80
+ vec3 triplanarEmissive(float layer, vec2 shift) {
80
81
  vec3 w = triplanarWeights();
81
82
  vec3 p = vWorldPos * uWorldUv.y;
82
- return texture(uEmissiveMap, vec3(p.zy, layer)).rgb * w.x +
83
- texture(uEmissiveMap, vec3(p.xz, layer)).rgb * w.y +
84
- texture(uEmissiveMap, vec3(p.xy, layer)).rgb * w.z;
83
+ return texture(uEmissiveMap, vec3(p.zy + shift, layer)).rgb * w.x +
84
+ texture(uEmissiveMap, vec3(p.xz + shift, layer)).rgb * w.y +
85
+ texture(uEmissiveMap, vec3(p.xy + shift, layer)).rgb * w.z;
85
86
  }
86
87
 
87
88
  /* A tangent-space normal off the map, its z rebuilt where a two-channel map stored none. */