rayzee 8.5.0 → 8.6.1

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 (64) hide show
  1. package/README.md +60 -56
  2. package/dist/{DLSSNeural-BNSJ8V3z.js → NeuralRetouch-CYOJ21Wn.js} +33 -33
  3. package/dist/{DLSSSuperRes-BoEW89Cl.js → NeuralSuperRes-Dc6jRYke.js} +25 -25
  4. package/dist/ToneMapGPU-BVE852iN.js +533 -0
  5. package/dist/rayzee.es.js +27235 -9074
  6. package/dist/rayzee.umd.js +255 -187
  7. package/package.json +1 -1
  8. package/src/AssetConfig.js +21 -7
  9. package/src/Color/BakedViews.js +134 -0
  10. package/src/Color/BuiltinViews.js +261 -0
  11. package/src/Color/ColorManagement.js +1130 -0
  12. package/src/Color/ColorSpaces.js +432 -0
  13. package/src/Color/Displays.js +19 -0
  14. package/src/Color/InputColorSpaces.js +243 -0
  15. package/src/Color/LutBake.js +371 -0
  16. package/src/Color/OcioRuntime.js +338 -0
  17. package/src/Color/OcioViews.js +419 -0
  18. package/src/Color/ViewTransforms.js +323 -0
  19. package/src/Color/WorkingMatrix.js +86 -0
  20. package/src/EngineDefaults.js +55 -3
  21. package/src/EngineIssues.js +3 -0
  22. package/src/Passes/AIUpscaler.js +16 -7
  23. package/src/Passes/OIDNDenoiser.js +13 -5
  24. package/src/PathTracerApp.js +227 -7
  25. package/src/Processor/AssetLoader.js +1 -2
  26. package/src/Processor/EmissiveTriangleBuilder.js +34 -2
  27. package/src/Processor/GeometryExtractor.js +151 -138
  28. package/src/Processor/LightSerializer.js +8 -3
  29. package/src/Processor/MaterialPacking.js +168 -0
  30. package/src/Processor/PackedRayBuffer.js +6 -2
  31. package/src/Processor/ProceduralSky.js +4 -0
  32. package/src/Processor/SceneProcessor.js +25 -1
  33. package/src/Processor/SimpleSky.js +8 -0
  34. package/src/Processor/TextureCreator.js +137 -91
  35. package/src/Processor/TextureReadback.js +92 -0
  36. package/src/Processor/ToneMapCPU.js +80 -165
  37. package/src/Processor/ToneMapGPU.js +122 -151
  38. package/src/RenderSettings.js +1 -0
  39. package/src/Stages/Compositor.js +11 -2
  40. package/src/Stages/PathTracer.js +2 -0
  41. package/src/Stages/PathTracerStage.js +1 -1
  42. package/src/TSL/Common.js +15 -0
  43. package/src/TSL/Debugger.js +2 -3
  44. package/src/TSL/EmissiveSampling.js +6 -8
  45. package/src/TSL/ExtendKernel.js +9 -0
  46. package/src/TSL/Fresnel.js +23 -1
  47. package/src/TSL/HitFacet.js +102 -0
  48. package/src/TSL/LightsDirect.js +12 -33
  49. package/src/TSL/LightsSampling.js +15 -7
  50. package/src/TSL/MaterialEvaluation.js +26 -19
  51. package/src/TSL/MaterialProperties.js +74 -37
  52. package/src/TSL/MaterialTransmission.js +2 -3
  53. package/src/TSL/ShadeKernel.js +34 -21
  54. package/src/TSL/ShadowTerminator.js +125 -0
  55. package/src/TSL/Struct.js +9 -0
  56. package/src/TSL/Subsurface.js +2 -3
  57. package/src/index.js +32 -4
  58. package/src/managers/DenoisingManager.js +60 -44
  59. package/src/managers/EnvironmentManager.js +20 -0
  60. package/src/managers/MaterialDataManager.js +118 -208
  61. package/src/managers/UniformManager.js +1 -0
  62. package/src/{dlss/DLSSNeural.js → neural/NeuralRetouch.js} +42 -41
  63. package/src/{dlss/DLSSSuperRes.js → neural/NeuralSuperRes.js} +27 -26
  64. package/dist/ToneMapGPU-DzqSyzTx.js +0 -341
package/README.md CHANGED
@@ -26,6 +26,7 @@ A real-time WebGPU path tracing engine built on Three.js. Framework-agnostic —
26
26
  - [engine.lightManager](#enginelightmanager)
27
27
  - [engine.animationManager](#engineanimationmanager)
28
28
  - [Materials](#materials)
29
+ - [Colour Management](#colour-management)
29
30
  - [engine.environmentManager](#engineenvironmentmanager)
30
31
  - [engine.denoisingManager](#enginedenoisingmanager)
31
32
  - [engine.interactionManager](#engineinteractionmanager)
@@ -287,10 +288,10 @@ configureAssets({
287
288
  oidnWeightsBaseUrl: '/oidn-tzas/',
288
289
  upscalerModelBaseUrl: '/upscaler-onnx/',
289
290
 
290
- // DLSS. The runtime is a plain script the host must serve — it installs
291
- // `globalThis.DLSSRuntime` as a side effect and cannot be imported.
292
- dlssRuntimeUrl: '/dlss/dlss-runtime.js',
293
- dlssAssetBaseUrl: '/dlss/',
291
+ // OpenColorIO runtime (~6 MB of WebAssembly) — the engine never names the package, so a host
292
+ // that loads colour configs supplies it, bundled or served. Unset, colour management stays inert.
293
+ ocioRuntimeFactory: () => import('@bb-studio/ocio'), // or: ocioRuntimeUrl: '/vendor/ocio/index.js'
294
+ ocioWasmUrl: '/vendor/ocio/ocio-wasm.wasm', // optional override for the .wasm
294
295
 
295
296
  // Prefix for engine-managed IndexedDB stores. Set to a unique value if multiple
296
297
  // apps embed the engine on the same origin to avoid cache collisions.
@@ -414,13 +415,14 @@ Key settings:
414
415
  | `maxBounces` | `number` | 3 | Max ray bounce depth |
415
416
  | `maxSamples` | `number` | 60 | Max accumulated samples before stopping |
416
417
  | `exposure` | `number` | 1.0 | Exposure value |
417
- | `saturation` | `number` | 1.2 | Color saturation |
418
+ | `saturation` | `number` | 1.0 | Color saturation (1 = no grade) |
418
419
  | `enableEnvironment` | `boolean` | true | Use environment lighting |
419
420
  | `environmentIntensity` | `number` | 1.0 | Environment light strength |
420
- | `environmentRotation` | `number` | 270 | Environment Y-rotation (degrees) |
421
+ | `environmentRotation` | `number` | 0 | Environment Y-rotation (degrees); 0 shows the HDRI as authored, as Blender's unmapped world does |
421
422
  | `showBackground` | `boolean` | true | Show the environment as a visible backdrop for camera-miss rays (vs. a solid/transparent background) |
422
423
  | `samplingTechnique` | `number` | 2 | Sampler: `0` PCG, `1` scrambled Halton, `2` Owen-scrambled Sobol |
423
424
  | `fireflyThreshold` | `number` | 3.0 | Firefly clamping threshold |
425
+ | `shadowTerminatorOffset` | `number` | 0.1 | Cycles' Shadow Terminator → Geometry Offset: near the light's terminator on a smooth-shaded low-poly mesh, light and environment shadow rays start on the smooth surface the vertex normals describe, not the flat facet. Blender's default; `0` disables |
424
426
  | `transmissiveBounces` | `number` | 5 | Max bounces for transmissive materials |
425
427
  | `maxSubsurfaceSteps` | `number` | 8 | Max random-walk steps for subsurface scattering (raised to 64 by `configureForMode('production')`) |
426
428
  | `enableAlphaShadows` | `boolean` | false | Alpha-tested shadow rays (enabled by `configureForMode('production')`) |
@@ -429,7 +431,8 @@ Key settings:
429
431
  | `aperture` | `number` | 5.6 | DOF aperture (f-stop) |
430
432
  | `focalLength` | `number` | 50 | DOF focal length (mm) |
431
433
  | `transparentBackground` | `boolean` | false | Transparent canvas background |
432
- | `interactionModeEnabled` | `boolean` | true | Lower quality during camera movement for smoother navigation |
434
+ | `interactionModeEnabled` | `boolean` | true | Render at lower resolution while the camera moves, keeping the full bounce budget ("Fast Navigation" in the app) |
435
+ | `interactionRenderScale` | `number` | 0.5 | Per-axis render scale while the camera moves (0.5 = a quarter of the pixels); `1` turns the drop off. Ignored while OIDN is the live denoiser |
433
436
  | `renderMode` | `number` | 0 | Internal preview(0)/production(1) flag driving accumulation & ASVGF behavior — normally set via `configureForMode()`, not written directly |
434
437
  | `visMode` | `number` | 0 | Debug visualization mode (0 = off) |
435
438
  | `environmentMode` | `string` | 'hdri' | Sky mode: `'hdri'` \| `'procedural'` \| `'gradient'` \| `'color'` — not routed through `engine.settings`; use `engine.environmentManager.setMode()` instead |
@@ -445,7 +448,7 @@ Key settings:
445
448
  | `pixelFreezeThreshold` | `number` | 0.02 | Relative-error threshold for a pixel to become a freeze candidate |
446
449
  | `pixelFreezeStability` | `number` | 8 | Consecutive candidate frames required before a pixel freezes |
447
450
 
448
- See `ENGINE_DEFAULTS` for the full list with default values.
451
+ See `ENGINE_DEFAULTS` for the full list with default values. The default look is AgX (`toneMapping: 6`) at neutral saturation; tone mapping is chosen through [Colour Management](#colour-management) (`engine.color.setActiveView( id )`), not `settings`.
449
452
 
450
453
  #### Rendering Modes
451
454
 
@@ -552,8 +555,43 @@ engine.updateAllMeshVisibility() // re-sync after manual object
552
555
 
553
556
  // Read access to the active scene (returns the mesh-bearing scene)
554
557
  engine.getScene()
558
+
559
+ // Where a packed value came from: 'material' | 'mapped' | 'default' | 'host'
560
+ engine.getMaterialPropertySource(index, 'ior')
561
+ ```
562
+
563
+ A property a three.js material lacks falls back to `MATERIAL_DEFAULTS` (exported) — MeshPhysicalMaterial's own values, so a glTF metallic material gets IOR 1.5, not a guess derived from its metalness. Weights and roughnesses (metalness, roughness, transmission, opacity, clearcoat, sheen, iridescence, …) are clamped to [0, 1] on upload and on `setMaterialProperty`.
564
+
565
+ ### Colour Management
566
+
567
+ `engine.color` is an OpenColorIO pipeline: what textures and lights mean, what the render happens in, and what it is shown and saved as. **It is inert until a config is loaded** — the render stays linear Rec.709 and the view transforms are three.js's own seven, so a host that never loads one sees no change. The host supplies the runtime (`ocioRuntimeFactory` or `ocioRuntimeUrl` in [`configureAssets`](#configuring-assets-cdn-urls--cache-namespace)).
568
+
569
+ ```js
570
+ configureAssets({ ocioRuntimeFactory: () => import('@bb-studio/ocio') });
571
+
572
+ await engine.loadColorConfig({ builtin: 'ocio://cg-config-v4.0.0_aces-v2.0_ocio-v2.5' }); // a runtime built-in
573
+ await engine.loadColorConfig({ files, configPath: 'config.ocio', id: 'studio' }); // or a folder: [{ relativePath, data }]
574
+
575
+ engine.color.setView({ display: 'sRGB - Display', view: 'ACES 2.0 - SDR 100 nits (Rec.709)', look: null });
576
+ engine.color.setLook(look); // a look from status().config.looks, on the active view
577
+ engine.color.setActiveView(id); // any registered view, OCIO or built-in (three.js constant)
578
+ engine.color.setContext({ SHOT: '010' }); // $SHOT in the config resolves to this
579
+ engine.color.status(); // config, working space, active view, registered views
580
+
581
+ engine.color.setWorkingSpace('ACEScg'); // render in the config's space…
582
+ await engine.applyColorWorkingSpace(); // …which rebuilds textures, materials and the environment
583
+
584
+ await engine.setTextureColorSpace(texture, 'srgb'); // null (auto), 'srgb', 'linear' or a config space
585
+ const { data } = await engine.renderToBuffer({ colorSpace: 'ACES2065-1', source: 'display' }); // float delivery buffer
586
+ await engine.unloadColorConfig();
555
587
  ```
556
588
 
589
+ - **Load and unload through `engine.loadColorConfig()` / `unloadColorConfig()`** once a scene exists: they undo an adopted working space while the config that converted the environment is still loaded.
590
+ - A view is baked to a log2 shaper and a 65³ table, interpolated tetrahedrally; the same table drives the canvas, the GPU and CPU readbacks and the menu (`listViewTransforms()`, `onRegistryChange()`). An OCIO view returns display-encoded colour, so the engine switches the output pass to linear while one is active.
591
+ - **Baked views.** `await engine.color.saveBakedView(id)` writes a view's table to a file (157 KB gzip for 65³), and `await engine.color.loadBakedView(bytes, { expect })` registers it with no runtime and no config — show the look on the first frame, load the config later. When that config loads, a baked view whose files match the fingerprint it was baked from is kept as is: no rebake, no new id, no restart.
592
+ - `renderToBuffer({ colorSpace })` takes `'srgb'` (display bytes through the active view), `'linear'` (the working-space accumulation) or a config colour space; `source: 'display'` reads what the viewport shows, denoised, instead of the raw accumulation.
593
+ - Degradations (a view that cannot bake, a display the canvas cannot show) are recorded as warnings in the [degradation contract](#degradation-contract).
594
+
557
595
  ### engine.environmentManager
558
596
 
559
597
  Environment maps, sky modes, and procedural generation.
@@ -593,10 +631,8 @@ engine.denoisingManager.setOIDNQuality('high')
593
631
  engine.denoisingManager.setStrategy('oidn') // OIDN owns the live view; see below
594
632
  engine.denoisingManager.continuousDenoiseInterval = 250 // cap refreshes at 4/sec (default 8 = uncapped)
595
633
  engine.denoisingManager.setUpscalerEnabled(true)
596
- engine.denoisingManager.setUpscalerBackend('dlss') // 'esrgan' (default) | 'dlss'
597
- engine.denoisingManager.setUpscalerScaleFactor(2) // ESRGAN only; DLSS is fixed at 2x
634
+ engine.denoisingManager.setUpscalerScaleFactor(2) // 2 or 4
598
635
  engine.denoisingManager.setUpscalerQuality('high') // ESRGAN only
599
- engine.denoisingManager.setNeuralRendering(true, { intensity: 1, colorStrength: 0 })
600
636
  ```
601
637
 
602
638
  ### engine.interactionManager
@@ -954,6 +990,18 @@ import {
954
990
  PRODUCTION_RENDER_CONFIG,
955
991
  INTERACTIVE_RENDER_CONFIG,
956
992
  MAX_RESERVABLE_RENDER_SIZE,
993
+ RENDER_PROFILES,
994
+ MATERIAL_DEFAULTS,
995
+ } from 'rayzee';
996
+
997
+ // Colour management — engine.color is the instance a host normally uses; these build UI against
998
+ // it, or reach the view-transform registry without an app
999
+ import {
1000
+ ColorManagement, getActiveColorManagement, isColorManaged, DEFAULT_WORKING_SPACE,
1001
+ listViewTransforms, getViewTransform, addViewTransform, removeViewTransform, onRegistryChange,
1002
+ buildOcioView, addOcioView, addAllOcioViews,
1003
+ convertColor, convertPixelsF32, extractMatrix, hasColorSpace,
1004
+ displayCanvasFit,
957
1005
  } from 'rayzee';
958
1006
 
959
1007
  // Leveled/namespaced logging, shared with the workers
@@ -1017,6 +1065,7 @@ import { setBindingAudit, getBindingAuditFindings, clearBindingAuditFindings } f
1017
1065
  |---|---|---|
1018
1066
  | `oidn-web` | Intel Open Image Denoise for high-quality final renders | Yes — `npm install oidn-web` (**>=0.4.0**) |
1019
1067
  | `onnxruntime-web` | AI-powered upscaling | No — loaded from CDN at runtime |
1068
+ | `@bb-studio/ocio` | OpenColorIO runtime for [Colour Management](#colour-management) (~6 MB WebAssembly) | Only to load colour configs — `npm install @bb-studio/ocio`, then pass it as `ocioRuntimeFactory` |
1020
1069
 
1021
1070
  > **Note:** `onnxruntime-web` is also listed in `package.json` under `optionalDependencies` for bundler compatibility, but the engine's own runtime path always fetches it from a CDN (see `ortRuntimeUrl` / `ortWasmPaths` in [Configuring Assets](#configuring-assets-cdn-urls--cache-namespace)) rather than importing the installed package — installing it locally has no effect unless you also override those URLs to point at your own copy.
1022
1071
 
@@ -1204,51 +1253,6 @@ engine.addEventListener(EngineEvents.UPSCALING_END, () => console.log('Upsc
1204
1253
 
1205
1254
  **Chaining with OIDN:** Upscaling and OIDN **can** run together — on render completion, OIDN runs first, then its denoised output is fed into the upscaler. Enable both; no manual coordination required.
1206
1255
 
1207
- ### The DLSS passes
1208
-
1209
- Two further neural passes, ported from NVIDIA's DLSS weights. Both run once when a render finishes
1210
- and both need a denoised frame — on raw Monte-Carlo noise they measurably lose to a plain resize, so
1211
- enable OIDN alongside them.
1212
-
1213
- Unlike the ONNX upscaler these are **not fetched from a CDN**: `dlss-runtime.js` installs
1214
- `globalThis.DLSSRuntime` as a side effect and cannot be imported, so the host serves it and points
1215
- `configureAssets` at it (see above). It lives at `app/public/dlss/` in this repo, and the local edits
1216
- it carries are written up in `app/public/dlss/PATCHES.md` — re-vendoring it without re-applying them
1217
- breaks the retouch pass with an explanatory throw.
1218
-
1219
- ```js
1220
- // Super resolution, as a second AI Upscaler backend
1221
- engine.denoisingManager.setUpscalerEnabled(true);
1222
- engine.denoisingManager.setUpscalerBackend('dlss');
1223
-
1224
- // The retouch pass — appearance, not resolution. Independent of the upscaler.
1225
- engine.denoisingManager.setNeuralRendering(true, {
1226
- intensity: 1, // 0..1 how much of the pass reaches the image
1227
- localTone: 1, // 0..2 local light shaping; 1 is neutral
1228
- localStructure: 1, // 0..2 fine surface detail; 1 is neutral
1229
- colorStrength: 0, // 0..1 0 keeps the render's chroma, 1 takes the model's
1230
- });
1231
- ```
1232
-
1233
- The chain is **denoise → retouch (at render size) → super resolution (2x) → tone map**, scene-referred
1234
- throughout. The retouch pass runs *before* the upscale deliberately: it sees a quarter of the pixels
1235
- there, and above `DLSS_NR_MAX_PIXELS` (4.19 MP) it takes minutes and then loses every GPU device in
1236
- the page. `DenoisingManager` skips it above that size rather than letting it run.
1237
-
1238
- | | Super resolution | Retouch |
1239
- |---|---|---|
1240
- | What it changes | Resolution, fixed 2x | Appearance only |
1241
- | Weights | 3.2 MB | 141 MB, fetched on first use |
1242
- | Cost (1.9M-tri interior, warm) | 260 ms at 1024²→2048², 947 ms at 2048²→4096² | ~6 s at 2048² |
1243
- | Against a native render | Ties Real-ESRGAN on accuracy, 3x faster, sharper than native | Close to a no-op on path-traced images |
1244
-
1245
- Exported for building UI against: `SR_SCALE`, `SR_MAX_INPUT`, `DLSS_NR_DEFAULTS`, `DLSS_NR_RANGES`,
1246
- `DLSS_NR_MAX_PIXELS`, and `renderUpscaled( app, { outputWidth, outputHeight, samples } )` — the
1247
- offline entry point that drives a half-size render, denoise and upscale in one call.
1248
-
1249
- ⚠️ Each model brings **its own `GPUDevice`**, built by the runtime and not shareable. With both on,
1250
- the page holds three: the renderer's and one each.
1251
-
1252
1256
  ## Troubleshooting
1253
1257
 
1254
1258
  **OIDN: `Cannot find module './tza'` (webpack)**
@@ -1,12 +1,12 @@
1
1
  import { t as e } from "./rolldown-runtime-CAFD8bLK.js";
2
- import { o as t, r as n, t as r } from "./ToneMapGPU-DzqSyzTx.js";
3
- //#region src/dlss/DLSSNeural.js
2
+ import { S as t, t as n, y as r } from "./ToneMapGPU-BVE852iN.js";
3
+ //#region src/neural/NeuralRetouch.js
4
4
  var i = /* @__PURE__ */ e({
5
- DLSSNeural: () => m,
6
- DLSS_NR_COLOR_STRENGTH: () => 0,
7
- DLSS_NR_DEFAULTS: () => a,
8
- DLSS_NR_MAX_PIXELS: () => c,
9
- DLSS_NR_RANGES: () => l,
5
+ NeuralRetouch: () => m,
6
+ RETOUCH_COLOR_STRENGTH: () => 0,
7
+ RETOUCH_DEFAULTS: () => a,
8
+ RETOUCH_MAX_PIXELS: () => c,
9
+ RETOUCH_RANGES: () => l,
10
10
  enhanceFrame: () => g
11
11
  }), a = Object.freeze({
12
12
  enabled: !0,
@@ -29,7 +29,7 @@ function o(e = {}) {
29
29
  colorStrength: t
30
30
  };
31
31
  }
32
- var s = t("dlss"), c = 2048 * 2048, l = Object.freeze({
32
+ var s = t("neural"), c = 2048 * 2048, l = Object.freeze({
33
33
  intensity: [0, 1],
34
34
  localTone: [0, 2],
35
35
  localStructure: [0, 2],
@@ -39,16 +39,16 @@ var s = t("dlss"), c = 2048 * 2048, l = Object.freeze({
39
39
  }), u = null;
40
40
  function d() {
41
41
  if (u) return u;
42
- let { dlssRuntimeUrl: e, dlssAssetBaseUrl: t } = n();
43
- return globalThis.__DLSS5_ASSET_BASE__ = t, u = new Promise((t, n) => {
44
- if (globalThis.DLSSRuntime?.getSrNrChain) return t(globalThis.DLSSRuntime.getSrNrChain());
42
+ let { neuralRuntimeUrl: e, neuralAssetBaseUrl: t } = r();
43
+ return t ? (globalThis.__NEURAL_ASSET_BASE__ = t, u = new Promise((t, n) => {
44
+ if (globalThis.NeuralRuntime?.getSrNrChain) return t(globalThis.NeuralRuntime.getSrNrChain());
45
45
  let r = document.createElement("script");
46
46
  r.src = e, r.onload = () => {
47
- let e = globalThis.DLSSRuntime?.getSrNrChain;
48
- if (!e) return n(/* @__PURE__ */ Error("DLSS runtime loaded but exposed no neural-rendering entry"));
47
+ let e = globalThis.NeuralRuntime?.getSrNrChain;
48
+ if (!e) return n(/* @__PURE__ */ Error("Neural runtime loaded but exposed no retouch entry"));
49
49
  t(e());
50
- }, r.onerror = () => n(/* @__PURE__ */ Error(`Failed to load the DLSS runtime from ${e}`)), document.head.appendChild(r);
51
- }), u;
50
+ }, r.onerror = () => n(/* @__PURE__ */ Error(`Failed to load the neural runtime from ${e}`)), document.head.appendChild(r);
51
+ }), u) : Promise.reject(/* @__PURE__ */ Error("No neural model location: set neuralAssetBaseUrl with configureAssets()"));
52
52
  }
53
53
  var f = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1) var<storage, read_write> dst: array<u32>;\n\n@compute @workgroup_size(8, 8)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let size = textureDimensions(src);\n if ( gid.x >= size.x || gid.y >= size.y ) { return; }\n let c = textureLoad(src, vec2<i32>(gid.xy), 0);\n let r = u32(clamp(c.r, 0.0, 1.0) * 255.0 + 0.5);\n let g = u32(clamp(c.g, 0.0, 1.0) * 255.0 + 0.5);\n let b = u32(clamp(c.b, 0.0, 1.0) * 255.0 + 0.5);\n dst[gid.y * size.x + gid.x] = r | (g << 8u) | (b << 16u) | (255u << 24u);\n}\n", p = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1) var<storage, read_write> dst: array<u32>;\n\n@compute @workgroup_size(8, 8)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let size = textureDimensions(src);\n if ( gid.x >= size.x || gid.y >= size.y ) { return; }\n let c = textureLoad(src, vec2<i32>(gid.xy), 0);\n let a = (gid.y * size.x + gid.x) * 2u;\n dst[a] = pack2x16float(c.rg);\n dst[a + 1u] = pack2x16float(vec2<f32>(c.b, 1.0));\n}\n", m = class e {
54
54
  constructor(e, t) {
@@ -64,8 +64,8 @@ var f = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1
64
64
  return this.chain.pipeline.geometry.validHeight;
65
65
  }
66
66
  static async create({ width: t, height: n, canvas: r = null, settings: i = {}, onProgress: a = () => {} }) {
67
- if (!Number.isInteger(t) || !Number.isInteger(n) || t < 1 || n < 1) throw Error("DLSSNeural.create: width and height must be positive integers");
68
- if (t * n > 4194304) throw Error(`DLSSNeural.create: ${t}x${n} is ${(t * n / 1e6).toFixed(1)} MP, above the ${(c / 1e6).toFixed(1)} MP this pass survives. Past it the run takes minutes and then loses every GPU device in the page.`);
67
+ if (!Number.isInteger(t) || !Number.isInteger(n) || t < 1 || n < 1) throw Error("NeuralRetouch.create: width and height must be positive integers");
68
+ if (t * n > 4194304) throw Error(`NeuralRetouch.create: ${t}x${n} is ${(t * n / 1e6).toFixed(1)} MP, above the ${(c / 1e6).toFixed(1)} MP this pass survives. Past it the run takes minutes and then loses every GPU device in the page.`);
69
69
  let s = r ?? document.createElement("canvas");
70
70
  r || (s.style.cssText = "position:fixed;left:-10000px;top:0;pointer-events:none");
71
71
  let l = new e(await (await d()).create(s, t, n, a, o(i).runtime), s);
@@ -74,21 +74,21 @@ var f = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1
74
74
  _allocate() {
75
75
  let { validWidth: e, validHeight: t } = this.chain.pipeline.geometry;
76
76
  this.source = this.device.createBuffer({
77
- label: "rayzee:dlss-nr-source",
77
+ label: "rayzee:retouch-source",
78
78
  size: e * t * 8,
79
79
  usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
80
80
  }), this.staging = new Uint16Array(e * t * 4);
81
81
  let n = e * t * 4;
82
82
  this._readbackStorage = this.device.createBuffer({
83
- label: "rayzee:dlss-nr-readback",
83
+ label: "rayzee:retouch-readback",
84
84
  size: n,
85
85
  usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
86
86
  }), this._readbackMap = this.device.createBuffer({
87
- label: "rayzee:dlss-nr-readback-map",
87
+ label: "rayzee:retouch-readback-map",
88
88
  size: n,
89
89
  usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
90
90
  }), this._readbackPipeline = this.device.createComputePipeline({
91
- label: "rayzee:dlss-nr-readback",
91
+ label: "rayzee:retouch-readback",
92
92
  layout: "auto",
93
93
  compute: {
94
94
  module: this.device.createShaderModule({ code: f }),
@@ -97,15 +97,15 @@ var f = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1
97
97
  });
98
98
  let r = e * t * 8;
99
99
  this._hdrStorage = this.device.createBuffer({
100
- label: "rayzee:dlss-nr-hdr",
100
+ label: "rayzee:retouch-hdr",
101
101
  size: r,
102
102
  usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
103
103
  }), this._hdrMap = this.device.createBuffer({
104
- label: "rayzee:dlss-nr-hdr-map",
104
+ label: "rayzee:retouch-hdr-map",
105
105
  size: r,
106
106
  usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
107
107
  }), this._hdrPipeline = this.device.createComputePipeline({
108
- label: "rayzee:dlss-nr-hdr",
108
+ label: "rayzee:retouch-hdr",
109
109
  layout: "auto",
110
110
  compute: {
111
111
  module: this.device.createShaderModule({ code: p }),
@@ -115,7 +115,7 @@ var f = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1
115
115
  }
116
116
  async _packHDR(e, t, n = !1) {
117
117
  let r = this.chain.pipeline.slots[this.slot]?.hdrOutput;
118
- if (!r) throw Error("DLSSNeural: the runtime has no scene-referred output. Either no frame has been produced yet, or dlss-runtime.js was re-vendored without the patch described in its PATCHES.md.");
118
+ if (!r) throw Error("NeuralRetouch: the runtime has no scene-referred output. Either no frame has been produced yet, or neural-runtime.js was re-vendored without its `rayzee-patch` edits.");
119
119
  let i = this.device.createBindGroup({
120
120
  layout: this._hdrPipeline.getBindGroupLayout(0),
121
121
  entries: [{
@@ -125,7 +125,7 @@ var f = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1
125
125
  binding: 1,
126
126
  resource: { buffer: this._hdrStorage }
127
127
  }]
128
- }), a = this.device.createCommandEncoder({ label: "rayzee:dlss-nr-hdr" }), o = a.beginComputePass();
128
+ }), a = this.device.createCommandEncoder({ label: "rayzee:retouch-hdr" }), o = a.beginComputePass();
129
129
  o.setPipeline(this._hdrPipeline), o.setBindGroup(0, i), o.dispatchWorkgroups(Math.ceil(e / 8), Math.ceil(t / 8)), o.end(), n && a.copyBufferToBuffer(this._hdrStorage, 0, this._hdrMap, 0, e * t * 8), this.device.queue.submit([a.finish()]);
130
130
  }
131
131
  async readOutputHDR() {
@@ -139,20 +139,20 @@ var f = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1
139
139
  };
140
140
  }
141
141
  async readOutputToned(e) {
142
- let { validWidth: t, validHeight: n } = this.chain.pipeline.geometry;
143
- return await this._packHDR(t, n), this._toneMapper ??= new r(this.device, "rayzee:dlss-nr-tonemap"), this._toneMapper.ensureSize(t, n), {
142
+ let { validWidth: t, validHeight: r } = this.chain.pipeline.geometry;
143
+ return await this._packHDR(t, r), this._toneMapper ??= new n(this.device, "rayzee:retouch-tonemap"), this._toneMapper.ensureSize(t, r), {
144
144
  rgba8: await this._toneMapper.toRGBA8(this._hdrStorage, {
145
145
  exposure: e.exposure ?? 1,
146
146
  toneMapping: e.toneMapping ?? 0,
147
147
  saturation: e.saturation ?? 1
148
148
  }),
149
149
  width: t,
150
- height: n
150
+ height: r
151
151
  };
152
152
  }
153
153
  async readOutput() {
154
154
  let { validWidth: e, validHeight: t } = this.chain.pipeline.geometry, n = this.chain.pipeline.slots[this.slot]?.output;
155
- if (!n) throw Error("DLSSNeural.readOutput: the pass has not produced a frame yet");
155
+ if (!n) throw Error("NeuralRetouch.readOutput: the pass has not produced a frame yet");
156
156
  let r = this.device.createBindGroup({
157
157
  layout: this._readbackPipeline.getBindGroupLayout(0),
158
158
  entries: [{
@@ -162,7 +162,7 @@ var f = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1
162
162
  binding: 1,
163
163
  resource: { buffer: this._readbackStorage }
164
164
  }]
165
- }), i = this.device.createCommandEncoder({ label: "rayzee:dlss-nr-readback" }), a = i.beginComputePass();
165
+ }), i = this.device.createCommandEncoder({ label: "rayzee:retouch-readback" }), a = i.beginComputePass();
166
166
  a.setPipeline(this._readbackPipeline), a.setBindGroup(0, r), a.dispatchWorkgroups(Math.ceil(e / 8), Math.ceil(t / 8)), a.end(), i.copyBufferToBuffer(this._readbackStorage, 0, this._readbackMap, 0, e * t * 4), this.device.queue.submit([i.finish()]), await this._readbackMap.mapAsync(GPUMapMode.READ);
167
167
  let o = new Uint8ClampedArray(this._readbackMap.getMappedRange().slice(0));
168
168
  return this._readbackMap.unmap(), o;
@@ -187,9 +187,9 @@ async function g({ source: e, settings: t = {}, instance: n = null, exposure: r
187
187
  onProgress: a
188
188
  });
189
189
  let { runtime: c, colorStrength: l } = o(t), u = s.staging;
190
- if (!e.half || e.half.length !== u.length) throw Error(`DLSSNeural: expected ${u.length} packed halfs, got ${e.half?.length}`);
190
+ if (!e.half || e.half.length !== u.length) throw Error(`NeuralRetouch: expected ${u.length} packed halfs, got ${e.half?.length}`);
191
191
  u.set(e.half), s.device.queue.writeBuffer(s.source, 0, u), s.chain.pipeline.paperWhite = 1 / Math.min(Math.max(r, 1 / h), h), s.chain.pipeline.colorStrength = l;
192
- let d = performance.now(), f = s.device.createCommandEncoder({ label: "rayzee:dlss-nr" });
192
+ let d = performance.now(), f = s.device.createCommandEncoder({ label: "rayzee:retouch" });
193
193
  await s.chain.encode(f, s.slot, { buffer: s.source }, c, () => {}, { reset: !0 }), s.device.queue.submit([f.finish()]), await s.device.queue.onSubmittedWorkDone();
194
194
  let p = i ? await s.readOutputToned(i) : await s.readOutputHDR();
195
195
  return {
@@ -1,5 +1,5 @@
1
1
  import { t as e } from "./rolldown-runtime-CAFD8bLK.js";
2
- import { o as t, r as n, t as r } from "./ToneMapGPU-DzqSyzTx.js";
2
+ import { S as t, t as n, y as r } from "./ToneMapGPU-BVE852iN.js";
3
3
  //#region src/EngineEvents.js
4
4
  var i = {
5
5
  RENDER_COMPLETE: "engine:renderComplete",
@@ -35,26 +35,26 @@ var i = {
35
35
  ISSUE: "engine:issue",
36
36
  SCENE_METADATA_APPLIED: "engine:sceneMetadataApplied"
37
37
  }, a = /* @__PURE__ */ e({
38
- DLSSSuperRes: () => g,
38
+ NeuralSuperRes: () => g,
39
39
  SR_MAX_INPUT: () => c,
40
40
  SR_SCALE: () => 2,
41
41
  presentRGBA8: () => b,
42
42
  readDenoisedHalf: () => h,
43
43
  releaseDenoisedReader: () => m,
44
44
  renderUpscaled: () => v
45
- }), o = 2, s = t("dlss"), c = 2048, l = null;
45
+ }), o = 2, s = t("neural"), c = 2048, l = null;
46
46
  function u() {
47
47
  if (l) return l;
48
- let { dlssRuntimeUrl: e, dlssAssetBaseUrl: t } = n();
49
- return globalThis.__DLSS5_ASSET_BASE__ = t, l = new Promise((t, n) => {
50
- if (globalThis.DLSSRuntime?.getNativeSR) return t(globalThis.DLSSRuntime.getNativeSR());
48
+ let { neuralRuntimeUrl: e, neuralAssetBaseUrl: t } = r();
49
+ return t ? (globalThis.__NEURAL_ASSET_BASE__ = t, l = new Promise((t, n) => {
50
+ if (globalThis.NeuralRuntime?.getNativeSR) return t(globalThis.NeuralRuntime.getNativeSR());
51
51
  let r = document.createElement("script");
52
52
  r.src = e, r.onload = () => {
53
- let e = globalThis.DLSSRuntime?.getNativeSR;
54
- if (!e) return n(/* @__PURE__ */ Error("DLSS runtime loaded but exposed no super-resolution entry"));
53
+ let e = globalThis.NeuralRuntime?.getNativeSR;
54
+ if (!e) return n(/* @__PURE__ */ Error("Neural runtime loaded but exposed no super-resolution entry"));
55
55
  t(e());
56
- }, r.onerror = () => n(/* @__PURE__ */ Error(`Failed to load the DLSS runtime from ${e}`)), document.head.appendChild(r);
57
- }), l;
56
+ }, r.onerror = () => n(/* @__PURE__ */ Error(`Failed to load the neural runtime from ${e}`)), document.head.appendChild(r);
57
+ }), l) : Promise.reject(/* @__PURE__ */ Error("No neural model location: set neuralAssetBaseUrl with configureAssets()"));
58
58
  }
59
59
  var d = "\n@group(0) @binding(0) var src: texture_2d<f32>;\n@group(0) @binding(1) var<storage, read_write> dst: array<u32>;\n\n@compute @workgroup_size(8, 8)\nfn main( @builtin(global_invocation_id) gid: vec3<u32> ) {\n let size = textureDimensions( src );\n if ( gid.x >= size.x || gid.y >= size.y ) { return; }\n let c = textureLoad( src, vec2<i32>( gid.xy ), 0 ).rgb;\n let a = ( gid.y * size.x + gid.x ) * 2u;\n dst[ a ] = pack2x16float( c.rg );\n dst[ a + 1u ] = pack2x16float( vec2<f32>( c.b, 1.0 ) );\n}\n", f = null;
60
60
  function p(e, t, n) {
@@ -65,21 +65,21 @@ function p(e, t, n) {
65
65
  width: t,
66
66
  height: n,
67
67
  storage: e.createBuffer({
68
- label: "rayzee:dlss-sr-pack",
68
+ label: "rayzee:neural-sr-pack",
69
69
  size: r,
70
70
  usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
71
71
  }),
72
72
  map: e.createBuffer({
73
- label: "rayzee:dlss-sr-pack-map",
73
+ label: "rayzee:neural-sr-pack-map",
74
74
  size: r,
75
75
  usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
76
76
  }),
77
77
  pipeline: e.createComputePipeline({
78
- label: "rayzee:dlss-sr-pack",
78
+ label: "rayzee:neural-sr-pack",
79
79
  layout: "auto",
80
80
  compute: {
81
81
  module: e.createShaderModule({
82
- label: "rayzee:dlss-sr-pack",
82
+ label: "rayzee:neural-sr-pack",
83
83
  code: d
84
84
  }),
85
85
  entryPoint: "main"
@@ -92,7 +92,7 @@ function m() {
92
92
  }
93
93
  async function h(e) {
94
94
  let t = e?._outGPUTexture;
95
- if (!t) throw Error("DLSSSuperRes: no denoised frame — enable OIDN and finish a render first");
95
+ if (!t) throw Error("NeuralSuperRes: no denoised frame — enable OIDN and finish a render first");
96
96
  let n = e.gpuDevice, { width: r, height: i } = e._outTexSize, a = p(n, r, i), o = n.createBindGroup({
97
97
  layout: a.pipeline.getBindGroupLayout(0),
98
98
  entries: [{
@@ -102,7 +102,7 @@ async function h(e) {
102
102
  binding: 1,
103
103
  resource: { buffer: a.storage }
104
104
  }]
105
- }), s = n.createCommandEncoder({ label: "rayzee:dlss-sr-pack" }), c = s.beginComputePass();
105
+ }), s = n.createCommandEncoder({ label: "rayzee:neural-sr-pack" }), c = s.beginComputePass();
106
106
  c.setPipeline(a.pipeline), c.setBindGroup(0, o), c.dispatchWorkgroups(Math.ceil(r / 8), Math.ceil(i / 8)), c.end(), s.copyBufferToBuffer(a.storage, 0, a.map, 0, r * i * 8), n.queue.submit([s.finish()]), await a.map.mapAsync(GPUMapMode.READ);
107
107
  let l = new Uint16Array(a.map.getMappedRange().slice(0));
108
108
  return a.map.unmap(), {
@@ -131,8 +131,8 @@ var g = class e {
131
131
  return this.sr.geometry.outputHeight;
132
132
  }
133
133
  static async create({ width: t, height: n, onProgress: r = () => {} } = {}) {
134
- if (!Number.isInteger(t) || !Number.isInteger(n) || t < 1 || n < 1) throw Error("DLSSSuperRes.create: width and height must be positive integers");
135
- if (t > 2048 || n > 2048) throw Error(`DLSSSuperRes.create: input capped at ${c}px per side (${c * 2}px output), got ${t}x${n}. Above that the runtime's history plane exceeds maxTextureDimension2D and it fails later with an unrelated bind-group error.`);
134
+ if (!Number.isInteger(t) || !Number.isInteger(n) || t < 1 || n < 1) throw Error("NeuralSuperRes.create: width and height must be positive integers");
135
+ if (t > 2048 || n > 2048) throw Error(`NeuralSuperRes.create: input capped at ${c}px per side (${c * 2}px output), got ${t}x${n}. Above that the runtime's history plane exceeds maxTextureDimension2D and it fails later with an unrelated bind-group error.`);
136
136
  let i = await u(), a = document.createElement("canvas");
137
137
  a.style.cssText = "position:fixed;left:-10000px;top:0;pointer-events:none", document.body.appendChild(a);
138
138
  let o;
@@ -155,11 +155,11 @@ var g = class e {
155
155
  this._color = new Uint16Array(e * t * 4), this._depth = new Float32Array(e * t), this._motion = new Uint16Array(e * t * 2);
156
156
  }
157
157
  async _run(e) {
158
- if (this.disposed) throw Error("DLSSSuperRes: disposed");
158
+ if (this.disposed) throw Error("NeuralSuperRes: disposed");
159
159
  let t = this.inputWidth, n = this.inputHeight;
160
- if (e.width !== t || e.height !== n) throw Error(`DLSSSuperRes: expected a ${t}x${n} source, got ${e.width}x${e.height}`);
160
+ if (e.width !== t || e.height !== n) throw Error(`NeuralSuperRes: expected a ${t}x${n} source, got ${e.width}x${e.height}`);
161
161
  let r = this._color;
162
- if (!e.half || e.half.length !== r.length) throw Error(`DLSSSuperRes: expected ${r.length} packed halfs from readDenoisedHalf, got ${e.half?.length}`);
162
+ if (!e.half || e.half.length !== r.length) throw Error(`NeuralSuperRes: expected ${r.length} packed halfs from readDenoisedHalf, got ${e.half?.length}`);
163
163
  r.set(e.half), this._depth.fill(.5), this._motion.fill(0);
164
164
  let i = performance.now(), a = await this.sr.render(this.slot, {
165
165
  color: r,
@@ -174,11 +174,11 @@ var g = class e {
174
174
  };
175
175
  }
176
176
  async upscaleToRGBA8(e, t = {}) {
177
- let { result: n, ms: i } = await this._run(e), { outputWidth: a, outputHeight: o } = this.geometry;
178
- this._toneMapper ??= new r(this.sr.device, "rayzee:dlss-sr-tonemap"), this._toneMapper.ensureSize(a, o);
177
+ let { result: r, ms: i } = await this._run(e), { outputWidth: a, outputHeight: o } = this.geometry;
178
+ this._toneMapper ??= new n(this.sr.device, "rayzee:neural-sr-tonemap"), this._toneMapper.ensureSize(a, o);
179
179
  let s = performance.now();
180
180
  return {
181
- rgba8: await this._toneMapper.toRGBA8(n.hdr.buffer ?? n.hdr, {
181
+ rgba8: await this._toneMapper.toRGBA8(r.hdr.buffer ?? r.hdr, {
182
182
  exposure: t.exposure ?? 1,
183
183
  toneMapping: t.toneMapping ?? 0,
184
184
  saturation: t.saturation ?? 1,
@@ -211,7 +211,7 @@ function _(e, t, n) {
211
211
  e.addEventListener(i.DENOISING_END, l);
212
212
  let u = setInterval(() => {
213
213
  c && s(!0);
214
- }, 200), d = setTimeout(() => s(!1, /* @__PURE__ */ Error("DLSSSuperRes: timed out waiting for the render to finish")), n);
214
+ }, 200), d = setTimeout(() => s(!1, /* @__PURE__ */ Error("NeuralSuperRes: timed out waiting for the render to finish")), n);
215
215
  });
216
216
  }
217
217
  async function v(e, { outputWidth: t, outputHeight: n, samples: r = 64, upscaler: i = null, timeoutMs: a = 6e5, present: o = !0, onProgress: s = () => {} } = {}) {