rayzee 5.3.7 → 5.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +85 -2
  2. package/package.json +1 -1
  3. package/src/README.md +0 -284
package/README.md CHANGED
@@ -93,7 +93,8 @@ A single HTML file — no Node.js, no build step. Uses [ES module import maps](h
93
93
  "three/webgpu": "https://cdn.jsdelivr.net/npm/three@0.183.0/build/three.webgpu.js",
94
94
  "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.183.0/examples/jsm/",
95
95
  "stats-gl": "https://cdn.jsdelivr.net/npm/stats-gl@4.0.2/dist/main.js",
96
- "rayzee": "https://cdn.jsdelivr.net/gh/atul-mourya/RayTracing@main/rayzee/dist/rayzee.es.js"
96
+ "oidn-web": "https://cdn.jsdelivr.net/npm/oidn-web@0.3.5/dist/oidn.js",
97
+ "rayzee": "https://cdn.jsdelivr.net/npm/rayzee/dist/rayzee.es.js"
97
98
  }
98
99
  }
99
100
  </script>
@@ -164,6 +165,56 @@ export default function Viewport({ modelUrl }) {
164
165
 
165
166
  No special build config is needed — models and HDRs are loaded via URL at runtime.
166
167
 
168
+ ### Integrating Alongside an Existing Three.js App
169
+
170
+ If your app already has a WebGL/WebGPU rasterized view and you want to add a path-traced mode on demand, run rayzee on its own **separate canvas** (WebGL and WebGPU can't share one) and toggle visibility.
171
+
172
+ ```js
173
+ import { PathTracerApp } from 'rayzee';
174
+
175
+ // 1. WebGPU detection
176
+ if (!navigator.gpu || !(await navigator.gpu.requestAdapter())) return;
177
+
178
+ // 2. Overlay canvas (hidden until toggled on)
179
+ const ptCanvas = document.createElement('canvas');
180
+ Object.assign(ptCanvas.style, { position: 'absolute', inset: 0, display: 'none' });
181
+ container.appendChild(ptCanvas);
182
+
183
+ let engine = null;
184
+ async function togglePathTrace(on) {
185
+ if (on && !engine) {
186
+ ptCanvas.width = container.clientWidth;
187
+ ptCanvas.height = container.clientHeight;
188
+ engine = new PathTracerApp(ptCanvas, { autoResize: false });
189
+ await engine.init();
190
+ await engine.loadEnvironment('/env.hdr'); // required for realistic lighting
191
+ await engine.loadObject3D(yourScene); // rayzee takes ownership — pass a clone if the host still renders it
192
+ engine.animate();
193
+ }
194
+ ptCanvas.style.display = on ? 'block' : 'none';
195
+ hostCanvas.style.display = on ? 'none' : 'block';
196
+ on ? engine?.resume() : engine?.pause(); // pause the inactive renderer to avoid GPU contention
197
+ }
198
+ ```
199
+
200
+ Key constraints:
201
+
202
+ - **`loadObject3D` takes ownership** of the passed `Object3D` (sets it as the active model, disposes the previous one). If your host app continues to render the same scene graph, pass `scene.clone(true)` — deep-cloning shares geometry/texture data, so memory cost is small. Clone once on first toggle, not on every switch.
203
+ - **Rayzee ignores `onBeforeCompile`.** It reads PBR material properties (albedo, roughness, metalness, …) directly into its own GPU buffers; custom shader injection on the host material has no effect on the path-traced view.
204
+ - **Always load an environment.** Path tracing without an env map produces a black background and no indirect lighting.
205
+ - **`three` is a peer dep on both sides.** Vite/webpack dedupe automatically. For script-tag setups, load one copy of `three` globally.
206
+
207
+ ### Vite tip
208
+
209
+ When rayzee is installed from npm, its pre-built `dist/rayzee.es.js` uses worker and `import.meta.url` patterns that Vite's dep pre-bundler re-parses incorrectly. Exclude it:
210
+
211
+ ```js
212
+ // vite.config.js
213
+ export default defineConfig({
214
+ optimizeDeps: { exclude: ['rayzee'] },
215
+ });
216
+ ```
217
+
167
218
  ## API Reference
168
219
 
169
220
  ### PathTracerApp
@@ -533,6 +584,28 @@ OIDN provides high-quality AI denoising for final renders. It runs automatically
533
584
 
534
585
  > **Note:** The neural network model is downloaded on first use. Subsequent runs use the browser cache. OIDN also works with `configureForMode('final-render')`, which enables it automatically alongside high-quality render settings.
535
586
 
587
+ ### Enabling the AI Upscaler
588
+
589
+ The upscaler runs ONNX super-resolution models via `onnxruntime-web`. Unlike OIDN, `onnxruntime-web` is lazily fetched from a CDN inside a Web Worker — **no npm install or import map entry is needed**.
590
+
591
+ ```js
592
+ engine.denoisingManager.setUpscalerEnabled(true);
593
+ engine.denoisingManager.setUpscalerQuality('fast'); // 'fast' | 'balanced' | 'quality'
594
+ engine.denoisingManager.setUpscalerScaleFactor(2); // 2 | 4
595
+
596
+ engine.addEventListener(EngineEvents.UPSCALING_START, () => console.log('Upscaling started'));
597
+ engine.addEventListener(EngineEvents.UPSCALING_PROGRESS, (e) => console.log('Upscaling', e));
598
+ engine.addEventListener(EngineEvents.UPSCALING_END, () => console.log('Upscaling complete'));
599
+ ```
600
+
601
+ | Quality | Model | 2× size | 4× size |
602
+ |---|---|---|---|
603
+ | `'fast'` | SPAN | 1.6 MB | 1.6 MB |
604
+ | `'balanced'` | SRVGGNetCompact | 2.4 MB | 4.9 MB |
605
+ | `'quality'` | RRDBNet / MoSR | 67 MB | 16.5 MB |
606
+
607
+ **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.
608
+
536
609
  ## Troubleshooting
537
610
 
538
611
  **OIDN: `Cannot find module './tza'` (webpack)**
@@ -553,12 +626,22 @@ Then load it via a script tag or import map instead:
553
626
  <script type="importmap">
554
627
  {
555
628
  "imports": {
556
- "oidn-web": "https://cdn.jsdelivr.net/npm/oidn-web@0.3.0/+esm"
629
+ "oidn-web": "https://cdn.jsdelivr.net/npm/oidn-web@0.3.5/dist/oidn.js"
557
630
  }
558
631
  }
559
632
  </script>
560
633
  ```
561
634
 
635
+ **OIDN: `TypeError: t.alea is not a function` or `Argument 'x' passed to 'conv2d' must be a Tensor ... got 'L'`**
636
+ You're loading `oidn-web` via `jsdelivr.net/npm/oidn-web/+esm` or `esm.sh/oidn-web`. Don't — use the **self-bundled** `/dist/oidn.js` path instead:
637
+
638
+ ```diff
639
+ - "oidn-web": "https://cdn.jsdelivr.net/npm/oidn-web@0.3.5/+esm"
640
+ + "oidn-web": "https://cdn.jsdelivr.net/npm/oidn-web@0.3.5/dist/oidn.js"
641
+ ```
642
+
643
+ Why: `oidn-web` transitively depends on `@tensorflow/tfjs-core`, which does `import * as t from "seedrandom"` and calls `t.alea(...)`. jsDelivr's `/+esm` CJS→ESM shim of `seedrandom` emits only `export default` (no named exports), so `t.alea` is undefined. Swapping to `esm.sh` trades that for a different issue: deep-path imports produce multiple tfjs-core instances, so a Tensor made in one module fails `instanceof` checks in another (`got 'L'`). The `/dist/oidn.js` file in the npm package is a single pre-bundled ESM with all of tfjs inlined — no external imports, one tfjs instance, same exports. Use it.
644
+
562
645
  **Black screen / "WebGPU not supported"**
563
646
  Your browser may not support WebGPU. Use Chrome 113+, Edge 113+, Safari 18+, or Firefox 141+. Ensure you're on HTTPS or localhost.
564
647
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rayzee",
3
- "version": "5.3.7",
3
+ "version": "5.3.8",
4
4
  "type": "module",
5
5
  "description": "Real-time WebGPU path tracing engine built on Three.js",
6
6
  "main": "dist/rayzee.umd.js",
package/src/README.md DELETED
@@ -1,284 +0,0 @@
1
- # Rayzee Engine
2
-
3
- WebGPU path tracing engine. Framework-agnostic — works with React, Vue, Svelte, or vanilla JS.
4
-
5
- ## Quick Start
6
-
7
- ```html
8
- <canvas id="c" width="512" height="512"></canvas>
9
- <script type="module">
10
- import { PathTracerApp } from 'rayzee';
11
-
12
- const engine = new PathTracerApp(document.getElementById('c'));
13
- await engine.init();
14
- await engine.loadEnvironment('studio.hdr');
15
- await engine.loadModel('scene.glb');
16
- engine.animate();
17
- </script>
18
- ```
19
-
20
- ## Constructor
21
-
22
- ```js
23
- new PathTracerApp(canvas, options?)
24
- ```
25
-
26
- | Param | Type | Description |
27
- |-------|------|-------------|
28
- | `canvas` | `HTMLCanvasElement` | Render target |
29
- | `options.autoResize` | `boolean` | Auto-listen for window resize (default `true`) |
30
-
31
- ## API Reference
32
-
33
- ### Settings — Unified Parameter Access
34
-
35
- All render parameters go through a single API. No individual setter methods.
36
-
37
- ```js
38
- engine.set('maxBounces', 8);
39
- engine.set('exposure', 1.5);
40
- engine.get('maxBounces'); // 8
41
- engine.setMany({ maxBounces: 8, exposure: 1.5 }); // batch, single reset
42
- engine.getAll(); // snapshot of all settings
43
- ```
44
-
45
- **Available setting keys:**
46
-
47
- | Key | Type | Default | Description |
48
- |-----|------|---------|-------------|
49
- | `maxBounces` | `number` | 3 | Ray bounce limit |
50
- | `samplesPerPixel` | `number` | 1 | SPP multiplier |
51
- | `maxSamples` | `number` | 60 | Max accumulated samples |
52
- | `transmissiveBounces` | `number` | 5 | Bounces through transparent materials |
53
- | `fireflyThreshold` | `number` | 1.8 | Clamp bright outliers |
54
- | `exposure` | `number` | 1.0 | Manual exposure |
55
- | `enableDOF` | `boolean` | false | Depth of field |
56
- | `focusDistance` | `number` | 0.8 | Focus distance |
57
- | `aperture` | `number` | 5.6 | F-stop |
58
- | `focalLength` | `number` | 50 | Focal length in mm |
59
- | `apertureScale` | `number` | 1.0 | Aperture multiplier |
60
- | `samplingTechnique` | `number` | 3 | Sampling strategy |
61
- | `environmentIntensity` | `number` | 1.0 | Environment brightness |
62
- | `backgroundIntensity` | `number` | 1.0 | Background brightness |
63
- | `showBackground` | `boolean` | true | Show environment background |
64
- | `transparentBackground` | `boolean` | false | Alpha transparency |
65
- | `enableEnvironment` | `boolean` | true | Enable environment lighting |
66
- | `globalIlluminationIntensity` | `number` | 1.0 | GI multiplier |
67
- | `enableEmissiveTriangleSampling` | `boolean` | false | Direct emissive sampling |
68
- | `emissiveBoost` | `number` | 1.0 | Emissive multiplier |
69
- | `useAdaptiveSampling` | `boolean` | false | Variance-guided sampling |
70
- | `adaptiveSamplingMax` | `number` | 8 | Max samples for high-variance pixels |
71
- | `visMode` | `number` | 0 | Debug visualization mode |
72
- | `debugVisScale` | `number` | 100 | Debug vis scale factor |
73
- | `renderLimitMode` | `string` | 'frames' | `'frames'` or `'time'` |
74
- | `renderTimeLimit` | `number` | 30 | Time limit in seconds |
75
- | `environmentRotation` | `number` | 0.0 | Env rotation in radians |
76
-
77
- ### Lifecycle
78
-
79
- | Method | Description |
80
- |--------|-------------|
81
- | `await init()` | Initialize WebGPU renderer and pipeline |
82
- | `animate()` | Start render loop |
83
- | `pause()` / `resume()` | Pause/resume animation |
84
- | `reset(soft?)` | Reset accumulation (`soft=true` preserves temporal history) |
85
- | `dispose()` | Release all GPU resources |
86
-
87
- ### Scene Loading
88
-
89
- | Method | Description |
90
- |--------|-------------|
91
- | `await loadModel(url)` | Load GLB/GLTF, build BVH, upload to GPU |
92
- | `await loadEnvironment(url)` | Load HDR environment map |
93
- | `await loadExampleModels(index, modelFiles)` | Load from a model catalog array |
94
-
95
- ### Rendering Mode
96
-
97
- | Method | Description |
98
- |--------|-------------|
99
- | `configureForMode(mode, opts?)` | Batch-configure for `'preview'`, `'final-render'`, or `'results'` |
100
- | `setRenderMode(0\|1)` | 0=progressive, 1=tiled |
101
- | `setTileCount(n)` | Tiles per axis (e.g. 3 = 3x3 grid) |
102
- | `isComplete()` | Whether render converged |
103
- | `getFrameCount()` | Current accumulated frame count |
104
- | `getOutputCanvas()` | Returns the correct canvas for reading pixels |
105
- | `takeScreenshot()` | Download current render as PNG |
106
-
107
- ### Managers
108
-
109
- Access camera, lights, and denoising through focused manager objects:
110
-
111
- #### `engine.cameraManager`
112
-
113
- | Property / Method | Description |
114
- |-------------------|-------------|
115
- | `.camera` | Active `PerspectiveCamera` |
116
- | `.controls` | `OrbitControls` instance |
117
- | `.switchCamera(index)` | Switch to loaded camera (0=default) |
118
- | `.getCameraNames()` | Array of camera display names |
119
- | `.setAutoFocusMode('manual'\|'auto')` | Auto-focus mode |
120
- | `.setAFScreenPoint(x, y)` | Focus point in screen-space (0-1) |
121
- | `.enterAFPointPlacementMode()` | Click-to-place AF point |
122
- | `.exitAFPointPlacementMode()` | Exit AF placement |
123
-
124
- #### `engine.lightManager`
125
-
126
- | Method | Description |
127
- |--------|-------------|
128
- | `.addLight(type)` | `'DirectionalLight'` \| `'PointLight'` \| `'SpotLight'` \| `'RectAreaLight'` |
129
- | `.removeLight(uuid)` | Remove by UUID |
130
- | `.getLights()` | Get all light descriptors |
131
- | `.clearLights()` | Remove all lights |
132
- | `.updateLights()` | Sync lights to GPU |
133
- | `.setShowLightHelper(bool)` | Toggle light visualizations |
134
-
135
- #### `engine.denoiseManager`
136
-
137
- | Method | Description |
138
- |--------|-------------|
139
- | `.setDenoiserStrategy(s, preset?)` | `'none'` \| `'asvgf'` \| `'ssrc'` \| `'edgeaware'` |
140
- | `.setASVGFEnabled(bool, preset?)` | Toggle ASVGF with optional quality preset |
141
- | `.applyASVGFPreset(name)` | `'low'` \| `'medium'` \| `'high'` |
142
- | `.setAutoExposureEnabled(bool)` | Toggle auto-exposure |
143
- | `.setAdaptiveSamplingEnabled(bool)` | Toggle adaptive sampling |
144
-
145
- ### Stage Parameter Updates
146
-
147
- For fine-grained control over individual pipeline stages:
148
-
149
- | Method | Description |
150
- |--------|-------------|
151
- | `updateASVGFParameters(params)` | Update ASVGF params (temporalAlpha, phiColor, etc.) |
152
- | `updateSSRCParameters(params)` | Update SSRC params |
153
- | `updateEdgeAwareUniforms(params)` | Update edge-aware filter uniforms |
154
- | `updateAutoExposureParameters(params)` | Update auto-exposure params |
155
- | `updateAdaptiveSamplingParameters(params)` | Update adaptive sampling params |
156
- | `setTileHelperEnabled(bool)` | Toggle tile highlight overlay (2D canvas, never baked into renders) |
157
-
158
- ### OIDN & AI Upscaler
159
-
160
- | Method | Description |
161
- |--------|-------------|
162
- | `setOIDNEnabled(bool)` | Enable/disable OIDN denoiser |
163
- | `updateOIDNQuality(quality)` | `'fast'` \| `'balance'` \| `'high'` |
164
- | `setUpscalerEnabled(bool)` | Enable/disable AI upscaler |
165
- | `setUpscalerScaleFactor(n)` | Upscale factor (2, 4) |
166
- | `setUpscalerQuality(quality)` | `'fast'` \| `'balance'` |
167
-
168
- ### Environment Modes
169
-
170
- | Method | Description |
171
- |--------|-------------|
172
- | `setEnvironmentMode(m)` | `'hdri'` \| `'procedural'` \| `'gradient'` \| `'color'` |
173
- | `await setEnvironmentMap(texture)` | Set custom env texture |
174
- | `generateProceduralSkyTexture()` | Regenerate procedural sky |
175
- | `generateGradientTexture()` | Regenerate gradient sky |
176
- | `generateSolidColorTexture()` | Regenerate solid color sky |
177
- | `markEnvironmentNeedsUpdate()` | Flag env texture for GPU re-upload |
178
-
179
- ### Materials
180
-
181
- | Method | Description |
182
- |--------|-------------|
183
- | `updateMaterialProperty(idx, prop, val)` | Update single material property |
184
- | `updateTextureTransform(idx, name, matrix)` | Update UV transform |
185
- | `rebuildMaterials(scene)` | Full material rebuild and GPU upload |
186
-
187
- ### Interaction
188
-
189
- | Method | Description |
190
- |--------|-------------|
191
- | `selectObject(obj)` | Select for outline highlight |
192
- | `toggleSelectMode()` | Toggle click-to-select |
193
- | `toggleFocusMode()` | Toggle click-to-focus |
194
- | `focusOnPoint(vec3)` | Move orbit target to world point |
195
- | `dispatchInteractionEvent(event)` | Forward events to interaction manager |
196
- | `onInteractionEvent(type, handler)` | Subscribe to interaction events (returns unsubscribe fn) |
197
-
198
- ### Direct Stage Access
199
-
200
- For advanced consumers, all pipeline stages are accessible via `engine.stages`:
201
-
202
- ```js
203
- engine.stages.pathTracer // PathTracer
204
- engine.stages.normalDepth // NormalDepth
205
- engine.stages.motionVector // MotionVector
206
- engine.stages.asvgf // ASVGF
207
- engine.stages.variance
208
- engine.stages.bilateralFilter
209
- engine.stages.adaptiveSampling
210
- engine.stages.edgeFilter
211
- engine.stages.autoExposure
212
- engine.stages.ssrc
213
- engine.stages.display // Display
214
- engine.overlayManager // OverlayManager (tile helper, scene helpers)
215
- ```
216
-
217
- ## Events
218
-
219
- Subscribe via `engine.addEventListener(EngineEvents.X, handler)`.
220
-
221
- | Event | Extra Fields | When |
222
- |-------|-------------|------|
223
- | `RENDER_COMPLETE` | | Accumulation finished |
224
- | `RENDER_RESET` | | Accumulation restarted |
225
- | `DENOISING_START` | | OIDN denoiser begins |
226
- | `DENOISING_END` | | OIDN denoiser finishes |
227
- | `UPSCALING_START` | | AI upscaler begins |
228
- | `UPSCALING_PROGRESS` | `progress` | Upscaler progress (0-1) |
229
- | `UPSCALING_END` | | AI upscaler finishes |
230
- | `LOADING_UPDATE` | `status`, `progress`, ... | Asset loading progress |
231
- | `LOADING_RESET` | | Loading state cleared |
232
- | `STATS_UPDATE` | `timeElapsed`, `samples` | Per-frame render stats |
233
- | `OBJECT_SELECTED` | `object` | Object selected |
234
- | `OBJECT_DESELECTED` | `object` | Object deselected |
235
- | `OBJECT_DOUBLE_CLICKED` | `object`, `uuid` | Object double-clicked |
236
- | `SELECT_MODE_CHANGED` | `enabled` | Select mode toggled |
237
- | `AUTO_FOCUS_UPDATED` | `distance` | Auto-focus distance changed |
238
- | `AUTO_EXPOSURE_UPDATED` | `exposure`, `luminance` | Auto-exposure computed |
239
- | `AF_POINT_PLACED` | `point` | Focus point placed via click |
240
- | `SETTING_CHANGED` | `key`, `value`, `prev` | Any render setting changed |
241
-
242
- ## Exports
243
-
244
- ```js
245
- import {
246
- PathTracerApp, // Main engine class
247
- EngineEvents, // Event type constants
248
-
249
- // Settings & managers
250
- RenderSettings, // Unified parameter store
251
- CameraManager, // Camera switching, auto-focus, DOF
252
- LightManager, // Light CRUD and GPU transfer
253
- DenoisingManager, // Denoiser strategy, OIDN, upscaler
254
-
255
- // Configuration
256
- ENGINE_DEFAULTS, // Default config values
257
- ASVGF_QUALITY_PRESETS,// { low, medium, high }
258
- CAMERA_PRESETS, // { portrait, landscape, macro, product, architectural, cinematic }
259
- CAMERA_RANGES, // { fov, focusDistance, aperture, focalLength } with min/max
260
- SKY_PRESETS, // { clearMorning, clearNoon, overcast, goldenHour, sunset, dusk }
261
- AF_DEFAULTS, // Auto-focus constants
262
- FINAL_RENDER_CONFIG, // High-quality render preset
263
- PREVIEW_RENDER_CONFIG,// Interactive preview preset
264
-
265
- // Pipeline (for building custom stages)
266
- RenderPipeline,
267
- RenderStage,
268
- StageExecutionMode,
269
- PipelineContext,
270
- } from 'rayzee';
271
- ```
272
-
273
- ## React Integration
274
-
275
- Use the provided adapter to bridge engine events to Zustand stores:
276
-
277
- ```js
278
- import { connectEngineToStore } from './src/lib/EngineAdapter.js';
279
-
280
- const cleanup = connectEngineToStore(engine, { useStore, useCameraStore, usePathTracerStore });
281
- // cleanup() to unsubscribe
282
- ```
283
-
284
- For other frameworks, subscribe to `EngineEvents` directly and update your state layer.