rayzee 9.2.0 → 9.2.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.
package/README.md CHANGED
@@ -1043,8 +1043,9 @@ are written only while it is on), runs **one** final denoise with `app.runFinalD
1043
1043
  it back with `renderToBuffer( { source: 'display' } )`. Driving it yourself is the same three calls.
1044
1044
  `renderToBuffer` reports the picture it read as `source`, and records `output.source_fallback` when
1045
1045
  `'display'` was asked for, a denoiser is in use, and nothing had published — so a strict host cannot
1046
- ship a noisy image by mistake. Its `'srgb'` bytes are tone-mapped on the CPU and match the canvas to
1047
- within one level (it rounds half a level up); `'linear'` is exact.
1046
+ ship a noisy image by mistake. Its `'srgb'` bytes are tone-mapped on the GPU — 9 ms at 4096×2160,
1047
+ where the CPU pass it replaced took 1.4 s on an M-series Mac and 10 s on a cloud host — and match the
1048
+ canvas to within one level (it rounds half a level up); `'linear'` is exact.
1048
1049
 
1049
1050
  Constructing `PathTracerApp` yourself instead: pass `strict: true`; storage is then off unless you
1050
1051
  set it. Outside Chrome, pass `hostMemoryGB`.
@@ -1114,7 +1115,7 @@ app.dispose();
1114
1115
  `Worker`, so a model using either also needs `globalThis.Worker = NodeWorker`.
1115
1116
 
1116
1117
  Measured on this bench's corpus: all 29 scenes match the Chrome goldens (`npm run bench:node`, RMSE
1117
- ≤ 0.0036, no pixel over 0.02 — the CPU tone map accounts for most of it), and a textured glTF with an
1118
+ ≤ 0.0036, no pixel over 0.02 — the readback's tone map accounts for most of it), and a textured glTF with an
1118
1119
  HDR, a PNG sky or a gradient matches Chrome block for block within 0.05 of a level. Not available
1119
1120
  without a browser: on-disk storage (OPFS), gobo libraries (they draw on a 2D canvas), and the AI
1120
1121
  upscaler.
@@ -1148,7 +1149,7 @@ list. Both need `timestamp-query`, and `getDenoiseProfile()` returns `null` when
1148
1149
 
1149
1150
  `engine.storage` is a `StorageManager` over the browser's origin private file system, or `null` where
1150
1151
  there is none (a private window, Node) — everything works without it, only slower. The engine keeps
1151
- its caches there: downloads (models, skies, OIDN weights — revalidated with `HEAD` at most daily, and served from the cache meanwhile),
1152
+ its caches there: downloads (models, skies, OIDN weights — revalidated at most daily with a 1-byte `Range` request, and served from the cache meanwhile),
1152
1153
  unpacked `.tar.gz` archives and archive indexes, built scenes (reopened without rebuilding BVHs when
1153
1154
  the first build took ≥ 10 s), and environment sampling tables. Caches share a budget of 30 % of the
1154
1155
  quota and are evicted least-recently-used; `engine.storage.usage()` reports each area.
@@ -1246,7 +1247,7 @@ engine.addEventListener(EngineEvents.RENDER_COMPLETE, (e) => {
1246
1247
  | `FRAME` | Fires once per `animate()` tick — hook external instrumentation (stats panels, telemetry) here |
1247
1248
  | `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 |
1248
1249
  | `UPSCALING_START` / `UPSCALING_PROGRESS` / `UPSCALING_END` | AI upscaler runs |
1249
- | `LOADING_UPDATE` / `LOADING_RESET` | Asset loading progress |
1250
+ | `LOADING_UPDATE` / `LOADING_RESET` | Asset loading progress. A failed load ends with `failed: true` and the error as `status`; an archive that asks which parts to load ends with `LOADING_RESET` |
1250
1251
  | `STATS_UPDATE` | Performance stats updated |
1251
1252
  | `OBJECT_SELECTED` / `OBJECT_DESELECTED` | Object selection changes |
1252
1253
  | `OBJECT_DOUBLE_CLICKED` | Object double-clicked |
@@ -1,5 +1,5 @@
1
1
  import { t as e } from "./rolldown-runtime-CAFD8bLK.js";
2
- import { C as t, t as n, y as r } from "./ToneMapGPU-CNgexVto.js";
2
+ import { C as t, t as n, y as r } from "./ToneMapGPU-B6XIe3DU.js";
3
3
  //#region src/neural/NeuralRetouch.js
4
4
  var i = /* @__PURE__ */ e({
5
5
  NeuralRetouch: () => m,
@@ -1,5 +1,5 @@
1
1
  import { t as e } from "./rolldown-runtime-CAFD8bLK.js";
2
- import { C as t, t as n, y as r } from "./ToneMapGPU-CNgexVto.js";
2
+ import { C as t, t as n, y as r } from "./ToneMapGPU-B6XIe3DU.js";
3
3
  //#region src/EngineEvents.js
4
4
  var i = {
5
5
  RENDER_COMPLETE: "engine:renderComplete",
@@ -388,7 +388,10 @@ function Q() {
388
388
  };
389
389
  }
390
390
  Q().wgsl;
391
- var fe = (e) => `
391
+ var fe = {
392
+ packed: "\n@group(0) @binding(0) var<storage, read> src: array<u32>;\n\nfn rayzee_source( x: u32, y: u32 ) -> vec4<f32> {\n let a = ( y * params.width + x ) * 2u;\n return vec4<f32>( unpack2x16float( src[ a ] ), unpack2x16float( src[ a + 1u ] ) );\n}",
393
+ texture: "\n@group(0) @binding(0) var src: texture_2d<f32>;\n\nfn rayzee_source( x: u32, y: u32 ) -> vec4<f32> {\n return textureLoad( src, vec2<u32>( x, y ), 0 );\n}"
394
+ }, pe = (e, t) => `
392
395
  struct Params {
393
396
  width: u32,
394
397
  height: u32,
@@ -396,11 +399,12 @@ struct Params {
396
399
  flipY: u32,
397
400
  exposure: f32,
398
401
  saturation: f32,
402
+ alpha: u32,
399
403
  };
400
404
 
401
- @group(0) @binding(0) var<storage, read> src: array<u32>;
402
405
  @group(0) @binding(1) var<storage, read_write> dst: array<u32>;
403
406
  @group(0) @binding(2) var<uniform> params: Params;
407
+ ${fe[t]}
404
408
 
405
409
  ${e}
406
410
 
@@ -411,17 +415,16 @@ fn main( @builtin(global_invocation_id) gid: vec3<u32> ) {
411
415
  var srcY = gid.y;
412
416
  if ( params.flipY == 1u ) { srcY = params.height - 1u - gid.y; }
413
417
 
414
- let a = ( srcY * params.width + gid.x ) * 2u;
415
- let rg = unpack2x16float( src[ a ] );
416
- let ba = unpack2x16float( src[ a + 1u ] );
417
-
418
- let mapped = rayzee_tone_map( vec3<f32>( rg.x, rg.y, ba.x ), params.mode, params.exposure, params.saturation );
418
+ let linear = rayzee_source( gid.x, srcY );
419
+ let mapped = rayzee_tone_map( linear.rgb, params.mode, params.exposure, params.saturation );
419
420
  let b8 = rayzee_to_u8( rayzee_encode( mapped, params.mode ) );
420
- dst[ gid.y * params.width + gid.x ] = b8.x | ( b8.y << 8u ) | ( b8.z << 16u ) | ( 255u << 24u );
421
+ var a8 = 255u;
422
+ if ( params.alpha == 1u ) { a8 = rayzee_to_u8( vec3<f32>( linear.a ) ).x; }
423
+ dst[ gid.y * params.width + gid.x ] = b8.x | ( b8.y << 8u ) | ( b8.z << 16u ) | ( a8 << 24u );
421
424
  }
422
- `, $ = 32, pe = class {
423
- constructor(e, t = "rayzee:tonemap") {
424
- this.device = e, this.label = t, this.width = 0, this.height = 0, this._pipeline = null, this._storage = null, this._map = null, this._params = null, this._paramData = new ArrayBuffer($), this._paramU32 = new Uint32Array(this._paramData), this._paramF32 = new Float32Array(this._paramData), this._shaderVersion = -1, this._bindings = [], this._tables = /* @__PURE__ */ new Map(), this.disposed = !1;
425
+ `, $ = 32, me = class {
426
+ constructor(e, t = "rayzee:tonemap", { input: n = "packed" } = {}) {
427
+ this.device = e, this.label = t, this.input = n, this.width = 0, this.height = 0, this._pipeline = null, this._storage = null, this._map = null, this._params = null, this._paramData = new ArrayBuffer($), this._paramU32 = new Uint32Array(this._paramData), this._paramF32 = new Float32Array(this._paramData), this._shaderVersion = -1, this._bindings = [], this._tables = /* @__PURE__ */ new Map(), this.disposed = !1;
425
428
  }
426
429
  _ensurePipeline() {
427
430
  let { wgsl: e, bindings: t, version: n } = Q();
@@ -431,7 +434,7 @@ fn main( @builtin(global_invocation_id) gid: vec3<u32> ) {
431
434
  compute: {
432
435
  module: this.device.createShaderModule({
433
436
  label: this.label,
434
- code: fe(e)
437
+ code: pe(e, this.input)
435
438
  }),
436
439
  entryPoint: "main"
437
440
  }
@@ -489,24 +492,24 @@ fn main( @builtin(global_invocation_id) gid: vec3<u32> ) {
489
492
  usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
490
493
  }), this.width = e, this.height = t;
491
494
  }
492
- async toRGBA8(e, { exposure: t = 1, toneMapping: n = 0, saturation: r = 1, flipY: i = !1 } = {}) {
495
+ async toRGBA8(e, { exposure: t = 1, toneMapping: n = 0, saturation: r = 1, flipY: i = !1, preserveAlpha: a = !1 } = {}) {
493
496
  if (this.disposed) throw Error("PackedToneMapper: disposed");
494
497
  if (!this._storage) throw Error("PackedToneMapper: call ensureSize() first");
495
498
  this._ensurePipeline(), this._ensureTables();
496
- let { width: a, height: o } = this;
497
- this._paramU32[0] = a, this._paramU32[1] = o, this._paramU32[2] = n >>> 0, this._paramU32[3] = +!!i, this._paramF32[4] = t, this._paramF32[5] = r, this.device.queue.writeBuffer(this._params, 0, this._paramData);
498
- let s = [...this._tables.entries()].map(([e, t]) => ({
499
+ let { width: o, height: s } = this;
500
+ this._paramU32[0] = o, this._paramU32[1] = s, this._paramU32[2] = n >>> 0, this._paramU32[3] = +!!i, this._paramF32[4] = t, this._paramF32[5] = r, this._paramU32[6] = +!!a, this.device.queue.writeBuffer(this._params, 0, this._paramData);
501
+ let c = [...this._tables.entries()].map(([e, t]) => ({
499
502
  binding: e,
500
503
  resource: t.view
501
- })), c = this.device.createBindGroup({
504
+ })), l = this.device.createBindGroup({
502
505
  layout: this._pipeline.getBindGroupLayout(0),
503
506
  entries: [
504
- ...s,
507
+ ...c,
505
508
  {
506
509
  binding: 0,
507
- resource: {
510
+ resource: this.input === "texture" ? e.createView() : {
508
511
  buffer: e,
509
- size: a * o * 8
512
+ size: o * s * 8
510
513
  }
511
514
  },
512
515
  {
@@ -518,10 +521,13 @@ fn main( @builtin(global_invocation_id) gid: vec3<u32> ) {
518
521
  resource: { buffer: this._params }
519
522
  }
520
523
  ]
521
- }), l = this.device.createCommandEncoder({ label: this.label }), u = l.beginComputePass();
522
- u.setPipeline(this._pipeline), u.setBindGroup(0, c), u.dispatchWorkgroups(Math.ceil(a / 8), Math.ceil(o / 8)), u.end(), l.copyBufferToBuffer(this._storage, 0, this._map, 0, a * o * 4), this.device.queue.submit([l.finish()]), await this._map.mapAsync(GPUMapMode.READ);
523
- let d = new Uint8ClampedArray(this._map.getMappedRange().slice(0));
524
- return this._map.unmap(), d;
524
+ }), u = this.device.createCommandEncoder({ label: this.label }), d = u.beginComputePass();
525
+ d.setPipeline(this._pipeline), d.setBindGroup(0, l), d.dispatchWorkgroups(Math.ceil(o / 8), Math.ceil(s / 8)), d.end(), u.copyBufferToBuffer(this._storage, 0, this._map, 0, o * s * 4), this.device.queue.submit([u.finish()]), await this._map.mapAsync(GPUMapMode.READ);
526
+ let f = new Uint8ClampedArray(this._map.getMappedRange().slice(0));
527
+ return this._map.unmap(), f;
528
+ }
529
+ release() {
530
+ this._releaseBuffers(), this.width = this.height = 0;
525
531
  }
526
532
  _releaseBuffers() {
527
533
  this._storage?.destroy(), this._map?.destroy(), this._params?.destroy(), this._storage = null, this._map = null, this._params = null;
@@ -535,4 +541,4 @@ fn main( @builtin(global_invocation_id) gid: vec3<u32> ) {
535
541
  }
536
542
  };
537
543
  //#endregion
538
- export { C, E, S, T, Z as _, W as a, A as b, Y as c, J as d, ie as f, oe as g, se as h, L as i, G as l, ce as m, le as n, ae as o, K as p, R as r, X as s, pe as t, q as u, k as v, x as w, s as x, j as y };
544
+ export { C, E, S, T, Z as _, W as a, A as b, Y as c, J as d, ie as f, oe as g, se as h, L as i, G as l, ce as m, le as n, ae as o, K as p, R as r, X as s, me as t, q as u, k as v, x as w, s as x, j as y };