rayzee 11.2.0 → 11.3.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 (63) hide show
  1. package/README.md +62 -33
  2. package/dist/ArchiveImporter-D735xX-4.js +7860 -0
  3. package/dist/BidirectionalIntegrator-M89c0AlP.js +954 -0
  4. package/dist/{BufferLayout-D_IBo2ci.js → BufferLayout-xPRH9jYD.js} +41 -5
  5. package/dist/{NeuralRetouch-DFGbnmLb.js → NeuralRetouch-DiBH63kz.js} +1 -1
  6. package/dist/{NeuralSuperRes-BtXvyJQl.js → NeuralSuperRes-CZNQP13W.js} +1 -1
  7. package/dist/{PathTracer-BHXGJtPN.js → PathTracer-BXCCVrPK.js} +4371 -4612
  8. package/dist/{PhysicalSky-DN6u8UX4.js → PhysicalSky-DqmaS0lb.js} +2 -2
  9. package/dist/{RayzeeRenderer-Dw1x8mVL.js → RayzeeRenderer-DUSMFhmc.js} +426 -363
  10. package/dist/SolarLimb-bZE6y63S.js +762 -0
  11. package/dist/addons/archives.es.js +1 -1
  12. package/dist/addons/bidirectional.es.js +1 -1
  13. package/dist/addons/physical-sky.es.js +1 -1
  14. package/dist/rayzee-core.es.js +7 -7
  15. package/dist/rayzee.es.js +472 -468
  16. package/dist/rayzee.umd.js +106 -105
  17. package/dist/sceneCachePolicy-BAib5fCp.js +1602 -0
  18. package/package.json +1 -1
  19. package/src/EngineDefaults.js +1 -1
  20. package/src/PathTracerApp.js +4 -3
  21. package/src/Processor/ArchiveImporter.js +173 -94
  22. package/src/Processor/ArchiveReader.js +20 -23
  23. package/src/Processor/AssetLoader.js +48 -1
  24. package/src/Processor/BVHRefitter.js +109 -13
  25. package/src/Processor/BufferLayout.js +115 -0
  26. package/src/Processor/ChunkedRecords.js +3 -2
  27. package/src/Processor/EmissiveTriangleBuilder.js +6 -6
  28. package/src/Processor/GeometryExtractor.js +189 -79
  29. package/src/Processor/HostMemory.js +39 -9
  30. package/src/Processor/InstanceTable.js +714 -42
  31. package/src/Processor/PBRT/PBRTCurves.js +224 -6
  32. package/src/Processor/PBRT/PBRTMaterials.js +3 -0
  33. package/src/Processor/PBRT/PBRTSceneBuilder.js +82 -25
  34. package/src/Processor/PackedRayBuffer.js +5 -2
  35. package/src/Processor/SceneProcessor.js +747 -141
  36. package/src/Processor/TLASBuilder.js +32 -17
  37. package/src/Processor/USD/USDLayer.js +1149 -0
  38. package/src/Processor/USD/USDScene.js +1655 -0
  39. package/src/Processor/USD/USDStage.js +682 -0
  40. package/src/Processor/USD/USDText.js +674 -0
  41. package/src/Processor/USD/index.js +138 -0
  42. package/src/Processor/Workers/BVHRefitWorker.js +3 -3
  43. package/src/RayzeeRenderer.js +168 -27
  44. package/src/Stages/NormalDepth.js +7 -12
  45. package/src/Stages/PathTracer.js +12 -17
  46. package/src/Stages/PathTracerStage.js +273 -96
  47. package/src/Storage/GeometrySpill.js +46 -14
  48. package/src/Storage/SceneGraphCodec.js +17 -3
  49. package/src/Storage/SpillStore.js +9 -0
  50. package/src/TSL/BVHTraversal.js +183 -7
  51. package/src/TSL/Common.js +57 -13
  52. package/src/TSL/ShadeKernel.js +3 -2
  53. package/src/TSL/TextureSampling.js +11 -8
  54. package/src/TSL/patches.js +84 -0
  55. package/src/integrators/BidirectionalIntegrator.js +20 -2
  56. package/src/managers/DenoisingManager.js +4 -4
  57. package/src/managers/InteractionManager.js +19 -6
  58. package/src/managers/MaterialDataManager.js +22 -5
  59. package/src/managers/UniformManager.js +3 -0
  60. package/dist/ArchiveImporter-eNlu0_6F.js +0 -5198
  61. package/dist/BidirectionalIntegrator-D1-6UySB.js +0 -946
  62. package/dist/SolarLimb-CPaeZVwz.js +0 -721
  63. package/dist/sceneCachePolicy-DA7iGoL4.js +0 -485
package/README.md CHANGED
@@ -328,7 +328,7 @@ const engine = new PathTracerApp(canvas, options?)
328
328
  | `options.maxSceneBytes` | `number` | Raise or lower the CPU memory ceiling a scene may need before the engine refuses it (default 9,216 MB). See [Memory monitoring](#memory-monitoring). |
329
329
  | `options.hostMemoryGB` | `number` | The host's memory, for runtimes without Chrome's `navigator.deviceMemory` (which then read as 4 GB and cap the render reserve at 2048). Sizes the reserve and the path pool. |
330
330
  | `options.storage` | `false \| 'auto' \| StorageManager` | On-disk storage (default: `configureAssets( { storage } )`; off under `strict` unless you set it there or here). A manager you pass stays yours to dispose. See [On-disk storage](#on-disk-storage-opfs). |
331
- | `options.memorySpill` | `boolean` | Experimental, default `false`: build a large static scene through disk — triangle records, BLAS nodes and the three.js geometry are written out as the build finishes with them — and raise the pbrt triangle and placement caps to 60M / 8M. See [On-disk storage](#on-disk-storage-opfs). |
331
+ | `options.memorySpill` | `'auto' \| boolean` | Default `'auto'`: build a static scene through disk when it would not fit in memory — triangle records, BLAS nodes and the three.js geometry are written out as the build finishes with them, and the instance matrix lists, the top-level tree and the triangle order maps once the load is done. `'auto'` does so only for a scene whose in-memory estimate passes the safe line (7 GB); `true` for every static scene; `false` never. Unless `false`, the pbrt and USD triangle and placement caps rise to 120M / 60M. Needs storage. Change it later with `engine.setMemorySpill( mode )`; `engine.sceneSpilled` says whether the current scene went to disk. See [On-disk storage](#on-disk-storage-opfs). |
332
332
 
333
333
  The engine creates and mounts everything it needs (denoiser canvas, tile/HUD overlay) into a single parent on `init()`. Performance HUDs (e.g. `stats-gl`) are not bundled — listen to `EngineEvents.FRAME` and tick your own panel.
334
334
 
@@ -390,8 +390,15 @@ await engine.loadFile({ name: 'Sponza', files: [ // or path + file pairs: a dro
390
390
 
391
391
  Loose files picked together load the same way. Hidden files and folders (`.DS_Store`, `.git/`) are left out. The model
392
392
  that loads is a `scene` / `model` / `main` / `asset` glTF when there is one, else the shallowest model, glTF first; the
393
- others are named in an `asset.ambiguous_entry` warning. A large pbrt folder of several parts asks which to load, as an
394
- archive does (below). `sceneSource` is `{ kind: 'local-folder', folder: { name, size, lastModified, sample, files }, key }`
393
+ others are named in an `asset.ambiguous_entry` warning. A large pbrt or USD folder of several parts asks which to load,
394
+ as an archive does (below).
395
+
396
+ A USD scene — a folder or archive whose main model is a `.usd` / `.usda` / `.usdc` layer, or a loose layer — loads
397
+ through the engine's own USD importer, part of the archives add-on: composition (sublayers, references, payloads,
398
+ inherits, specializes, variants), meshes, curves, point instancers, PxrDisneyBsdf / PxrSurface / UsdPreviewSurface
399
+ materials, cameras, lights and the dome light as the environment. Each layer is read only when composition reaches it. A
400
+ `.usdz` stays with three.js's loader (`usdFormat`). Ptex is not read: a Ptex input takes the mesh's mean
401
+ `displayColor`. `sceneSource` is `{ kind: 'local-folder', folder: { name, size, lastModified, sample, files }, key }`
395
402
  — `sample` hashes every file's path, size and date, so any change inside the folder changes it — and
396
403
  `sceneSourceFolder` hands the files back, as `{ name, files: [{ path, file }] }`.
397
404
 
@@ -406,8 +413,8 @@ The archive can be inspected without retaining any of it, then loaded one elemen
406
413
  ```js
407
414
  const { kind, root, elements, entryCount, totalBytes } = await engine.inspectArchive(file);
408
415
 
409
- await engine.loadFile(file, { element: elements[0].path }); // one element
410
- await engine.loadFile(file, { element: [ a.path, b.path ] }); // several together
416
+ await engine.loadFile(file, { element: elements[0].prefix }); // one element
417
+ await engine.loadFile(file, { element: [ a.prefix, b.prefix ] }); // several together
411
418
  ```
412
419
 
413
420
  Everything above a chosen element comes along — the root scene file, the material library, an
@@ -415,8 +422,9 @@ ancestor's `textures` folder — and an `Include` pointing at an element you lef
415
422
  which is what makes a partial load work. Selecting every element is a valid answer and loads the
416
423
  whole scene.
417
424
 
418
- Past 4 GB unpacked, a multi-element archive **throws** `ARCHIVE_NEEDS_ELEMENT` rather than taking
419
- all of it. The error carries the element list, so a host can turn it into a picker:
425
+ Past 4 GB unpacked (a USD scene: past 1 GB of layers), a multi-element archive or folder **throws**
426
+ `ARCHIVE_NEEDS_ELEMENT` rather than taking all of it. The error carries the element list — each
427
+ `{ name, prefix, files, bytes, scenes }` — so a host can turn it into a picker:
420
428
 
421
429
  ```js
422
430
  try {
@@ -427,20 +435,23 @@ try {
427
435
  }
428
436
  ```
429
437
 
430
- Per-load options for pbrt archives:
438
+ Per-load options for pbrt and USD scenes:
431
439
 
432
440
  | Option | Default | Effect |
433
441
  |---|---|---|
434
442
  | `promptBytes` | 4 GB | moves the line past which a multi-element archive asks for elements |
435
- | `maxTriangles` | 45M (60M with `memorySpill`) | past it, placements are skipped and the build reports itself truncated |
436
- | `maxPlacements` | 6M (8M with `memorySpill`) | the same, for placements |
443
+ | `maxTriangles` | 45M (120M with storage, unless `memorySpill: false`) | past it, placements are skipped and the build reports itself truncated (a USD scene thins curve sets and point instancers first, and never cuts a mesh short unless meshes alone are over) |
444
+ | `maxPlacements` | 6M (60M with storage, unless `memorySpill: false`) | the same, for placements |
437
445
  | `curveTolerance` | 0.05 | how far a curve segment may stray, × the curve's half-width; curves become strips with adaptive segments. `0` gives the old uniform strips bit for bit |
438
446
  | `instanceIncludes` | `true` | a file included again under the same material, with no side effects, is placed as an instance of its first reading instead of being read and stored again |
439
447
 
440
- 45M is the highest rung measured to survive without the spill; raising either cap is a deliberate
441
- act on a fresh browser tab. With `memorySpill`, 80M stored triangles (4.35M placements) have loaded
442
- and rendered; an 89M load ran out of memory while parsing, and WebGPU's 4 GB buffer limit stops the
443
- triangle data at 89.5M in any case.
448
+ 45M is the highest rung measured to survive without the spill, which is why the caps rise only where the build can
449
+ spill; the preflight still refuses what cannot fit. With the spill, the whole Moana USD island — 111.6M triangles, 51.0M
450
+ placed copies — loads and renders in Chrome on a 24 GB Apple M-series in about 4½ minutes. Past
451
+ WebGPU's 4 GB buffer limit the triangle and node stores go up in parts, so buffer size no longer caps a
452
+ scene. Past 1M placed copies the top-level tree is built over clusters of four neighbouring copies
453
+ (about 80 bytes a copy instead of 128), which costs such a scene 17–20 % frame time and nothing below
454
+ that size.
444
455
 
445
456
  #### Settings
446
457
 
@@ -466,7 +477,7 @@ Key settings:
466
477
  | `enableEnvironment` | `boolean` | true | Use environment lighting |
467
478
  | `environmentIntensity` | `number` | 1.0 | Environment light strength |
468
479
  | `environmentRotation` | `number` | 0 | Environment Y-rotation (degrees); 0 shows the HDRI as authored, as Blender's unmapped world does |
469
- | `areaLightIntensityScale` | `number` | 1 | Power of a glTF model's placeholder area lights (RectAreaLight extras), read when the model loads, so set it first; 1 is the authored power |
480
+ | `areaLightIntensityScale` | `number` | 0.1 | Power of a glTF model's placeholder area lights (RectAreaLight extras), read when the model loads, so set it first; 1 is the authored power |
470
481
  | `maxTextureSize` | `number` | 4096 | Longest edge of a material texture, read when a model loads (clamped to the hardware ceiling); `setMaxTextureSize()` applies it to the current scene too |
471
482
  | `wavefrontSortMaterials` | `boolean` | true | Sort rays by material before shading, above 8 materials; read when the shaders next build |
472
483
  | `showBackground` | `boolean` | true | Show the environment as a visible backdrop for camera-miss rays (vs. a solid/transparent background) |
@@ -593,8 +604,9 @@ Colour, storage and the integrators have no loader: colour and storage are used
593
604
  the moment it is chosen (a lazy one would trace plain frames meanwhile and break reproducible renders).
594
605
 
595
606
  **File formats.** The core reads glTF/GLB (Draco, KTX2 and meshopt decoders are fetched only for a file that uses
596
- them), `.hdr` and LDR images. FBX, OBJ, STL, PLY, Collada, 3MF, USD/USDZ and EXR are formats to register — import only
597
- those you read and a bundler leaves the rest out; each three.js loader is downloaded the first time its format is read:
607
+ them), `.hdr` and LDR images. FBX, OBJ, STL, PLY, Collada, 3MF, USDZ and EXR are formats to register — import only
608
+ those you read and a bundler leaves the rest out; each three.js loader is downloaded the first time its format is read
609
+ (a `.usd` / `.usda` / `.usdc` layer is read by the engine's own USD importer, in the archives add-on below):
598
610
 
599
611
  ```js
600
612
  import { objFormat, usdFormat, exrFormat } from 'rayzee/addons/formats';
@@ -827,6 +839,7 @@ engine.setMeshVisibilityByUuid(uuid, prev => !prev) // toggle via updater fn
827
839
  // Lower-level — for callers that already have a meshIndex or have mutated object.visible directly
828
840
  engine.setMeshVisibility(meshIndex, visible)
829
841
  engine.updateAllMeshVisibility() // re-sync after manual object.visible mutations
842
+ // With memorySpill, an edit whose top-level tree is on disk lands once it is read back (a moment later).
830
843
 
831
844
  // Read access to the active scene (returns the mesh-bearing scene)
832
845
  engine.getScene()
@@ -964,9 +977,11 @@ await engine.refitBVH(positions) // the whole scene is posed
964
977
  ```
965
978
 
966
979
  **`updateMeshTransforms` is the one a gizmo drag wants.** Triangles are stored in each object's own
967
- space, so a rigid move only rewrites a matrix — no vertex pass, no geometry upload. Using
968
- `refitBLASes` for a move instead rewrites vertices needlessly, and drags along any other object
969
- sharing the same geometry.
980
+ space, so a rigid move only rewrites a matrix — no vertex pass, no geometry upload — and refits only the
981
+ tree nodes above what moved, uploading just those. Using `refitBLASes` for a move instead rewrites
982
+ vertices needlessly, and drags along any other object sharing the same geometry. It returns
983
+ `{ refitTimeMs, placements }`, or `null` on a `memorySpill` scene whose matrices or tree are on disk:
984
+ the move then lands once they are read back.
970
985
 
971
986
  All three take **indices into `engine.sceneMeshes`**, which is a depth-first walk of the rendered
972
987
  scene and includes the engine's own hidden ground disk. Build your index list from that array, never
@@ -1149,8 +1164,10 @@ Before extraction the engine prices the scene and applies two lines, both record
1149
1164
 
1150
1165
  Raise or lower the hard line with `new PathTracerApp(canvas, { maxSceneBytes })`. The estimate runs
1151
1166
  low at the very top of its range, so the per-load `maxTriangles` cap (45M) is the more reliable
1152
- guard on a scene of that size. With `memorySpill` the estimate leaves out what the build keeps on
1153
- disk (the BVH, and triangle records past what a streamed build holds at once).
1167
+ guard on a scene of that size. For a spilling build the estimate leaves out what the build keeps on
1168
+ disk (the BVH, the three.js geometry, and triangle records past what a streamed build holds at once)
1169
+ and prices the build by its larger phase — extraction, or the top-level tree — since the two never
1170
+ hold their arrays at the same time. The whole Moana island estimates 8.6 GB that way.
1154
1171
 
1155
1172
  ---
1156
1173
 
@@ -1255,9 +1272,9 @@ unavailable or fails, the CPU does it instead: the result's `toneMappedOn` says
1255
1272
  Constructing `PathTracerApp` yourself instead: pass `strict: true`; storage is then off unless you
1256
1273
  set it. Outside Chrome, pass `hostMemoryGB`.
1257
1274
 
1258
- The engine has one set of defaults, the viewer's. For lens-accurate depth of field, set `dofMode: 'physical'` —
1259
- through `settings` here, or `engine.settings` before loading the model. glTF placeholder area lights render at their
1260
- authored power (`areaLightIntensityScale: 1`).
1275
+ The engine has one set of defaults, the viewer's. For lens-accurate depth of field and glTF placeholder area
1276
+ lights at their authored power, set `dofMode: 'physical'` and `areaLightIntensityScale: 1` — through `settings`
1277
+ here, or `engine.settings` before loading the model.
1261
1278
 
1262
1279
  **Provenance.** `engine.getProvenance()` — also `frame.provenance` from `captureHeadless` — is plain
1263
1280
  JSON naming what produced the image: engine and three.js versions, the adapter, every live setting with its source, the colour pipeline, the render size and
@@ -1389,23 +1406,35 @@ a link that expires (a signed URL). `fetchFile( url, storage )` / `cachedObjectU
1389
1406
  for a host's own assets. Failures record `storage.*` issues and fall back to memory; storage never
1390
1407
  throws for being absent or full.
1391
1408
 
1392
- **Memory spill (experimental).** With `memorySpill: true`, a static scene of more than one 64 MB chunk
1393
- is built through disk, so its large arrays are never all in memory at once:
1409
+ **Memory spill.** A static scene too large for memory is built through disk, so its large arrays are never all in
1410
+ memory at once. By default (`memorySpill: 'auto'`) a scene spills only when its in-memory estimate passes the safe
1411
+ line (7 GB) — ordinary models never do and load exactly as before; `true` spills every static scene of more than one
1412
+ 64 MB chunk, `false` none. The decision is made per load, and a spilling scene's environment is narrowed to 8192 texels
1413
+ wide:
1394
1414
 
1395
1415
  - Extraction and BVH building run together. Each stored range of triangles goes to a BLAS worker as
1396
- soon as it is written, and extraction waits while more than 1.5 GB of triangle records are held.
1416
+ soon as it is written, and extraction waits while more than 1 GB of triangle records are held.
1397
1417
  On the 55.7M-triangle Moana subset the build peak fell from 6.6 to 4.1 GB.
1398
- - The three.js geometry goes to disk after the build last reads it, and comes back when the build
1399
- ends. On a 70M-triangle scene the page held 0.84 GB after extraction instead of 4.07 GB.
1418
+ - The three.js geometry goes to disk after the build last reads it. Past 1 GB of it, it **stays there**
1419
+ until something needs it: `await engine.ensureSceneResident()` reads it back, and so does a rebuild of
1420
+ the same model. Meanwhile clicking the model selects nothing and a selection draws no outline (its
1421
+ arrays are empty). Less than 1 GB comes back when the build ends. On a 70M-triangle scene
1422
+ the page held 0.84 GB after extraction instead of 4.07 GB.
1400
1423
  - Each triangle chunk and BLAS goes to the GPU, then to disk. At 50M triangles the page settles at
1401
1424
  7.2 GB instead of 9.1 GB.
1425
+ - Once the load is done, the instance matrix lists, the top-level tree with its copy records and the
1426
+ triangle order maps go to disk too. An edit reads back what it needs (a visibility change the tree, a
1427
+ move the matrices, the tree and that object's copy records) and lands once it has; 30 s after the
1428
+ last edit it all goes back. On the Moana island the CPU data held at rest fell from 6.9 to 2.2 GB, and
1429
+ a tab in Chrome from 5.2 to 3.6 GB.
1430
+ - An environment wider than 8192 pixels is box-filtered down when it loads.
1402
1431
 
1403
1432
  With or without the spill, a mesh past 2M triangles is built as spatial pieces of ≤ 512k triangles
1404
1433
  on a worker pool and joined under the tree that split them, so no build holds a second copy of it.
1405
1434
 
1406
- The render is unchanged. Visibility and rigid moves need nothing read back. Material edits that
1407
- rewrite triangles (side, transparency, emission), and refits, read it back first. `refitBLASes`
1408
- throws on a spilled scene until `await engine.ensureSceneResident()`.
1435
+ The render is unchanged. Material edits that rewrite triangles (side, transparency, emission), and
1436
+ refits, read the scene back first. `refitBLASes` throws on a spilled scene until
1437
+ `await engine.ensureSceneResident()`.
1409
1438
 
1410
1439
  ### Saving Scene State
1411
1440