rayzee 7.19.1 → 7.20.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  # Rayzee Engine
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/rayzee?label=npm)](https://www.npmjs.com/package/rayzee)
4
- [![minzipped size](https://img.shields.io/badge/minzipped-174.9%20KB-blue)](https://www.npmjs.com/package/rayzee)
4
+ [![minzipped size](https://img.shields.io/badge/minzipped-176%20KB-blue)](https://www.npmjs.com/package/rayzee)
5
5
  [![downloads](https://img.shields.io/npm/dw/rayzee?label=downloads)](https://www.npmjs.com/package/rayzee)
6
6
  [![jsDelivr](https://img.shields.io/jsdelivr/npm/hm/rayzee?label=jsDelivr)](https://www.jsdelivr.com/package/npm/rayzee)
7
7
 
package/dist/rayzee.es.js CHANGED
@@ -6789,6 +6789,9 @@ var Ec = Qr("emissive"), Dc = class {
6789
6789
  }
6790
6790
  async refitBVH(e, t) {
6791
6791
  if (!this.bvhData || !this.triangleData || !this.originalToBvhMap) throw Error("No BVH data available for refit. Run buildBVH() first.");
6792
+ let n = this.triangleCount * 9;
6793
+ if (e?.length !== n) throw Error(`SceneProcessor.refitBVH: expected ${n} position floats (${this.triangleCount} triangles × 9), got ${e?.length ?? "none"}. Positions must cover every triangle in the scene, meshes in this.meshes order.`);
6794
+ if (t && t.length !== n) throw Error(`SceneProcessor.refitBVH: expected ${n} normal floats, got ${t.length}.`);
6792
6795
  if (!this._refitWorker) try {
6793
6796
  this._refitWorker = new Worker(kc, { type: "module" });
6794
6797
  } catch (e) {
@@ -6825,13 +6828,16 @@ var Ec = Qr("emissive"), Dc = class {
6825
6828
  }
6826
6829
  refitBLASes(e, t, n) {
6827
6830
  if (!this.instanceTable || !this.bvhData || !this.triangleData) throw Error("No TLAS/BLAS data available. Run buildBVH() first.");
6828
- let r = performance.now();
6831
+ let r = this.triangleCount * 9;
6832
+ if (t?.length !== r) throw Error(`SceneProcessor.refitBLASes: expected ${r} position floats (${this.triangleCount} triangles × 9, full scene), got ${t?.length ?? "none"}.`);
6833
+ if (n && n.length !== r) throw Error(`SceneProcessor.refitBLASes: expected ${r} normal floats, got ${n.length}.`);
6834
+ let i = performance.now();
6829
6835
  this._blasRefitter ||= new ec();
6830
6836
  for (let r of e) {
6831
6837
  let e = this.instanceTable.entries[r];
6832
6838
  e && (this._updateMeshTrianglePositions(e, t), n && this._patchMeshSmoothNormals(e, n), this._blasRefitter.refitRange(this.bvhData, this.triangleData, e.blasOffset, e.blasNodeCount), this.instanceTable.recomputeAABB(r, this.bvhData, this.triangleData));
6833
6839
  }
6834
- return this._refitTLAS(), { refitTimeMs: performance.now() - r };
6840
+ return this._refitTLAS(), { refitTimeMs: performance.now() - i };
6835
6841
  }
6836
6842
  computeBLASDirtyRanges(e) {
6837
6843
  let t = X.FLOATS_PER_TRIANGLE, n = [], r = [];
@@ -7343,7 +7349,7 @@ var Hc = Qr("pathtracer"), Uc = 4, Wc = class extends nr {
7343
7349
  }, this.environment = new Gi(this.scene, this.uniforms), this.environment.callbacks.onReset = () => this.reset(), this.environment.callbacks.getSceneTextureNodes = () => this.shaderBuilder.getSceneTextureNodes(), this.shaderBuilder = new zs(), this._initRenderingState(), this.setupBlueNoise(), this.tempVector2 = new on(), this.lastCameraMatrix = new St(), this.lastProjectionMatrix = new St(), this.lastRenderMode = -1, this.renderModeChangeTimeout = null, this.renderModeChangeDelay = 50, this.pendingRenderMode = null, this.lastInteractionModeState = !1, this.cameraChanged = !1, this.updateCompletionThreshold();
7344
7350
  }
7345
7351
  _initDataTextures() {
7346
- this.triangleStorageAttr = null, this.triangleStorageNode = null, this.triangleCount = 0, this.bvhStorageAttr = null, this.bvhStorageNode = null, this.bvhNodeCount = 0, this.directionalLightsData = null, this.pointLightsData = null, this.spotLightsData = null, this.areaLightsData = null, this.goboMaps = null, this.iesProfiles = null, this.stbnScalarTexture = null, this.stbnVec2Texture = null, this.lightStorageAttr = new o(new Float32Array(16), 4), this.lightStorageNode = Ce(this.lightStorageAttr, "vec4", 1).toReadOnly(), this._lightBufferRealloc = !1, this._lbvhDataCache = null, this._emissiveDataCache = null, this._bitTrailMapCache = null, this._instanceTable = null, this.spheres = [];
7352
+ this.triangleStorageAttr = null, this.triangleStorageNode = null, this.triangleCount = 0, this.bvhStorageAttr = null, this.bvhStorageNode = null, this.bvhNodeCount = 0, this.directionalLightsData = null, this.pointLightsData = null, this.spotLightsData = null, this.areaLightsData = null, this.goboMaps = null, this.iesProfiles = null, this.stbnScalarTexture = null, this.stbnVec2Texture = null, this.blueNoiseReady = Promise.resolve(), this.lightStorageAttr = new o(new Float32Array(16), 4), this.lightStorageNode = Ce(this.lightStorageAttr, "vec4", 1).toReadOnly(), this._lightBufferRealloc = !1, this._lbvhDataCache = null, this._emissiveDataCache = null, this._bitTrailMapCache = null, this._instanceTable = null, this.spheres = [];
7347
7353
  }
7348
7354
  _defineUniformGetters() {
7349
7355
  let e = this.uniforms;
@@ -7419,12 +7425,14 @@ var Hc = Qr("pathtracer"), Uc = 4, Wc = class extends nr {
7419
7425
  setupBlueNoise() {
7420
7426
  let e = new en();
7421
7427
  e.setCrossOrigin("anonymous");
7422
- let t = (e) => (e.minFilter = Dt, e.magFilter = Dt, e.wrapS = Kt, e.wrapT = Kt, e.generateMipmaps = !1, e), { stbnScalarAtlas: n, stbnVec2Atlas: r } = Vc();
7423
- e.load(n, (e) => {
7428
+ let t = (e) => (e.minFilter = Dt, e.magFilter = Dt, e.wrapS = Kt, e.wrapT = Kt, e.generateMipmaps = !1, e), { stbnScalarAtlas: n, stbnVec2Atlas: r } = Vc(), i = e.loadAsync(n).then((e) => {
7424
7429
  this.stbnScalarTexture = t(e), Rn.value = e, Hc.debug(`STBN scalar atlas ${Q.px(e.image.width, e.image.height)}`);
7425
- }), e.load(r, (e) => {
7430
+ }), a = e.loadAsync(r).then((e) => {
7426
7431
  this.stbnVec2Texture = t(e), zn.value = e, Hc.debug(`STBN vec2 atlas ${Q.px(e.image.width, e.image.height)}`);
7427
7432
  });
7433
+ this.blueNoiseReady = Promise.allSettled([i, a]).then((e) => {
7434
+ for (let t of e) t.status === "rejected" && Hc.warn("STBN atlas failed to load", t.reason);
7435
+ });
7428
7436
  }
7429
7437
  setupEventListeners() {
7430
7438
  this.on("pipeline:reset", () => {
@@ -16595,7 +16603,7 @@ var qp = 4096, Jp = class {
16595
16603
  } catch (e) {
16596
16604
  rm.warn("prior canvas owner dispose failed", e);
16597
16605
  }
16598
- nm.set(e, this), this.canvas = e, this._autoResize = t.autoResize !== !1, this._container = t.container || null, this.settings = new Qf(J), this.renderer = null, this.scene = null, this.meshScene = null, this._sceneHelpers = null, this.assetLoader = null, this._sdf = null, this._animRefitInFlight = !1, this._maxTextureSize = J.maxTextureSize, this.pipeline = null, this.stages = {}, this.cameraManager = null, this.lightManager = null, this.goboManager = null, this.iesManager = null, this.denoisingManager = null, this.overlayManager = null, this.interactionManager = null, this.transformManager = null, this.animationManager = new Qp(), this.environmentManager = null, this.isInitialized = !1, this.pauseRendering = !1, this.pathTracerEnabled = !0, this.animationManagerId = null, this.needsReset = !1, this._loadingInProgress = !1, this._needsDisplayRefresh = !1, this._paused = !1, this._emissiveSamplingUserSet = !1, this.completion = new pf(), this._resizeDebounceTimer = null, this._trackedListeners = [], this._disposed = !1, this._deviceLost = !1;
16606
+ nm.set(e, this), this.canvas = e, this._autoResize = t.autoResize !== !1, this._container = t.container || null, this.settings = new Qf(J), this.renderer = null, this.scene = null, this.meshScene = null, this._sceneHelpers = null, this.assetLoader = null, this._sdf = null, this._animRefitInFlight = !1, this._maxTextureSize = J.maxTextureSize, this.pipeline = null, this.stages = {}, this.cameraManager = null, this.lightManager = null, this.goboManager = null, this.iesManager = null, this.denoisingManager = null, this.overlayManager = null, this.interactionManager = null, this.transformManager = null, this.animationManager = new Qp(), this.environmentManager = null, this.isInitialized = !1, this.pauseRendering = !1, this.pathTracerEnabled = !0, this.animationManagerId = null, this.needsReset = !1, this._loadingInProgress = !1, this._needsDisplayRefresh = !1, this._paused = !1, this._emissiveSamplingUserSet = !1, this.completion = new pf(), this._resizeDebounceTimer = null, this._trackedListeners = [], this._disposed = !1, this._deviceLost = !1, this._deterministic = !1, this._dispatchPinned = !1, this._deterministicRestore = null;
16599
16607
  }
16600
16608
  _addTrackedListener(e, t, n) {
16601
16609
  e && (e.addEventListener(t, n), this._trackedListeners.push({
@@ -16883,6 +16891,9 @@ var qp = 4096, Jp = class {
16883
16891
  cameraNames: this.cameraManager.getCameraNames()
16884
16892
  });
16885
16893
  }
16894
+ get sceneMeshes() {
16895
+ return this._sdf?.meshes ?? [];
16896
+ }
16886
16897
  async refitBVH(e, t) {
16887
16898
  let n = await this._sdf.refitBVH(e, t);
16888
16899
  return this.stages.pathTracer.updateTriangleData(this._sdf.triangleData), this.stages.pathTracer.updateBVHData(this._sdf.bvhData), this.reset(), n;
@@ -16963,6 +16974,71 @@ var qp = 4096, Jp = class {
16963
16974
  refreshFrame() {
16964
16975
  this._needsDisplayRefresh = !0, this.wake();
16965
16976
  }
16977
+ setDeterministicMode(e = !0, { pinDispatch: t = !0 } = {}) {
16978
+ let n = this.stages.pathTracer;
16979
+ if (!n) return !1;
16980
+ if (e) this._deterministicRestore ||= {
16981
+ settings: {
16982
+ useAdaptiveSampling: this.settings.get("useAdaptiveSampling"),
16983
+ usePixelFreeze: this.settings.get("usePixelFreeze"),
16984
+ interactionModeEnabled: this.settings.get("interactionModeEnabled"),
16985
+ renderLimitMode: this.settings.get("renderLimitMode"),
16986
+ renderTimeLimit: this.settings.get("renderTimeLimit")
16987
+ },
16988
+ bounceEarlyExit: n._bounceEarlyExitThreshold,
16989
+ dynamicDispatch: n._useDynamicDispatch,
16990
+ autoFocusMode: this.cameraManager?.autoFocusMode,
16991
+ autoExposure: this.stages.autoExposure?.enabled
16992
+ }, this.settings.setMany({
16993
+ useAdaptiveSampling: !1,
16994
+ usePixelFreeze: !1,
16995
+ interactionModeEnabled: !1,
16996
+ renderLimitMode: "frames",
16997
+ renderTimeLimit: 0
16998
+ }, { silent: !0 }), t ? (n._bounceEarlyExitThreshold = -1, n._useDynamicDispatch = !1) : (n._bounceEarlyExitThreshold = this._deterministicRestore.bounceEarlyExit, n._useDynamicDispatch = this._deterministicRestore.dynamicDispatch), this.cameraManager?.setAutoFocusMode("manual"), this.stages.autoExposure && (this.stages.autoExposure.enabled = !1), this._deterministic = !0, this._dispatchPinned = t;
16999
+ else if (this._deterministicRestore) {
17000
+ let e = this._deterministicRestore;
17001
+ this.settings.setMany(e.settings, { silent: !0 }), n._bounceEarlyExitThreshold = e.bounceEarlyExit, n._useDynamicDispatch = e.dynamicDispatch, e.autoFocusMode !== void 0 && this.cameraManager?.setAutoFocusMode(e.autoFocusMode), this.stages.autoExposure && e.autoExposure !== void 0 && (this.stages.autoExposure.enabled = e.autoExposure), this._deterministicRestore = null, this._deterministic = !1, this._dispatchPinned = !1;
17002
+ }
17003
+ return this.reset(), this.stopAnimation(), this._deterministic;
17004
+ }
17005
+ get isDeterministic() {
17006
+ return this._deterministic && this._dispatchPinned;
17007
+ }
17008
+ async renderFrames(e, { reset: t = !0, yieldEvery: n = 8, onProgress: r } = {}) {
17009
+ let i = this.stages.pathTracer;
17010
+ if (!i) throw Error("renderFrames: app is not initialized");
17011
+ if (!(e > 0)) throw Error(`renderFrames: count must be positive, got ${e}`);
17012
+ await i.blueNoiseReady;
17013
+ let a = (t ? 0 : i.frameCount) + e;
17014
+ this.settings.get("maxSamples") < a && this.settings.set("maxSamples", a, {
17015
+ silent: !0,
17016
+ reset: !1
17017
+ }), t && this.reset(), this.stopAnimation();
17018
+ let o = e + 64, s = 0;
17019
+ for (; i.frameCount < a && s < o;) {
17020
+ if (this._deviceLost) throw Error("renderFrames: WebGPU device lost");
17021
+ if (!i.isReady) throw Error("renderFrames: path tracer stage is not ready");
17022
+ this.pipeline.render(), s++, r?.(i.frameCount), n > 0 && s % n === 0 && await new Promise((e) => setTimeout(e, 0));
17023
+ }
17024
+ if (i.frameCount < a) throw Error(`renderFrames: stalled at ${i.frameCount}/${a} samples after ${s} passes — something retired the render (maxSamples, a stray reset, or a canvas resize)`);
17025
+ return i.frameCount;
17026
+ }
17027
+ enableGPUTiming(e = !0) {
17028
+ let t = this.renderer?.backend;
17029
+ return !t || e && t.hasFeature?.("timestamp-query") !== !0 ? !1 : (t.trackTimestamp = e, t.trackTimestamp === e);
17030
+ }
17031
+ async getGPUTimings() {
17032
+ let e = this.renderer;
17033
+ if (!e?.backend?.trackTimestamp) return null;
17034
+ await e.resolveTimestampsAsync("compute"), await e.resolveTimestampsAsync("render");
17035
+ let t = e.info.compute.timestamp || 0, n = e.info.render.timestamp || 0;
17036
+ return {
17037
+ compute: t,
17038
+ render: n,
17039
+ total: t + n
17040
+ };
17041
+ }
16966
17042
  getCanvas() {
16967
17043
  if (!this.renderer?.domElement) return null;
16968
17044
  let e = this.denoisingManager;