@meimu/mutracer 0.1.5 → 0.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 (590) hide show
  1. package/LICENSES/Classroom-CC0.txt +121 -0
  2. package/README.md +10 -7
  3. package/THIRD_PARTY_NOTICES.md +13 -8
  4. package/dist/assets/bvh.worker.js +1 -1
  5. package/dist/mutracer.umd.js +12316 -9228
  6. package/docs/api.md +232 -21
  7. package/docs/caustics.md +80 -0
  8. package/docs/denoising.md +30 -15
  9. package/docs/materials.md +6 -5
  10. package/docs/performance.md +5 -2
  11. package/docs/progressive-rendering.md +73 -1
  12. package/docs/technical/continuous-spectrum.md +93 -0
  13. package/docs/threejs.md +14 -5
  14. package/docs/updates.md +46 -2
  15. package/docs/viewer-checklist.md +65 -0
  16. package/docs/viewer.md +15 -8
  17. package/lib/Display.d.ts +13 -2
  18. package/lib/Display.js +28 -7
  19. package/lib/Display.js.map +1 -1
  20. package/lib/Engine.d.ts +4 -0
  21. package/lib/Engine.js +99 -37
  22. package/lib/Engine.js.map +1 -1
  23. package/lib/Render.d.ts +98 -15
  24. package/lib/Render.js +275 -27
  25. package/lib/Render.js.map +1 -1
  26. package/lib/RenderLoop.d.ts +11 -1
  27. package/lib/RenderLoop.js +120 -15
  28. package/lib/RenderLoop.js.map +1 -1
  29. package/lib/main.d.ts +6 -3
  30. package/lib/main.js +1 -0
  31. package/lib/main.js.map +1 -1
  32. package/lib/math/access.d.ts +4 -0
  33. package/lib/math/access.js +10 -0
  34. package/lib/math/access.js.map +1 -0
  35. package/lib/math/mat3.d.ts +4 -0
  36. package/lib/math/mat3.js +54 -0
  37. package/lib/math/mat3.js.map +1 -0
  38. package/lib/math/mat4.d.ts +19 -0
  39. package/lib/math/mat4.js +413 -0
  40. package/lib/math/mat4.js.map +1 -0
  41. package/lib/math/storage.d.ts +6 -0
  42. package/lib/math/storage.js +22 -0
  43. package/lib/math/storage.js.map +1 -0
  44. package/lib/math/types.d.ts +3 -0
  45. package/lib/math/types.js +2 -0
  46. package/lib/math/types.js.map +1 -0
  47. package/lib/math/vec2.d.ts +13 -0
  48. package/lib/math/vec2.js +52 -0
  49. package/lib/math/vec2.js.map +1 -0
  50. package/lib/math/vec3.d.ts +23 -0
  51. package/lib/math/vec3.js +139 -0
  52. package/lib/math/vec3.js.map +1 -0
  53. package/lib/math.d.ts +5 -17
  54. package/lib/math.js +5 -55
  55. package/lib/math.js.map +1 -1
  56. package/lib/oidn.d.ts +1 -1
  57. package/lib/oidn.js +4 -2
  58. package/lib/oidn.js.map +1 -1
  59. package/lib/oidnBundledWeights.cdn.d.ts +2 -2
  60. package/lib/renderer/AovPrimitiveCache.d.ts +10 -0
  61. package/lib/renderer/AovPrimitiveCache.js +48 -0
  62. package/lib/renderer/AovPrimitiveCache.js.map +1 -0
  63. package/lib/renderer/Box3.d.ts +5 -0
  64. package/lib/renderer/Box3.js +9 -0
  65. package/lib/renderer/Box3.js.map +1 -0
  66. package/lib/renderer/GPUTraceQueue.d.ts +11 -0
  67. package/lib/renderer/GPUTraceQueue.js +33 -0
  68. package/lib/renderer/GPUTraceQueue.js.map +1 -0
  69. package/lib/renderer/MaterialData.d.ts +15 -0
  70. package/lib/renderer/MaterialData.js +61 -0
  71. package/lib/renderer/MaterialData.js.map +1 -0
  72. package/lib/renderer/MaterialTable.d.ts +11 -98
  73. package/lib/renderer/MaterialTable.js +34 -412
  74. package/lib/renderer/MaterialTable.js.map +1 -1
  75. package/lib/renderer/RenderingPipeline.d.ts +36 -13
  76. package/lib/renderer/RenderingPipeline.js +1 -17
  77. package/lib/renderer/RenderingPipeline.js.map +1 -1
  78. package/lib/renderer/TileRender.d.ts +0 -1
  79. package/lib/renderer/TileRender.js +14 -1
  80. package/lib/renderer/TileRender.js.map +1 -1
  81. package/lib/renderer/WGPUAov.d.ts +39 -0
  82. package/lib/renderer/WGPUAov.js +239 -0
  83. package/lib/renderer/WGPUAov.js.map +1 -0
  84. package/lib/renderer/WGPUBindlessMaterialData.d.ts +17 -0
  85. package/lib/renderer/WGPUBindlessMaterialData.js +48 -0
  86. package/lib/renderer/WGPUBindlessMaterialData.js.map +1 -0
  87. package/lib/renderer/WGPUBindlessTextures.d.ts +47 -0
  88. package/lib/renderer/WGPUBindlessTextures.js +180 -0
  89. package/lib/renderer/WGPUBindlessTextures.js.map +1 -0
  90. package/lib/renderer/WGPUBloomPass.js +17 -97
  91. package/lib/renderer/WGPUBloomPass.js.map +1 -1
  92. package/lib/renderer/WGPUCausticLightPass.d.ts +48 -0
  93. package/lib/renderer/WGPUCausticLightPass.js +217 -0
  94. package/lib/renderer/WGPUCausticLightPass.js.map +1 -0
  95. package/lib/renderer/WGPUComputePass.d.ts +1 -1
  96. package/lib/renderer/WGPUComputePass.js.map +1 -1
  97. package/lib/renderer/WGPUEnvMapDistribution.d.ts +12 -0
  98. package/lib/renderer/WGPUEnvMapDistribution.js +150 -0
  99. package/lib/renderer/WGPUEnvMapDistribution.js.map +1 -0
  100. package/lib/renderer/WGPUFullQuadPass.js +10 -9
  101. package/lib/renderer/WGPUFullQuadPass.js.map +1 -1
  102. package/lib/renderer/WGPUJNLMDenoiser.d.ts +1 -20
  103. package/lib/renderer/WGPUJNLMDenoiser.js +4 -267
  104. package/lib/renderer/WGPUJNLMDenoiser.js.map +1 -1
  105. package/lib/renderer/WGPUPhotonMap.d.ts +37 -0
  106. package/lib/renderer/WGPUPhotonMap.js +191 -0
  107. package/lib/renderer/WGPUPhotonMap.js.map +1 -0
  108. package/lib/renderer/WGPURayTraceOutput.d.ts +13 -1
  109. package/lib/renderer/WGPURayTraceOutput.js +132 -29
  110. package/lib/renderer/WGPURayTraceOutput.js.map +1 -1
  111. package/lib/renderer/WGPURayTracePass.d.ts +83 -56
  112. package/lib/renderer/WGPURayTracePass.js +884 -837
  113. package/lib/renderer/WGPURayTracePass.js.map +1 -1
  114. package/lib/renderer/WGPURenderingPipeline.d.ts +5 -3
  115. package/lib/renderer/WGPURenderingPipeline.js +297 -82
  116. package/lib/renderer/WGPURenderingPipeline.js.map +1 -1
  117. package/lib/renderer/WGPUShaderCache.d.ts +2 -2
  118. package/lib/renderer/WGPUShaderCache.js +10 -5
  119. package/lib/renderer/WGPUShaderCache.js.map +1 -1
  120. package/lib/renderer/WGPUShaderCapabilities.d.ts +10 -0
  121. package/lib/renderer/WGPUShaderCapabilities.js +54 -0
  122. package/lib/renderer/WGPUShaderCapabilities.js.map +1 -0
  123. package/lib/renderer/WGPUSkyBaker.d.ts +13 -0
  124. package/lib/renderer/WGPUSkyBaker.js +85 -0
  125. package/lib/renderer/WGPUSkyBaker.js.map +1 -0
  126. package/lib/renderer/WebGLAov.d.ts +41 -0
  127. package/lib/renderer/WebGLAov.js +106 -0
  128. package/lib/renderer/WebGLAov.js.map +1 -0
  129. package/lib/renderer/WebGLFullQuadPass.d.ts +7 -4
  130. package/lib/renderer/WebGLFullQuadPass.js +22 -2
  131. package/lib/renderer/WebGLFullQuadPass.js.map +1 -1
  132. package/lib/renderer/WebGLJNLMDenoiser.d.ts +1 -1
  133. package/lib/renderer/WebGLJNLMDenoiser.js +83 -74
  134. package/lib/renderer/WebGLJNLMDenoiser.js.map +1 -1
  135. package/lib/renderer/WebGLRayTraceOutputPass.js +7 -4
  136. package/lib/renderer/WebGLRayTraceOutputPass.js.map +1 -1
  137. package/lib/renderer/WebGLRayTracePass.d.ts +18 -3
  138. package/lib/renderer/WebGLRayTracePass.js +121 -9
  139. package/lib/renderer/WebGLRayTracePass.js.map +1 -1
  140. package/lib/renderer/WebGLRenderingPipeline.js +126 -22
  141. package/lib/renderer/WebGLRenderingPipeline.js.map +1 -1
  142. package/lib/renderer/WebGLSkyBaker.d.ts +39 -0
  143. package/lib/renderer/WebGLSkyBaker.js +422 -0
  144. package/lib/renderer/WebGLSkyBaker.js.map +1 -0
  145. package/lib/renderer/WebGLSkySource.d.ts +9 -0
  146. package/lib/renderer/WebGLSkySource.js +28 -0
  147. package/lib/renderer/WebGLSkySource.js.map +1 -0
  148. package/lib/renderer/accumulationTarget.d.ts +6 -0
  149. package/lib/renderer/accumulationTarget.js.map +1 -1
  150. package/lib/renderer/aov.d.ts +42 -0
  151. package/lib/renderer/aov.js +50 -0
  152. package/lib/renderer/aov.js.map +1 -0
  153. package/lib/renderer/aovDisplay.d.ts +14 -0
  154. package/lib/renderer/aovDisplay.js +32 -0
  155. package/lib/renderer/aovDisplay.js.map +1 -0
  156. package/lib/renderer/aovScene.d.ts +21 -0
  157. package/lib/renderer/aovScene.js +139 -0
  158. package/lib/renderer/aovScene.js.map +1 -0
  159. package/lib/renderer/binnedSahBvh.js +2 -1
  160. package/lib/renderer/binnedSahBvh.js.map +1 -1
  161. package/lib/renderer/bvhAccel.d.ts +20 -10
  162. package/lib/renderer/bvhAccel.js +168 -58
  163. package/lib/renderer/bvhAccel.js.map +1 -1
  164. package/lib/renderer/bvhWorkerBuild.d.ts +1 -0
  165. package/lib/renderer/cameraSnapshot.js +2 -1
  166. package/lib/renderer/cameraSnapshot.js.map +1 -1
  167. package/lib/renderer/cameraUniform.d.ts +2 -0
  168. package/lib/renderer/cameraUniform.js +12 -0
  169. package/lib/renderer/cameraUniform.js.map +1 -0
  170. package/lib/renderer/causticDiagnostics.d.ts +31 -0
  171. package/lib/renderer/causticDiagnostics.js +5 -0
  172. package/lib/renderer/causticDiagnostics.js.map +1 -0
  173. package/lib/renderer/causticEmission.d.ts +10 -0
  174. package/lib/renderer/causticEmission.js +40 -0
  175. package/lib/renderer/causticEmission.js.map +1 -0
  176. package/lib/renderer/causticUniform.d.ts +12 -0
  177. package/lib/renderer/causticUniform.js +22 -0
  178. package/lib/renderer/causticUniform.js.map +1 -0
  179. package/lib/renderer/caustics.d.ts +16 -0
  180. package/lib/renderer/caustics.js +93 -0
  181. package/lib/renderer/caustics.js.map +1 -0
  182. package/lib/renderer/committedScene.js +4 -0
  183. package/lib/renderer/committedScene.js.map +1 -1
  184. package/lib/renderer/denoiser.d.ts +3 -11
  185. package/lib/renderer/denoiser.js.map +1 -1
  186. package/lib/renderer/depthQuery.js +4 -1
  187. package/lib/renderer/depthQuery.js.map +1 -1
  188. package/lib/renderer/displacementPreparation.d.ts +11 -0
  189. package/lib/renderer/displacementPreparation.js +351 -0
  190. package/lib/renderer/displacementPreparation.js.map +1 -0
  191. package/lib/renderer/displacementRange.d.ts +1 -0
  192. package/lib/renderer/displacementRange.js +9 -0
  193. package/lib/renderer/displacementRange.js.map +1 -0
  194. package/lib/renderer/displayParityDiagnostics.d.ts +11 -0
  195. package/lib/renderer/displayParityDiagnostics.js +2 -0
  196. package/lib/renderer/displayParityDiagnostics.js.map +1 -0
  197. package/lib/renderer/envMapCreation.d.ts +9 -8
  198. package/lib/renderer/envMapCreation.js +36 -12
  199. package/lib/renderer/envMapCreation.js.map +1 -1
  200. package/lib/renderer/envMapDistribution.d.ts +12 -2
  201. package/lib/renderer/envMapDistribution.js +43 -34
  202. package/lib/renderer/envMapDistribution.js.map +1 -1
  203. package/lib/renderer/geometryBvhBounds.d.ts +4 -0
  204. package/lib/renderer/geometryBvhBounds.js +82 -0
  205. package/lib/renderer/geometryBvhBounds.js.map +1 -0
  206. package/lib/renderer/geometryUpdateState.d.ts +32 -0
  207. package/lib/renderer/geometryUpdateState.js +2 -0
  208. package/lib/renderer/geometryUpdateState.js.map +1 -0
  209. package/lib/renderer/geometryUpdates.d.ts +17 -9
  210. package/lib/renderer/geometryUpdates.js +92 -33
  211. package/lib/renderer/geometryUpdates.js.map +1 -1
  212. package/lib/renderer/glsl/aovDisplay.frag.d.ts +3 -0
  213. package/lib/renderer/glsl/aovDisplay.frag.js +54 -0
  214. package/lib/renderer/glsl/aovDisplay.frag.js.map +1 -0
  215. package/lib/renderer/glsl/aovReflectance.glsl.d.ts +2 -0
  216. package/lib/renderer/glsl/aovReflectance.glsl.js +87 -0
  217. package/lib/renderer/glsl/aovReflectance.glsl.js.map +1 -0
  218. package/lib/renderer/glsl/aovReflectanceSamples.glsl.d.ts +2 -0
  219. package/lib/renderer/glsl/aovReflectanceSamples.glsl.js +135 -0
  220. package/lib/renderer/glsl/aovReflectanceSamples.glsl.js.map +1 -0
  221. package/lib/renderer/glsl/aovTrace.frag.d.ts +2 -0
  222. package/lib/renderer/glsl/aovTrace.frag.js +121 -0
  223. package/lib/renderer/glsl/aovTrace.frag.js.map +1 -0
  224. package/lib/renderer/glsl/chunks/cameraRay.glsl.js +12 -12
  225. package/lib/renderer/glsl/chunks/emissiveLight.glsl.d.ts +2 -0
  226. package/lib/renderer/glsl/chunks/emissiveLight.glsl.js +35 -0
  227. package/lib/renderer/glsl/chunks/emissiveLight.glsl.js.map +1 -0
  228. package/lib/renderer/glsl/chunks/envMap.glsl.js +73 -67
  229. package/lib/renderer/glsl/chunks/envMap.glsl.js.map +1 -1
  230. package/lib/renderer/glsl/chunks/intersect.glsl.js +432 -434
  231. package/lib/renderer/glsl/chunks/intersect.glsl.js.map +1 -1
  232. package/lib/renderer/glsl/chunks/materialBuffer.glsl.d.ts +1 -0
  233. package/lib/renderer/glsl/chunks/materialBuffer.glsl.js +160 -157
  234. package/lib/renderer/glsl/chunks/materialBuffer.glsl.js.map +1 -1
  235. package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js +802 -802
  236. package/lib/renderer/glsl/chunks/rand.glsl.js +3 -3
  237. package/lib/renderer/glsl/chunks/random.glsl.js +6 -6
  238. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.d.ts +1 -0
  239. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js +72 -67
  240. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js.map +1 -1
  241. package/lib/renderer/glsl/chunks/sampleLight.glsl.js +94 -76
  242. package/lib/renderer/glsl/chunks/sampleLight.glsl.js.map +1 -1
  243. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.d.ts +1 -0
  244. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js +143 -120
  245. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js.map +1 -1
  246. package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js +21 -18
  247. package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js.map +1 -1
  248. package/lib/renderer/glsl/chunks/sampling.glsl.js +91 -94
  249. package/lib/renderer/glsl/chunks/sampling.glsl.js.map +1 -1
  250. package/lib/renderer/glsl/chunks/sobol.glsl.js +79 -79
  251. package/lib/renderer/glsl/chunks/textureLinear.glsl.js +5 -5
  252. package/lib/renderer/glsl/chunks/uvProjection.glsl.js +12 -12
  253. package/lib/renderer/glsl/chunks/uvProjection.glsl.js.map +1 -1
  254. package/lib/renderer/glsl/depthQuery.frag.js +7 -7
  255. package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js +17 -9
  256. package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js.map +1 -1
  257. package/lib/renderer/glsl/rayTrace.frag.d.ts +1 -1
  258. package/lib/renderer/glsl/rayTrace.frag.js +271 -248
  259. package/lib/renderer/glsl/rayTrace.frag.js.map +1 -1
  260. package/lib/renderer/glsl/shadowCatcher.frag.js +37 -32
  261. package/lib/renderer/glsl/shadowCatcher.frag.js.map +1 -1
  262. package/lib/renderer/glsl/webglPipeline.frag.js +65 -60
  263. package/lib/renderer/glsl/webglPipeline.frag.js.map +1 -1
  264. package/lib/renderer/lightConstants.d.ts +10 -0
  265. package/lib/renderer/lightConstants.js +11 -0
  266. package/lib/renderer/lightConstants.js.map +1 -0
  267. package/lib/renderer/lightCore.d.ts +12 -0
  268. package/lib/renderer/lightCore.js +13 -0
  269. package/lib/renderer/lightCore.js.map +1 -0
  270. package/lib/renderer/lightSampling.d.ts +22 -18
  271. package/lib/renderer/lightSampling.js +135 -62
  272. package/lib/renderer/lightSampling.js.map +1 -1
  273. package/lib/renderer/lightsData.d.ts +21 -0
  274. package/lib/renderer/lightsData.js +192 -0
  275. package/lib/renderer/lightsData.js.map +1 -0
  276. package/lib/renderer/lightsUtil.d.ts +3 -26
  277. package/lib/renderer/lightsUtil.js +3 -153
  278. package/lib/renderer/lightsUtil.js.map +1 -1
  279. package/lib/renderer/materialBufferData.d.ts +70 -0
  280. package/lib/renderer/materialBufferData.js +2 -0
  281. package/lib/renderer/materialBufferData.js.map +1 -0
  282. package/lib/renderer/materialConstants.d.ts +11 -0
  283. package/lib/renderer/materialConstants.js +11 -0
  284. package/lib/renderer/materialConstants.js.map +1 -1
  285. package/lib/renderer/materialCore.d.ts +8 -0
  286. package/lib/renderer/materialCore.js +9 -0
  287. package/lib/renderer/materialCore.js.map +1 -0
  288. package/lib/renderer/materialEmission.d.ts +2 -2
  289. package/lib/renderer/materialEmission.js +3 -3
  290. package/lib/renderer/materialEmission.js.map +1 -1
  291. package/lib/renderer/materialLayout.d.ts +2 -101
  292. package/lib/renderer/materialLayout.js +110 -172
  293. package/lib/renderer/materialLayout.js.map +1 -1
  294. package/lib/renderer/materialLayoutSchema.d.ts +26 -0
  295. package/lib/renderer/materialLayoutSchema.js +172 -0
  296. package/lib/renderer/materialLayoutSchema.js.map +1 -0
  297. package/lib/renderer/materialParams.d.ts +69 -0
  298. package/lib/renderer/materialParams.js +272 -0
  299. package/lib/renderer/materialParams.js.map +1 -0
  300. package/lib/renderer/materialTextureSlots.d.ts +14 -324
  301. package/lib/renderer/materialTextureSlots.js +21 -8
  302. package/lib/renderer/materialTextureSlots.js.map +1 -1
  303. package/lib/renderer/materialTextures.d.ts +6 -0
  304. package/lib/renderer/{texturesFromMaterials.js → materialTextures.js} +1 -2
  305. package/lib/renderer/materialTextures.js.map +1 -0
  306. package/lib/renderer/mergeMeshesToGeometry.js +6 -147
  307. package/lib/renderer/mergeMeshesToGeometry.js.map +1 -1
  308. package/lib/renderer/meshInstances.d.ts +4 -21
  309. package/lib/renderer/meshInstances.js +10 -56
  310. package/lib/renderer/meshInstances.js.map +1 -1
  311. package/lib/renderer/oidnNetwork.d.ts +2 -2
  312. package/lib/renderer/oidnNetwork.js +1 -1
  313. package/lib/renderer/oidnNetwork.js.map +1 -1
  314. package/lib/renderer/openPbrEnergyLut.js +850 -846
  315. package/lib/renderer/openPbrEnergyLut.js.map +1 -1
  316. package/lib/renderer/ownedDenoiser.d.ts +9 -0
  317. package/lib/renderer/ownedDenoiser.js +2 -0
  318. package/lib/renderer/ownedDenoiser.js.map +1 -0
  319. package/lib/renderer/packedMeshInstances.d.ts +23 -0
  320. package/lib/renderer/packedMeshInstances.js +80 -0
  321. package/lib/renderer/packedMeshInstances.js.map +1 -0
  322. package/lib/renderer/prepareMeshBVH.d.ts +12 -47
  323. package/lib/renderer/prepareMeshBVH.js +21 -642
  324. package/lib/renderer/prepareMeshBVH.js.map +1 -1
  325. package/lib/renderer/proceduralEnvironmentPower.d.ts +3 -0
  326. package/lib/renderer/proceduralEnvironmentPower.js +8 -0
  327. package/lib/renderer/proceduralEnvironmentPower.js.map +1 -0
  328. package/lib/renderer/progressiveScheduler.d.ts +1 -0
  329. package/lib/renderer/progressiveScheduler.js +7 -3
  330. package/lib/renderer/progressiveScheduler.js.map +1 -1
  331. package/lib/renderer/renderPipeline.d.ts +4 -1
  332. package/lib/renderer/renderPipeline.js.map +1 -1
  333. package/lib/renderer/renderingLimits.d.ts +9 -0
  334. package/lib/renderer/renderingLimits.js +18 -0
  335. package/lib/renderer/renderingLimits.js.map +1 -0
  336. package/lib/renderer/researchTransport.d.ts +31 -0
  337. package/lib/renderer/researchTransport.js +5 -0
  338. package/lib/renderer/researchTransport.js.map +1 -0
  339. package/lib/renderer/sceneAssembly.d.ts +73 -0
  340. package/lib/renderer/sceneAssembly.js +109 -0
  341. package/lib/renderer/sceneAssembly.js.map +1 -0
  342. package/lib/renderer/sceneChangeCore.d.ts +39 -0
  343. package/lib/renderer/sceneChangeCore.js +307 -0
  344. package/lib/renderer/sceneChangeCore.js.map +1 -0
  345. package/lib/renderer/sceneChangeDetector.d.ts +3 -6
  346. package/lib/renderer/sceneChangeDetector.js +24 -150
  347. package/lib/renderer/sceneChangeDetector.js.map +1 -1
  348. package/lib/renderer/sceneLayoutSchema.d.ts +119 -0
  349. package/lib/renderer/sceneLayoutSchema.js +111 -0
  350. package/lib/renderer/sceneLayoutSchema.js.map +1 -0
  351. package/lib/renderer/sceneLightChanges.d.ts +3 -3
  352. package/lib/renderer/sceneLightChanges.js.map +1 -1
  353. package/lib/renderer/scenePreparation.d.ts +55 -0
  354. package/lib/renderer/scenePreparation.js +360 -0
  355. package/lib/renderer/scenePreparation.js.map +1 -0
  356. package/lib/renderer/scratchSampling.js +18 -18
  357. package/lib/renderer/scratchSampling.js.map +1 -1
  358. package/lib/renderer/shader.d.ts +2 -0
  359. package/lib/renderer/shader.js +2 -0
  360. package/lib/renderer/shader.js.map +1 -1
  361. package/lib/renderer/shaderCapabilities.d.ts +23 -0
  362. package/lib/renderer/shaderCapabilities.js +55 -0
  363. package/lib/renderer/shaderCapabilities.js.map +1 -0
  364. package/lib/renderer/shaderCapacity.d.ts +2 -0
  365. package/lib/renderer/shaderCapacity.js +5 -0
  366. package/lib/renderer/shaderCapacity.js.map +1 -0
  367. package/lib/renderer/skyModel.d.ts +9 -0
  368. package/lib/renderer/skyModel.js +10 -0
  369. package/lib/renderer/skyModel.js.map +1 -0
  370. package/lib/renderer/spectrum.d.ts +21 -0
  371. package/lib/renderer/spectrum.js +154 -0
  372. package/lib/renderer/spectrum.js.map +1 -0
  373. package/lib/renderer/textureAtlas.d.ts +60 -0
  374. package/lib/renderer/textureAtlas.js +145 -0
  375. package/lib/renderer/textureAtlas.js.map +1 -0
  376. package/lib/renderer/textureAtlasPixels.d.ts +7 -0
  377. package/lib/renderer/textureAtlasPixels.js +68 -0
  378. package/lib/renderer/textureAtlasPixels.js.map +1 -0
  379. package/lib/renderer/util.d.ts +1 -1
  380. package/lib/renderer/util.js.map +1 -1
  381. package/lib/renderer/webgl.d.ts +9 -2
  382. package/lib/renderer/webgl.js +54 -9
  383. package/lib/renderer/webgl.js.map +1 -1
  384. package/lib/renderer/webglLightSampling.d.ts +39 -0
  385. package/lib/renderer/webglLightSampling.js +15 -0
  386. package/lib/renderer/webglLightSampling.js.map +1 -0
  387. package/lib/renderer/wgpuBindless.d.ts +26 -0
  388. package/lib/renderer/wgpuBindless.js +95 -0
  389. package/lib/renderer/wgpuBindless.js.map +1 -0
  390. package/lib/renderer/wgpuBindlessSource.d.ts +2 -0
  391. package/lib/renderer/wgpuBindlessSource.js +51 -0
  392. package/lib/renderer/wgpuBindlessSource.js.map +1 -0
  393. package/lib/renderer/wgpuMaterialConstants.d.ts +4 -0
  394. package/lib/renderer/wgpuMaterialConstants.js +52 -0
  395. package/lib/renderer/wgpuMaterialConstants.js.map +1 -0
  396. package/lib/renderer/wgpuSceneUniform.d.ts +42 -0
  397. package/lib/renderer/wgpuSceneUniform.js +125 -0
  398. package/lib/renderer/wgpuSceneUniform.js.map +1 -0
  399. package/lib/renderer/wgpuShaderSource.d.ts +22 -0
  400. package/lib/renderer/wgpuShaderSource.js +33 -0
  401. package/lib/renderer/wgpuShaderSource.js.map +1 -0
  402. package/lib/renderer/wgsl/aovDisplay.wgsl.d.ts +1 -0
  403. package/lib/renderer/wgsl/aovDisplay.wgsl.js +70 -0
  404. package/lib/renderer/wgsl/aovDisplay.wgsl.js.map +1 -0
  405. package/lib/renderer/wgsl/aovReflectance.wgsl.d.ts +2 -0
  406. package/lib/renderer/wgsl/aovReflectance.wgsl.js +98 -0
  407. package/lib/renderer/wgsl/aovReflectance.wgsl.js.map +1 -0
  408. package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.d.ts +2 -0
  409. package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.js +135 -0
  410. package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.js.map +1 -0
  411. package/lib/renderer/wgsl/aovResolve.wgsl.d.ts +5 -0
  412. package/lib/renderer/wgsl/aovResolve.wgsl.js +38 -0
  413. package/lib/renderer/wgsl/aovResolve.wgsl.js.map +1 -0
  414. package/lib/renderer/wgsl/aovSnapshot.wgsl.d.ts +4 -0
  415. package/lib/renderer/wgsl/aovSnapshot.wgsl.js +21 -0
  416. package/lib/renderer/wgsl/aovSnapshot.wgsl.js.map +1 -0
  417. package/lib/renderer/wgsl/aovTrace.wgsl.d.ts +2 -0
  418. package/lib/renderer/wgsl/aovTrace.wgsl.js +115 -0
  419. package/lib/renderer/wgsl/aovTrace.wgsl.js.map +1 -0
  420. package/lib/renderer/wgsl/bloom.wgsl.d.ts +13 -0
  421. package/lib/renderer/wgsl/bloom.wgsl.js +92 -0
  422. package/lib/renderer/wgsl/bloom.wgsl.js.map +1 -0
  423. package/lib/renderer/wgsl/causticLight.compute.d.ts +6 -0
  424. package/lib/renderer/wgsl/causticLight.compute.js +537 -0
  425. package/lib/renderer/wgsl/causticLight.compute.js.map +1 -0
  426. package/lib/renderer/wgsl/chunks/background.wgsl.d.ts +2 -0
  427. package/lib/renderer/wgsl/chunks/background.wgsl.js +102 -0
  428. package/lib/renderer/wgsl/chunks/background.wgsl.js.map +1 -0
  429. package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.d.ts +2 -0
  430. package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js +12 -0
  431. package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js.map +1 -0
  432. package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.d.ts +2 -0
  433. package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js +16 -0
  434. package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js.map +1 -0
  435. package/lib/renderer/wgsl/chunks/caustics.wgsl.d.ts +1 -0
  436. package/lib/renderer/wgsl/chunks/caustics.wgsl.js +62 -0
  437. package/lib/renderer/wgsl/chunks/caustics.wgsl.js.map +1 -0
  438. package/lib/renderer/wgsl/chunks/common.wgsl.js +4 -4
  439. package/lib/renderer/wgsl/chunks/envMap.wgsl.d.ts +1 -1
  440. package/lib/renderer/wgsl/chunks/envMap.wgsl.js +41 -35
  441. package/lib/renderer/wgsl/chunks/envMap.wgsl.js.map +1 -1
  442. package/lib/renderer/wgsl/chunks/intersect.wgsl.d.ts +13 -1
  443. package/lib/renderer/wgsl/chunks/intersect.wgsl.js +747 -704
  444. package/lib/renderer/wgsl/chunks/intersect.wgsl.js.map +1 -1
  445. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js +16 -16
  446. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js.map +1 -1
  447. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.d.ts +4 -1
  448. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js +83 -79
  449. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js.map +1 -1
  450. package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js +855 -857
  451. package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js.map +1 -1
  452. package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js +137 -137
  453. package/lib/renderer/wgsl/chunks/rand.wgsl.js +3 -3
  454. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.d.ts +3 -1
  455. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js +52 -32
  456. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js.map +1 -1
  457. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.d.ts +1 -1
  458. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js +152 -144
  459. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js.map +1 -1
  460. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.d.ts +1 -1
  461. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js +269 -245
  462. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js.map +1 -1
  463. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.d.ts +1 -1
  464. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js +27 -14
  465. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js.map +1 -1
  466. package/lib/renderer/wgsl/chunks/sampling.wgsl.d.ts +1 -1
  467. package/lib/renderer/wgsl/chunks/sampling.wgsl.js +91 -95
  468. package/lib/renderer/wgsl/chunks/sampling.wgsl.js.map +1 -1
  469. package/lib/renderer/wgsl/chunks/shadowCatcherAccumulation.wgsl.d.ts +1 -1
  470. package/lib/renderer/wgsl/chunks/shadowCatcherAccumulation.wgsl.js +1 -0
  471. package/lib/renderer/wgsl/chunks/shadowCatcherAccumulation.wgsl.js.map +1 -1
  472. package/lib/renderer/wgsl/chunks/sobol.wgsl.js +83 -83
  473. package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js +12 -12
  474. package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js.map +1 -1
  475. package/lib/renderer/wgsl/compose.frag.wgsl.d.ts +8 -3
  476. package/lib/renderer/wgsl/compose.frag.wgsl.js +143 -118
  477. package/lib/renderer/wgsl/compose.frag.wgsl.js.map +1 -1
  478. package/lib/renderer/wgsl/customDenoise.wgsl.js +10 -10
  479. package/lib/renderer/wgsl/depthQuery.wgsl.js +7 -7
  480. package/lib/renderer/wgsl/jnlm.compute.d.ts +25 -0
  481. package/lib/renderer/wgsl/jnlm.compute.js +315 -0
  482. package/lib/renderer/wgsl/jnlm.compute.js.map +1 -0
  483. package/lib/renderer/wgsl/offlineAdaptive.compute.js +28 -28
  484. package/lib/renderer/wgsl/oidnAuxiliary.wgsl.d.ts +1 -0
  485. package/lib/renderer/wgsl/oidnAuxiliary.wgsl.js +17 -0
  486. package/lib/renderer/wgsl/oidnAuxiliary.wgsl.js.map +1 -0
  487. package/lib/renderer/wgsl/photonMap.compute.d.ts +29 -0
  488. package/lib/renderer/wgsl/photonMap.compute.js +352 -0
  489. package/lib/renderer/wgsl/photonMap.compute.js.map +1 -0
  490. package/lib/renderer/wgsl/proceduralSky.compute.d.ts +1 -0
  491. package/lib/renderer/wgsl/proceduralSky.compute.js +198 -0
  492. package/lib/renderer/wgsl/proceduralSky.compute.js.map +1 -0
  493. package/lib/renderer/wgsl/rayTrace.compute.d.ts +25 -1
  494. package/lib/renderer/wgsl/rayTrace.compute.js +645 -500
  495. package/lib/renderer/wgsl/rayTrace.compute.js.map +1 -1
  496. package/lib/scene/Camera.js +7 -3
  497. package/lib/scene/Camera.js.map +1 -1
  498. package/lib/scene/EnvironmentLight.d.ts +5 -9
  499. package/lib/scene/EnvironmentLight.js +4 -14
  500. package/lib/scene/EnvironmentLight.js.map +1 -1
  501. package/lib/scene/EnvironmentLightState.d.ts +18 -0
  502. package/lib/scene/EnvironmentLightState.js +19 -0
  503. package/lib/scene/EnvironmentLightState.js.map +1 -0
  504. package/lib/scene/Geometry.d.ts +12 -6
  505. package/lib/scene/Geometry.js +37 -13
  506. package/lib/scene/Geometry.js.map +1 -1
  507. package/lib/scene/InstanceState.d.ts +39 -0
  508. package/lib/scene/InstanceState.js +77 -0
  509. package/lib/scene/InstanceState.js.map +1 -0
  510. package/lib/scene/InstancedMesh.d.ts +1 -1
  511. package/lib/scene/InstancedMesh.js +3 -0
  512. package/lib/scene/InstancedMesh.js.map +1 -1
  513. package/lib/scene/MaterialState.d.ts +209 -0
  514. package/lib/scene/MaterialState.js +231 -0
  515. package/lib/scene/MaterialState.js.map +1 -0
  516. package/lib/scene/Mesh.d.ts +4 -6
  517. package/lib/scene/Mesh.js +3 -11
  518. package/lib/scene/Mesh.js.map +1 -1
  519. package/lib/scene/MeshState.d.ts +20 -0
  520. package/lib/scene/MeshState.js +35 -0
  521. package/lib/scene/MeshState.js.map +1 -0
  522. package/lib/scene/OpenPBRMaterial.d.ts +6 -168
  523. package/lib/scene/OpenPBRMaterial.js +5 -223
  524. package/lib/scene/OpenPBRMaterial.js.map +1 -1
  525. package/lib/scene/PixelTexture.d.ts +6 -0
  526. package/lib/scene/PixelTexture.js +10 -0
  527. package/lib/scene/PixelTexture.js.map +1 -0
  528. package/lib/scene/ProceduralSky.d.ts +24 -0
  529. package/lib/scene/ProceduralSky.js +40 -0
  530. package/lib/scene/ProceduralSky.js.map +1 -0
  531. package/lib/scene/RectLight.d.ts +2 -13
  532. package/lib/scene/RectLight.js +3 -21
  533. package/lib/scene/RectLight.js.map +1 -1
  534. package/lib/scene/RectLightState.d.ts +31 -0
  535. package/lib/scene/RectLightState.js +26 -0
  536. package/lib/scene/RectLightState.js.map +1 -0
  537. package/lib/scene/Scene.d.ts +15 -4
  538. package/lib/scene/Scene.js.map +1 -1
  539. package/lib/scene/SceneNode.js +7 -6
  540. package/lib/scene/SceneNode.js.map +1 -1
  541. package/lib/scene/Texture.d.ts +10 -41
  542. package/lib/scene/Texture.js +4 -33
  543. package/lib/scene/Texture.js.map +1 -1
  544. package/lib/scene/TextureState.d.ts +35 -0
  545. package/lib/scene/TextureState.js +35 -0
  546. package/lib/scene/TextureState.js.map +1 -0
  547. package/lib/scene/attributeData.d.ts +4 -0
  548. package/lib/scene/attributeData.js +10 -0
  549. package/lib/scene/attributeData.js.map +1 -0
  550. package/lib/scene/lightState.d.ts +8 -0
  551. package/lib/scene/lightState.js +2 -0
  552. package/lib/scene/lightState.js.map +1 -0
  553. package/lib/scene/openPbrSchema.d.ts +7 -12
  554. package/lib/scene/openPbrSchema.js +273 -28
  555. package/lib/scene/openPbrSchema.js.map +1 -1
  556. package/lib/scene/skyParameters.d.ts +20 -0
  557. package/lib/scene/skyParameters.js +28 -0
  558. package/lib/scene/skyParameters.js.map +1 -0
  559. package/lib/scene/textureData.d.ts +9 -0
  560. package/lib/scene/textureData.js +2 -0
  561. package/lib/scene/textureData.js.map +1 -0
  562. package/lib/scene/texturePixels.d.ts +6 -0
  563. package/lib/scene/texturePixels.js +10 -0
  564. package/lib/scene/texturePixels.js.map +1 -0
  565. package/lib/settings/display.d.ts +33 -0
  566. package/lib/settings/display.js +7 -0
  567. package/lib/settings/display.js.map +1 -1
  568. package/lib/settings/render.d.ts +36 -3
  569. package/lib/settings/render.js +4 -1
  570. package/lib/settings/render.js.map +1 -1
  571. package/lib/tinybvh/tinybvh.wasm +0 -0
  572. package/lib/util/commonGeometry.js +7 -7
  573. package/lib/util/commonGeometry.js.map +1 -1
  574. package/lib/util/fromTHREE.d.ts +4 -1
  575. package/lib/util/fromTHREE.js +20 -7
  576. package/lib/util/fromTHREE.js.map +1 -1
  577. package/lib/util/geometry.js +42 -29
  578. package/lib/util/geometry.js.map +1 -1
  579. package/lib/util/loadRGBE.js +3 -4
  580. package/lib/util/loadRGBE.js.map +1 -1
  581. package/lib/util/studioLighting.d.ts +18 -0
  582. package/lib/util/studioLighting.js +36 -0
  583. package/lib/util/studioLighting.js.map +1 -0
  584. package/lib/version.d.ts +1 -1
  585. package/lib/version.js +1 -1
  586. package/lib/version.js.map +1 -1
  587. package/llms.txt +5 -0
  588. package/package.json +33 -7
  589. package/lib/renderer/texturesFromMaterials.d.ts +0 -6
  590. package/lib/renderer/texturesFromMaterials.js.map +0 -1
package/lib/Render.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { aovMask } from './renderer/aov.js';
2
+ import { displayAovKind } from './renderer/aovDisplay.js';
1
3
  import { Events } from './util/events.js';
2
4
  import { cameraSnapshot } from './renderer/cameraSnapshot.js';
3
5
  import { collectTraceSettings, imageSettingsKey } from './settings/render.js';
@@ -11,7 +13,7 @@ function validateDenoiserOptions(options) {
11
13
  throw new Error('Denoiser type must be jnlm, oidn or custom.');
12
14
  const allowed = options.type === 'jnlm'
13
15
  ? ['type', 'schedule', ...Object.keys(DEFAULT_JNLM_OPTIONS)]
14
- : options.type === 'custom' ? ['type', 'schedule', 'denoiser']
16
+ : options.type === 'custom' ? ['type', 'schedule', 'denoiser', 'aovs']
15
17
  : ['type', 'schedule', 'model', 'weightsBaseUrl', 'weightsUrl', 'aux', 'hdr', 'hdrTransfer', 'auxiliaryModelUrls', 'engine', 'precision', 'dynamicTile', 'maxTileSize', 'signal'];
16
18
  for (const key of Object.keys(options))
17
19
  if (!allowed.includes(key))
@@ -21,6 +23,7 @@ function validateDenoiserOptions(options) {
21
23
  if (options.type === 'jnlm')
22
24
  createJNLMDenoiser(options);
23
25
  else if (options.type === 'custom') {
26
+ aovMask(options.aovs ?? []);
24
27
  if (!options.denoiser || typeof options.denoiser !== 'object' || typeof options.denoiser.denoise !== 'function' || (options.denoiser.prepare !== undefined && typeof options.denoiser.prepare !== 'function'))
25
28
  throw new Error('Custom denoiser must implement denoise and optional prepare.');
26
29
  }
@@ -63,6 +66,8 @@ function validateDenoiserOptions(options) {
63
66
  function isURL(value) { return (typeof value === 'string' && value.length > 0) || value instanceof URL; }
64
67
  // Snapshot nested values too, so application edits cannot silently change a cache key.
65
68
  function snapshotDenoiserOptions(options) {
69
+ if (options.type === 'custom')
70
+ return Object.freeze({ ...options, aovs: Object.freeze([...(options.aovs ?? [])]) });
66
71
  if (options.type !== 'oidn')
67
72
  return Object.freeze({ ...options });
68
73
  const next = { ...options };
@@ -94,9 +99,12 @@ function denoiserKey(options) {
94
99
  }
95
100
  /** One independently configured image and its accumulation, owned by an engine. */
96
101
  export default class Render {
102
+ /** Enabled surface outputs. Default []; readPixels rejects outputs not enabled here. */ aovs = [];
103
+ /** Independent AOV sample cap. Default 16. */ aovSamples = 16;
97
104
  /** Maximum complete samples. Default 2048. */ maxSamples = 2048;
98
105
  /**
99
106
  * Maximum scattering depth, rounded and clamped to [1, 20] (NaN becomes 1).
107
+ * Complete caustic light-to-camera paths can be longer than this depth.
100
108
  * Total path events, including transmission and alpha skips, are capped at 20
101
109
  * and at three times this depth. Intel Mac WebGL uses min(depth, 3), doubled
102
110
  * for scenes with transmission or alpha, with its existing early termination.
@@ -104,6 +112,7 @@ export default class Render {
104
112
  */ bounces = 3;
105
113
  /** Per-sample radiance clamp; 0 disables it. Default 0. */ clamping = 0;
106
114
  /** Sampling sequence. Default sobol. */ samplingPattern = 'sobol';
115
+ /** Caustic estimators. Default undefined (all disabled). */ caustics;
107
116
  /** WebGPU light candidates per vertex; ignored on WebGL. Default 4. */ directLightCandidates = 4;
108
117
  /** Rounded material edges. Default true. */ bevel = true;
109
118
  /** Bevel probes, clamped to 1–32. Default 8. */ bevelSamples = 8;
@@ -111,8 +120,11 @@ export default class Render {
111
120
  /** WebGPU primary-ray alpha policy; ignored on WebGL. Default stochastic. */ alphaBlendStrategy = 'stochastic';
112
121
  /** Minimum transmissive path alpha. Default 1. Changing it restarts this render. */ transmissiveOutputAlphaMin = 1;
113
122
  /** Execution budget in milliseconds. Default 21. */ timeBudgetMs = 21;
114
- /** Maximum tiles per frame. Default Infinity. */ maxTiles = Infinity;
115
- /** Allow several samples per frame when possible. Default false. */ allowMultipleSamplesPerFrame = false;
123
+ /** Maximum tile grid size per sample, rounded up to a rectangular grid. Fewer tiles make each tile larger; this does not cap work per frame or refine call. Default Infinity. */ maxTiles = Infinity;
124
+ /** Let one refine submit several samples within an estimated timeBudgetMs; one sample or tile can exceed it. WebGPU requires GPU timestamps. Default false. */ batchSamples = false;
125
+ /** @deprecated Use batchSamples; this alias will be removed in a later release. Default false. */
126
+ get allowMultipleSamplesPerFrame() { return this.batchSamples; }
127
+ set allowMultipleSamplesPerFrame(value) { this.batchSamples = value; }
116
128
  /** Adaptive resolution controller, or false. Default false. */ adaptiveResolution = false;
117
129
  _resolutionScale = 1;
118
130
  /** Canvas-relative scale. Default 1; cannot be assigned on a fixed-size render. */
@@ -156,6 +168,7 @@ export default class Render {
156
168
  if (current === null && next === null)
157
169
  return this._denoiserReady;
158
170
  if (next && current && denoiserKey(next) === denoiserKey(current)
171
+ && (next.type !== 'custom' || current.type === 'custom' && aovMask(next.aovs ?? []) === aovMask(current.aovs ?? []))
159
172
  && next.schedule === current.schedule && (next.type !== 'oidn' ||
160
173
  (current.type === 'oidn' && next.signal === current.signal)))
161
174
  return this._denoiserReady;
@@ -168,6 +181,8 @@ export default class Render {
168
181
  _status = 'preparing';
169
182
  _disposed = false;
170
183
  _busy = false;
184
+ _refineOptions;
185
+ _refillController;
171
186
  _offlineCamera = false;
172
187
  _input = { scene: -1, camera: -1, settings: '' };
173
188
  _adaptiveScale = 1;
@@ -205,8 +220,10 @@ export default class Render {
205
220
  throw new Error('Provide positive integer width and height, or resolutionScale, exclusively.');
206
221
  this._fixed = { width: options.width, height: options.height };
207
222
  }
208
- const { width: _width, height: _height, resolutionScale, fallback, denoiser, ...settings } = options;
223
+ const { width: _width, height: _height, resolutionScale, fallback, denoiser, allowMultipleSamplesPerFrame, ...settings } = options;
209
224
  Object.assign(this, settings);
225
+ if (settings.batchSamples === undefined && allowMultipleSamplesPerFrame !== undefined)
226
+ this.batchSamples = allowMultipleSamplesPerFrame;
210
227
  if (resolutionScale !== undefined)
211
228
  this.resolutionScale = resolutionScale;
212
229
  this._adaptiveScale = this._resolutionScale;
@@ -217,11 +234,11 @@ export default class Render {
217
234
  if (denoiser)
218
235
  void this.setDenoiser(denoiser).catch(error => this._engine._notifyError(error));
219
236
  }
220
- /** Actual target width; before allocation uses the requested dimensions. */ get width() { return this._target?.getMemory().width || this._size().width; }
221
- /** Actual target height; before allocation uses the requested dimensions. */ get height() { return this._target?.getMemory().height || this._size().height; }
222
- /** Complete samples since the last restart; stale engine inputs report 0. Default 0. */
237
+ /** Output width: exact for fixed renders; otherwise the target width, or the requested width before allocation. */ get width() { return this._fixed?.width ?? (this._target?.getMemory().width || this._size().width); }
238
+ /** Output height: exact for fixed renders; otherwise the target height, or the requested height before allocation. */ get height() { return this._fixed?.height ?? (this._target?.getMemory().height || this._size().height); }
239
+ /** Complete beauty samples since the last restart; stale engine inputs report 0. Default 0. */
223
240
  get samples() { return this._current ? this._target?.getTotalSamplesRendered() ?? 0 : 0; }
224
- /** Whether complete samples reached maxSamples. Default false. */ get converged() { return this.samples >= this.maxSamples; }
241
+ /** Whether complete beauty samples reached maxSamples. Default false. */ get converged() { return this.samples >= this.maxSamples; }
225
242
  /** Current execution state. Default preparing. */ get status() {
226
243
  if (!this._current && this._status !== 'error')
227
244
  return this._engine._ready ? 'converging' : 'preparing';
@@ -232,7 +249,79 @@ export default class Render {
232
249
  /** @internal */ get _presentable() { return this._complete && (!this._denoisePending || this._denoisedSamples > 0 || (this._schedule() === 'converged' && this.maxSamples > 1)); }
233
250
  /** @internal */ get _output() { if (this._disposed)
234
251
  throw new Error('Render is disposed.'); return this._target; }
252
+ /** @deprecated Use refineUntil for custom frame loops; this will be removed in a later release. Latest WebGPU full beauty sample estimate in milliseconds, extrapolated from tile GPU time when tiled. Default undefined; also undefined for stale inputs, during converge or without GPU timestamps. */
253
+ get gpuSampleTimeMs() { return this._gpuSampleTimeMs; }
254
+ /** @internal Latest WebGPU full beauty sample estimate in milliseconds; with tiling, extrapolated from tile GPU time. Default undefined; also undefined for stale inputs, during converge or without GPU timestamps. */
255
+ get _gpuSampleTimeMs() { return !this._busy && this._current ? this._target?.getRealtimeSampleTime?.() : undefined; }
256
+ /** @internal Latest WebGPU beauty tile estimate in milliseconds, including amortized caustic work; equal to the sample estimate without tiling. Default undefined; also undefined for stale inputs, during converge or without GPU timestamps. */
257
+ get gpuTileTimeMs() { return !this._busy && this._current ? this._target?.getRealtimeTileTime?.() : undefined; }
258
+ /**
259
+ * @deprecated Use refineUntil; this will be removed in a later release. Waits for the
260
+ * next release of WebGPU sampling queue capacity and returns true when sampling was
261
+ * queued. Returns false immediately with no queued sampling, on WebGL, or for only
262
+ * denoising, display or offline convergence work. Does not submit work. Throws after
263
+ * disposal.
264
+ */
265
+ whenReadyToRefine() { return this._whenReadyToRefine(); }
266
+ /** @internal Waits for the next release of WebGPU sampling queue capacity and returns true
267
+ * when sampling was queued. Returns false immediately with no queued sampling,
268
+ * on WebGL, or for only denoising, display or offline convergence work.
269
+ * Does not submit work. Throws after disposal.
270
+ */
271
+ _whenReadyToRefine() {
272
+ if (this._disposed)
273
+ throw new Error('Render is disposed.');
274
+ return !this._busy ? this._target?.whenTraceAvailable?.() ?? Promise.resolve(false) : Promise.resolve(false);
275
+ }
276
+ /** Complete surface-output samples since restart; stale inputs report 0. Independent of beauty samples. Default 0. */
277
+ get aovSamplesRendered() { return this._current ? this._target?.getAovSamples?.() ?? 0 : 0; }
278
+ /** @internal */
279
+ _completeFor(channel) {
280
+ const kind = displayAovKind(channel);
281
+ return kind && this.aovs.includes(kind) && this._target?.aovReady
282
+ ? this._current && this._target.aovReady(kind) : this._complete;
283
+ }
284
+ /** @internal */
285
+ _restartAovs() {
286
+ this._target?.activate();
287
+ this._target?.restartAovs?.();
288
+ this._status = 'converging';
289
+ }
290
+ _refineAov(kind) {
291
+ if (this._engine._initializationError)
292
+ throw this._engine._initializationError;
293
+ if (!this.aovs.includes(kind))
294
+ throw new Error(`AOV ${kind} is not enabled`);
295
+ if (!this._engine._ready) {
296
+ const generation = this._engine._deviceGeneration;
297
+ void this._engine.init().catch(error => {
298
+ if (this._disposed || generation !== this._engine._deviceGeneration)
299
+ return;
300
+ this._status = 'error';
301
+ this._engine._notifyError(error);
302
+ });
303
+ return this._status = 'preparing';
304
+ }
305
+ const started = performance.now();
306
+ const target = this._synchronize();
307
+ if (!target)
308
+ return this._status = 'preparing';
309
+ const before = target.getAovSamples?.() ?? 0;
310
+ const limit = kind === 'id' || kind === 'motion' ? 1 : Math.min(this.maxSamples, this.aovSamples);
311
+ if (!target.refineAovs?.(this._targetCamera(this._engine._inputs.value), Math.min(limit, (target.getAovSamples?.() ?? 0) + 1)))
312
+ return this._status = 'compiling';
313
+ if ((target.getAovSamples?.() ?? 0) > before) {
314
+ this._frameTime = Math.max(.001, performance.now() - started);
315
+ this._frameStart = started;
316
+ this._frameScale = this._adaptiveScale;
317
+ this._adaptResolution(true);
318
+ }
319
+ return this._status = (target.getAovSamples?.() ?? 0) >= limit ? 'finished' : 'converging';
320
+ }
235
321
  _validate() {
322
+ aovMask(this.aovs);
323
+ if (!Number.isInteger(this.aovSamples) || this.aovSamples < 1)
324
+ throw new Error('aovSamples must be a positive integer.');
236
325
  if (!Number.isFinite(this.maxSamples) || this.maxSamples < 1)
237
326
  throw new Error('maxSamples must be positive.');
238
327
  if (this.dispersionWavelengths !== 1 && this.dispersionWavelengths !== 3)
@@ -247,8 +336,51 @@ export default class Render {
247
336
  const scale = this.adaptiveResolution ? Math.min(this._adaptiveScale, this._resolutionScale) : this._resolutionScale;
248
337
  return { width: Math.max(1, Math.round(this._engine.display.canvas.width * scale)), height: Math.max(1, Math.round(this._engine.display.canvas.height * scale)) };
249
338
  }
339
+ /**
340
+ * Backends may round targets up. A fixed render widens the view over the extra
341
+ * pixels so the requested centered rectangle keeps its framing and square pixels.
342
+ */
343
+ _targetCamera(camera) {
344
+ const memory = this._target?.getMemory(), fixed = this._fixed;
345
+ if (!memory || !fixed || (memory.width === fixed.width && memory.height === fixed.height))
346
+ return camera;
347
+ const scaleX = memory.width / fixed.width, scaleY = memory.height / fixed.height;
348
+ const widened = camera.clone();
349
+ widened.transform = camera.transform;
350
+ if (camera.projection === 'perspective') {
351
+ widened.fov = Math.atan(Math.tan(camera.fov * Math.PI / 360) * scaleY) * 360 / Math.PI;
352
+ widened.aspect = (camera.aspect ?? fixed.width / fixed.height) * scaleX / scaleY;
353
+ // Keeps the lens focal length, and with it depth of field.
354
+ widened.sensorHeight = camera.sensorHeight * scaleY;
355
+ }
356
+ else {
357
+ const x = (camera.left + camera.right) / 2, y = (camera.bottom + camera.top) / 2;
358
+ widened.left = x + (camera.left - x) * scaleX;
359
+ widened.right = x + (camera.right - x) * scaleX;
360
+ widened.bottom = y + (camera.bottom - y) * scaleY;
361
+ widened.top = y + (camera.top - y) * scaleY;
362
+ }
363
+ return widened;
364
+ }
365
+ /** @internal Crops a target-sized RGBA image to a fixed render's requested rectangle. */
366
+ _cropOutput(image) {
367
+ const fixed = this._fixed;
368
+ if (!fixed || !image.width || (image.width === fixed.width && image.height === fixed.height))
369
+ return image;
370
+ const { width, height } = fixed, data = new image.data.constructor(width * height * 4);
371
+ const left = (image.width - width) >> 1, top = (image.height - height) >> 1;
372
+ for (let y = 0; y < height; y++) {
373
+ const start = ((y + top) * image.width + left) * 4;
374
+ data.set(image.data.subarray(start, start + width * 4), y * width * 4);
375
+ }
376
+ return { width, height, data };
377
+ }
250
378
  _settings(sampleCap = this.maxSamples) {
251
- return collectTraceSettings(this, sampleCap);
379
+ const settings = collectTraceSettings(this, sampleCap);
380
+ settings.batchSamples = this._refineOptions?.batchSamples ?? settings.batchSamples;
381
+ if (this._denoiserOptions?.type === 'custom')
382
+ settings.aovs = [...new Set([...this.aovs, ...(this._denoiserOptions.aovs ?? [])])];
383
+ return settings;
252
384
  }
253
385
  _synchronize(sampleCap = this.maxSamples, offline = false) {
254
386
  this._validate();
@@ -264,6 +396,8 @@ export default class Render {
264
396
  const inputs = this._engine._inputs;
265
397
  target.configure(settings);
266
398
  target.activate();
399
+ target.setRealtimeBatchBudget?.(this._refineOptions?.targetBatchTimeMs ?? Infinity);
400
+ target.setRealtimeDeferPostProcess?.(!!this._refineOptions?.deferResolve);
267
401
  if ((!offline && this._offlineCamera) || inputs.scene !== this._input.scene || inputs.camera !== this._input.camera || key !== this._input.settings) {
268
402
  if (!offline)
269
403
  this._offlineCamera = false;
@@ -289,13 +423,13 @@ export default class Render {
289
423
  this._sampleStart = performance.now();
290
424
  this._sampleScale = this._adaptiveScale;
291
425
  }
292
- const compiling = target.trace(this._engine._inputs.value, limit);
426
+ const compiling = target.trace(this._targetCamera(this._engine._inputs.value), limit);
293
427
  if (compiling)
294
428
  this._sampleStart = undefined;
295
429
  return compiling;
296
430
  }
297
- _adaptResolution() {
298
- if (!this._busy && this.adaptiveResolution && this._frameTime > 0 && this.samples > 0) {
431
+ _adaptResolution(surfaceOnly = false) {
432
+ if (!this._busy && this.adaptiveResolution && this._frameTime > 0 && (surfaceOnly ? this.aovSamplesRendered > 0 : this.samples > 0)) {
299
433
  const { targetFrameMs, minScale } = this.adaptiveResolution;
300
434
  const start = this._frameStart, time = this._frameTime, scale = this._frameScale, maxScale = this._resolutionScale;
301
435
  const { width, height } = this._engine.display.canvas;
@@ -328,24 +462,118 @@ export default class Render {
328
462
  this._adaptiveFrames.clear();
329
463
  this._adaptiveFastFrames = 0;
330
464
  }
331
- /** Accumulates within this frame's budget. Rejects calls during converge or after disposal. */
332
- refine() {
465
+ /** Accumulates within this frame's budget. Default undefined traces beauty and requested AOVs. Pass an enabled AOV kind to refine surface outputs only, without beauty or denoising; progress is aovSamplesRendered. Options default to this render's execution settings. Rejects calls during converge or after disposal. */
466
+ refine(channel, options) {
333
467
  if (this._busy)
334
468
  throw new Error('Cannot refine a render while converge is running.');
335
469
  if (this._disposed)
336
470
  throw new Error('Render is disposed.');
337
471
  this._engine._setRenderError();
472
+ const previous = this._refineOptions;
473
+ this._refineOptions = options;
338
474
  try {
339
- return this._refine();
475
+ if (options?.targetBatchTimeMs !== undefined && (!Number.isFinite(options.targetBatchTimeMs) || options.targetBatchTimeMs <= 0))
476
+ throw new RangeError('targetBatchTimeMs must be positive and finite.');
477
+ return channel === undefined ? this._refine() : this._refineAov(channel);
340
478
  }
341
479
  catch (error) {
342
480
  this._engine._setRenderError(this._engine._notifyError(error));
343
481
  return this._status = 'error';
344
482
  }
345
483
  finally {
484
+ this._refineOptions = previous;
346
485
  this._engine._reportShaderProgress();
347
486
  }
348
487
  }
488
+ /**
489
+ * Calls refine() once synchronously, then keeps sampling on WebGPU until deadline.
490
+ * Call present() right after it; later samples appear at the next presentation.
491
+ * Sampling continues only with batchSamples on, the final channel displayed, a
492
+ * visible page and tiles that fit timeBudgetMs. It stops on abort or convergence.
493
+ * Preparing, compiling, denoising and the first incomplete sample advance only
494
+ * through the synchronous call, which is all WebGL runs. A new call ends the
495
+ * previous one. Asynchronous errors set status to error and resolve; synchronous
496
+ * errors follow refine().
497
+ * @param deadline End time in performance.now() milliseconds.
498
+ * @param options.signal Optional application cancellation; default none. An
499
+ * already aborted signal still permits the synchronous refine().
500
+ */
501
+ refineUntil(deadline, options) {
502
+ return this._refineToDeadline(deadline, options?.signal);
503
+ }
504
+ _refineToDeadline(deadline, signal, options, beforeRefill) {
505
+ this._refillController?.abort();
506
+ const controller = this._refillController = new AbortController();
507
+ // Keep lifecycle exceptions synchronous, just like refine(). Install the
508
+ // controller first so a synchronous sample listener can revoke this call.
509
+ try {
510
+ this.refine(undefined, options);
511
+ }
512
+ catch (error) {
513
+ controller.abort();
514
+ if (this._refillController === controller)
515
+ this._refillController = undefined;
516
+ throw error;
517
+ }
518
+ const device = this._engine.device;
519
+ const canContinue = (afterWait = false) => !controller.signal.aborted && !signal?.aborted &&
520
+ !this._disposed && !this._busy && device !== undefined && device === this._engine.device &&
521
+ (typeof document === 'undefined' || !document.hidden) && performance.now() < deadline &&
522
+ this.batchSamples && this.status === 'converging' && !this.denoising && this.samples > 0 &&
523
+ this.gpuTileTimeMs !== undefined && this.gpuTileTimeMs <= this.timeBudgetMs &&
524
+ this._engine.display.channel === 'final' && (!afterWait || this._engine._isPresented(this._target));
525
+ if (!canContinue()) {
526
+ if (this._refillController === controller)
527
+ this._refillController = undefined;
528
+ return Promise.resolve();
529
+ }
530
+ return (async () => {
531
+ let timer;
532
+ const abort = () => controller.abort();
533
+ const visibility = () => { if (document.hidden)
534
+ abort(); };
535
+ let stopped;
536
+ const cancelled = new Promise(resolve => { stopped = () => resolve(false); });
537
+ controller.signal.addEventListener('abort', stopped, { once: true });
538
+ signal?.addEventListener('abort', abort, { once: true });
539
+ if (typeof document !== 'undefined')
540
+ document.addEventListener('visibilitychange', visibility);
541
+ if (Number.isFinite(deadline))
542
+ timer = setTimeout(abort, Math.min(2147483647, Math.max(0, deadline - performance.now())));
543
+ try {
544
+ while (canContinue()) {
545
+ if (!await Promise.race([this._whenReadyToRefine(), cancelled]))
546
+ break;
547
+ beforeRefill?.();
548
+ if (!canContinue(true))
549
+ break;
550
+ this.refine(undefined, { targetBatchTimeMs: 4, deferResolve: true });
551
+ }
552
+ }
553
+ catch (error) {
554
+ if (!controller.signal.aborted && !this._disposed) {
555
+ this._engine._setRenderError(this._engine._notifyError(error));
556
+ this._status = 'error';
557
+ }
558
+ }
559
+ finally {
560
+ if (timer !== undefined)
561
+ clearTimeout(timer);
562
+ signal?.removeEventListener('abort', abort);
563
+ controller.signal.removeEventListener('abort', stopped);
564
+ if (typeof document !== 'undefined')
565
+ document.removeEventListener('visibilitychange', visibility);
566
+ if (this._refillController === controller)
567
+ this._refillController = undefined;
568
+ }
569
+ })();
570
+ }
571
+ /** @internal Whether this render currently has a between-frame lease. */
572
+ get _refilling() { return !!this._refillController && !this._refillController.signal.aborted; }
573
+ /** @internal Preserve loop-specific synchronous overrides while using refineUntil. */
574
+ _refineUntil(deadline, signal, options, beforeRefill) {
575
+ return this._refineToDeadline(deadline, signal, options, beforeRefill);
576
+ }
349
577
  _refine() {
350
578
  if (this._engine._initializationError)
351
579
  throw this._engine._initializationError;
@@ -374,6 +602,9 @@ export default class Render {
374
602
  if (this._trace(target, limit))
375
603
  return this._status = 'compiling';
376
604
  }
605
+ else if (target.refineAovs && !target.refineAovs(this._targetCamera(this._engine._inputs.value))) {
606
+ return this._status = 'compiling';
607
+ }
377
608
  this._maybeDenoise(false, limit);
378
609
  if (this._denoisePending)
379
610
  return this._status = this.converged ? 'denoising' : 'converging';
@@ -406,8 +637,13 @@ export default class Render {
406
637
  return this.maxSamples;
407
638
  if (this._denoisedSamples === 0)
408
639
  return 1;
409
- if (performance.now() - this._lastDenoiseTime >= 10000)
640
+ const sinceUpdate = performance.now() - this._lastDenoiseTime;
641
+ if (sinceUpdate >= 10000)
410
642
  return Math.min(this.maxSamples, this.samples + 1);
643
+ // Batched sampling doubles the count within a few frames. Without a floor,
644
+ // most filtering would go to images replaced almost at once.
645
+ if (sinceUpdate < 500)
646
+ return this.maxSamples;
411
647
  return Math.min(this.maxSamples, Math.max(4, this._denoisedSamples * 2));
412
648
  }
413
649
  /** Reloads a filter dropped by device recovery; failures report through engine errors. */
@@ -446,7 +682,7 @@ export default class Render {
446
682
  if (revision !== this._filterRevision || this._disposed)
447
683
  return;
448
684
  if (options.type === 'custom') {
449
- this._filter = { kind: 'custom', denoiser: options.denoiser };
685
+ this._filter = { kind: 'custom', denoiser: options.denoiser, aovs: options.aovs };
450
686
  return;
451
687
  }
452
688
  const { loadOIDNNetwork } = await loadOIDN();
@@ -483,9 +719,10 @@ export default class Render {
483
719
  });
484
720
  }
485
721
  _cancelDenoise() { this._denoiseController?.abort(); this._denoiseController = undefined; this._denoiseRevision++; this._target?.cancelDenoise?.(); this._denoisePending = undefined; this._denoisedSamples = 0; }
486
- /** @internal */ _inputsChanged(resetTiming = false) { this._cancelDenoise(); if (resetTiming)
722
+ /** @internal */ _inputsChanged(resetTiming = false) { this._refillController?.abort(); this._cancelDenoise(); if (resetTiming)
487
723
  this._target?.invalidateTiming?.(); }
488
724
  /** @internal */ _deviceLost(recovering) {
725
+ this._refillController?.abort();
489
726
  this._cancelAdaptiveFrames();
490
727
  this._cancelDenoise();
491
728
  this._filterRevision++;
@@ -496,7 +733,7 @@ export default class Render {
496
733
  this._input = { scene: -1, camera: -1, settings: '' };
497
734
  this._status = recovering ? 'preparing' : 'error';
498
735
  }
499
- /** @internal */ _displayChanged() { this._cancelDenoise(); this._target?.invalidateDenoisedOutput(); }
736
+ /** @internal */ _displayChanged() { this._refillController?.abort(); this._cancelDenoise(); this._target?.invalidateDenoisedOutput(); }
500
737
  _maybeDenoise(force = false, sampleTarget = this._nextSampleTarget()) {
501
738
  const target = this._target, filter = this._filter;
502
739
  if (!target || !filter || this._denoisePending || this.samples < 1 || this._denoisedSamples === this.samples)
@@ -535,7 +772,7 @@ export default class Render {
535
772
  if (frameStart !== undefined)
536
773
  this._frameTime = Math.max(this._frameTime, this._lastDenoiseTime - frameStart);
537
774
  }
538
- });
775
+ }, controller.signal);
539
776
  this._denoisePending = task;
540
777
  void task.catch(error => { if (revision === this._denoiseRevision && !this._disposed)
541
778
  this._engine._notifyError(error); }).finally(() => {
@@ -547,12 +784,21 @@ export default class Render {
547
784
  }
548
785
  });
549
786
  }
550
- /** Reads native RGBA float32, top row first. Default hdr. Custom denoised output is resolved linear HDR ray color before display background/catcher composition; built-ins retain their native display-space output. Unavailable denoised output falls back to hdr. */
551
787
  async readPixels(kind = 'hdr') {
552
788
  if (this._disposed)
553
789
  throw new Error('Render is disposed.');
554
790
  const target = this._target;
555
- if (!target)
791
+ if (['depth', 'position', 'roughness', 'diffuseAlbedo', 'specularAlbedo', 'id', 'motion'].includes(kind)) {
792
+ const aov = kind;
793
+ aovMask(this.aovs);
794
+ if (!this.aovs.includes(aov))
795
+ throw new Error(`AOV ${aov} is not enabled`);
796
+ if (!target?.readAov)
797
+ throw new Error('AOV output is not ready');
798
+ target.activate();
799
+ return this._cropOutput(await target.readAov(aov));
800
+ }
801
+ if (!target || this.samples === 0)
556
802
  return { width: 0, height: 0, data: new Float32Array(0) };
557
803
  if (kind === 'denoised' && this._denoisedSamples === 0) {
558
804
  if (!this._warnedDenoisedReadback) {
@@ -562,21 +808,22 @@ export default class Render {
562
808
  kind = 'hdr';
563
809
  }
564
810
  target.activate();
565
- return target.readOutput(kind);
811
+ return this._cropOutput(await target.readOutput(kind));
566
812
  }
567
813
  /** Borrows a read-only WebGPU texture; undefined on WebGL or before a complete sample. Kind is required. HDR is native resolved linear ray color before denoising/display composition, with DenoiseInput.color normalization and coverage. Display is the latest compose, including filters and display passes. Valid only until this render's next refine/converge, display present/setSize, restart/dispose or device loss; never retain, write or destroy it. */
568
814
  getOutputTexture(kind) {
569
- if (!this._complete || this._engine.backend !== 'webgpu')
815
+ if (this._engine.backend !== 'webgpu' || (kind === 'hdr' ? !this._complete : !this._current || !this._target?.presentationComplete || (!this._complete && !this._target.getAovSamples?.())))
570
816
  return;
571
817
  return this._target?.getOutputTexture?.(kind);
572
818
  }
573
819
  /** Discards only this render's accumulation and pending denoising. */
574
820
  restart() { if (this._disposed)
575
- throw new Error('Render is disposed.'); this._cancelDenoise(); this._cancelAdaptiveFrames(); this._sampleStart = this._frameStart = undefined; this._frameTime = 0; this._target?.restartSamples(); this._status = 'converging'; }
821
+ throw new Error('Render is disposed.'); this._refillController?.abort(); this._cancelDenoise(); this._cancelAdaptiveFrames(); this._sampleStart = this._frameStart = undefined; this._frameTime = 0; this._target?.restartSamples(); this._status = 'converging'; }
576
822
  /** Releases only this render's image resources and denoiser. */
577
823
  dispose() {
578
824
  if (this._disposed)
579
825
  return;
826
+ this._refillController?.abort();
580
827
  this._disposed = true;
581
828
  this._events.clear();
582
829
  this._filterRevision++;
@@ -622,6 +869,7 @@ export default class Render {
622
869
  if (current.scene !== inputs.scene || current.camera !== inputs.camera)
623
870
  throw new Error('Engine inputs changed during converge.');
624
871
  };
872
+ this._refillController?.abort();
625
873
  this._busy = true;
626
874
  const abortConverge = () => this._cancelDenoise();
627
875
  options.signal?.addEventListener('abort', abortConverge, { once: true });
@@ -650,7 +898,7 @@ export default class Render {
650
898
  this._cancelDenoise();
651
899
  target.activate();
652
900
  target.restartSamples();
653
- target.configure({ ...this._settings(cap), allowMultipleSamplesPerFrame: true });
901
+ target.configure({ ...this._settings(cap), batchSamples: true });
654
902
  let batch = options.targetBatchTimeMs && this._engine.device ? 1 : Math.min(batchLimit, cap);
655
903
  let previous = -1, lastPreview = performance.now();
656
904
  const started = performance.now();
@@ -661,7 +909,7 @@ export default class Render {
661
909
  target.activate();
662
910
  target.setOfflineRenderOptions({ samplesPerBatch: batch, deferPostProcess: true, sampleSequenceOffset: offset });
663
911
  const before = target.getTotalSamplesRendered(), batchStarted = performance.now();
664
- this._status = target.trace(camera, cap) ? 'compiling' : 'converging';
912
+ this._status = target.trace(this._targetCamera(camera), cap) ? 'compiling' : 'converging';
665
913
  const count = target.getTotalSamplesRendered();
666
914
  if (count !== previous) {
667
915
  previous = count;