@meimu/mutracer 0.2.0 → 0.3.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.
Files changed (372) hide show
  1. package/CHANGELOG.md +222 -0
  2. package/LICENSES/FidelityFX-FSR.txt +19 -0
  3. package/LICENSES/pbrt-v4-Apache-2.0.txt +202 -0
  4. package/README.md +3 -0
  5. package/THIRD_PARTY_NOTICES.md +18 -4
  6. package/dist/assets/bvh.worker.js +1 -1
  7. package/dist/mutracer.umd.js +9328 -7614
  8. package/docs/api.md +83 -35
  9. package/docs/caustics.md +80 -0
  10. package/docs/materials.md +9 -6
  11. package/docs/performance.md +7 -0
  12. package/docs/post-processing.md +62 -9
  13. package/docs/progressive-rendering.md +53 -9
  14. package/docs/sampling.md +4 -0
  15. package/docs/technical/acceleration.md +52 -0
  16. package/docs/technical/aovs.md +79 -0
  17. package/docs/technical/caustics.md +109 -0
  18. package/docs/technical/continuous-spectrum.md +122 -0
  19. package/docs/technical/display-upscale.md +82 -0
  20. package/docs/technical/openpbr.md +99 -0
  21. package/docs/technical/pbrt-import.md +168 -0
  22. package/docs/technical/tiling.md +74 -0
  23. package/docs/technical/webgl.md +53 -0
  24. package/docs/updates.md +3 -1
  25. package/docs/viewer-checklist.md +65 -0
  26. package/docs/viewer.md +18 -6
  27. package/lib/Display.d.ts +19 -5
  28. package/lib/Display.js +10 -7
  29. package/lib/Display.js.map +1 -1
  30. package/lib/Engine.d.ts +4 -1
  31. package/lib/Engine.js +77 -14
  32. package/lib/Engine.js.map +1 -1
  33. package/lib/Render.d.ts +81 -24
  34. package/lib/Render.js +201 -26
  35. package/lib/Render.js.map +1 -1
  36. package/lib/RenderLoop.d.ts +7 -3
  37. package/lib/RenderLoop.js +68 -44
  38. package/lib/RenderLoop.js.map +1 -1
  39. package/lib/main.d.ts +4 -2
  40. package/lib/main.js +1 -0
  41. package/lib/main.js.map +1 -1
  42. package/lib/oidn.d.ts +1 -1
  43. package/lib/renderer/AovPrimitiveCache.js +39 -8
  44. package/lib/renderer/AovPrimitiveCache.js.map +1 -1
  45. package/lib/renderer/DisplayPostProcess.d.ts +8 -3
  46. package/lib/renderer/DisplayPostProcess.js +51 -18
  47. package/lib/renderer/DisplayPostProcess.js.map +1 -1
  48. package/lib/renderer/GPUTraceQueue.d.ts +2 -1
  49. package/lib/renderer/GPUTraceQueue.js +3 -1
  50. package/lib/renderer/GPUTraceQueue.js.map +1 -1
  51. package/lib/renderer/MaterialData.js +7 -2
  52. package/lib/renderer/MaterialData.js.map +1 -1
  53. package/lib/renderer/RenderingPipeline.d.ts +11 -1
  54. package/lib/renderer/RenderingPipeline.js.map +1 -1
  55. package/lib/renderer/TileRender.d.ts +2 -2
  56. package/lib/renderer/TileRender.js +128 -7
  57. package/lib/renderer/TileRender.js.map +1 -1
  58. package/lib/renderer/WGPUAov.d.ts +6 -1
  59. package/lib/renderer/WGPUAov.js +108 -14
  60. package/lib/renderer/WGPUAov.js.map +1 -1
  61. package/lib/renderer/WGPUCanvasSurface.js +12 -1
  62. package/lib/renderer/WGPUCanvasSurface.js.map +1 -1
  63. package/lib/renderer/WGPUCausticLightPass.d.ts +48 -0
  64. package/lib/renderer/WGPUCausticLightPass.js +217 -0
  65. package/lib/renderer/WGPUCausticLightPass.js.map +1 -0
  66. package/lib/renderer/WGPUEnvMapDistribution.js +19 -19
  67. package/lib/renderer/WGPUFullQuadPass.js +3 -3
  68. package/lib/renderer/WGPUPhotonMap.d.ts +37 -0
  69. package/lib/renderer/WGPUPhotonMap.js +191 -0
  70. package/lib/renderer/WGPUPhotonMap.js.map +1 -0
  71. package/lib/renderer/WGPURayTraceOutput.d.ts +13 -1
  72. package/lib/renderer/WGPURayTraceOutput.js +122 -28
  73. package/lib/renderer/WGPURayTraceOutput.js.map +1 -1
  74. package/lib/renderer/WGPURayTracePass.d.ts +65 -21
  75. package/lib/renderer/WGPURayTracePass.js +730 -409
  76. package/lib/renderer/WGPURayTracePass.js.map +1 -1
  77. package/lib/renderer/WGPURenderingPipeline.js +110 -68
  78. package/lib/renderer/WGPURenderingPipeline.js.map +1 -1
  79. package/lib/renderer/WebGLAov.js +3 -3
  80. package/lib/renderer/WebGLAov.js.map +1 -1
  81. package/lib/renderer/WebGLFullQuadPass.d.ts +2 -1
  82. package/lib/renderer/WebGLFullQuadPass.js +10 -0
  83. package/lib/renderer/WebGLFullQuadPass.js.map +1 -1
  84. package/lib/renderer/WebGLJNLMDenoiser.js +66 -66
  85. package/lib/renderer/WebGLJNLMDenoiser.js.map +1 -1
  86. package/lib/renderer/WebGLRayTraceOutputPass.js +4 -4
  87. package/lib/renderer/WebGLRayTracePass.d.ts +20 -11
  88. package/lib/renderer/WebGLRayTracePass.js +157 -116
  89. package/lib/renderer/WebGLRayTracePass.js.map +1 -1
  90. package/lib/renderer/WebGLRenderingPipeline.js +17 -14
  91. package/lib/renderer/WebGLRenderingPipeline.js.map +1 -1
  92. package/lib/renderer/WebGLSkyBaker.js +60 -60
  93. package/lib/renderer/accumulationTarget.d.ts +2 -1
  94. package/lib/renderer/accumulationTarget.js.map +1 -1
  95. package/lib/renderer/aov.d.ts +13 -1
  96. package/lib/renderer/aov.js +21 -2
  97. package/lib/renderer/aov.js.map +1 -1
  98. package/lib/renderer/aovDisplay.js +2 -2
  99. package/lib/renderer/aovDisplay.js.map +1 -1
  100. package/lib/renderer/binnedSahBvh.d.ts +2 -1
  101. package/lib/renderer/binnedSahBvh.js +24 -17
  102. package/lib/renderer/binnedSahBvh.js.map +1 -1
  103. package/lib/renderer/bvhAccel.d.ts +3 -1
  104. package/lib/renderer/bvhAccel.js +36 -6
  105. package/lib/renderer/bvhAccel.js.map +1 -1
  106. package/lib/renderer/cameraUniform.d.ts +1 -1
  107. package/lib/renderer/cameraUniform.js +6 -2
  108. package/lib/renderer/cameraUniform.js.map +1 -1
  109. package/lib/renderer/causticDiagnostics.d.ts +31 -0
  110. package/lib/renderer/causticDiagnostics.js +5 -0
  111. package/lib/renderer/causticDiagnostics.js.map +1 -0
  112. package/lib/renderer/causticEmission.d.ts +10 -0
  113. package/lib/renderer/causticEmission.js +40 -0
  114. package/lib/renderer/causticEmission.js.map +1 -0
  115. package/lib/renderer/causticUniform.d.ts +12 -0
  116. package/lib/renderer/causticUniform.js +22 -0
  117. package/lib/renderer/causticUniform.js.map +1 -0
  118. package/lib/renderer/caustics.d.ts +16 -0
  119. package/lib/renderer/caustics.js +93 -0
  120. package/lib/renderer/caustics.js.map +1 -0
  121. package/lib/renderer/compactVertices.d.ts +14 -0
  122. package/lib/renderer/compactVertices.js +124 -0
  123. package/lib/renderer/compactVertices.js.map +1 -0
  124. package/lib/renderer/easu.d.ts +11 -0
  125. package/lib/renderer/easu.js +156 -0
  126. package/lib/renderer/easu.js.map +1 -0
  127. package/lib/renderer/geometryUpdateState.d.ts +1 -0
  128. package/lib/renderer/geometryUpdateState.js.map +1 -1
  129. package/lib/renderer/geometryUpdates.js +3 -2
  130. package/lib/renderer/geometryUpdates.js.map +1 -1
  131. package/lib/renderer/glsl/aovDisplay.frag.js +5 -5
  132. package/lib/renderer/glsl/aovReflectance.glsl.js +53 -53
  133. package/lib/renderer/glsl/aovReflectanceSamples.glsl.js +1 -1
  134. package/lib/renderer/glsl/aovTrace.frag.js +45 -37
  135. package/lib/renderer/glsl/aovTrace.frag.js.map +1 -1
  136. package/lib/renderer/glsl/chunks/cameraProjection.glsl.d.ts +2 -0
  137. package/lib/renderer/glsl/chunks/cameraProjection.glsl.js +16 -0
  138. package/lib/renderer/glsl/chunks/cameraProjection.glsl.js.map +1 -0
  139. package/lib/renderer/glsl/chunks/cameraRay.glsl.d.ts +1 -1
  140. package/lib/renderer/glsl/chunks/cameraRay.glsl.js +9 -16
  141. package/lib/renderer/glsl/chunks/cameraRay.glsl.js.map +1 -1
  142. package/lib/renderer/glsl/chunks/emissiveLight.glsl.d.ts +2 -0
  143. package/lib/renderer/glsl/chunks/emissiveLight.glsl.js +35 -0
  144. package/lib/renderer/glsl/chunks/emissiveLight.glsl.js.map +1 -0
  145. package/lib/renderer/glsl/chunks/envMap.glsl.js +73 -73
  146. package/lib/renderer/glsl/chunks/intersect.glsl.js +478 -465
  147. package/lib/renderer/glsl/chunks/intersect.glsl.js.map +1 -1
  148. package/lib/renderer/glsl/chunks/materialBuffer.glsl.d.ts +1 -0
  149. package/lib/renderer/glsl/chunks/materialBuffer.glsl.js +156 -153
  150. package/lib/renderer/glsl/chunks/materialBuffer.glsl.js.map +1 -1
  151. package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js +771 -771
  152. package/lib/renderer/glsl/chunks/rand.glsl.js +3 -3
  153. package/lib/renderer/glsl/chunks/random.glsl.js +6 -6
  154. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.d.ts +1 -0
  155. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js +70 -63
  156. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js.map +1 -1
  157. package/lib/renderer/glsl/chunks/sampleLight.glsl.js +89 -75
  158. package/lib/renderer/glsl/chunks/sampleLight.glsl.js.map +1 -1
  159. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.d.ts +1 -0
  160. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js +160 -118
  161. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js.map +1 -1
  162. package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js +14 -14
  163. package/lib/renderer/glsl/chunks/sampling.glsl.js +88 -91
  164. package/lib/renderer/glsl/chunks/sampling.glsl.js.map +1 -1
  165. package/lib/renderer/glsl/chunks/sobol.glsl.js +79 -79
  166. package/lib/renderer/glsl/chunks/spectralPrefix.glsl.d.ts +6 -0
  167. package/lib/renderer/glsl/chunks/spectralPrefix.glsl.js +47 -0
  168. package/lib/renderer/glsl/chunks/spectralPrefix.glsl.js.map +1 -0
  169. package/lib/renderer/glsl/chunks/textureLinear.glsl.js +5 -5
  170. package/lib/renderer/glsl/chunks/uvProjection.glsl.js +11 -11
  171. package/lib/renderer/glsl/depthQuery.frag.js +13 -7
  172. package/lib/renderer/glsl/depthQuery.frag.js.map +1 -1
  173. package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js +10 -10
  174. package/lib/renderer/glsl/rayTrace.frag.d.ts +1 -1
  175. package/lib/renderer/glsl/rayTrace.frag.js +338 -252
  176. package/lib/renderer/glsl/rayTrace.frag.js.map +1 -1
  177. package/lib/renderer/glsl/shadowCatcher.frag.js +27 -26
  178. package/lib/renderer/glsl/shadowCatcher.frag.js.map +1 -1
  179. package/lib/renderer/glsl/webglPipeline.frag.js +59 -59
  180. package/lib/renderer/gpuMemory.js +1 -1
  181. package/lib/renderer/gpuMemory.js.map +1 -1
  182. package/lib/renderer/lightSampling.d.ts +3 -2
  183. package/lib/renderer/lightSampling.js +14 -8
  184. package/lib/renderer/lightSampling.js.map +1 -1
  185. package/lib/renderer/openPbrEnergyLut.d.ts +2 -1
  186. package/lib/renderer/openPbrEnergyLut.js +18 -1
  187. package/lib/renderer/openPbrEnergyLut.js.map +1 -1
  188. package/lib/renderer/pathLimits.d.ts +5 -4
  189. package/lib/renderer/pathLimits.js +6 -5
  190. package/lib/renderer/pathLimits.js.map +1 -1
  191. package/lib/renderer/prepareMeshBVH.d.ts +2 -0
  192. package/lib/renderer/prepareMeshBVH.js +5 -3
  193. package/lib/renderer/prepareMeshBVH.js.map +1 -1
  194. package/lib/renderer/progressiveScheduler.js +5 -4
  195. package/lib/renderer/progressiveScheduler.js.map +1 -1
  196. package/lib/renderer/renderPipeline.d.ts +5 -0
  197. package/lib/renderer/renderPipeline.js +1 -0
  198. package/lib/renderer/renderPipeline.js.map +1 -1
  199. package/lib/renderer/researchTransport.d.ts +31 -0
  200. package/lib/renderer/researchTransport.js +5 -0
  201. package/lib/renderer/researchTransport.js.map +1 -0
  202. package/lib/renderer/sceneAssembly.d.ts +1 -1
  203. package/lib/renderer/sceneAssembly.js +4 -3
  204. package/lib/renderer/sceneAssembly.js.map +1 -1
  205. package/lib/renderer/sceneChangeDetector.d.ts +1 -1
  206. package/lib/renderer/sceneChangeDetector.js +3 -1
  207. package/lib/renderer/sceneChangeDetector.js.map +1 -1
  208. package/lib/renderer/sceneLayoutSchema.d.ts +2 -0
  209. package/lib/renderer/sceneLayoutSchema.js +3 -3
  210. package/lib/renderer/sceneLayoutSchema.js.map +1 -1
  211. package/lib/renderer/scenePreparation.d.ts +3 -2
  212. package/lib/renderer/scenePreparation.js +18 -2
  213. package/lib/renderer/scenePreparation.js.map +1 -1
  214. package/lib/renderer/scratchSampling.js +6 -6
  215. package/lib/renderer/spectrum.d.ts +21 -0
  216. package/lib/renderer/spectrum.js +154 -0
  217. package/lib/renderer/spectrum.js.map +1 -0
  218. package/lib/renderer/staticBvhPreparation.d.ts +9 -0
  219. package/lib/renderer/staticBvhPreparation.js +8 -2
  220. package/lib/renderer/staticBvhPreparation.js.map +1 -1
  221. package/lib/renderer/surfaceHit.d.ts +10 -0
  222. package/lib/renderer/surfaceHit.js +22 -0
  223. package/lib/renderer/surfaceHit.js.map +1 -0
  224. package/lib/renderer/tangentRequirements.d.ts +2 -0
  225. package/lib/renderer/tangentRequirements.js +7 -0
  226. package/lib/renderer/tangentRequirements.js.map +1 -0
  227. package/lib/renderer/textureAtlas.d.ts +4 -0
  228. package/lib/renderer/textureAtlas.js +48 -2
  229. package/lib/renderer/textureAtlas.js.map +1 -1
  230. package/lib/renderer/webgl.js +4 -0
  231. package/lib/renderer/webgl.js.map +1 -1
  232. package/lib/renderer/webglLightSampling.d.ts +39 -0
  233. package/lib/renderer/webglLightSampling.js +15 -0
  234. package/lib/renderer/webglLightSampling.js.map +1 -0
  235. package/lib/renderer/webglVertexAttributes.d.ts +17 -0
  236. package/lib/renderer/webglVertexAttributes.js +44 -0
  237. package/lib/renderer/webglVertexAttributes.js.map +1 -0
  238. package/lib/renderer/wgpuBindlessSource.js +3 -3
  239. package/lib/renderer/wgpuMaterialConstants.js +4 -3
  240. package/lib/renderer/wgpuMaterialConstants.js.map +1 -1
  241. package/lib/renderer/wgpuSceneUniform.js +2 -2
  242. package/lib/renderer/wgpuSceneUniform.js.map +1 -1
  243. package/lib/renderer/wgpuShaderSource.d.ts +22 -0
  244. package/lib/renderer/wgpuShaderSource.js +3 -1
  245. package/lib/renderer/wgpuShaderSource.js.map +1 -1
  246. package/lib/renderer/wgsl/aovCompact.wgsl.d.ts +4 -0
  247. package/lib/renderer/wgsl/aovCompact.wgsl.js +26 -0
  248. package/lib/renderer/wgsl/aovCompact.wgsl.js.map +1 -0
  249. package/lib/renderer/wgsl/aovDisplay.wgsl.js +9 -9
  250. package/lib/renderer/wgsl/aovReflectance.wgsl.js +55 -55
  251. package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.js +1 -1
  252. package/lib/renderer/wgsl/aovResolve.wgsl.d.ts +4 -0
  253. package/lib/renderer/wgsl/aovResolve.wgsl.js +21 -2
  254. package/lib/renderer/wgsl/aovResolve.wgsl.js.map +1 -1
  255. package/lib/renderer/wgsl/aovSnapshot.wgsl.js +2 -2
  256. package/lib/renderer/wgsl/aovSnapshot.wgsl.js.map +1 -1
  257. package/lib/renderer/wgsl/aovTrace.wgsl.js +33 -33
  258. package/lib/renderer/wgsl/aovTraceDisplay.wgsl.d.ts +2 -0
  259. package/lib/renderer/wgsl/aovTraceDisplay.wgsl.js +56 -0
  260. package/lib/renderer/wgsl/aovTraceDisplay.wgsl.js.map +1 -0
  261. package/lib/renderer/wgsl/bloom.wgsl.js +18 -18
  262. package/lib/renderer/wgsl/causticLight.compute.d.ts +6 -0
  263. package/lib/renderer/wgsl/causticLight.compute.js +539 -0
  264. package/lib/renderer/wgsl/causticLight.compute.js.map +1 -0
  265. package/lib/renderer/wgsl/chunks/background.wgsl.d.ts +2 -0
  266. package/lib/renderer/wgsl/chunks/background.wgsl.js +102 -0
  267. package/lib/renderer/wgsl/chunks/background.wgsl.js.map +1 -0
  268. package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.d.ts +2 -0
  269. package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js +12 -0
  270. package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js.map +1 -0
  271. package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.d.ts +2 -0
  272. package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js +16 -0
  273. package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js.map +1 -0
  274. package/lib/renderer/wgsl/chunks/caustics.wgsl.d.ts +1 -0
  275. package/lib/renderer/wgsl/chunks/caustics.wgsl.js +62 -0
  276. package/lib/renderer/wgsl/chunks/caustics.wgsl.js.map +1 -0
  277. package/lib/renderer/wgsl/chunks/common.wgsl.js +4 -4
  278. package/lib/renderer/wgsl/chunks/envMap.wgsl.js +37 -37
  279. package/lib/renderer/wgsl/chunks/intersect.wgsl.d.ts +6 -2
  280. package/lib/renderer/wgsl/chunks/intersect.wgsl.js +634 -620
  281. package/lib/renderer/wgsl/chunks/intersect.wgsl.js.map +1 -1
  282. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.d.ts +1 -1
  283. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js +23 -21
  284. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js.map +1 -1
  285. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.d.ts +3 -1
  286. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js +77 -74
  287. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js.map +1 -1
  288. package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js +795 -795
  289. package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js +139 -139
  290. package/lib/renderer/wgsl/chunks/rand.wgsl.js +3 -3
  291. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.d.ts +5 -1
  292. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js +45 -29
  293. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js.map +1 -1
  294. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.d.ts +1 -1
  295. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js +142 -138
  296. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js.map +1 -1
  297. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.d.ts +1 -1
  298. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js +228 -189
  299. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js.map +1 -1
  300. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.d.ts +1 -1
  301. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js +11 -11
  302. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js.map +1 -1
  303. package/lib/renderer/wgsl/chunks/sampling.wgsl.d.ts +1 -1
  304. package/lib/renderer/wgsl/chunks/sampling.wgsl.js +88 -92
  305. package/lib/renderer/wgsl/chunks/sampling.wgsl.js.map +1 -1
  306. package/lib/renderer/wgsl/chunks/sobol.wgsl.js +83 -83
  307. package/lib/renderer/wgsl/chunks/spectralPrefix.wgsl.d.ts +6 -0
  308. package/lib/renderer/wgsl/chunks/spectralPrefix.wgsl.js +66 -0
  309. package/lib/renderer/wgsl/chunks/spectralPrefix.wgsl.js.map +1 -0
  310. package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js +11 -11
  311. package/lib/renderer/wgsl/chunks/vertexAttributes.wgsl.d.ts +2 -0
  312. package/lib/renderer/wgsl/chunks/vertexAttributes.wgsl.js +61 -0
  313. package/lib/renderer/wgsl/chunks/vertexAttributes.wgsl.js.map +1 -0
  314. package/lib/renderer/wgsl/compose.frag.wgsl.d.ts +2 -0
  315. package/lib/renderer/wgsl/compose.frag.wgsl.js +100 -98
  316. package/lib/renderer/wgsl/compose.frag.wgsl.js.map +1 -1
  317. package/lib/renderer/wgsl/customDenoise.wgsl.js +10 -10
  318. package/lib/renderer/wgsl/depthQuery.wgsl.d.ts +1 -1
  319. package/lib/renderer/wgsl/depthQuery.wgsl.js +12 -3
  320. package/lib/renderer/wgsl/depthQuery.wgsl.js.map +1 -1
  321. package/lib/renderer/wgsl/easu.wgsl.d.ts +2 -0
  322. package/lib/renderer/wgsl/easu.wgsl.js +80 -0
  323. package/lib/renderer/wgsl/easu.wgsl.js.map +1 -0
  324. package/lib/renderer/wgsl/easuDetail.wgsl.d.ts +21 -0
  325. package/lib/renderer/wgsl/easuDetail.wgsl.js +230 -0
  326. package/lib/renderer/wgsl/easuDetail.wgsl.js.map +1 -0
  327. package/lib/renderer/wgsl/jnlm.compute.js +74 -74
  328. package/lib/renderer/wgsl/jnlm.compute.js.map +1 -1
  329. package/lib/renderer/wgsl/offlineAdaptive.compute.js +26 -26
  330. package/lib/renderer/wgsl/oidnAuxiliary.wgsl.js +3 -3
  331. package/lib/renderer/wgsl/photonMap.compute.d.ts +29 -0
  332. package/lib/renderer/wgsl/photonMap.compute.js +352 -0
  333. package/lib/renderer/wgsl/photonMap.compute.js.map +1 -0
  334. package/lib/renderer/wgsl/proceduralSky.compute.js +64 -64
  335. package/lib/renderer/wgsl/rayTrace.compute.d.ts +23 -1
  336. package/lib/renderer/wgsl/rayTrace.compute.js +531 -543
  337. package/lib/renderer/wgsl/rayTrace.compute.js.map +1 -1
  338. package/lib/scene/MaterialState.d.ts +2 -2
  339. package/lib/scene/MaterialState.js +2 -2
  340. package/lib/scene/MaterialState.js.map +1 -1
  341. package/lib/scene/Scene.js.map +1 -1
  342. package/lib/settings/render.d.ts +22 -0
  343. package/lib/settings/render.js +2 -0
  344. package/lib/settings/render.js.map +1 -1
  345. package/lib/util/fromTHREE.js +23 -16
  346. package/lib/util/fromTHREE.js.map +1 -1
  347. package/lib/version.d.ts +1 -1
  348. package/lib/version.js +1 -1
  349. package/lib/version.js.map +1 -1
  350. package/llms.txt +2 -1
  351. package/package.json +7 -4
  352. package/lib/oidnBundledWeights.cdn.d.ts +0 -2
  353. package/lib/oidnBundledWeights.cdn.js +0 -5
  354. package/lib/oidnBundledWeights.cdn.js.map +0 -1
  355. package/lib/renderer/bvh.worker.d.ts +0 -1
  356. package/lib/renderer/bvh.worker.js +0 -16
  357. package/lib/renderer/bvh.worker.js.map +0 -1
  358. package/lib/renderer/bvhWorkerBuild.d.ts +0 -13
  359. package/lib/renderer/bvhWorkerBuild.js +0 -17
  360. package/lib/renderer/bvhWorkerBuild.js.map +0 -1
  361. package/lib/renderer/lightCore.d.ts +0 -12
  362. package/lib/renderer/lightCore.js +0 -13
  363. package/lib/renderer/lightCore.js.map +0 -1
  364. package/lib/renderer/materialCore.d.ts +0 -8
  365. package/lib/renderer/materialCore.js +0 -9
  366. package/lib/renderer/materialCore.js.map +0 -1
  367. package/lib/scene/PixelTexture.d.ts +0 -6
  368. package/lib/scene/PixelTexture.js +0 -10
  369. package/lib/scene/PixelTexture.js.map +0 -1
  370. package/lib/util/studioLighting.d.ts +0 -18
  371. package/lib/util/studioLighting.js +0 -36
  372. package/lib/util/studioLighting.js.map +0 -1
@@ -1,9 +1,8 @@
1
- import { hdrResolveWGSL } from './wgsl/compose.frag.wgsl.js';
1
+ import { hdrResolveWGSL, TONE_MAPPING_MODES } from './wgsl/compose.frag.wgsl.js';
2
2
  import { oidnAuxiliaryDefine } from './wgsl/oidnAuxiliary.wgsl.js';
3
3
  import { displayAovKind, DEFAULT_AOV_DISPLAY } from './aovDisplay.js';
4
4
  import { WGPUAov } from './WGPUAov.js';
5
- import { aovMask } from './aov.js';
6
- import { scheduleFrame } from '../util/frame.js';
5
+ import { aovMask, COMPACT_AOV_KINDS, DISPLAY_AOV_SAMPLE_CAP } from './aov.js';
7
6
  import { DisplayPostProcess } from './DisplayPostProcess.js';
8
7
  import { customDenoiseLayersMain, customDenoiseCoverageMain } from './wgsl/customDenoise.wgsl.js';
9
8
  import { WGPUCanvasSurface } from './WGPUCanvasSurface.js';
@@ -18,6 +17,7 @@ import WGPURayTracePass from './WGPURayTracePass.js';
18
17
  import { composeMain, composeDefine, compositeDenoiseOutputMain, compositeDenoiseDisplayMain, linearToSrgbDefine } from './wgsl/compose.frag.wgsl.js';
19
18
  import halton from './halton.js';
20
19
  import { makeTileRender, makeTileRenderWithPredict } from './TileRender.js';
20
+ import { WORKGROUP_SIZE } from './wgsl/rayTrace.compute.js';
21
21
  import { WGPURayTraceOutputPass } from './WGPURayTraceOutput.js';
22
22
  import { vec3 } from '../math.js';
23
23
  import WGPUBloomPass from './WGPUBloomPass.js';
@@ -28,16 +28,16 @@ export const oidnAlbedoSrgbEncodeMain = /* wgsl */ `
28
28
  if (globalId.x >= u32(imageSize.x) || globalId.y >= u32(imageSize.y)) { return; }
29
29
  let index = globalId.x + globalId.y * u32(imageSize.x);
30
30
  let raw = textureLoad(in_albedo, vec2u(globalId.xy), 0);
31
- let encoded = sT(raw.rgb);
31
+ let encoded = uq(raw.rgb);
32
32
  out_albedo[index] = vec4f(encoded, raw.a);
33
33
  `;
34
34
  export const oidnAlbedoSrgbDecodeMain = /* wgsl */ `
35
35
  if (globalId.x >= u32(imageSize.x) || globalId.y >= u32(imageSize.y)) { return; }
36
36
  let index = globalId.x + globalId.y * u32(imageSize.x);
37
37
  let filtered = in_albedo[index];
38
- let linear = sS(filtered.rgb);
38
+ let linear = uo(filtered.rgb);
39
39
  var result = linear;
40
- let jD = textureLoad(in_rawAlbedo, vec2i(globalId.xy), 0).a;
40
+ let jN = textureLoad(in_rawAlbedo, vec2i(globalId.xy), 0).a;
41
41
  if (preserveSurfaceTexture != 0u) {
42
42
 
43
43
 
@@ -45,33 +45,33 @@ if (preserveSurfaceTexture != 0u) {
45
45
  let pixel = vec2i(globalId.xy);
46
46
  let center = textureLoad(in_rawNormal, pixel, 0);
47
47
  let n = normalize(center.rgb * 2.0 - 1.0 + vec3f(1e-8));
48
- var oc = 0.0;
48
+ var oR = 0.0;
49
49
  for (var y = -1; y <= 1; y++) {
50
50
  for (var x = -1; x <= 1; x++) {
51
- let vw = textureLoad(in_rawNormal,
51
+ let xA = textureLoad(in_rawNormal,
52
52
  clamp(pixel + vec2i(x, y), vec2i(0), imageSize - 1), 0);
53
- let nn = normalize(vw.rgb * 2.0 - 1.0 + vec3f(1e-8));
54
- oc = max(oc,
55
- max(1.0 - dot(n, nn), abs(center.a - vw.a)));
53
+ let nn = normalize(xA.rgb * 2.0 - 1.0 + vec3f(1e-8));
54
+ oR = max(oR,
55
+ max(1.0 - dot(n, nn), abs(center.a - xA.a)));
56
56
  }
57
57
  }
58
- let vO = smoothstep(0.02, 0.1, oc);
58
+ let xY = smoothstep(0.02, 0.1, oR);
59
59
  let raw = clamp(textureLoad(in_rawAlbedo, pixel, 0).rgb,
60
60
  vec3f(0.0), vec3f(1.0));
61
- result = mix(raw, linear, vO);
61
+ result = mix(raw, linear, xY);
62
62
  }
63
- out_albedo[index] = vec4f(result, jD);
63
+ out_albedo[index] = vec4f(result, jN);
64
64
  `;
65
65
  export const oidnNormalSanitizeMain = /* wgsl */ `
66
66
  if (globalId.x >= u32(imageSize.x) || globalId.y >= u32(imageSize.y)) { return; }
67
67
  let index = globalId.x + globalId.y * u32(imageSize.x);
68
- out_normal[index] = vec4f(rL(in_normal[index].rgb), 1.0);
68
+ out_normal[index] = vec4f(sW(in_normal[index].rgb), 1.0);
69
69
  `;
70
70
  function createTimeQuery(device) {
71
71
  try {
72
72
  const querySet = device.createQuerySet({
73
73
  type: 'timestamp',
74
- count: 2
74
+ count: 16
75
75
  });
76
76
  const resolveBuffer = device.createBuffer({
77
77
  size: querySet.count * 8,
@@ -100,6 +100,9 @@ function makeWGPUAccumulationTarget(canvas, device, rayTracePass, surface, scrat
100
100
  // the next presentation or read resolves them once.
101
101
  let realtimeDeferPostProcess = false;
102
102
  let postProcessPending = false;
103
+ // Resolve uses the configuration that produced these buffers, even if another
104
+ // target has since changed the shared trace pass's caustic settings.
105
+ let sampledOutput;
103
106
  let offlineSamplesPerBatch = 0;
104
107
  let deferPostProcess = false;
105
108
  let sampleSequenceOffset = 0;
@@ -109,6 +112,7 @@ function makeWGPUAccumulationTarget(canvas, device, rayTracePass, surface, scrat
109
112
  let elapsedFrameTime = 32;
110
113
  let elapsedTileTime;
111
114
  let tileTimingGeneration = 0;
115
+ let causticBatchTimeMs = 0, photonBatchTimeMs = 0;
112
116
  let lastGpuTraceTiming;
113
117
  let displayTrace;
114
118
  let diagnosticsReadbackPromise = Promise.resolve();
@@ -228,13 +232,15 @@ function makeWGPUAccumulationTarget(canvas, device, rayTracePass, surface, scrat
228
232
  }).query
229
233
  : undefined;
230
234
  const tileRender = makeTileRender();
231
- const tileRenderWithPredict = timeQuery ? makeTileRenderWithPredict() : undefined;
235
+ const tileRenderWithPredict = timeQuery ? makeTileRenderWithPredict(WORKGROUP_SIZE) : undefined;
232
236
  tileRender.setDesiredMsPerTile(maxTimePerTile);
233
237
  tileRenderWithPredict?.setDesiredMsPerTile(maxTimePerTile);
234
238
  function invalidateTilePrediction() {
235
239
  tileTimingGeneration++;
236
240
  tileRenderWithPredict?.needsUpdatePredicting();
237
241
  lastGpuTraceTiming = undefined;
242
+ causticBatchTimeMs = 0;
243
+ photonBatchTimeMs = 0;
238
244
  // A changed render configuration needs fresh timing. Refresh
239
245
  // its estimator without submitting a hidden probe in that mode.
240
246
  needsUpdatePredicting = offlineSamplesPerBatch === 0;
@@ -261,9 +267,9 @@ function makeWGPUAccumulationTarget(canvas, device, rayTracePass, surface, scrat
261
267
  var color = load_colorTex(uv, 0);
262
268
  let coverage = clamp(load_coverageTex(uv, 0).a, 0.0, 1.0);
263
269
  color = vec4f(
264
- jQ(color.r, coverage, flatBackgroundColor.a > 0.5, true),
265
- jQ(color.g, coverage, flatBackgroundColor.a > 0.5, true),
266
- jQ(color.b, coverage, flatBackgroundColor.a > 0.5, true), color.a);
270
+ ka(color.r, coverage, flatBackgroundColor.a > 0.5, true),
271
+ ka(color.g, coverage, flatBackgroundColor.a > 0.5, true),
272
+ ka(color.b, coverage, flatBackgroundColor.a > 0.5, true), color.a);
267
273
  output.color = color;
268
274
  `
269
275
  }));
@@ -387,11 +393,11 @@ output.color = color;
387
393
  oidnNormalSanitizePass.setOutputParams({ normal: { channels: 4 } });
388
394
  const outputPass = scratch.get('outputPass', () => new WGPUFullQuadPass('output', device, {
389
395
  fsMain: /* wgsl */ `
390
- let xs = min(
396
+ let zU = min(
391
397
  vec2i(uv2 * vec2f(colorTexRegion())),
392
398
  vec2i(colorTexRegion()) - vec2i(1)
393
399
  );
394
- var color = load_colorTex(xs, 0);
400
+ var color = load_colorTex(zU, 0);
395
401
  color = vec4(color.rgb * color.a, color.a);
396
402
  output.color = color;
397
403
  `,
@@ -424,7 +430,8 @@ output.color = color;
424
430
  _updateSeed(renderWidth, renderHeight);
425
431
  const activeTimeQuery = timeQuery;
426
432
  const isUnmapped = activeTimeQuery?.resultBuffer.mapState === 'unmapped';
427
- rayTracePass.createPass(encoder, clear, tiles, activeTimeQuery ? { querySet: activeTimeQuery.querySet } : undefined);
433
+ const measuredCausticBatch = rayTracePass.createPass(encoder, clear, tiles, activeTimeQuery ? { querySet: activeTimeQuery.querySet } : undefined);
434
+ sampledOutput = rayTracePass.getOutputBuffer();
428
435
  if (activeTimeQuery) {
429
436
  encoder.resolveQuerySet(activeTimeQuery.querySet, 0, activeTimeQuery.querySet.count, activeTimeQuery.resolveBuffer, 0);
430
437
  if (isUnmapped) {
@@ -440,20 +447,31 @@ output.color = color;
440
447
  diagnosticsReadbackPromise = activeTimeQuery.resultBuffer
441
448
  .mapAsync(GPUMapMode.READ).then(() => {
442
449
  const mappedRange = activeTimeQuery.resultBuffer.getMappedRange();
443
- const times = new BigInt64Array(mappedRange, 0, 2);
444
- const traceTime = Math.max(Number(times[1] - times[0]) / 1_000_000, 0.1);
450
+ const times = new BigInt64Array(mappedRange, 0, 16);
451
+ const causticTime = (measuredCausticBatch & 1) ? Math.max(Number(times[3] - times[2] + times[5] - times[4]) / 1_000_000, 0) : 0;
452
+ // Independent timestamp pairs avoid Metal's cross-pass counter bug.
453
+ const photonTime = (measuredCausticBatch & 2) ? Math.max(Number(times[7] - times[6] + times[9] - times[8] + times[11] - times[10] + times[13] - times[12] + times[15] - times[14]) / 1_000_000, 0) : 0;
454
+ const ptTime = Math.max(Number(times[1] - times[0]) / 1_000_000, 0);
445
455
  // A readback may finish after scene preparation or a mode switch.
446
456
  // It must not overwrite throughput learned for the current scene.
447
457
  const timingIsCurrent = !disposed && submittedTimingGeneration === tileTimingGeneration &&
448
458
  !isFirstFrame;
449
459
  if (timingIsCurrent) {
460
+ if (measuredCausticBatch & 1)
461
+ causticBatchTimeMs = causticTime;
462
+ if (measuredCausticBatch & 2)
463
+ photonBatchTimeMs = photonTime;
464
+ const traceTime = Math.max(ptTime + (causticBatchTimeMs + photonBatchTimeMs) / submittedTileCount, .1);
450
465
  lastGpuTraceTiming = {
466
+ causticTimeMs: causticBatchTimeMs, photonMappingTimeMs: photonBatchTimeMs,
467
+ photonStagesMs: (measuredCausticBatch & 2) ? [6, 8, 10, 12, 14].map(i => Math.max(Number(times[i + 1] - times[i]) / 1_000_000, 0)) : undefined,
468
+ pathTracingTimeMs: ptTime,
451
469
  tileTimeMs: traceTime,
452
470
  tileTimePerSampleMs: traceTime,
453
471
  estimatedFullFrameTimeMs: traceTime * submittedTileCount,
454
472
  tileCount: submittedTileCount
455
473
  };
456
- submittedTileRenderWithPredict.setLastTraceTime(traceTime);
474
+ submittedTileRenderWithPredict.setLastTraceTime(traceTime, tiles[0], tiles[1]);
457
475
  }
458
476
  activeTimeQuery.resultBuffer.unmap();
459
477
  }).catch(() => {
@@ -556,7 +574,7 @@ output.color = color;
556
574
  denoisedTexture = prepareDenoisedTexture(encoder, denoisedBuffer, denoisedTexture);
557
575
  if (resolve) {
558
576
  rayTraceOutputPass.setSampleCount(sampleCount);
559
- rayTraceOutputPass.createPass(encoder, rayTracePass.getOutputBuffer(), resolvedHasShadowCatcher);
577
+ rayTraceOutputPass.createPass(encoder, sampledOutput ?? rayTracePass.getOutputBuffer(), resolvedHasShadowCatcher);
560
578
  }
561
579
  composePass.setUniform('shadowCatcherEnabled', +resolvedHasShadowCatcher);
562
580
  let foregroundTexture = getFrameInput(resolvedHasShadowCatcher ? 'foreground' : 'color');
@@ -629,10 +647,12 @@ output.color = color;
629
647
  finishPresentation(encoder, displayTexture);
630
648
  }
631
649
  function finishPresentation(encoder, displayTexture) {
650
+ const presentationWidth = displayAovKind(output) ? displayTexture.width : renderWidth;
651
+ const presentationHeight = displayAovKind(output) ? displayTexture.height : renderHeight;
632
652
  const activeHDRPeakMeter = hdrOutputActive
633
653
  ? (hdrPeakMeter ??= scratch.get('hdrPeak', () => new WGPUHDRPeakMeter(device)))
634
654
  : undefined;
635
- const hdrPeakReadbackSubmitted = activeHDRPeakMeter?.encode(encoder, displayTexture, renderWidth, renderHeight) ?? false;
655
+ const hdrPeakReadbackSubmitted = activeHDRPeakMeter?.encode(encoder, displayTexture, presentationWidth, presentationHeight) ?? false;
636
656
  if (output === 'normal' || output === 'albedo') {
637
657
  displayTrace?.push('AOV:Raw');
638
658
  displayTexture = getFrameInput(output);
@@ -641,14 +661,14 @@ output.color = color;
641
661
  displayTrace?.push('AOV:Raw');
642
662
  displayTexture = getFrameInput('shadowCatcher');
643
663
  }
644
- if (displayTexture.width < renderWidth || displayTexture.height < renderHeight) {
645
- readbackPass.setSize(renderWidth, renderHeight);
664
+ if (displayTexture.width < presentationWidth || displayTexture.height < presentationHeight) {
665
+ readbackPass.setSize(presentationWidth, presentationHeight);
646
666
  readbackPass.createPass(encoder, { inputTex: displayTexture });
647
667
  displayTexture = readbackPass.getOutput('color');
648
668
  }
649
669
  // Keep the completed denoise visible until its replacement is ready.
650
670
  if (!(preserveDenoisedOutput && output === 'final' && !denoiseValid && presentationDenoised)) {
651
- const width = renderWidth, height = renderHeight;
671
+ const width = presentationWidth, height = presentationHeight;
652
672
  if (!presentationTexture || presentationTexture.width !== width || presentationTexture.height !== height || presentationTexture.format !== displayTexture.format) {
653
673
  const previous = presentationTexture;
654
674
  presentationTexture = device.createTexture({
@@ -673,20 +693,28 @@ output.color = color;
673
693
  postProcessPending = false;
674
694
  drawPostProcess(device.createCommandEncoder(), false, true);
675
695
  }
696
+ const aovResolution = () => execution?.aovResolution === 'display' ? { width: canvas.width, height: canvas.height } : undefined;
697
+ const compactAov = () => !!aovResolution() && !!execution?.aovs?.every(kind => COMPACT_AOV_KINDS.includes(kind));
676
698
  function trace(camera, maxSamples) {
699
+ applyTraceQuality();
677
700
  // A call to draw means accumulation has been invalidated. Cancel OIDN
678
701
  // before checking shader compilation: pipeline-affecting parameter changes
679
702
  // otherwise leave the previous asynchronous denoise alive while resources
680
703
  // and bind groups are being replaced.
681
704
  cancelDenoise();
682
- if (rayTracePass.isCompilingShader()) {
683
- isFirstFrame = true;
684
- sampleCount = 0;
685
- return true;
686
- }
687
705
  // Update the camera before compiling and sampling.
688
706
  rayTracePass.setCamera(camera);
689
707
  aovCamera = camera;
708
+ rayTracePass.updatePipeline();
709
+ const pipelineError = rayTracePass.getPipelineError();
710
+ if (pipelineError)
711
+ throw pipelineError;
712
+ // Waiting for a shader is not an input change: this render's samples and
713
+ // complete image stay valid, and only Render's restart discards them.
714
+ if (rayTracePass.isCompilingShader() || !rayTracePass.isPipelineReady())
715
+ return true;
716
+ if (execution?.aovs?.length && !rayTracePass.prepareAovs(execution.aovs, compactAov()))
717
+ return true;
690
718
  const resetAccumulation = isFirstFrame;
691
719
  if (resetAccumulation)
692
720
  aov.reset();
@@ -696,20 +724,11 @@ output.color = color;
696
724
  denoiseValid = false;
697
725
  tileTimingGeneration++;
698
726
  elapsedTileTime = undefined;
699
- rayTracePass.setCamera(camera);
700
727
  (tileRenderWithPredict || tileRender).reset();
701
728
  // Reset
702
729
  isFirstFrame = false;
703
730
  sampleCount = 0;
704
731
  }
705
- rayTracePass.updatePipeline();
706
- if (rayTracePass.isCompilingShader() || !rayTracePass.isPipelineReady()) {
707
- isFirstFrame = true;
708
- sampleCount = 0;
709
- return true;
710
- }
711
- if (execution?.aovs?.length && !rayTracePass.prepareAovs(execution.aovs))
712
- return true;
713
732
  // Keep the last completed denoise visible while a static while-converging batch
714
733
  // accumulates, including the incomplete first sample after a scene edit.
715
734
  if (!preserveDenoisedOutput || isFirstFrame) {
@@ -802,7 +821,13 @@ output.color = color;
802
821
  return false;
803
822
  }
804
823
  if (sampleCount !== frameSampleCount && execution?.aovs?.length) {
805
- rayTracePass.renderAovs(aov, camera, sampleCount, execution.aovSamples ?? 16, execution.aovs);
824
+ // Display AOVs only add detail: keep the first beauty image's latency and
825
+ // spread their full-canvas samples over frames instead of batching them.
826
+ // The converging trace completes any remaining samples.
827
+ const display = aovResolution();
828
+ const aovTarget = display && sampleCount < maxSamples ? Math.min(sampleCount - 1, aov.samples + 1) : sampleCount;
829
+ if (aovTarget > 0)
830
+ rayTracePass.renderAovs(aov, camera, aovTarget, Math.min(execution.aovSamples ?? 16, display ? DISPLAY_AOV_SAMPLE_CAP : Infinity), execution.aovs, display);
806
831
  }
807
832
  if (sampleCount !== frameSampleCount && realtime && realtimeDeferPostProcess && sampleCount < renderSampleTarget) {
808
833
  postProcessPending = true;
@@ -840,6 +865,7 @@ output.color = color;
840
865
  // The target retains its complete presentation texture through the resize.
841
866
  clearDenoisedOutput();
842
867
  tileTimingGeneration++;
868
+ sampledOutput = undefined;
843
869
  renderWidth = nextRenderWidth;
844
870
  renderHeight = nextRenderHeight;
845
871
  (tileRenderWithPredict || tileRender).setSize(renderWidth, renderHeight);
@@ -877,13 +903,7 @@ output.color = color;
877
903
  }
878
904
  function setToneMappingParams(params) {
879
905
  const newExposure = params.exposure ?? 1;
880
- const newToneMappingMode = {
881
- agx: 0,
882
- aces: 1,
883
- cineon: 2,
884
- reinhard: 3,
885
- linear: 4
886
- }[params.toneMapping ?? 'agx'] ?? 0;
906
+ const newToneMappingMode = TONE_MAPPING_MODES[params.toneMapping ?? 'agx'] ?? 0;
887
907
  const newContrast = params.contrast ?? 1;
888
908
  const newSaturation = params.saturation ?? 1;
889
909
  const newTemperature = params.temperature ?? 0;
@@ -1289,31 +1309,37 @@ output.color = color;
1289
1309
  rayTraceOutputPass.dispose();
1290
1310
  });
1291
1311
  }
1312
+ // Keep tracing quality out of presentation: an old fallback must not
1313
+ // invalidate a new caustic pipeline while it is compiling.
1314
+ function applyTraceQuality() {
1315
+ if (execution) {
1316
+ rayTracePass.setQuality(execution);
1317
+ rayTracePass.setBevelSamples(execution.bevelSamples);
1318
+ rayTracePass.setAlphaBlendStrategy(execution.alphaBlendStrategy);
1319
+ rayTracePass.setSamplingPattern(execution.samplingPattern, execution.maxSamples);
1320
+ }
1321
+ }
1292
1322
  function activate() {
1293
1323
  rayTracePass.useTarget(targetKey);
1294
1324
  if (renderWidth && renderHeight)
1295
1325
  rayTracePass.setSize(renderWidth, renderHeight, screenWidth / screenHeight);
1296
1326
  if (execution) {
1297
- rayTracePass.setQuality(execution);
1298
1327
  rayTracePass.setClamping(execution.clamping);
1299
1328
  rayTracePass.setTransmissiveOutputAlphaMin(execution.transmissiveOutputAlphaMin);
1300
- rayTracePass.setBevelSamples(execution.bevelSamples);
1301
- rayTracePass.setAlphaBlendStrategy(execution.alphaBlendStrategy);
1302
- rayTracePass.setSamplingPattern(execution.samplingPattern, execution.maxSamples);
1303
1329
  }
1304
1330
  }
1305
1331
  return {
1306
1332
  invalidateTiming: invalidateTilePrediction,
1307
1333
  invalidateDenoisedOutput() { cancelDenoise(); denoiseValid = false; preserveDenoisedOutput = false; },
1308
1334
  configure(settings) {
1309
- const timingKeys = ['bounces', 'bevel', 'bevelSamples', 'directLightCandidates', 'dispersionWavelengths', 'alphaBlendStrategy', 'samplingPattern', 'clamping', 'transmissiveOutputAlphaMin'];
1335
+ const timingKeys = ['bounces', 'bevel', 'bevelSamples', 'directLightCandidates', 'dispersionWavelengths', 'alphaBlendStrategy', 'samplingPattern', 'clamping', 'transmissiveOutputAlphaMin', 'caustics'];
1310
1336
  if (!execution || timingKeys.some(key => execution[key] !== settings[key]))
1311
1337
  invalidateTilePrediction();
1312
1338
  if (settings.aovs?.length && (!Number.isInteger(settings.aovSamples ?? 16) || (settings.aovSamples ?? 16) < 1))
1313
1339
  throw new RangeError('aovSamples must be a positive integer');
1314
1340
  const previousMask = aovMask(execution?.aovs ?? []), nextMask = aovMask(settings.aovs ?? []);
1315
- if (previousMask !== nextMask || execution?.aovSamples !== settings.aovSamples)
1316
- aov.samples = 0;
1341
+ if (previousMask !== nextMask || execution?.aovSamples !== settings.aovSamples || execution?.aovResolution !== settings.aovResolution)
1342
+ aov.reset();
1317
1343
  execution = { ...settings, aovs: [...(settings.aovs ?? [])] };
1318
1344
  // Presentation may still name the previous preview's AOV. Drop that
1319
1345
  // selection before tracing with a smaller set; Display validates and
@@ -1341,7 +1367,8 @@ output.color = color;
1341
1367
  },
1342
1368
  setRealtimeBatchBudget(milliseconds) { realtimeBatchBudgetMs = milliseconds; },
1343
1369
  setRealtimeDeferPostProcess(defer) { realtimeDeferPostProcess = defer; },
1344
- getRealtimeSampleTime() { return lastGpuTraceTiming?.tileCount === 1 ? lastGpuTraceTiming.estimatedFullFrameTimeMs : undefined; },
1370
+ getRealtimeSampleTime() { return lastGpuTraceTiming?.estimatedFullFrameTimeMs; },
1371
+ getRealtimeTileTime() { return lastGpuTraceTiming?.tileTimePerSampleMs; },
1345
1372
  whenTraceAvailable() { return traceQueue.whenAvailable(); },
1346
1373
  get presentationComplete() { return !!presentationTexture; },
1347
1374
  get presentationDenoised() { return presentationDenoised; },
@@ -1380,15 +1407,16 @@ output.color = color;
1380
1407
  isFirstFrame = true;
1381
1408
  sampleCount = 0;
1382
1409
  },
1410
+ getAovTexture(kind) { return execution?.aovs?.includes(kind) ? aov.texture(kind) : undefined; },
1383
1411
  getOutputTexture(kind) {
1384
1412
  flushPostProcess();
1385
1413
  if (kind === 'hdr')
1386
1414
  return resolvedSamples > 0 ? getFrameInput('color') : undefined;
1387
1415
  return displayPostProcess.output ?? presentationTexture;
1388
1416
  },
1389
- applyPostProcesses(passes, render) {
1417
+ applyPostProcesses(passes, render, options, crop) {
1390
1418
  if (presentationTexture)
1391
- displayPostProcess.run(presentationTexture, passes, render);
1419
+ displayPostProcess.run(presentationTexture, passes, render, canvas, options, crop);
1392
1420
  },
1393
1421
  trace,
1394
1422
  drawPostProcess() {
@@ -1434,21 +1462,35 @@ output.color = color;
1434
1462
  refineAovs(camera, samples = sampleCount) {
1435
1463
  if (samples < 1 || !execution?.aovs?.length)
1436
1464
  return true;
1465
+ applyTraceQuality();
1437
1466
  rayTracePass.setCamera(camera);
1438
1467
  aovCamera = camera;
1439
1468
  rayTracePass.updatePipeline();
1469
+ const pipelineError = rayTracePass.getPipelineError();
1470
+ if (pipelineError)
1471
+ throw pipelineError;
1440
1472
  if (rayTracePass.isCompilingShader() || !rayTracePass.isPipelineReady())
1441
1473
  return false;
1442
- return rayTracePass.renderAovs(aov, camera, samples, execution.aovSamples ?? 16, execution.aovs);
1474
+ return rayTracePass.renderAovs(aov, camera, samples, Math.min(execution.aovSamples ?? 16, aovResolution() ? DISPLAY_AOV_SAMPLE_CAP : Infinity), execution.aovs, aovResolution());
1443
1475
  },
1444
1476
  async readAov(kind) {
1445
1477
  if (!execution?.aovs?.includes(kind) || !aovCamera || (sampleCount < 1 && aov.samples < 1))
1446
1478
  throw new Error('AOV output is not ready');
1447
- rayTracePass.setCamera(aovCamera);
1448
- while (!rayTracePass.renderAovs(aov, aovCamera, Math.max(sampleCount, aov.samples), execution.aovSamples ?? 16, execution.aovs)) {
1479
+ for (;;) {
1449
1480
  if (disposed)
1450
1481
  throw new Error('AOV compilation was interrupted');
1451
- await new Promise(resolve => scheduleFrame(() => resolve()));
1482
+ activate();
1483
+ applyTraceQuality();
1484
+ rayTracePass.setCamera(aovCamera);
1485
+ rayTracePass.updatePipeline();
1486
+ const pipelineError = rayTracePass.getPipelineError();
1487
+ if (pipelineError)
1488
+ throw pipelineError;
1489
+ if (!rayTracePass.isCompilingShader() && rayTracePass.isPipelineReady() &&
1490
+ rayTracePass.renderAovs(aov, aovCamera, Math.max(sampleCount, aov.samples), Math.min(execution.aovSamples ?? 16, aovResolution() ? DISPLAY_AOV_SAMPLE_CAP : Infinity), execution.aovs, aovResolution()))
1491
+ break;
1492
+ // Display frames stop on a hidden page, but compilation still completes.
1493
+ await new Promise(resolve => setTimeout(resolve, 16));
1452
1494
  }
1453
1495
  return aov.read(kind);
1454
1496
  },
@@ -1532,7 +1574,7 @@ output.color = color;
1532
1574
  setSize(input.width, input.height);
1533
1575
  rayTracePass.useTarget(targetKey);
1534
1576
  rayTracePass.setSize(renderWidth, renderHeight, screenWidth / screenHeight);
1535
- const buffers = rayTracePass.getOutputBuffer();
1577
+ const buffers = sampledOutput = rayTracePass.getOutputBuffer();
1536
1578
  const shadow = new Float32Array(input.width * input.height * 12);
1537
1579
  for (let i = 0; i < input.width * input.height; i++) {
1538
1580
  shadow.set(input.shadow.subarray(i * 8, i * 8 + 8), i * 12);