rayzee 9.4.1 → 9.5.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.
- package/README.md +226 -25
- package/dist/ActiveColor-YvuQq44O.js +13 -0
- package/dist/ArchiveImporter-xuUJiklP.js +4301 -0
- package/dist/AssetConfig-DSEntE65.js +30 -0
- package/dist/BidirectionalIntegrator-C5PKjJoT.js +934 -0
- package/dist/ColorManagement-CheBCPaW.js +1488 -0
- package/dist/EngineDefaults-DH3bI5t-.js +844 -0
- package/dist/EngineEvents-Ci8dVWCP.js +73 -0
- package/dist/EngineIssues-CIZnXHsF.js +72 -0
- package/dist/FileFormats-sPGJeCRc.js +102 -0
- package/dist/Logger-BnHghprG.js +97 -0
- package/dist/{NeuralRetouch-vkdXXyK2.js → NeuralRetouch-CW11yLZ_.js} +8 -6
- package/dist/{NeuralSuperRes-FVqRJKQV.js → NeuralSuperRes-BekaecYg.js} +55 -120
- package/dist/PathTracer-Ccl9KOuF.js +29729 -0
- package/dist/PhysicalSky-Dv2PMFGW.js +1219 -0
- package/dist/RayzeeRenderer-BQxnzCTD.js +3542 -0
- package/dist/SolarLimb-ken-JbDK.js +721 -0
- package/dist/ToneMapGPU-BHi5JzIq.js +177 -0
- package/dist/ViewTransforms-D0rTLBsX.js +255 -0
- package/dist/WorkingMatrix-C6y233hT.js +27 -0
- package/dist/ZipReader-gDSWr0I5.js +98 -0
- package/dist/addons/archives.es.js +3 -0
- package/dist/addons/bidirectional.es.js +2 -0
- package/dist/addons/color.es.js +3 -0
- package/dist/addons/formats.es.js +2 -0
- package/dist/addons/physical-sky.es.js +2 -0
- package/dist/addons/storage.es.js +3 -0
- package/dist/archiveFormats-BZw7TiDp.js +75 -0
- package/dist/identity-DrQsGT2o.js +39 -0
- package/dist/openStorage-DwcBRUj7.js +820 -0
- package/dist/rayzee-core.es.js +12 -0
- package/dist/rayzee.es.js +2266 -44125
- package/dist/rayzee.umd.js +485 -473
- package/dist/sceneCachePolicy-BmwYOYDu.js +183 -0
- package/dist/shared-BGBcSxBQ.js +17 -0
- package/package.json +23 -2
- package/src/Color/ActiveColor.js +34 -0
- package/src/Color/BasicColor.js +147 -0
- package/src/Color/ColorManagement.js +7 -31
- package/src/EngineDefaults.js +23 -14
- package/src/EngineEvents.js +2 -0
- package/src/EngineIssues.js +1 -0
- package/src/PathTracerApp.js +617 -4016
- package/src/Pipeline/PipelineContext.js +0 -4
- package/src/Platform.js +36 -0
- package/src/Processor/ArchiveCache.js +1 -1
- package/src/Processor/ArchiveImporter.js +1259 -0
- package/src/Processor/AssetLoader.js +322 -1746
- package/src/Processor/AtmosphereModel.js +1 -2
- package/src/Processor/BVHBuilder.js +4 -95
- package/src/Processor/EnvironmentExactTable.js +187 -0
- package/src/Processor/EquirectHDRInfo.js +30 -223
- package/src/Processor/FileFormats.js +116 -0
- package/src/Processor/GLTFDecoders.js +85 -0
- package/src/Processor/GLTFDiffuseTransmission.js +63 -0
- package/src/Processor/GeometryExtractor.js +12 -1
- package/src/Processor/IESParser.js +47 -35
- package/src/Processor/KernelManager.js +35 -2
- package/src/Processor/MaterialPacking.js +8 -7
- package/src/Processor/PBRT/PBRTMaterials.js +129 -41
- package/src/Processor/PBRT/PBRTParser.js +30 -17
- package/src/Processor/PBRT/PBRTSceneBuilder.js +548 -37
- package/src/Processor/PBRT/PBRTTextureBake.js +154 -0
- package/src/Processor/PBRT/PFM.js +59 -0
- package/src/Processor/PackedRayBuffer.js +116 -9
- package/src/Processor/ParallelBVHBuilder.js +3 -6
- package/src/Processor/PhysicalSky.js +5 -4
- package/src/Processor/PlatformImageLoader.js +50 -6
- package/src/Processor/QueueManager.js +12 -3
- package/src/Processor/ReinsertionOptimizer.js +2 -2
- package/src/Processor/SceneProcessor.js +15 -55
- package/src/Processor/ShaderBuilder.js +6 -16
- package/src/Processor/SimpleSky.js +1 -62
- package/src/Processor/SolarLimb.js +3 -0
- package/src/Processor/TextureCreator.js +1 -1
- package/src/Processor/Workers/BVHSubtreeWorker.js +1 -34
- package/src/Processor/Workers/BVHWorker.js +5 -18
- package/src/Processor/Workers/CDFWorker.js +6 -183
- package/src/Processor/archiveFormats.js +7 -0
- package/src/Processor/utils.js +2 -1
- package/src/RayzeeRenderer.js +3902 -0
- package/src/RenderSettings.js +49 -41
- package/src/Stages/ASVGF.js +5 -7
- package/src/Stages/AutoExposure.js +3 -12
- package/src/Stages/Compositor.js +8 -23
- package/src/Stages/NRD.js +9 -2
- package/src/Stages/NormalDepth.js +9 -6
- package/src/Stages/PathTracer.js +254 -38
- package/src/Stages/PathTracerStage.js +11 -16
- package/src/Storage/BLASCache.js +1 -1
- package/src/Storage/CDFCache.js +18 -17
- package/src/Storage/DownloadCache.js +1 -1
- package/src/Storage/SceneGraphCodec.js +46 -3
- package/src/Storage/SpillStore.js +1 -1
- package/src/Storage/StorageManager.js +2 -4
- package/src/Storage/areas.js +4 -0
- package/src/TSL/BVHTraversal.js +62 -24
- package/src/TSL/Bidirectional.js +204 -0
- package/src/TSL/BidirectionalLamps.js +132 -0
- package/src/TSL/Clearcoat.js +15 -6
- package/src/TSL/Common.js +19 -14
- package/src/TSL/ConnectKernel.js +147 -0
- package/src/TSL/Debugger.js +1 -1
- package/src/TSL/Displacement.js +4 -3
- package/src/TSL/EmissiveSampling.js +64 -17
- package/src/TSL/Environment.js +77 -106
- package/src/TSL/EnvironmentCDF.js +85 -39
- package/src/TSL/ExtendKernel.js +8 -3
- package/src/TSL/FinalWriteKernel.js +4 -4
- package/src/TSL/GenerateKernel.js +18 -4
- package/src/TSL/HitFacet.js +35 -5
- package/src/TSL/LightBVHSampling.js +40 -9
- package/src/TSL/LightGenerateKernel.js +293 -0
- package/src/TSL/LightGuide.js +198 -0
- package/src/TSL/LightSplatKernel.js +165 -0
- package/src/TSL/LightsCore.js +13 -38
- package/src/TSL/LightsDirect.js +28 -29
- package/src/TSL/LightsIndirect.js +3 -1
- package/src/TSL/LightsSampling.js +90 -38
- package/src/TSL/MaterialEvaluation.js +113 -31
- package/src/TSL/MaterialProperties.js +44 -17
- package/src/TSL/MaterialTransmission.js +52 -47
- package/src/TSL/MergeKernel.js +218 -0
- package/src/TSL/PathTracerCore.js +65 -29
- package/src/TSL/Random.js +4 -0
- package/src/TSL/SceneResources.js +51 -0
- package/src/TSL/ShadeKernel.js +881 -103
- package/src/TSL/Struct.js +10 -0
- package/src/TSL/Sun.js +1 -1
- package/src/TSL/TextureSampling.js +65 -60
- package/src/addons/archives.js +14 -0
- package/src/addons/bidirectional.js +13 -0
- package/src/addons/color.js +32 -0
- package/src/addons/formats.js +16 -0
- package/src/addons/physicalSky.js +14 -0
- package/src/addons/storage.js +19 -0
- package/src/core.js +35 -0
- package/src/index.js +3 -1
- package/src/integrators/BidirectionalIntegrator.js +832 -0
- package/src/managers/EnvironmentManager.js +94 -91
- package/src/managers/MaterialDataManager.js +42 -0
- package/src/managers/UniformManager.js +0 -1
- package/dist/ToneMapGPU-DKQM1pMd.js +0 -552
- package/dist/rolldown-runtime-CAFD8bLK.js +0 -11
- package/src/Processor/TreeletOptimizer.js +0 -574
package/README.md
CHANGED
|
@@ -21,6 +21,8 @@ A real-time WebGPU path tracing engine built on Three.js. Framework-agnostic —
|
|
|
21
21
|
- [API Reference](#api-reference)
|
|
22
22
|
- [Configuring Assets (CDN URLs & cache namespace)](#configuring-assets-cdn-urls--cache-namespace)
|
|
23
23
|
- [PathTracerApp](#pathtracerapp)
|
|
24
|
+
- [Renderer core (`rayzee/core`)](#renderer-core-rayzeecore)
|
|
25
|
+
- [Add-ons](#add-ons)
|
|
24
26
|
- [engine.cameraManager](#enginecameramanager)
|
|
25
27
|
- [Camera Projection (Orthographic, 360° Panorama)](#camera-projection-orthographic-360-panorama)
|
|
26
28
|
- [engine.lightManager](#enginelightmanager)
|
|
@@ -39,6 +41,9 @@ A real-time WebGPU path tracing engine built on Three.js. Framework-agnostic —
|
|
|
39
41
|
- [Memory Monitoring](#memory-monitoring)
|
|
40
42
|
- [Logging](#logging)
|
|
41
43
|
- [Deterministic & Headless Rendering](#deterministic--headless-rendering)
|
|
44
|
+
- [On-disk Storage (OPFS)](#on-disk-storage-opfs)
|
|
45
|
+
- [Saving Scene State](#saving-scene-state)
|
|
46
|
+
- [Render Checkpoints](#render-checkpoints)
|
|
42
47
|
- [Events](#events)
|
|
43
48
|
- [Advanced: Custom Pipeline Stages](#advanced-custom-pipeline-stages)
|
|
44
49
|
- [All Exports](#all-exports)
|
|
@@ -55,7 +60,7 @@ A real-time WebGPU path tracing engine built on Three.js. Framework-agnostic —
|
|
|
55
60
|
npm install rayzee three
|
|
56
61
|
```
|
|
57
62
|
|
|
58
|
-
`three` (>=0.
|
|
63
|
+
`three` (>=0.186.0) is a required peer dependency.
|
|
59
64
|
|
|
60
65
|
## Getting Started
|
|
61
66
|
|
|
@@ -137,10 +142,10 @@ A single HTML file — no Node.js, no build step. Uses [ES module import maps](h
|
|
|
137
142
|
<script type="importmap">
|
|
138
143
|
{
|
|
139
144
|
"imports": {
|
|
140
|
-
"three": "https://cdn.jsdelivr.net/npm/three@0.
|
|
141
|
-
"three/tsl": "https://cdn.jsdelivr.net/npm/three@0.
|
|
142
|
-
"three/webgpu": "https://cdn.jsdelivr.net/npm/three@0.
|
|
143
|
-
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.
|
|
145
|
+
"three": "https://cdn.jsdelivr.net/npm/three@0.186.0/build/three.webgpu.js",
|
|
146
|
+
"three/tsl": "https://cdn.jsdelivr.net/npm/three@0.186.0/build/three.tsl.js",
|
|
147
|
+
"three/webgpu": "https://cdn.jsdelivr.net/npm/three@0.186.0/build/three.webgpu.js",
|
|
148
|
+
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.186.0/examples/jsm/",
|
|
144
149
|
"oidn-web": "https://cdn.jsdelivr.net/npm/oidn-web@0.4.0/dist/oidn.js",
|
|
145
150
|
"rayzee": "https://cdn.jsdelivr.net/npm/rayzee/dist/rayzee.es.js"
|
|
146
151
|
}
|
|
@@ -306,7 +311,7 @@ All keys are optional — only what you pass is overridden. Call `getAssetConfig
|
|
|
306
311
|
|
|
307
312
|
### PathTracerApp
|
|
308
313
|
|
|
309
|
-
The main engine class. Extends
|
|
314
|
+
The main engine class. Extends `RayzeeRenderer`, the [renderer core](#renderer-core-rayzeecore), which extends three.js's `EventDispatcher`. Related functionality is grouped into **namespaced managers** accessed via `engine.cameraManager`, `engine.lightManager`, etc., or as direct methods on the engine instance.
|
|
310
315
|
|
|
311
316
|
```js
|
|
312
317
|
const engine = new PathTracerApp(canvas, options?)
|
|
@@ -346,12 +351,15 @@ Constructing a new `PathTracerApp` on a canvas that already has an active instan
|
|
|
346
351
|
#### Loading Assets
|
|
347
352
|
|
|
348
353
|
```js
|
|
349
|
-
await engine.loadModel(url) // Load GLB/GLTF
|
|
354
|
+
await engine.loadModel(url) // Load a GLB/GLTF by URL
|
|
355
|
+
await engine.loadFile(fileOrUrl) // Any supported file: GLB/GLTF/FBX/OBJ/STL/PLY/DAE/3MF/USD/USDZ, archives, HDR/EXR
|
|
350
356
|
await engine.loadObject3D(object3d, name?) // Load a Three.js Object3D directly (name is optional, defaults to 'object3d')
|
|
351
357
|
await engine.loadEnvironment(url) // Load HDR/EXR environment map
|
|
352
358
|
engine.cancelLoad() // Abort an in-flight download (network phase only; no-op once processing starts)
|
|
353
359
|
```
|
|
354
360
|
|
|
361
|
+
On `rayzee/core`, formats other than glTF and `.hdr` need the `rayzee/addons/formats` add-on — see [Add-ons](#add-ons).
|
|
362
|
+
|
|
355
363
|
`loadModel` / `loadObject3D` **replace** the current scene. To add or remove objects from a live scene without a full reload (and without reframing the camera):
|
|
356
364
|
|
|
357
365
|
```js
|
|
@@ -368,6 +376,8 @@ engine.setSceneObjectVisibility(id, visible) // Toggle visi
|
|
|
368
376
|
|
|
369
377
|
##### Loading part of a scene archive
|
|
370
378
|
|
|
379
|
+
On `rayzee/core`, archives and pbrt need the `rayzee/addons/archives` add-on — see [Renderer core](#renderer-core-rayzeecore).
|
|
380
|
+
|
|
371
381
|
A pbrt-v4 scene archive (`.tar`, `.tar.gz`, `.zip`) is usually a root `.pbrt` file that includes one
|
|
372
382
|
subtree per element, and the whole thing rarely fits in a browser tab — Moana is 29 GB unpacked.
|
|
373
383
|
The archive can be inspected without retaining any of it, then loaded one element at a time:
|
|
@@ -437,6 +447,7 @@ Key settings:
|
|
|
437
447
|
| `environmentRotation` | `number` | 0 | Environment Y-rotation (degrees); 0 shows the HDRI as authored, as Blender's unmapped world does |
|
|
438
448
|
| `showBackground` | `boolean` | true | Show the environment as a visible backdrop for camera-miss rays (vs. a solid/transparent background) |
|
|
439
449
|
| `samplingTechnique` | `number` | 2 | Sampler: `0` PCG, `1` scrambled Halton, `2` Owen-scrambled Sobol |
|
|
450
|
+
| `integrator` | `string` | 'path' | `'path'` \| `'bidirectional'` \| `'vcm'` (on the core, needs the bidirectional add-on). Bidirectional also traces light subpaths from every light — emissive surfaces, rect/disk, point, spot and directional lights, the sun and the environment — far faster for caustics and light through small openings, about 2× the cost per sample. On a lamp-lit interior with an HDRI it is ~20 % less noisy at equal time; a room lit only through a window stays better path traced. `'vcm'` adds photon merging, for caustics seen in mirrors and through glass. Switching rebuilds the kernels |
|
|
440
451
|
| `fireflyThreshold` | `number` | 3.0 | Firefly clamping threshold |
|
|
441
452
|
| `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 |
|
|
442
453
|
| `transmissiveBounces` | `number` | 5 | Max bounces for transmissive materials |
|
|
@@ -451,23 +462,23 @@ Key settings:
|
|
|
451
462
|
| `unitsPerMetre` | `number` | 1 | Physical mode: scene units per real metre, for files whose units are not metres. It carries over between model loads — reset it when the new file's units differ |
|
|
452
463
|
| `transparentBackground` | `boolean` | false | Transparent canvas background |
|
|
453
464
|
| `interactionModeEnabled` | `boolean` | true | Render at lower resolution while the camera moves, keeping the full bounce budget ("Fast Navigation" in the app) |
|
|
454
|
-
| `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 |
|
|
465
|
+
| `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. `PathTracerApp` only |
|
|
455
466
|
| `renderMode` | `number` | 0 | Internal preview(0)/production(1) flag driving accumulation & ASVGF behavior — normally set via `configureForMode()`, not written directly |
|
|
456
467
|
| `visMode` | `number` | 0 | Debug visualization mode (0 = off) |
|
|
457
|
-
| `environmentMode` | `string` | 'hdri' | Sky mode: `'hdri'` \| `'procedural'` \| `'
|
|
468
|
+
| `environmentMode` | `string` | 'hdri' | Sky mode: `'hdri'` \| `'procedural'` \| `'color'` — not routed through `engine.settings`; use `engine.environmentManager.setMode()` instead |
|
|
458
469
|
| `cameraProjection` | `string` | 'perspective' | `'perspective'` \| `'orthographic'` \| `'equirectangular'` — see [Camera Projection](#camera-projection-orthographic-360-panorama) |
|
|
459
470
|
| `panoramaLonRange` | `[number, number]` | `[-180, 180]` | Panorama longitude sweep, degrees, left→right |
|
|
460
471
|
| `panoramaLatRange` | `[number, number]` | `[-90, 90]` | Panorama latitude sweep, degrees, bottom→top |
|
|
461
472
|
| `panoramaLevelHorizon` | `boolean` | true | Yaw-only panorama basis, so orbit pitch/roll can't tilt the horizon |
|
|
462
473
|
| `useAdaptiveSampling` | `boolean` | true | Whole-frame early-stop once convergence reaches `adaptiveStopFraction` |
|
|
463
|
-
| `noiseThreshold` | `number` | 0.
|
|
474
|
+
| `noiseThreshold` | `number` | 0.1 | √-luminance-normalized per-pixel noise below which a pixel counts as converged (the production preset uses 0.02) |
|
|
464
475
|
| `adaptiveMinSamples` | `number` | 8 | Minimum samples before adaptive sampling can trigger |
|
|
465
|
-
| `adaptiveStopFraction` | `number` | 0.
|
|
476
|
+
| `adaptiveStopFraction` | `number` | 0.90 | Fraction of pixels that must converge before the frame retires (the production preset uses 0.94) |
|
|
466
477
|
| `usePixelFreeze` | `boolean` | true | Per-pixel freeze (Tier-2): skip individually-converged pixels via active-list compaction |
|
|
467
478
|
| `pixelFreezeThreshold` | `number` | 0.02 | Relative-error threshold for a pixel to become a freeze candidate |
|
|
468
479
|
| `pixelFreezeStability` | `number` | 8 | Consecutive candidate frames required before a pixel freezes |
|
|
469
480
|
|
|
470
|
-
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`.
|
|
481
|
+
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`. On the core without the colour add-on, set `renderer.renderer.toneMapping`.
|
|
471
482
|
|
|
472
483
|
#### Rendering Modes
|
|
473
484
|
|
|
@@ -480,6 +491,168 @@ To pause rendering for image-viewing UI, set `engine.pauseRendering = true` and
|
|
|
480
491
|
|
|
481
492
|
---
|
|
482
493
|
|
|
494
|
+
### Renderer core (`rayzee/core`)
|
|
495
|
+
|
|
496
|
+
`PathTracerApp` is built on `RayzeeRenderer`, the renderer without the viewer: a scene and camera in, path-traced samples accumulated, the image out. The denoisers, camera controls, gizmo, overlays, timeline and animation playback exist only in `PathTracerApp`; six capabilities come as add-ons — file formats beyond glTF and `.hdr`, the physical sky, scene archives, bidirectional path tracing, OpenColorIO colour and on-disk storage. Its entry point downloads about 40 % less (249 KB against 418 KB compressed). It takes the same constructor options except `container`, and renders the same pixels.
|
|
497
|
+
|
|
498
|
+
```js
|
|
499
|
+
import { RayzeeRenderer } from 'rayzee/core';
|
|
500
|
+
|
|
501
|
+
const renderer = await new RayzeeRenderer(canvas).init();
|
|
502
|
+
await renderer.loadModel('/models/scene.glb');
|
|
503
|
+
renderer.camera.position.set(0, 2, 6); // the camera it renders from; reset() after moving it
|
|
504
|
+
renderer.camera.lookAt(0, 0, 0);
|
|
505
|
+
renderer.reset();
|
|
506
|
+
await renderer.renderFrames(256);
|
|
507
|
+
const image = await renderer.renderToBuffer({ colorSpace: 'srgb' });
|
|
508
|
+
renderer.dispose();
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
Two runnable examples live in the repository: `rayzee/examples/core-node.mjs` (the core alone, in Node, writing a PNG)
|
|
512
|
+
and `rayzee/examples/core-browser/` (the core plus the physical sky, accumulating on a canvas).
|
|
513
|
+
|
|
514
|
+
#### Add-ons
|
|
515
|
+
|
|
516
|
+
Six capabilities install on the core explicitly. `PathTracerApp` installs all six itself, so nothing in this
|
|
517
|
+
section applies to it.
|
|
518
|
+
|
|
519
|
+
| Add-on | Import | Install | When | Without it |
|
|
520
|
+
|---|---|---|---|---|
|
|
521
|
+
| File formats | `fbxFormat`, `objFormat`, `stlFormat`, `plyFormat`, `colladaFormat`, `threeMFFormat`, `usdFormat`, `exrFormat` or `allFormats` from `rayzee/addons/formats` | `renderer.assetLoader.registerFormat(objFormat, exrFormat)` | after `init()` | only glTF/GLB, `.hdr` and images load; any other file's error names the add-on |
|
|
522
|
+
| Physical sky | `PhysicalSky` from `rayzee/addons/physical-sky` | `renderer.environmentManager.setProceduralSky(PhysicalSky)` | after `init()` | `'procedural'` mode records `capability.missing` (throws under `strict`) |
|
|
523
|
+
| Scene archives and pbrt | `ArchiveImporter` from `rayzee/addons/archives` | `renderer.assetLoader.setArchiveImporter(new ArchiveImporter(renderer.assetLoader))` | after `init()` | `.zip`, `.tar` and `.tgz` are not supported formats, and the error names the add-on |
|
|
524
|
+
| Bidirectional and VCM | `BidirectionalIntegrator` from `rayzee/addons/bidirectional` | `renderer.stages.pathTracer.registerIntegrator(['bidirectional', 'vcm'], pt => new BidirectionalIntegrator(pt))` | after `init()` | choosing either integrator records `capability.missing` (throws under `strict`) and keeps the current one |
|
|
525
|
+
| OpenColorIO colour | `ColorManagement` from `rayzee/addons/color` | `renderer.setColorManagement(ColorManagement)` | before or after `init()` | linear Rec.709 through three.js's own tone mappers; `loadColorConfig()` records `capability.missing` and rejects |
|
|
526
|
+
| On-disk storage | `acquireSharedStorage` from `rayzee/addons/storage` | `renderer.setStorageOpener(acquireSharedStorage)` | **before** `init()` | downloads land in memory and nothing is cached between visits |
|
|
527
|
+
|
|
528
|
+
`init()` creates the asset loader, the environment manager and the path tracer stage, which is why four of them come
|
|
529
|
+
after it. Storage is opened during `init()`, so its opener has to be set first.
|
|
530
|
+
|
|
531
|
+
All six, in that order:
|
|
532
|
+
|
|
533
|
+
```js
|
|
534
|
+
import { RayzeeRenderer, configureAssets } from 'rayzee/core';
|
|
535
|
+
import { acquireSharedStorage } from 'rayzee/addons/storage';
|
|
536
|
+
import { ColorManagement } from 'rayzee/addons/color';
|
|
537
|
+
import { ArchiveImporter } from 'rayzee/addons/archives';
|
|
538
|
+
import { PhysicalSky } from 'rayzee/addons/physical-sky';
|
|
539
|
+
import { BidirectionalIntegrator } from 'rayzee/addons/bidirectional';
|
|
540
|
+
import { allFormats } from 'rayzee/addons/formats';
|
|
541
|
+
|
|
542
|
+
configureAssets({ ocioRuntimeFactory: () => import('@bb-studio/ocio') });
|
|
543
|
+
|
|
544
|
+
const renderer = new RayzeeRenderer(canvas);
|
|
545
|
+
renderer.setStorageOpener(acquireSharedStorage); // before init()
|
|
546
|
+
renderer.setColorManagement(ColorManagement);
|
|
547
|
+
await renderer.init();
|
|
548
|
+
renderer.assetLoader.registerFormat(...allFormats);
|
|
549
|
+
renderer.assetLoader.setArchiveImporter(new ArchiveImporter(renderer.assetLoader));
|
|
550
|
+
renderer.environmentManager.setProceduralSky(PhysicalSky);
|
|
551
|
+
renderer.stages.pathTracer.registerIntegrator(['bidirectional', 'vcm'], pt => new BidirectionalIntegrator(pt));
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
**Loading on first use.** The physical sky and the archive importer can be installed as loaders instead, so their code
|
|
555
|
+
is fetched only the first time the sky is baked or an archive is read — `PathTracerApp` does this. The archive loader
|
|
556
|
+
takes the formats it reads, which `rayzee/core` exports, so the loader recognises an archive before its code exists:
|
|
557
|
+
|
|
558
|
+
```js
|
|
559
|
+
import { ARCHIVE_FORMATS } from 'rayzee/core';
|
|
560
|
+
|
|
561
|
+
renderer.environmentManager.setProceduralSkyLoader(() => import('rayzee/addons/physical-sky').then((m) => m.PhysicalSky));
|
|
562
|
+
renderer.assetLoader.setArchiveImporterLoader(
|
|
563
|
+
() => import('rayzee/addons/archives').then((m) => new m.ArchiveImporter(renderer.assetLoader)),
|
|
564
|
+
ARCHIVE_FORMATS,
|
|
565
|
+
);
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
Colour, storage and the integrators have no loader: colour and storage are used at startup, and an integrator applies
|
|
569
|
+
the moment it is chosen (a lazy one would trace plain frames meanwhile and break reproducible renders).
|
|
570
|
+
|
|
571
|
+
**File formats.** The core reads glTF/GLB (Draco, KTX2 and meshopt decoders are fetched only for a file that uses
|
|
572
|
+
them), `.hdr` and LDR images. FBX, OBJ, STL, PLY, Collada, 3MF, USD/USDZ and EXR are formats to register — import only
|
|
573
|
+
those you read and a bundler leaves the rest out; each three.js loader is downloaded the first time its format is read:
|
|
574
|
+
|
|
575
|
+
```js
|
|
576
|
+
import { objFormat, usdFormat, exrFormat } from 'rayzee/addons/formats';
|
|
577
|
+
|
|
578
|
+
renderer.assetLoader.registerFormat(objFormat, usdFormat, exrFormat);
|
|
579
|
+
await renderer.loadFile(objFile);
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
A format of your own registers the same way. A model format's `parse` gets the file and resolves to the model; an
|
|
583
|
+
environment format's `createLoader` returns a three.js loader whose `loadAsync` resolves to a texture:
|
|
584
|
+
|
|
585
|
+
```js
|
|
586
|
+
renderer.assetLoader.registerFormat({
|
|
587
|
+
name: 'Point cloud (XYZ)', label: 'XYZ', type: 'model', extensions: ['xyz'],
|
|
588
|
+
async parse(file, { filename }) {
|
|
589
|
+
return { model: buildPoints(await file.text(), filename) };
|
|
590
|
+
},
|
|
591
|
+
});
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
**Physical sky**, for `environmentMode: 'procedural'`:
|
|
595
|
+
|
|
596
|
+
```js
|
|
597
|
+
renderer.environmentManager.setProceduralSky(PhysicalSky);
|
|
598
|
+
await renderer.environmentManager.setMode('procedural');
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
**Bidirectional path tracing and vertex merging**, for `integrator: 'bidirectional' | 'vcm'`:
|
|
602
|
+
|
|
603
|
+
```js
|
|
604
|
+
renderer.stages.pathTracer.registerIntegrator(['bidirectional', 'vcm'], pt => new BidirectionalIntegrator(pt));
|
|
605
|
+
renderer.settings.set('integrator', 'bidirectional');
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
Its controls are on the active integrator (the same on `PathTracerApp`):
|
|
609
|
+
|
|
610
|
+
```js
|
|
611
|
+
const integrator = renderer.stages.pathTracer.activeIntegrator;
|
|
612
|
+
integrator.setMergeRadius(1); // 'vcm': gather radius in pixels
|
|
613
|
+
integrator.setMergeTrust(0.25); // 'vcm': how far merging is trusted against the other strategies
|
|
614
|
+
integrator.setLightGuiding(true); // learn where light paths from the sky and sun start
|
|
615
|
+
integrator.setBidirectionalStrategy('connect', { alone: true }); // keep one strategy, for verification
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
**Scene archives** (`.zip`, `.tar`, `.tar.gz`) and the pbrt scenes in them:
|
|
619
|
+
|
|
620
|
+
```js
|
|
621
|
+
renderer.assetLoader.setArchiveImporter(new ArchiveImporter(renderer.assetLoader));
|
|
622
|
+
await renderer.loadFile(archiveFile);
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
**OpenColorIO colour management** — configs, their views and looks, working spaces and export spaces. The host supplies
|
|
626
|
+
the OCIO runtime (the engine never names the package). Without the add-on, pick a tone mapper on the three.js renderer
|
|
627
|
+
instead (`renderer.renderer.toneMapping = AgXToneMapping`):
|
|
628
|
+
|
|
629
|
+
```js
|
|
630
|
+
configureAssets({ ocioRuntimeFactory: () => import('@bb-studio/ocio') });
|
|
631
|
+
renderer.setColorManagement(ColorManagement);
|
|
632
|
+
await renderer.loadColorConfig({ builtin: 'ocio://cg-config-v4.0.0_aces-v2.0_ocio-v2.5' });
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
**On-disk storage** (the browser's origin private file system), for the download, environment and scene caches and
|
|
636
|
+
the `memorySpill` option. Asking for it without the add-on (`storage: 'auto'`) records a `capability.missing` warning;
|
|
637
|
+
`storage: false` turns it off either way:
|
|
638
|
+
|
|
639
|
+
```js
|
|
640
|
+
const renderer = new RayzeeRenderer(canvas);
|
|
641
|
+
renderer.setStorageOpener(acquireSharedStorage);
|
|
642
|
+
await renderer.init();
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
Several renderers, core or full, can live in one page; they share only the colour management and the on-disk storage,
|
|
646
|
+
which are page-wide.
|
|
647
|
+
|
|
648
|
+
Code of your own that adds a setting declares it on the renderer's settings, so it gets the same provenance, change
|
|
649
|
+
events and session saving as the built-in ones:
|
|
650
|
+
|
|
651
|
+
```js
|
|
652
|
+
renderer.settings.define('myGlowStrength', { apply: (value) => glow.setStrength(value), reset: true });
|
|
653
|
+
renderer.settings.set('myGlowStrength', 2);
|
|
654
|
+
```
|
|
655
|
+
|
|
483
656
|
### engine.cameraManager
|
|
484
657
|
|
|
485
658
|
Camera switching, auto-focus, DOF, and direct Three.js access.
|
|
@@ -641,6 +814,8 @@ A property a three.js material lacks falls back to `MATERIAL_DEFAULTS` (exported
|
|
|
641
814
|
|
|
642
815
|
### Colour Management
|
|
643
816
|
|
|
817
|
+
On `rayzee/core` this is the `rayzee/addons/color` add-on — see [Renderer core](#renderer-core-rayzeecore).
|
|
818
|
+
|
|
644
819
|
`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)).
|
|
645
820
|
|
|
646
821
|
```js
|
|
@@ -678,9 +853,8 @@ engine.environmentManager.params // Current environment parameters
|
|
|
678
853
|
engine.environmentManager.texture // The loaded environment texture
|
|
679
854
|
await engine.loadEnvironment(url) // Load HDR/EXR environment map (method on engine)
|
|
680
855
|
await engine.environmentManager.setEnvironmentMap(tex) // Set a custom environment texture
|
|
681
|
-
await engine.environmentManager.setMode(mode) // 'hdri' | 'procedural' | '
|
|
682
|
-
await engine.environmentManager.generateProcedural() // Physical sky: spectral, multiple scattering, analytic sun
|
|
683
|
-
await engine.environmentManager.generateGradient() // Gradient sky
|
|
856
|
+
await engine.environmentManager.setMode(mode) // 'hdri' | 'procedural' | 'color'
|
|
857
|
+
await engine.environmentManager.generateProcedural() // Physical sky: spectral, multiple scattering, analytic sun (core: needs rayzee/addons/physical-sky)
|
|
684
858
|
await engine.environmentManager.generateSolid() // Solid color sky
|
|
685
859
|
engine.environmentManager.markDirty() // Flag environment for GPU re-upload
|
|
686
860
|
```
|
|
@@ -708,15 +882,15 @@ Denoiser strategy, ASVGF, OIDN, upscaler, and auto-exposure.
|
|
|
708
882
|
|
|
709
883
|
```js
|
|
710
884
|
// Strategy
|
|
711
|
-
engine.denoisingManager.setStrategy('asvgf', 'medium') // 'none' | 'asvgf' | 'edgeaware'
|
|
885
|
+
engine.denoisingManager.setStrategy('asvgf', 'medium') // 'none' | 'asvgf' | 'nrd' | 'edgeaware' | 'oidn'
|
|
712
886
|
engine.denoisingManager.denoiserStrategy // read back the active strategy (derived from stage state)
|
|
713
887
|
engine.denoisingManager.setASVGFEnabled(true, 'medium')
|
|
714
888
|
engine.denoisingManager.applyASVGFPreset('high') // 'low' | 'medium' | 'high'
|
|
715
889
|
engine.denoisingManager.setAutoExposure(true)
|
|
716
890
|
|
|
717
891
|
// Fine-grained parameters
|
|
718
|
-
engine.denoisingManager.setASVGFParams({ temporalAlpha: 0.1,
|
|
719
|
-
engine.denoisingManager.setEdgeAwareParams({
|
|
892
|
+
engine.denoisingManager.setASVGFParams({ temporalAlpha: 0.1, maxAccumFrames: 16 })
|
|
893
|
+
engine.denoisingManager.setEdgeAwareParams({ phiLuminance: 4.0, atrousIterations: 5 })
|
|
720
894
|
engine.denoisingManager.setAutoExposureParams({ keyValue: 0.18 })
|
|
721
895
|
|
|
722
896
|
// OIDN & Upscaler
|
|
@@ -727,7 +901,7 @@ engine.denoisingManager.setTemporalHistory(false) // live OIDN without th
|
|
|
727
901
|
engine.denoisingManager.continuousDenoiseInterval = 250 // cap refreshes at 4/sec (default 8 = uncapped)
|
|
728
902
|
engine.denoisingManager.setUpscalerEnabled(true)
|
|
729
903
|
engine.denoisingManager.setUpscalerScaleFactor(2) // 2 or 4
|
|
730
|
-
engine.denoisingManager.setUpscalerQuality('
|
|
904
|
+
engine.denoisingManager.setUpscalerQuality('quality') // 'fast' | 'balanced' | 'quality'
|
|
731
905
|
```
|
|
732
906
|
|
|
733
907
|
### engine.interactionManager
|
|
@@ -833,6 +1007,9 @@ surface** — pin a version and branch on the strings; they are never renamed or
|
|
|
833
1007
|
| `output.source_fallback` | `renderToBuffer( { source: 'display' } )` found no denoised picture and returned the raw accumulation |
|
|
834
1008
|
| `output.tonemap_fallback` | `renderToBuffer`'s `'srgb'` bytes were tone-mapped on the CPU, not the GPU — the picture is the same within a level, only slower (a warning: strict does not throw) |
|
|
835
1009
|
| `light.placeholder_skipped` | a `RectAreaLightPlaceholder` node lacked `userData.name` or `userData.type: 'RectAreaLight'`, so no light was made for it |
|
|
1010
|
+
| `capability.missing` | a feature was asked for whose add-on is not installed on the core (procedural sky, an unregistered integrator, a colour config, storage) — names the add-on |
|
|
1011
|
+
| `color.config_load_failed` / `viewTransform.bake_failed` / `viewTransform.display_mismatch` | a colour config failed to load (the previous one stays), a view could not be rebaked, or a view targets a display the canvas cannot show (a saved buffer is still right) — warnings |
|
|
1012
|
+
| `storage.unavailable` / `storage.quota_exceeded` / `storage.write_failed` / `storage.read_failed` / `storage.entry_corrupt` / `storage.cache_mismatch` | on-disk storage is off or failed; the engine carries on in memory — warnings |
|
|
836
1013
|
|
|
837
1014
|
`asset.unreachable` also covers what the engine fetches for itself: OIDN weights, IES profiles and
|
|
838
1015
|
gobos (`detail.asset` says which).
|
|
@@ -1102,7 +1279,9 @@ app.dispose();
|
|
|
1102
1279
|
JPEG or WebP to RGBA8, straight alpha, top row first — since the engine carries no decoder. It decodes
|
|
1103
1280
|
every glTF image, embedded or not, and JPEG/PNG skies. PNGs with bytes after `IEND`, which browsers
|
|
1104
1281
|
accept and strict decoders refuse, are trimmed first; a texture that still fails is recorded as
|
|
1105
|
-
`texture.build_failed` rather than dropped.
|
|
1282
|
+
`texture.build_failed` rather than dropped. Without `decodeImage`, each glTF image is recorded that way with what to
|
|
1283
|
+
configure (a strict host's load throws), and the model loads untextured. KTX2 (Basis) textures need no
|
|
1284
|
+
`decodeImage`: three's KTX2 loader decodes them, in a `NodeWorker` the engine lends it. Measured on a 91-texture model: `sharp` and
|
|
1106
1285
|
`@napi-rs/canvas` (`await loadImage()`, then a 2D canvas) both decode in parallel, ~0.3 s against
|
|
1107
1286
|
pngjs's 2.5 s serial. The canvas route premultiplies, which zeroes colour under alpha 0 and loses
|
|
1108
1287
|
it under low alpha; `sharp` is exact. `jpeg-js` differs from libjpeg-turbo by up to 63 levels.
|
|
@@ -1116,12 +1295,13 @@ app.dispose();
|
|
|
1116
1295
|
memory): on the main thread it held up the BVH workers, and a 1.9M-triangle, 91-texture model
|
|
1117
1296
|
loaded in 4.1–4.9 s. It now loads in 2.1 s, against Chrome's 2.9 s on the same machine.
|
|
1118
1297
|
- `nodePlatform()` also defines `ProgressEvent`, which three.js's `FileLoader` constructs while
|
|
1119
|
-
streaming; that is the only global it sets. three.js's own Draco and KTX2
|
|
1120
|
-
`Worker
|
|
1298
|
+
streaming; that is the only global it sets. three.js's own Draco and KTX2 loaders call the global
|
|
1299
|
+
`Worker`; the engine lends them `NodeWorker` for the length of each glTF parse, so a Draco or KTX2
|
|
1300
|
+
model loads with nothing set by the host.
|
|
1121
1301
|
|
|
1122
1302
|
Measured on this bench's corpus: all 29 scenes match the Chrome goldens (`npm run bench:node`, RMSE
|
|
1123
1303
|
≤ 0.0036, no pixel over 0.02 — the readback's tone map accounts for most of it), and a textured glTF with an
|
|
1124
|
-
HDR
|
|
1304
|
+
HDR or a PNG sky matches Chrome block for block within 0.05 of a level. Not available
|
|
1125
1305
|
without a browser: on-disk storage (OPFS), gobo libraries (they draw on a 2D canvas), and the AI
|
|
1126
1306
|
upscaler.
|
|
1127
1307
|
|
|
@@ -1152,6 +1332,8 @@ list. Both need `timestamp-query`, and `getDenoiseProfile()` returns `null` when
|
|
|
1152
1332
|
|
|
1153
1333
|
### On-disk Storage (OPFS)
|
|
1154
1334
|
|
|
1335
|
+
On `rayzee/core`, storage needs the `rayzee/addons/storage` add-on (`setStorageOpener`) — see [Renderer core](#renderer-core-rayzeecore).
|
|
1336
|
+
|
|
1155
1337
|
`engine.storage` is a `StorageManager` over the browser's origin private file system, or `null` where
|
|
1156
1338
|
there is none (a private window, Node) — everything works without it, only slower. The engine keeps
|
|
1157
1339
|
its caches there: downloads (models, skies, OIDN weights — revalidated at most daily with a 1-byte `Range` request, and served from the cache meanwhile),
|
|
@@ -1248,6 +1430,7 @@ engine.addEventListener(EngineEvents.RENDER_COMPLETE, (e) => {
|
|
|
1248
1430
|
| Event | Fired when |
|
|
1249
1431
|
|---|---|
|
|
1250
1432
|
| `RENDER_COMPLETE` | Rendering has converged |
|
|
1433
|
+
| `SHADERS_COMPILING` | The path tracer compiles its shaders in the background (`event.compiling` true, then false) — after a model load, a new material layer, a light transport switch. The page stays responsive; the canvas keeps its last frame until they are ready, and `renderFrames()` waits for them |
|
|
1251
1434
|
| `RENDER_RESET` | Accumulation buffer is reset |
|
|
1252
1435
|
| `FRAME` | Fires once per `animate()` tick — hook external instrumentation (stats panels, telemetry) here |
|
|
1253
1436
|
| `DENOISING_START` / `DENOISING_END` | Denoiser runs. `event.continuous` is `true` for a cadence denoise of the still-accumulating image, `false` for the one that ends a render |
|
|
@@ -1301,12 +1484,30 @@ class MyCustomStage extends RenderStage {
|
|
|
1301
1484
|
}
|
|
1302
1485
|
```
|
|
1303
1486
|
|
|
1487
|
+
To run between the path tracer and the compositor, subclass the renderer and return the stage from
|
|
1488
|
+
`_createExtraStages()` (call the parent's and add yours); for the compositor to show its picture, list
|
|
1489
|
+
`'my-stage:output'` in `_displaySources()`. `pipeline.addStage()` after `init()` appends after the
|
|
1490
|
+
compositor. A stage that needs an extra path-tracer output asks for it with
|
|
1491
|
+
`stages.pathTracer.requestOutput( name, options )` — `'gBuffer'` (the normal/depth and albedo a denoiser reads; the
|
|
1492
|
+
viewer asks for it itself) or `'hitDistance'`. Each is compiled into the path tracer only while asked for.
|
|
1493
|
+
|
|
1304
1494
|
### All Exports
|
|
1305
1495
|
|
|
1306
1496
|
```js
|
|
1307
|
-
//
|
|
1497
|
+
// The full engine (it also exports RayzeeRenderer)
|
|
1308
1498
|
import { PathTracerApp, EngineEvents, LEGACY_EVENT_NAMES } from 'rayzee';
|
|
1309
1499
|
|
|
1500
|
+
// The renderer core and its add-ons (see Renderer core)
|
|
1501
|
+
import { RayzeeRenderer } from 'rayzee/core';
|
|
1502
|
+
import { PhysicalSky } from 'rayzee/addons/physical-sky';
|
|
1503
|
+
import { ArchiveImporter } from 'rayzee/addons/archives';
|
|
1504
|
+
import { BidirectionalIntegrator } from 'rayzee/addons/bidirectional';
|
|
1505
|
+
import { ColorManagement } from 'rayzee/addons/color';
|
|
1506
|
+
import { acquireSharedStorage } from 'rayzee/addons/storage';
|
|
1507
|
+
|
|
1508
|
+
// Headless rendering (see Deterministic & Headless Rendering)
|
|
1509
|
+
import { renderHeadless, openHeadless, captureHeadless } from 'rayzee';
|
|
1510
|
+
|
|
1310
1511
|
// Platform services for hosts without a browser (see Running in Node)
|
|
1311
1512
|
import { configurePlatform, getPlatform } from 'rayzee';
|
|
1312
1513
|
import { nodePlatform, NodeWorker } from 'rayzee/node';
|
|
@@ -1431,7 +1632,7 @@ import { setBindingAudit, getBindingAuditFindings, clearBindingAuditFindings } f
|
|
|
1431
1632
|
OIDN provides high-quality AI denoising. It runs automatically once the render converges (reaches
|
|
1432
1633
|
`maxSamples`), and — in `'interactive'` mode — also on a cadence while the image is still
|
|
1433
1634
|
accumulating, so a preview shows a clean picture as it refines instead of only at the end. See
|
|
1434
|
-
[
|
|
1635
|
+
[When the denoiser runs](#when-the-denoiser-runs).
|
|
1435
1636
|
|
|
1436
1637
|
1. **Install the package**
|
|
1437
1638
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/Color/ActiveColor.js
|
|
2
|
+
var e = "Linear Rec.709 (sRGB)", t = null;
|
|
3
|
+
function n() {
|
|
4
|
+
return t;
|
|
5
|
+
}
|
|
6
|
+
function r(e) {
|
|
7
|
+
t = e, e?._publishWorkingMatrix?.();
|
|
8
|
+
}
|
|
9
|
+
function i(e) {
|
|
10
|
+
t === null && (t = e);
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { r as i, i as n, n as r, e as t };
|