@meimu/mutracer 0.0.0-stage → 0.1.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 (536) hide show
  1. package/LICENSE +21 -0
  2. package/LICENSES/Apache-2.0.txt +202 -0
  3. package/LICENSES/GLSL-PathTracer-MIT.txt +21 -0
  4. package/LICENSES/GlMatrix-MIT.txt +19 -0
  5. package/LICENSES/KinoBloom-MIT.txt +21 -0
  6. package/LICENSES/OIDNWeb-MIT.txt +21 -0
  7. package/LICENSES/Octicons-MIT.txt +21 -0
  8. package/LICENSES/RayTracingRenderer-MIT.txt +21 -0
  9. package/LICENSES/TinyBVH-MIT.txt +21 -0
  10. package/LICENSES/WebGPUUtils-MIT.txt +21 -0
  11. package/LICENSES/ZetaRay-MIT.txt +21 -0
  12. package/README.md +240 -2
  13. package/THIRD_PARTY_NOTICES.md +160 -0
  14. package/dist/assets/bvh.worker.js +1 -0
  15. package/dist/mutracer.umd.js +14360 -0
  16. package/docs/api.md +394 -0
  17. package/docs/bvh.md +141 -0
  18. package/docs/denoising.md +301 -0
  19. package/docs/getting-started.md +308 -0
  20. package/docs/materials.md +281 -0
  21. package/docs/performance.md +85 -0
  22. package/docs/post-processing.md +87 -0
  23. package/docs/progressive-rendering.md +160 -0
  24. package/docs/sampling.md +40 -0
  25. package/docs/threejs.md +274 -0
  26. package/docs/todo.md +61 -0
  27. package/docs/updates.md +208 -0
  28. package/lib/Display.d.ts +72 -0
  29. package/lib/Display.js +123 -0
  30. package/lib/Display.js.map +1 -0
  31. package/lib/Engine.d.ts +161 -0
  32. package/lib/Engine.js +681 -0
  33. package/lib/Engine.js.map +1 -0
  34. package/lib/Render.d.ts +265 -0
  35. package/lib/Render.js +742 -0
  36. package/lib/Render.js.map +1 -0
  37. package/lib/RenderLoop.d.ts +79 -0
  38. package/lib/RenderLoop.js +236 -0
  39. package/lib/RenderLoop.js.map +1 -0
  40. package/lib/Sync.d.ts +19 -0
  41. package/lib/Sync.js +19 -0
  42. package/lib/Sync.js.map +1 -0
  43. package/lib/constants.d.ts +2 -0
  44. package/lib/constants.js +3 -0
  45. package/lib/constants.js.map +1 -0
  46. package/lib/main.d.ts +56 -0
  47. package/lib/main.js +43 -0
  48. package/lib/main.js.map +1 -0
  49. package/lib/math.d.ts +23 -0
  50. package/lib/math.js +56 -0
  51. package/lib/math.js.map +1 -0
  52. package/lib/oidn.d.ts +45 -0
  53. package/lib/oidn.js +42 -0
  54. package/lib/oidn.js.map +1 -0
  55. package/lib/oidnBundledWeights.cdn.d.ts +2 -0
  56. package/lib/oidnBundledWeights.cdn.js +5 -0
  57. package/lib/oidnBundledWeights.cdn.js.map +1 -0
  58. package/lib/oidnBundledWeights.d.ts +2 -0
  59. package/lib/oidnBundledWeights.js +4 -0
  60. package/lib/oidnBundledWeights.js.map +1 -0
  61. package/lib/renderer/DisplayPostProcess.d.ts +14 -0
  62. package/lib/renderer/DisplayPostProcess.js +41 -0
  63. package/lib/renderer/DisplayPostProcess.js.map +1 -0
  64. package/lib/renderer/MaterialTable.d.ts +119 -0
  65. package/lib/renderer/MaterialTable.js +550 -0
  66. package/lib/renderer/MaterialTable.js.map +1 -0
  67. package/lib/renderer/OfflineAdaptiveSampling.d.ts +47 -0
  68. package/lib/renderer/OfflineAdaptiveSampling.js +36 -0
  69. package/lib/renderer/OfflineAdaptiveSampling.js.map +1 -0
  70. package/lib/renderer/RenderingPipeline.d.ts +232 -0
  71. package/lib/renderer/RenderingPipeline.js +18 -0
  72. package/lib/renderer/RenderingPipeline.js.map +1 -0
  73. package/lib/renderer/ScratchPool.d.ts +13 -0
  74. package/lib/renderer/ScratchPool.js +21 -0
  75. package/lib/renderer/ScratchPool.js.map +1 -0
  76. package/lib/renderer/TileRender.d.ts +44 -0
  77. package/lib/renderer/TileRender.js +283 -0
  78. package/lib/renderer/TileRender.js.map +1 -0
  79. package/lib/renderer/WGPUBloomPass.d.ts +17 -0
  80. package/lib/renderer/WGPUBloomPass.js +243 -0
  81. package/lib/renderer/WGPUBloomPass.js.map +1 -0
  82. package/lib/renderer/WGPUCanvasSurface.d.ts +21 -0
  83. package/lib/renderer/WGPUCanvasSurface.js +48 -0
  84. package/lib/renderer/WGPUCanvasSurface.js.map +1 -0
  85. package/lib/renderer/WGPUComputePass.d.ts +73 -0
  86. package/lib/renderer/WGPUComputePass.js +317 -0
  87. package/lib/renderer/WGPUComputePass.js.map +1 -0
  88. package/lib/renderer/WGPUFullQuadPass.d.ts +73 -0
  89. package/lib/renderer/WGPUFullQuadPass.js +389 -0
  90. package/lib/renderer/WGPUFullQuadPass.js.map +1 -0
  91. package/lib/renderer/WGPUHDRPeakMeter.d.ts +19 -0
  92. package/lib/renderer/WGPUHDRPeakMeter.js +112 -0
  93. package/lib/renderer/WGPUHDRPeakMeter.js.map +1 -0
  94. package/lib/renderer/WGPUJNLMDenoiser.d.ts +61 -0
  95. package/lib/renderer/WGPUJNLMDenoiser.js +412 -0
  96. package/lib/renderer/WGPUJNLMDenoiser.js.map +1 -0
  97. package/lib/renderer/WGPURayTraceOutput.d.ts +44 -0
  98. package/lib/renderer/WGPURayTraceOutput.js +368 -0
  99. package/lib/renderer/WGPURayTraceOutput.js.map +1 -0
  100. package/lib/renderer/WGPURayTracePass.d.ts +284 -0
  101. package/lib/renderer/WGPURayTracePass.js +2323 -0
  102. package/lib/renderer/WGPURayTracePass.js.map +1 -0
  103. package/lib/renderer/WGPURenderingPipeline.d.ts +9 -0
  104. package/lib/renderer/WGPURenderingPipeline.js +1448 -0
  105. package/lib/renderer/WGPURenderingPipeline.js.map +1 -0
  106. package/lib/renderer/WGPUSceneFeatures.d.ts +3 -0
  107. package/lib/renderer/WGPUSceneFeatures.js +20 -0
  108. package/lib/renderer/WGPUSceneFeatures.js.map +1 -0
  109. package/lib/renderer/WGPUScratchBuffer.d.ts +9 -0
  110. package/lib/renderer/WGPUScratchBuffer.js +21 -0
  111. package/lib/renderer/WGPUScratchBuffer.js.map +1 -0
  112. package/lib/renderer/WGPUScratchTexture.d.ts +10 -0
  113. package/lib/renderer/WGPUScratchTexture.js +27 -0
  114. package/lib/renderer/WGPUScratchTexture.js.map +1 -0
  115. package/lib/renderer/WGPUShaderCache.d.ts +26 -0
  116. package/lib/renderer/WGPUShaderCache.js +103 -0
  117. package/lib/renderer/WGPUShaderCache.js.map +1 -0
  118. package/lib/renderer/WebGLBloomPass.d.ts +18 -0
  119. package/lib/renderer/WebGLBloomPass.js +113 -0
  120. package/lib/renderer/WebGLBloomPass.js.map +1 -0
  121. package/lib/renderer/WebGLFullQuadPass.d.ts +65 -0
  122. package/lib/renderer/WebGLFullQuadPass.js +208 -0
  123. package/lib/renderer/WebGLFullQuadPass.js.map +1 -0
  124. package/lib/renderer/WebGLJNLMDenoiser.d.ts +32 -0
  125. package/lib/renderer/WebGLJNLMDenoiser.js +328 -0
  126. package/lib/renderer/WebGLJNLMDenoiser.js.map +1 -0
  127. package/lib/renderer/WebGLRayTraceOutputPass.d.ts +20 -0
  128. package/lib/renderer/WebGLRayTraceOutputPass.js +106 -0
  129. package/lib/renderer/WebGLRayTraceOutputPass.js.map +1 -0
  130. package/lib/renderer/WebGLRayTracePass.d.ts +142 -0
  131. package/lib/renderer/WebGLRayTracePass.js +845 -0
  132. package/lib/renderer/WebGLRayTracePass.js.map +1 -0
  133. package/lib/renderer/WebGLReadback.d.ts +4 -0
  134. package/lib/renderer/WebGLReadback.js +75 -0
  135. package/lib/renderer/WebGLReadback.js.map +1 -0
  136. package/lib/renderer/WebGLRenderingPipeline.d.ts +4 -0
  137. package/lib/renderer/WebGLRenderingPipeline.js +510 -0
  138. package/lib/renderer/WebGLRenderingPipeline.js.map +1 -0
  139. package/lib/renderer/WebGLScratchCopy.d.ts +10 -0
  140. package/lib/renderer/WebGLScratchCopy.js +27 -0
  141. package/lib/renderer/WebGLScratchCopy.js.map +1 -0
  142. package/lib/renderer/accumulationTarget.d.ts +26 -0
  143. package/lib/renderer/accumulationTarget.js +2 -0
  144. package/lib/renderer/accumulationTarget.js.map +1 -0
  145. package/lib/renderer/binnedSahBvh.d.ts +31 -0
  146. package/lib/renderer/binnedSahBvh.js +263 -0
  147. package/lib/renderer/binnedSahBvh.js.map +1 -0
  148. package/lib/renderer/bvh.worker.d.ts +1 -0
  149. package/lib/renderer/bvh.worker.js +16 -0
  150. package/lib/renderer/bvh.worker.js.map +1 -0
  151. package/lib/renderer/bvhAccel.d.ts +81 -0
  152. package/lib/renderer/bvhAccel.js +621 -0
  153. package/lib/renderer/bvhAccel.js.map +1 -0
  154. package/lib/renderer/bvhWorkerBuild.d.ts +12 -0
  155. package/lib/renderer/bvhWorkerBuild.js +17 -0
  156. package/lib/renderer/bvhWorkerBuild.js.map +1 -0
  157. package/lib/renderer/bvhWorkerClient.d.ts +57 -0
  158. package/lib/renderer/bvhWorkerClient.js +166 -0
  159. package/lib/renderer/bvhWorkerClient.js.map +1 -0
  160. package/lib/renderer/cameraLens.d.ts +5 -0
  161. package/lib/renderer/cameraLens.js +15 -0
  162. package/lib/renderer/cameraLens.js.map +1 -0
  163. package/lib/renderer/cameraSnapshot.d.ts +3 -0
  164. package/lib/renderer/cameraSnapshot.js +7 -0
  165. package/lib/renderer/cameraSnapshot.js.map +1 -0
  166. package/lib/renderer/committedScene.d.ts +13 -0
  167. package/lib/renderer/committedScene.js +126 -0
  168. package/lib/renderer/committedScene.js.map +1 -0
  169. package/lib/renderer/dataTextureUtil.d.ts +32 -0
  170. package/lib/renderer/dataTextureUtil.js +46 -0
  171. package/lib/renderer/dataTextureUtil.js.map +1 -0
  172. package/lib/renderer/denoiser.d.ts +65 -0
  173. package/lib/renderer/denoiser.js +2 -0
  174. package/lib/renderer/denoiser.js.map +1 -0
  175. package/lib/renderer/depthQuery.d.ts +14 -0
  176. package/lib/renderer/depthQuery.js +14 -0
  177. package/lib/renderer/depthQuery.js.map +1 -0
  178. package/lib/renderer/deviceRequirements.d.ts +23 -0
  179. package/lib/renderer/deviceRequirements.js +50 -0
  180. package/lib/renderer/deviceRequirements.js.map +1 -0
  181. package/lib/renderer/envMapCreation.d.ts +10 -0
  182. package/lib/renderer/envMapCreation.js +96 -0
  183. package/lib/renderer/envMapCreation.js.map +1 -0
  184. package/lib/renderer/envMapDistribution.d.ts +9 -0
  185. package/lib/renderer/envMapDistribution.js +107 -0
  186. package/lib/renderer/envMapDistribution.js.map +1 -0
  187. package/lib/renderer/float16.d.ts +1 -0
  188. package/lib/renderer/float16.js +19 -0
  189. package/lib/renderer/float16.js.map +1 -0
  190. package/lib/renderer/geometryBvh.d.ts +11 -0
  191. package/lib/renderer/geometryBvh.js +24 -0
  192. package/lib/renderer/geometryBvh.js.map +1 -0
  193. package/lib/renderer/geometryUpdates.d.ts +28 -0
  194. package/lib/renderer/geometryUpdates.js +131 -0
  195. package/lib/renderer/geometryUpdates.js.map +1 -0
  196. package/lib/renderer/glsl/chunks/cameraRay.glsl.d.ts +2 -0
  197. package/lib/renderer/glsl/chunks/cameraRay.glsl.js +37 -0
  198. package/lib/renderer/glsl/chunks/cameraRay.glsl.js.map +1 -0
  199. package/lib/renderer/glsl/chunks/common.glsl.d.ts +2 -0
  200. package/lib/renderer/glsl/chunks/common.glsl.js +17 -0
  201. package/lib/renderer/glsl/chunks/common.glsl.js.map +1 -0
  202. package/lib/renderer/glsl/chunks/envMap.glsl.d.ts +2 -0
  203. package/lib/renderer/glsl/chunks/envMap.glsl.js +192 -0
  204. package/lib/renderer/glsl/chunks/envMap.glsl.js.map +1 -0
  205. package/lib/renderer/glsl/chunks/intersect.glsl.d.ts +2 -0
  206. package/lib/renderer/glsl/chunks/intersect.glsl.js +1091 -0
  207. package/lib/renderer/glsl/chunks/intersect.glsl.js.map +1 -0
  208. package/lib/renderer/glsl/chunks/materialBuffer.glsl.d.ts +2 -0
  209. package/lib/renderer/glsl/chunks/materialBuffer.glsl.js +371 -0
  210. package/lib/renderer/glsl/chunks/materialBuffer.glsl.js.map +1 -0
  211. package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.d.ts +2 -0
  212. package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js +1767 -0
  213. package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js.map +1 -0
  214. package/lib/renderer/glsl/chunks/rand.glsl.d.ts +2 -0
  215. package/lib/renderer/glsl/chunks/rand.glsl.js +26 -0
  216. package/lib/renderer/glsl/chunks/rand.glsl.js.map +1 -0
  217. package/lib/renderer/glsl/chunks/random.glsl.d.ts +2 -0
  218. package/lib/renderer/glsl/chunks/random.glsl.js +27 -0
  219. package/lib/renderer/glsl/chunks/random.glsl.js.map +1 -0
  220. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.d.ts +2 -0
  221. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js +287 -0
  222. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js.map +1 -0
  223. package/lib/renderer/glsl/chunks/sampleLight.glsl.d.ts +2 -0
  224. package/lib/renderer/glsl/chunks/sampleLight.glsl.js +254 -0
  225. package/lib/renderer/glsl/chunks/sampleLight.glsl.js.map +1 -0
  226. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.d.ts +2 -0
  227. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js +279 -0
  228. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js.map +1 -0
  229. package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.d.ts +2 -0
  230. package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js +48 -0
  231. package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js.map +1 -0
  232. package/lib/renderer/glsl/chunks/sampling.glsl.d.ts +2 -0
  233. package/lib/renderer/glsl/chunks/sampling.glsl.js +194 -0
  234. package/lib/renderer/glsl/chunks/sampling.glsl.js.map +1 -0
  235. package/lib/renderer/glsl/chunks/sobol.glsl.d.ts +2 -0
  236. package/lib/renderer/glsl/chunks/sobol.glsl.js +170 -0
  237. package/lib/renderer/glsl/chunks/sobol.glsl.js.map +1 -0
  238. package/lib/renderer/glsl/chunks/textureLinear.glsl.d.ts +2 -0
  239. package/lib/renderer/glsl/chunks/textureLinear.glsl.js +27 -0
  240. package/lib/renderer/glsl/chunks/textureLinear.glsl.js.map +1 -0
  241. package/lib/renderer/glsl/chunks/uvProjection.glsl.d.ts +2 -0
  242. package/lib/renderer/glsl/chunks/uvProjection.glsl.js +72 -0
  243. package/lib/renderer/glsl/chunks/uvProjection.glsl.js.map +1 -0
  244. package/lib/renderer/glsl/depthQuery.frag.d.ts +3 -0
  245. package/lib/renderer/glsl/depthQuery.frag.js +55 -0
  246. package/lib/renderer/glsl/depthQuery.frag.js.map +1 -0
  247. package/lib/renderer/glsl/normalizeRayTraceOutput.frag.d.ts +6 -0
  248. package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js +46 -0
  249. package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js.map +1 -0
  250. package/lib/renderer/glsl/rayTrace.frag.d.ts +2 -0
  251. package/lib/renderer/glsl/rayTrace.frag.js +623 -0
  252. package/lib/renderer/glsl/rayTrace.frag.js.map +1 -0
  253. package/lib/renderer/glsl/shadowCatcher.frag.d.ts +3 -0
  254. package/lib/renderer/glsl/shadowCatcher.frag.js +119 -0
  255. package/lib/renderer/glsl/shadowCatcher.frag.js.map +1 -0
  256. package/lib/renderer/glsl/webglPipeline.frag.d.ts +4 -0
  257. package/lib/renderer/glsl/webglPipeline.frag.js +208 -0
  258. package/lib/renderer/glsl/webglPipeline.frag.js.map +1 -0
  259. package/lib/renderer/gpuMemory.d.ts +2 -0
  260. package/lib/renderer/gpuMemory.js +10 -0
  261. package/lib/renderer/gpuMemory.js.map +1 -0
  262. package/lib/renderer/halton.d.ts +1 -0
  263. package/lib/renderer/halton.js +15 -0
  264. package/lib/renderer/halton.js.map +1 -0
  265. package/lib/renderer/jnlm.d.ts +85 -0
  266. package/lib/renderer/jnlm.js +87 -0
  267. package/lib/renderer/jnlm.js.map +1 -0
  268. package/lib/renderer/lightSampling.d.ts +75 -0
  269. package/lib/renderer/lightSampling.js +305 -0
  270. package/lib/renderer/lightSampling.js.map +1 -0
  271. package/lib/renderer/lightsUtil.d.ts +26 -0
  272. package/lib/renderer/lightsUtil.js +154 -0
  273. package/lib/renderer/lightsUtil.js.map +1 -0
  274. package/lib/renderer/materialChanges.d.ts +13 -0
  275. package/lib/renderer/materialChanges.js +59 -0
  276. package/lib/renderer/materialChanges.js.map +1 -0
  277. package/lib/renderer/materialComparison.generated.d.ts +5 -0
  278. package/lib/renderer/materialComparison.generated.js +655 -0
  279. package/lib/renderer/materialComparison.generated.js.map +1 -0
  280. package/lib/renderer/materialConstants.d.ts +6 -0
  281. package/lib/renderer/materialConstants.js +3 -0
  282. package/lib/renderer/materialConstants.js.map +1 -0
  283. package/lib/renderer/materialEmission.d.ts +9 -0
  284. package/lib/renderer/materialEmission.js +21 -0
  285. package/lib/renderer/materialEmission.js.map +1 -0
  286. package/lib/renderer/materialIndices.d.ts +7 -0
  287. package/lib/renderer/materialIndices.js +34 -0
  288. package/lib/renderer/materialIndices.js.map +1 -0
  289. package/lib/renderer/materialLayout.d.ts +102 -0
  290. package/lib/renderer/materialLayout.js +189 -0
  291. package/lib/renderer/materialLayout.js.map +1 -0
  292. package/lib/renderer/materialTextureSlots.d.ts +537 -0
  293. package/lib/renderer/materialTextureSlots.js +219 -0
  294. package/lib/renderer/materialTextureSlots.js.map +1 -0
  295. package/lib/renderer/mergeMeshesToGeometry.d.ts +8 -0
  296. package/lib/renderer/mergeMeshesToGeometry.js +236 -0
  297. package/lib/renderer/mergeMeshesToGeometry.js.map +1 -0
  298. package/lib/renderer/meshInstances.d.ts +23 -0
  299. package/lib/renderer/meshInstances.js +66 -0
  300. package/lib/renderer/meshInstances.js.map +1 -0
  301. package/lib/renderer/meshMembership.d.ts +10 -0
  302. package/lib/renderer/meshMembership.js +72 -0
  303. package/lib/renderer/meshMembership.js.map +1 -0
  304. package/lib/renderer/oidnNetwork.d.ts +20 -0
  305. package/lib/renderer/oidnNetwork.js +123 -0
  306. package/lib/renderer/oidnNetwork.js.map +1 -0
  307. package/lib/renderer/openPbrEnergyLut.d.ts +32 -0
  308. package/lib/renderer/openPbrEnergyLut.js +965 -0
  309. package/lib/renderer/openPbrEnergyLut.js.map +1 -0
  310. package/lib/renderer/pathLimits.d.ts +4 -0
  311. package/lib/renderer/pathLimits.js +7 -0
  312. package/lib/renderer/pathLimits.js.map +1 -0
  313. package/lib/renderer/prepareMeshBVH.d.ts +110 -0
  314. package/lib/renderer/prepareMeshBVH.js +857 -0
  315. package/lib/renderer/prepareMeshBVH.js.map +1 -0
  316. package/lib/renderer/progressiveScheduler.d.ts +11 -0
  317. package/lib/renderer/progressiveScheduler.js +19 -0
  318. package/lib/renderer/progressiveScheduler.js.map +1 -0
  319. package/lib/renderer/renderPipeline.d.ts +57 -0
  320. package/lib/renderer/renderPipeline.js +49 -0
  321. package/lib/renderer/renderPipeline.js.map +1 -0
  322. package/lib/renderer/sampling.d.ts +10 -0
  323. package/lib/renderer/sampling.js +28 -0
  324. package/lib/renderer/sampling.js.map +1 -0
  325. package/lib/renderer/sceneChangeDetector.d.ts +29 -0
  326. package/lib/renderer/sceneChangeDetector.js +232 -0
  327. package/lib/renderer/sceneChangeDetector.js.map +1 -0
  328. package/lib/renderer/sceneLightChanges.d.ts +14 -0
  329. package/lib/renderer/sceneLightChanges.js +34 -0
  330. package/lib/renderer/sceneLightChanges.js.map +1 -0
  331. package/lib/renderer/scratchSampling.d.ts +3 -0
  332. package/lib/renderer/scratchSampling.js +39 -0
  333. package/lib/renderer/scratchSampling.js.map +1 -0
  334. package/lib/renderer/shader.d.ts +37 -0
  335. package/lib/renderer/shader.js +41 -0
  336. package/lib/renderer/shader.js.map +1 -0
  337. package/lib/renderer/staticBvhPreparation.d.ts +24 -0
  338. package/lib/renderer/staticBvhPreparation.js +116 -0
  339. package/lib/renderer/staticBvhPreparation.js.map +1 -0
  340. package/lib/renderer/textureRegion.d.ts +8 -0
  341. package/lib/renderer/textureRegion.js +9 -0
  342. package/lib/renderer/textureRegion.js.map +1 -0
  343. package/lib/renderer/texturesFromMaterials.d.ts +6 -0
  344. package/lib/renderer/texturesFromMaterials.js +37 -0
  345. package/lib/renderer/texturesFromMaterials.js.map +1 -0
  346. package/lib/renderer/util.d.ts +17 -0
  347. package/lib/renderer/util.js +56 -0
  348. package/lib/renderer/util.js.map +1 -0
  349. package/lib/renderer/webgl.d.ts +131 -0
  350. package/lib/renderer/webgl.js +586 -0
  351. package/lib/renderer/webgl.js.map +1 -0
  352. package/lib/renderer/webglShaders.d.ts +4 -0
  353. package/lib/renderer/webglShaders.js +41 -0
  354. package/lib/renderer/webglShaders.js.map +1 -0
  355. package/lib/renderer/wgsl/chunks/common.wgsl.d.ts +2 -0
  356. package/lib/renderer/wgsl/chunks/common.wgsl.js +23 -0
  357. package/lib/renderer/wgsl/chunks/common.wgsl.js.map +1 -0
  358. package/lib/renderer/wgsl/chunks/envMap.wgsl.d.ts +2 -0
  359. package/lib/renderer/wgsl/chunks/envMap.wgsl.js +128 -0
  360. package/lib/renderer/wgsl/chunks/envMap.wgsl.js.map +1 -0
  361. package/lib/renderer/wgsl/chunks/intersect.wgsl.d.ts +6 -0
  362. package/lib/renderer/wgsl/chunks/intersect.wgsl.js +1441 -0
  363. package/lib/renderer/wgsl/chunks/intersect.wgsl.js.map +1 -0
  364. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.d.ts +8 -0
  365. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js +85 -0
  366. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js.map +1 -0
  367. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.d.ts +7 -0
  368. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js +315 -0
  369. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js.map +1 -0
  370. package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.d.ts +3 -0
  371. package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js +1737 -0
  372. package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js.map +1 -0
  373. package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.d.ts +4 -0
  374. package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js +352 -0
  375. package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js.map +1 -0
  376. package/lib/renderer/wgsl/chunks/rand.wgsl.d.ts +2 -0
  377. package/lib/renderer/wgsl/chunks/rand.wgsl.js +25 -0
  378. package/lib/renderer/wgsl/chunks/rand.wgsl.js.map +1 -0
  379. package/lib/renderer/wgsl/chunks/random.wgsl.d.ts +1 -0
  380. package/lib/renderer/wgsl/chunks/random.wgsl.js +2 -0
  381. package/lib/renderer/wgsl/chunks/random.wgsl.js.map +1 -0
  382. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.d.ts +5 -0
  383. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js +328 -0
  384. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js.map +1 -0
  385. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.d.ts +2 -0
  386. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js +400 -0
  387. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js.map +1 -0
  388. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.d.ts +3 -0
  389. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js +439 -0
  390. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js.map +1 -0
  391. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.d.ts +2 -0
  392. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js +40 -0
  393. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js.map +1 -0
  394. package/lib/renderer/wgsl/chunks/sampling.wgsl.d.ts +2 -0
  395. package/lib/renderer/wgsl/chunks/sampling.wgsl.js +198 -0
  396. package/lib/renderer/wgsl/chunks/sampling.wgsl.js.map +1 -0
  397. package/lib/renderer/wgsl/chunks/shadowCatcherAccumulation.wgsl.d.ts +8 -0
  398. package/lib/renderer/wgsl/chunks/shadowCatcherAccumulation.wgsl.js +16 -0
  399. package/lib/renderer/wgsl/chunks/shadowCatcherAccumulation.wgsl.js.map +1 -0
  400. package/lib/renderer/wgsl/chunks/sobol.wgsl.d.ts +2 -0
  401. package/lib/renderer/wgsl/chunks/sobol.wgsl.js +170 -0
  402. package/lib/renderer/wgsl/chunks/sobol.wgsl.js.map +1 -0
  403. package/lib/renderer/wgsl/chunks/uvProjection.wgsl.d.ts +2 -0
  404. package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js +42 -0
  405. package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js.map +1 -0
  406. package/lib/renderer/wgsl/compose.frag.wgsl.d.ts +5 -0
  407. package/lib/renderer/wgsl/compose.frag.wgsl.js +218 -0
  408. package/lib/renderer/wgsl/compose.frag.wgsl.js.map +1 -0
  409. package/lib/renderer/wgsl/customDenoise.wgsl.d.ts +4 -0
  410. package/lib/renderer/wgsl/customDenoise.wgsl.js +28 -0
  411. package/lib/renderer/wgsl/customDenoise.wgsl.js.map +1 -0
  412. package/lib/renderer/wgsl/depthQuery.wgsl.d.ts +3 -0
  413. package/lib/renderer/wgsl/depthQuery.wgsl.js +34 -0
  414. package/lib/renderer/wgsl/depthQuery.wgsl.js.map +1 -0
  415. package/lib/renderer/wgsl/offlineAdaptive.compute.d.ts +2 -0
  416. package/lib/renderer/wgsl/offlineAdaptive.compute.js +108 -0
  417. package/lib/renderer/wgsl/offlineAdaptive.compute.js.map +1 -0
  418. package/lib/renderer/wgsl/rayTrace.compute.d.ts +16 -0
  419. package/lib/renderer/wgsl/rayTrace.compute.js +927 -0
  420. package/lib/renderer/wgsl/rayTrace.compute.js.map +1 -0
  421. package/lib/scene/AmbientLight.d.ts +17 -0
  422. package/lib/scene/AmbientLight.js +15 -0
  423. package/lib/scene/AmbientLight.js.map +1 -0
  424. package/lib/scene/Camera.d.ts +78 -0
  425. package/lib/scene/Camera.js +111 -0
  426. package/lib/scene/Camera.js.map +1 -0
  427. package/lib/scene/DirectionalLight.d.ts +18 -0
  428. package/lib/scene/DirectionalLight.js +17 -0
  429. package/lib/scene/DirectionalLight.js.map +1 -0
  430. package/lib/scene/EnvironmentLight.d.ts +14 -0
  431. package/lib/scene/EnvironmentLight.js +14 -0
  432. package/lib/scene/EnvironmentLight.js.map +1 -0
  433. package/lib/scene/Geometry.d.ts +87 -0
  434. package/lib/scene/Geometry.js +108 -0
  435. package/lib/scene/Geometry.js.map +1 -0
  436. package/lib/scene/IESProfile.d.ts +19 -0
  437. package/lib/scene/IESProfile.js +165 -0
  438. package/lib/scene/IESProfile.js.map +1 -0
  439. package/lib/scene/InstancedMesh.d.ts +43 -0
  440. package/lib/scene/InstancedMesh.js +79 -0
  441. package/lib/scene/InstancedMesh.js.map +1 -0
  442. package/lib/scene/Mesh.d.ts +14 -0
  443. package/lib/scene/Mesh.js +17 -0
  444. package/lib/scene/Mesh.js.map +1 -0
  445. package/lib/scene/OpenPBRMaterial.d.ts +224 -0
  446. package/lib/scene/OpenPBRMaterial.js +240 -0
  447. package/lib/scene/OpenPBRMaterial.js.map +1 -0
  448. package/lib/scene/RectLight.d.ts +31 -0
  449. package/lib/scene/RectLight.js +26 -0
  450. package/lib/scene/RectLight.js.map +1 -0
  451. package/lib/scene/Scene.d.ts +55 -0
  452. package/lib/scene/Scene.js +2 -0
  453. package/lib/scene/Scene.js.map +1 -0
  454. package/lib/scene/SceneNode.d.ts +16 -0
  455. package/lib/scene/SceneNode.js +33 -0
  456. package/lib/scene/SceneNode.js.map +1 -0
  457. package/lib/scene/SphereLight.d.ts +22 -0
  458. package/lib/scene/SphereLight.js +20 -0
  459. package/lib/scene/SphereLight.js.map +1 -0
  460. package/lib/scene/SpotLight.d.ts +35 -0
  461. package/lib/scene/SpotLight.js +29 -0
  462. package/lib/scene/SpotLight.js.map +1 -0
  463. package/lib/scene/Texture.d.ts +38 -0
  464. package/lib/scene/Texture.js +37 -0
  465. package/lib/scene/Texture.js.map +1 -0
  466. package/lib/scene/anisotropyParameters.d.ts +1 -0
  467. package/lib/scene/anisotropyParameters.js +13 -0
  468. package/lib/scene/anisotropyParameters.js.map +1 -0
  469. package/lib/scene/geometryChanges.d.ts +5 -0
  470. package/lib/scene/geometryChanges.js +18 -0
  471. package/lib/scene/geometryChanges.js.map +1 -0
  472. package/lib/scene/materialTextureNames.d.ts +2 -0
  473. package/lib/scene/materialTextureNames.js +9 -0
  474. package/lib/scene/materialTextureNames.js.map +1 -0
  475. package/lib/scene/openPbrSchema.d.ts +400 -0
  476. package/lib/scene/openPbrSchema.js +149 -0
  477. package/lib/scene/openPbrSchema.js.map +1 -0
  478. package/lib/scene/thinFilmParameters.d.ts +4 -0
  479. package/lib/scene/thinFilmParameters.js +12 -0
  480. package/lib/scene/thinFilmParameters.js.map +1 -0
  481. package/lib/settings/display.d.ts +118 -0
  482. package/lib/settings/display.js +34 -0
  483. package/lib/settings/display.js.map +1 -0
  484. package/lib/settings/engine.d.ts +37 -0
  485. package/lib/settings/engine.js +26 -0
  486. package/lib/settings/engine.js.map +1 -0
  487. package/lib/settings/render.d.ts +178 -0
  488. package/lib/settings/render.js +36 -0
  489. package/lib/settings/render.js.map +1 -0
  490. package/lib/tinybvh/LICENSE +21 -0
  491. package/lib/tinybvh/TinyBvhBuilder.d.ts +17 -0
  492. package/lib/tinybvh/TinyBvhBuilder.js +211 -0
  493. package/lib/tinybvh/TinyBvhBuilder.js.map +1 -0
  494. package/lib/tinybvh/tinybvh.wasm +0 -0
  495. package/lib/types.d.ts +13 -0
  496. package/lib/types.js +2 -0
  497. package/lib/types.js.map +1 -0
  498. package/lib/util/canvas.d.ts +2 -0
  499. package/lib/util/canvas.js +13 -0
  500. package/lib/util/canvas.js.map +1 -0
  501. package/lib/util/commonGeometry.d.ts +15 -0
  502. package/lib/util/commonGeometry.js +240 -0
  503. package/lib/util/commonGeometry.js.map +1 -0
  504. package/lib/util/events.d.ts +7 -0
  505. package/lib/util/events.js +23 -0
  506. package/lib/util/events.js.map +1 -0
  507. package/lib/util/frame.d.ts +2 -0
  508. package/lib/util/frame.js +10 -0
  509. package/lib/util/frame.js.map +1 -0
  510. package/lib/util/fromTHREE.d.ts +105 -0
  511. package/lib/util/fromTHREE.js +1111 -0
  512. package/lib/util/fromTHREE.js.map +1 -0
  513. package/lib/util/geometry.d.ts +13 -0
  514. package/lib/util/geometry.js +292 -0
  515. package/lib/util/geometry.js.map +1 -0
  516. package/lib/util/loadRGBE.d.ts +7 -0
  517. package/lib/util/loadRGBE.js +168 -0
  518. package/lib/util/loadRGBE.js.map +1 -0
  519. package/lib/util/math.d.ts +8 -0
  520. package/lib/util/math.js +64 -0
  521. package/lib/util/math.js.map +1 -0
  522. package/lib/util/mesh.d.ts +7 -0
  523. package/lib/util/mesh.js +20 -0
  524. package/lib/util/mesh.js.map +1 -0
  525. package/lib/util/threeDeformation.d.ts +20 -0
  526. package/lib/util/threeDeformation.js +218 -0
  527. package/lib/util/threeDeformation.js.map +1 -0
  528. package/lib/version.d.ts +2 -0
  529. package/lib/version.js +3 -0
  530. package/lib/version.js.map +1 -0
  531. package/llms.txt +62 -0
  532. package/oidn/weights/LICENSE.txt +202 -0
  533. package/oidn/weights/README.md +43 -0
  534. package/oidn/weights/rt_hdr_alb_nrm.tza +0 -0
  535. package/oidn/weights/rt_hdr_alb_nrm_small.tza +0 -0
  536. package/package.json +124 -4
package/docs/api.md ADDED
@@ -0,0 +1,394 @@
1
+ # API reference
2
+
3
+ Exports come from `@meimu/mutracer`; declarations carry TSDoc and defaults.
4
+ See [progressive rendering](./progressive-rendering.md) for complete examples.
5
+
6
+ ## Engine
7
+
8
+ `new Engine({canvas?, backend?, device?})` manages the device and one GPU
9
+ scene. `scene` and `camera` default to undefined. Assign them and call
10
+ `update()` to commit edits before rendering; see [updates](./updates.md).
11
+
12
+ | Setting | Default | Meaning |
13
+ | --- | --- | --- |
14
+ | `canvas` | new HTML canvas, or OffscreenCanvas without document | Accepts either canvas type; default `engine.display.canvas` |
15
+ | `device` | undefined | Caller-owned WebGPU device; see [requirements](#device-requirements) |
16
+ | `backend` | `'auto'` | Automatic WebGPU/WebGL selection; `'webgpu'` requires WebGPU; `'webgl'` forces WebGL 2 |
17
+ | `bvhBuilder` | `'builtin'` | JavaScript or `'tinybvh'` WebAssembly |
18
+ | `bvhWorkerCount` | `'auto'` | Hardware concurrency minus one, clamped 1–4; or positive integer |
19
+ | `bvhLayout` | `'bvh2'` | Static TinyBVH layout; see [BVH](./bvh.md) |
20
+ | `bvhSpatialSplits` | `false` | TinyBVH spatial splits |
21
+ | `textureAtlasBudgetBytes` | 384 MiB | Material texture budget |
22
+
23
+ | Method / property | Meaning |
24
+ | --- | --- |
25
+ | `update(): boolean` | Sole scene/camera edit detection point; returns whether inputs changed |
26
+ | `prepare(scene, {onProgress?, signal?})` | Optional CPU preparation for a future scene; options default undefined |
27
+ | `init()` / `info` | Shared initialization promise and `EngineInfo`; info initially undefined |
28
+ | `setDevice(device)` | Replace a caller-owned device; see [device loss](#device-loss) |
29
+ | `backend` / `device` | Actual backend; device undefined before init and on WebGL |
30
+ | `lastError` | Most recent synchronous engine/render error; initially undefined |
31
+ | `getDiagnostics()` | Device, scene, compilation, timing, resident-target diagnostics; available after init or CPU preparation |
32
+ | `readDepthSamples(area)` | Depth query using the committed engine camera; see [depth sampling](#depth-sampling) |
33
+ | `on(name, listener)` | Subscribe; returns unsubscribe |
34
+ | `dispose()` | Release renders, GPU resources, Workers and owned denoisers |
35
+
36
+ `init()` is optional: `update()` and `refine()` initialize lazily. Concurrent
37
+ calls share a promise. `EngineInfo` includes backend, adapterName, optional
38
+ webgpuFallbackReason and limits for texture layers/dimensions.
39
+ Events are `progress` (`{stage: 'device' | 'bvh' | 'shaders', progress}`),
40
+ `error` (`Error`), and `devicelost` (`{reason, recovering}`). Each error object
41
+ is reported once; console errors are deduplicated by message. Invalid light
42
+ values are clamped and reported while rendering continues.
43
+
44
+ ### Device requirements
45
+
46
+ `EngineParams.device` defaults to undefined (the library's shared device). A
47
+ supplied device implies WebGPU, even with `backend: 'auto'`, and cannot be
48
+ combined with `backend: 'webgl'`. `init()` rejects unsupported limits through
49
+ `lastError` and the `error` event, listing each required and actual value. The
50
+ device is caller-owned; `dispose()` does not destroy it or share it with other
51
+ engines implicitly. Adapter name uses `device.adapterInfo` when available,
52
+ otherwise `WebGPU`.
53
+
54
+ `getRecommendedDeviceDescriptor(adapter)` requests supported optional features
55
+ and the adapter limits used by the default engine path. Core rendering needs
56
+ no optional features: timestamp-query falls back to wall-clock timing; core
57
+ shaders use f32 and manual float texture filtering. shader-f16 and subgroups
58
+ are OIDN optimizations; its automatic precision falls back to FP32 and its
59
+ non-subgroup kernels remain available. Texture-format tier features and
60
+ bgra8unorm-storage are not prerequisites for the core render-attachment path.
61
+ Explicit OIDN FP16 or WebNN options can require shader-f16.
62
+
63
+ The core floor is 8 storage buffers, 8 sampled textures, 1 storage texture,
64
+ 4 bind groups, workgroup X 64 / Y 16 / 256 invocations, and 12288 bytes for
65
+ buffer size and storage-buffer binding size (one aligned 16×16 target block).
66
+ Core kernels need 0 bytes of workgroup shared memory. Actual scene, image and
67
+ texture sizes impose larger buffer and texture limits. OIDN shares this same
68
+ device and can require more buffer capacity and workgroup shared memory for
69
+ its convolution tiles; the recommended descriptor requests adapter maxima.
70
+ Use smaller OIDN tiles or automatic precision when appropriate; network
71
+ initialization reports incompatible configurations.
72
+
73
+ ### Device loss
74
+
75
+ `engine.on('devicelost', ({reason, recovering}) => ...)` reports loss, including
76
+ an externally destroyed shared device. Shared devices recover on the next
77
+ `update()` or `refine()`; renders report `preparing`, discard their samples,
78
+ and upload the committed scene again. CPU BVHs, decoded textures and downloaded
79
+ OIDN weights remain cached. Device-bound networks reload. Multiple engines
80
+ share the new device. Active `converge()` rejects with a device-loss error.
81
+ RenderLoop keeps ticking during recovery.
82
+
83
+ For caller-owned devices, `recovering` is false, renders report `error`, and
84
+ `lastError` explains the loss. Call `await engine.setDevice(replacement)` and
85
+ then `engine.update()` to resume. It uses the same limit validation as init;
86
+ only engines originally constructed with `device` accept setDevice. The
87
+ replacement is also caller-owned. Custom denoisers detect changes in
88
+ `input.device` / `prepare({device})` and rebuild their own resources.
89
+
90
+ WebGL context loss also reports `devicelost` with reason `webglcontextlost` and
91
+ `recovering: true`. Rendering waits in `preparing` until the browser dispatches
92
+ `webglcontextrestored`, then rebuilds resources and restarts all renders.
93
+
94
+ ## Render
95
+
96
+ `new Render(engine, options?)` creates one independent accumulation. All renders
97
+ use the engine's committed scene/camera. Options are mutable except fixed
98
+ constructor dimensions. Image-quality changes restart only this render;
99
+ budget and display changes retain samples. Batch assignments use
100
+ `Object.assign(render, settings)` with `RenderSettings`, or constructor options.
101
+ `maxSamples` changes restart accumulation only with `samplingPattern: 'zsobol'`;
102
+ other sequences retain their completed samples.
103
+
104
+ | Option | Default | Meaning |
105
+ | --- | --- | --- |
106
+ | `maxSamples` | `2048` | Complete sample budget |
107
+ | `bounces` / `clamping` | `3` / `0` | Scattering depth / per-sample radiance clamp; 0 disables clamping |
108
+ | `samplingPattern` | `'sobol'` | Sobol, ZSobol or random; see [sampling](./sampling.md) |
109
+ | `directLightCandidates` | `4` | WebGPU light candidates, clamped 1–16; ignored on WebGL |
110
+ | `bevel` / `bevelSamples` | `true` / `8` | Bevel shading / probes, clamped 1–32 |
111
+ | `dispersionWavelengths` | `3` | 3 wavelengths, or one randomly chosen wavelength |
112
+ | `alphaBlendStrategy` | `'stochastic'` | WebGPU primary BLEND policy; ignored on WebGL |
113
+ | `transmissiveOutputAlphaMin` | `1` | Path-depth alpha rule over transparent backgrounds; changes restart this render |
114
+ | `resolutionScale` | `1` | Relative to display canvas; exclusive with fixed width/height |
115
+ | `width` / `height` | undefined | Paired fixed constructor dimensions; getters report actual output dimensions |
116
+ | `adaptiveResolution` | `false` | `{targetFrameMs, minScale}` for scale-based renders; both required, positive, minScale ≤ resolutionScale |
117
+ | `timeBudgetMs` / `maxTiles` | `21` / `Infinity` | Tile time budget / tiles per call |
118
+ | `allowMultipleSamplesPerFrame` | `false` | Add multiple samples when time permits |
119
+ | `fallback` | `null` | Single-level Render on the same engine |
120
+ | `denoiser` | `null` | Per-render configuration; read back through the frozen `denoiser` getter and change with `setDenoiser()`; see [denoising](./denoising.md) |
121
+
122
+ `bounces` is rounded and clamped to [1, 20] in both backends; NaN becomes 1.
123
+ The path loop allows at most `min(bounces * 3, 20)` events, including transmission,
124
+ alpha skips and escape checks. Opaque paths also have their own scattering-depth
125
+ termination. This event budget can truncate deep transparent paths even when
126
+ the requested scattering depth is larger. Intel Mac WebGL retains its driver
127
+ workaround: `min(bounces, 3)` loop events, doubled for scenes with transmission
128
+ or alpha, plus its existing early depth termination.
129
+
130
+ | Method / property | Meaning |
131
+ | --- | --- |
132
+ | `refine()` | Trace within this render's budget; returns status |
133
+ | `converge(options)` | Deterministic offline image; see below |
134
+ | `readPixels(kind = 'hdr')` | Read this render; see [pixel outputs](#pixel-outputs) |
135
+ | `engine` | Owning engine |
136
+ | `denoising` | Queued/running inference, including intermediate updates; default false |
137
+ | `on('sample', listener)` | Complete samples: `{samples, isFirstFrame, frameTimeMs}`; returns unsubscribe |
138
+ | `samples` | Complete samples since restart; stale engine inputs report 0 |
139
+ | `converged` | `samples >= maxSamples`, independently of filtering |
140
+ | `status` | Preparing, compiling, converging, denoising, finished or error |
141
+ | `setDenoiser(options)` | Replace the denoiser configuration; resolves when the filter is ready |
142
+ | `restart()` | Discard this accumulation |
143
+ | `dispose()` | Release this render and its denoiser lease |
144
+
145
+ `refine()` returns `'preparing'` during device/BVH setup and `'compiling'`
146
+ during shader compilation. Intermediate progressive denoising stays
147
+ `'converging'`; final denoising reports `'denoising'`. `'finished'` includes
148
+ completed filtering. Synchronous execution failures return `'error'` and set
149
+ engine.lastError. Invalid lifecycle operations (disposed render or refine during
150
+ converge) throw.
151
+
152
+ A fallback gets one sample when the requested render cannot finish its first
153
+ sample within budget and the fallback has no current complete image. A ready
154
+ fallback is not traced again. Fallback chains and cycles are rejected.
155
+
156
+ ### converge(options)
157
+
158
+ | Option | Default | Meaning |
159
+ | --- | --- | --- |
160
+ | `samples` | required | Fixed spp, or adaptive cap |
161
+ | `camera` | committed camera | Copied override for this call; does not change engine.camera |
162
+ | `samplesPerBatch` | `8` | Samples per submission |
163
+ | `targetBatchTimeMs` | undefined | Adapt batch sizes on WebGPU |
164
+ | `adaptiveSampling` | undefined | Two-stage variance allocation on WebGPU; WebGL falls back to fixed spp |
165
+ | `sampleSequenceOffset` | `0` | Sequence base; disjoint ranges for independent frames |
166
+ | `previewIntervalMs` | undefined | Minimum delay between intermediate resolved images; never implicitly presents |
167
+ | `onProgress` | undefined | `{stage: 'pilot' | 'final' | 'denoising', samples, targetSamples}` |
168
+ | `signal` | undefined | Cancellation signal |
169
+ | `timeoutMs` | `600000` | Timeout per stage |
170
+
171
+ Resolves `{samples, averageSamplesPerPixel, pilotSamples, adaptiveSampling,
172
+ varianceHistory?}` after filtering. It rejects if engine input revisions change.
173
+ The same render cannot refine concurrently; other renders remain usable.
174
+
175
+ ## RenderLoop and Sync
176
+
177
+ `start()` uses requestAnimationFrame when available and a 16 ms setTimeout
178
+ otherwise. Worker visibility and control forwarding are described in
179
+ [worker integration](./getting-started.md#running-in-a-worker).
180
+
181
+ `new RenderLoop(engine, options?)` provides the interactive policy described in
182
+ [progressive rendering](./progressive-rendering.md#loop-policy).
183
+
184
+ | Option | Default | Meaning |
185
+ | --- | --- | --- |
186
+ | `display` | engine.display | Display used for presentation |
187
+ | `preview` | half-resolution adaptive Render | Render, RenderOptions or false; default quality in [ownership](./progressive-rendering.md#options-and-ownership) |
188
+ | `final` | new Render with preview fallback | Render or RenderOptions |
189
+ | `sync` | none | Sync or ordered Sync array on this engine |
190
+ | `idleMs` | 150 | Consecutive-edit idle deadline in milliseconds |
191
+ | `coalesceSceneUpdates` | false | Defer commits during preview inference, then commit latest camera/scene |
192
+
193
+ `engine`, `display`, `preview` (possibly undefined) and `final` are read-only.
194
+ `changing` defaults false; `samples` counts final only and reports 0 during preview; `status` starts preparing.
195
+ `select({changing})` defaults to changing ? preview : final. `addSync`/`removeSync`
196
+ manage integrations without disposing them. `tick` executes a manual frame;
197
+ `start`/`stop` manage animation frames. `converge` accepts the same options as
198
+ Render.converge and resumes a started loop. `dispose` releases owned renders.
199
+
200
+ Events: `status` carries `{status, previous}` only on transitions; `sample`
201
+ carries `{samples, preview: false, isFirstFrame, frameTimeMs}` for final only.
202
+ `on` returns unsubscribe and supports multiple listeners.
203
+
204
+ Extend `Sync` with `constructor(engine)` and `update(): void`. `engine` is readonly;
205
+ `active` defaults false. Integrations can use protected `setActive(boolean)` or
206
+ `activateFor(ms)`; `dispose()` clears base activity. Construction must not write
207
+ to the engine. Three.js integration uses [THREESync](./threejs.md#options).
208
+
209
+ ## Display
210
+
211
+ `Display.canvas` is `HTMLCanvasElement | OffscreenCanvas`. `toBlob()` uses
212
+ OffscreenCanvas.convertToBlob in a worker or for an offscreen display. See
213
+ [worker integration](./getting-started.md#running-in-a-worker).
214
+
215
+ Use `engine.display`; creation of additional displays is outside this API.
216
+ `setSize(width, height)` changes canvas pixels. Scale-based renders resize on
217
+ their next refine; fixed renders retain their dimensions.
218
+ `present(render)` only presents: it returns the render or its ready fallback,
219
+ or undefined without changing the canvas when neither is ready.
220
+ `toBlob(render, {type?, quality?})` composes that render at its actual dimensions,
221
+ without resizing or changing the current canvas. MIME defaults to image/png;
222
+ quality defaults to the browser encoder value.
223
+
224
+ | Setting | Default |
225
+ | --- | --- |
226
+ | `toneMapping` | `'agx'` (`aces`, `cineon`, `reinhard`, `linear` also supported) |
227
+ | `toneMappingExposure`, `contrast`, `saturation` | `1` |
228
+ | `temperature`, `tint`, `vignette` | `0` |
229
+ | `bloomIntensity`, `bloomThreshold`, `bloomRadius` | `0`, `1`, `0.6` |
230
+ | `hdrOutputEnabled` | `false`; WebGPU only |
231
+ | `channel: DisplayChannel` | `'final'`; also albedo, normal, shadow, shadowCatcher |
232
+ | `shadowCatcherColor`, `shadowCatcherAlpha` | `[0, 0, 0]`, `1` |
233
+
234
+ All display settings apply at composition and retain accumulated samples.
235
+ Use the exported `DisplaySettings` type for a partial batch:
236
+
237
+ ```ts
238
+ const settings: DisplaySettings = {toneMappingExposure: 2, bloomIntensity: 0.2};
239
+ Object.assign(engine.display, settings);
240
+ engine.display.present(render);
241
+ ```
242
+
243
+ Ordinary setting fields remain enumerable and read back the assigned value.
244
+ For example, `bevelSamples` and `directLightCandidates` are clamped when
245
+ submitted, without rewriting the assigned field. Existing accessors for
246
+ resolution, fallback and worker count retain their validation rules.
247
+
248
+ `DenoiserOptions` is a union of `JNLMDenoiserOptions`, `OIDNDenoiserOptions`
249
+ and `CustomDenoiserOptions`,
250
+ with required `type`. The getter is frozen; reassign to edit. Invalid types,
251
+ foreign fields and invalid JNLM settings preserve the previous filter and
252
+ result. Schedule-only edits keep inference running. See [denoising](./denoising.md).
253
+
254
+ `Denoiser` is the caller-owned third-party WebGPU interface. Its optional
255
+ `prepare` receives device/dimensions, and `denoise` receives `DenoiseInput`
256
+ plus abort signal/schedule.
257
+ The packed buffer formats, ownership, cancellation, device changes and display
258
+ semantics are documented in [Custom denoisers](./denoising.md#custom-denoisers).
259
+
260
+ ### Pixel outputs
261
+
262
+ `readPixels(kind = 'hdr')` returns `{ width, height, data: Float32Array }`,
263
+ RGBA with the top row first. Dimensions describe the internal render texture,
264
+ which WebGPU rounds up to multiples of 16. Before a pipeline exists, it returns an empty image.
265
+
266
+ | Kind | Values |
267
+ | --- | --- |
268
+ | `hdr` | Original linear HDR samples, unchanged by denoising |
269
+ | `denoised` | Completed output: custom WebGPU filters return native resolved HDR ray color before display background/catcher composition; built-in WebGPU filters normally return display-linear after composition/tone mapping; WebGL JNLM returns tone mapped, display encoded colors |
270
+ | `albedo` | Native linear albedo guide and coverage alpha |
271
+ | `normal` | Native normal guide: RGB encoded as `normal * 0.5 + 0.5`, alpha indicates valid surface data |
272
+
273
+ On WebGPU, the optional OIDN alpha postfilter operates on display colors;
274
+ its final native output is also display encoded. Readback preserves these
275
+ existing pipeline semantics. If no denoiser is attached or denoising has not
276
+ completed, `denoised` returns `hdr` and warns once per render. The method
277
+ makes a CPU copy and can be costly; avoid calling it every animation frame.
278
+
279
+ ### Depth sampling
280
+
281
+ After rendering the current scene and camera, call
282
+ `await engine.readDepthSamples({ x: 0.5, y: 0.5, size: 0.07 })`.
283
+ The result is a `Float32Array` of 49 depths, in row order from the top left,
284
+ including the area's edges. It can be used for area autofocus without CPU
285
+ mesh traversal or reading a full-frame image.
286
+
287
+ `x` and `y` specify the center in viewport coordinates (0..1 from the top
288
+ left). `size` is the square's half height as a fraction of viewport height;
289
+ `0` samples a single point. All three fields are required. Depth is measured
290
+ along the camera's forward axis in scene units, independent of pixel jitter
291
+ and depth of field. Invisible shadow catchers and zero-opacity surfaces are
292
+ skipped; glass and partially transparent surfaces use their front surface.
293
+
294
+ Missed and out-of-viewport samples are `0`. Before GPU scene preparation
295
+ completes, or while another depth query is in flight, the result is
296
+ `undefined`; retry after a later rendered frame. Queries are asynchronous on
297
+ WebGPU and WebGL 2 and do not change accumulated rendering samples. Callers
298
+ should discard results when their scene, camera or sampling area changes
299
+ while a query is pending. GPU failures reject the promise.
300
+
301
+
302
+ ## Scene types
303
+
304
+ Public spatial values use `Vec2` (`[number, number] | Float32Array`), `Vec3` (`[number, number, number] | Float32Array`) and `Mat4` (`Float32Array | number[]`, column-major, 16 elements), exported from the main entry.
305
+
306
+ | Export | Description |
307
+ | --- | --- |
308
+ | `Scene` | `{ meshes: (Mesh \| InstancedMesh)[], lights, background? }`; see below |
309
+ | `Mesh` | `new Mesh(geometry, material \| material[])`, `transform` |
310
+ | `InstancedMesh`, `InstancedMeshOptions` | `new InstancedMesh(geometry, material \| material[], {count, transforms?, colors?})`; local Float32 column-major matrices default to identity, multiplied by inherited transform; count selects the active prefix; `colors` defaults to undefined (white linear RGB); `markUpdated(): this` notifies both matrices and colors; `markTransformsUpdated(start = 0, count = this.count - start): this` and `markColorsUpdated(start = 0, count = this.count - start): this` notify each separately. Each advances version once, initially 0. See [updates and costs](./updates.md#instanced-meshes) |
311
+ | `Geometry`, `GeometryAttribute` | Triangle data: required `position`; optional `normal` and `indices` are generated at construction; `vertexCount` / `triangleCount` getters; optional `uv`, `uv1`, `tangent`, `color`, `materialIndex` (raw per-vertex indices, itemSize 1; all three corners of each triangle must match; invalid indices fall back to material 0 with one warning); `dynamic` (default `false`) for [deforming geometry](./updates.md#dynamic-geometry) |
312
+ | `OpenPBRMaterial` | `new OpenPBRMaterial(params?)`; see [materials](./materials.md) |
313
+ | `Texture` | HTMLImageElement, HTMLCanvasElement, ImageBitmap, OffscreenCanvas or `{ data, width, height }`; `Uint8Array`/`Uint8ClampedArray` color is sRGB; `Float32Array`/`Int32Array` color is linear |
314
+ | `Camera` | `new Camera({ projection: 'perspective', ... })` or orthographic; `position`, `lookAt()`, `copy(source)`, `clone()`; aspect defaults to automatic; depth of field with `fStop`, `focusDistance`, `sensorHeight`, `metersPerUnit` ([details](./getting-started.md#depth-of-field)) |
315
+ | `RectLight`, `SphereLight`, `SpotLight`, `DirectionalLight`, `EnvironmentLight`, `AmbientLight` | Parameter-object constructors; analytic lights use `transform`, `position`, `lookAt()` and rigid axes. See [lights](./getting-started.md#lights) |
316
+ | `IESProfile`, `parseIESProfile(text)` | Photometric profiles for `SpotLight` |
317
+ | `SceneBackground` | `[r, g, b, a]`, `Texture` or `GroundedSkyboxBackground` |
318
+
319
+ `OpenPBRMaterial` accepts canonical `specularRoughnessAnisotropy` (default `0`),
320
+ `coatRoughnessAnisotropy` (`0`), `subsurfaceScatterAnisotropy` (`0`),
321
+ `geometryOpacity` (`1`) and `geometryThinWalled` (`false`). The old names are
322
+ deprecated aliases sharing storage; conflicting constructor values throw.
323
+ See [compatibility names](./materials.md#compatibility-names).
324
+
325
+ `OpenPBRMaterial` also accepts `thinFilmThicknessMinimum` (default `0` µm)
326
+ and `thinFilmMapChannel` (default `r`, one of `r/g/b/a`). `thinFilmThickness`
327
+ (default `0.5` µm) is the maximum endpoint with a map and the constant without
328
+ one. See [thin-film textures](./materials.md#textures) for range behavior.
329
+
330
+ `coatWeightMap`, `coatRoughnessMap`, `fuzzColorMap`, `fuzzRoughnessMap`,
331
+ `specularWeightMap` and `specularColorMap` accept `Texture` and each default to
332
+ `undefined`. Channels and color decoding are listed in [material textures](./materials.md#textures).
333
+ They follow the existing material/texture update mechanism.
334
+
335
+ `coatNormalMap` defaults to `undefined`, retaining the shared shading normal. With a map, linear RGB supplies an independent coat normal; `coatNormalScale` defaults to `[1, 1]` and scales its decoded XY. See [coat normals](./materials.md#coat-normals) for frame, sampling and update behavior.
336
+
337
+ Raw texture sources contain exactly `width * height * 4` RGBA values, with
338
+ rows ordered from top to bottom. `Uint8Array` and `Uint8ClampedArray` store
339
+ 8-bit values: color slots decode RGB from sRGB, while data slots (roughness,
340
+ normal, coat weight, etc.) read normalized channels directly. `Float32Array`
341
+ (and `Int32Array` with linear integer values) supplies linear color and data
342
+ channels, including HDR colors above 1. These sources can share a material
343
+ texture array with Canvas images and other image sources on both backends.
344
+
345
+ Material arrays containing linear raw sources use half-float storage (finite
346
+ range up to 65504, rounded to half-float precision) and twice the bytes per
347
+ pixel of an 8-bit array. Raw sources retain straight alpha and their original
348
+ RGB even at zero alpha; Canvas composition can discard transparent RGB and
349
+ round partially transparent colors. When the atlas budget requires resizing,
350
+ raw sources use nearest-neighbor downsampling; image sources use Canvas
351
+ resampling. Equal dimensions and opaque pixels allow exact byte/image
352
+ comparisons. Float colors interpolate in linear space, while 8-bit color
353
+ samples interpolate before sRGB decoding; gradients can therefore differ even
354
+ when their endpoint colors agree. Half-float and 8-bit filtering also have
355
+ different precision.
356
+
357
+ `Geometry` and `Texture` expose `version` (initially `0`)
358
+ and `markUpdated(): this`. `Geometry` also has the read-only `topologyVersion`
359
+ (initially `0`) and `markVerticesUpdated(): this`, which advances only
360
+ `version`. See [scene updates](./updates.md) for when to call each.
361
+
362
+ ## Helpers
363
+
364
+ | Export | Description |
365
+ | --- | --- |
366
+ | `createPlaneGeometry`, `createCubeGeometry`, `createSphereGeometry`, `createCurvePlaneGeometry` | Procedural geometry (plane is 2×2 in XZ, cube and sphere span −1..1) |
367
+ | `generateVertexNormals`, `generateVertexTangents` | Attribute generation |
368
+ | `computeMeshesBoundingBox(meshes)` | World-space bounds |
369
+ | `loadRGBE(url)`, `parseRGBE(buffer)` | Radiance `.hdr` → float `Texture` |
370
+ | `THREESync` | Keeps a `THREE.Scene` in sync: `new THREESync(engine, {scene?, camera?, controls?, updateControls?})`; RenderLoop calls update; dispose when done; conversion hooks `convertMaterial` / `convertLight`; see [Three.js](./threejs.md#custom-conversion) |
371
+ | `fromTHREECamera(camera, options?)` | Converts a Three.js camera; one-shot conversion; THREESync retains and updates cameras. Reads `focus` and the film height; `FromTHREECameraOptions` sets `fStop` (default `0`), `focusDistance` and `metersPerUnit` (default `1`) |
372
+ | `fromTHREEScene` | One-shot Three.js scene conversion with FromTHREESceneOptions conversion hooks; every call reruns hooks and creates fresh default objects |
373
+ | `FromTHREESceneOptions` | Optional `onMeshConverted(mesh, source, group, groupIndex)` callback; default: none |
374
+ | `VERSION` | Library version |
375
+
376
+ `@meimu/mutracer/oidn` exports weight constants (`OIDN_MODEL_FILENAMES`,
377
+ `OIDN_AUXILIARY_MODEL_FILENAMES`, `OIDN_WEIGHTS_PACKAGE`,
378
+ `OIDN_WEIGHTS_PACKAGE_VERSION`, `DEFAULT_OIDN_WEIGHTS_BASE_URL`,
379
+ `DEFAULT_OIDN_WEIGHTS_PACKAGE_BASE_URL`) and `resolveOIDNModelUrl` /
380
+ `resolveOIDNAuxiliaryModelUrls`. Configure packaged/custom OIDN networks,
381
+ execution engines, precision and dynamic tiles through `render.setDenoiser()`;
382
+ see [denoising](./denoising.md#custom-oidn-networks). The main entry exports
383
+ `OIDNEngine`, `OIDNPrecision`, `OIDNHDRTransfer`, `OIDNDynamicTileOptions`,
384
+ `OIDNDynamicTileSetting` and `OIDNAuxiliaryModelUrls` as types.
385
+
386
+ ## GPU output and display passes
387
+
388
+ `render.getOutputTexture(kind)` borrows native HDR or the latest display image;
389
+ `display.addPostProcess(pass)` returns unregister and runs on every present/export.
390
+ Both are WebGPU-only. See [formats, lifecycle and overlay example](./post-processing.md).
391
+
392
+ Anisotropy direction options: `anisotropyMap` (default `undefined`) reads linear RG as a tangent direction and B as a multiplier for base specular strength. `specularAnisotropyRotation` (default `0`) rotates that direction counter-clockwise in radians; `coatAnisotropyRotation` (default `0`) rotates the coat relative to the geometry tangent. See [materials](./materials.md#anisotropy-directions) for frame and fallback conventions.
393
+
394
+ `specularAnisotropyModel` defaults to `'openpbr'`. Selecting `'gltf'` keeps `specularRoughness` as source perceptual roughness and `specularRoughnessAnisotropy` (or its compatibility name) as source strength. The renderer converts both after their texture factors and before coat roughening. See [source conversion](./threejs.md#anisotropy-source-conversion) for the equations and metadata precedence.
package/docs/bvh.md ADDED
@@ -0,0 +1,141 @@
1
+ # BVH construction
2
+
3
+ `engine.update()` and `render.refine()` initialize and prepare the current
4
+ scene automatically. Refinement returns preparing during CPU construction and
5
+ compiling during shader compilation; the canvas retains its previous image.
6
+
7
+ ```ts
8
+ engine.on('progress', ({stage, progress}) => loading.update(stage, progress));
9
+ function frame() {
10
+ engine.update(); const status = final.refine(); engine.display.present(final);
11
+ if (status !== 'preparing' && status !== 'compiling') loading.hide();
12
+ requestAnimationFrame(frame);
13
+ }
14
+ ```
15
+
16
+ | Use case | Action |
17
+ | --- | --- |
18
+ | Normal rendering | Commit updates and refine the chosen render |
19
+ | Loading indicator | Listen to engine progress and inspect render.status |
20
+ | Offline image | Await render.converge |
21
+ | Future scene | Optional engine.prepare(nextScene) |
22
+ | Change BVH settings | Assign engine settings and call engine.update |
23
+
24
+ ## Optional early construction
25
+
26
+ `prepare(scene, { onProgress?, signal? })` only builds static
27
+ BLASes. It does not initialize a device, upload resources or compile shaders.
28
+ Both options default to undefined; an aborted call rejects with its abort
29
+ reason. Shared geometry builds once, dynamic/empty geometry is skipped.
30
+
31
+ ```ts
32
+ await engine.prepare(nextScene, {
33
+ onProgress: fraction => console.log(fraction), signal: controller.signal
34
+ });
35
+ console.log(engine.getDiagnostics()?.bvh?.lastBuild);
36
+ ```
37
+
38
+ `lastBuild` contains `geometryCount` and `bvhTimeMs` (total builder time,
39
+ excluding queueing and WASM loading). It can be read after construction even
40
+ before device initialization; diagnostics `backend` is then undefined.
41
+ The preparation method resolves void. With no work, statistics are zero
42
+ and the callback is not invoked.
43
+
44
+ ## Settings
45
+
46
+ | Setting | Default | Description |
47
+ | --- | --- | --- |
48
+ | `engine.bvhBuilder` | `'builtin'` | `'builtin'` (JavaScript) or `'tinybvh'` (WebAssembly, loaded on first use) |
49
+ | `engine.bvhWorkerCount` | `'auto'` | Maximum Workers per engine: `'auto'` or a positive safe integer. Auto uses `hardwareConcurrency - 1`, clamped to 1–4; 1 when unavailable |
50
+ | `engine.bvhLayout` | `'bvh2'` | Layout of static TinyBVH BLASes: `'bvh2'`, `'bvh4'`, `'bvh-gpu'` or `'cwbvh'` |
51
+ | `engine.bvhSpatialSplits` | `false` | With `'tinybvh'`, build spatial-split BVHs (SBVH) |
52
+ | `geometry.dynamic` | `false` | Refittable built-in BLAS for deforming geometry; see [dynamic geometry](./updates.md#dynamic-geometry) |
53
+
54
+ Changes to builder/layout/spatial splits invalidate cached build configurations.
55
+ Old BLASes stay usable until replacements finish; rendering reports preparing
56
+ through this work. Worker count changes affect the next build, with no BVH
57
+ rebuild required. Both builders parallelize independent geometries, while one
58
+ geometry builds on one Worker. Pools are reused and released by dispose().
59
+
60
+ ## Caveats
61
+
62
+ Progress counts completed tasks, including failed/stale tasks, rather than
63
+ triangles or elapsed time. Engine `progress` events cover device (0/1),
64
+ BVH tasks and shader pipelines only during preparing/compiling. Explicit
65
+ background prebuilds use their own `onProgress` callback. Shader progress is
66
+ measured on both backends; WebGL diagnostics aggregate compiled programs
67
+ for the engine lifetime.
68
+ Stale results are discarded. Without Worker support, construction runs on
69
+ the calling thread. More Workers increase simultaneous memory use, and
70
+ summed builder time can exceed wall time. Disposal cancels active and queued
71
+ preparations without further callbacks; completed CPU BVHs remain cached.
72
+
73
+ ## Builders
74
+
75
+ ### Built-in (default)
76
+
77
+ A JavaScript port of [TinyBVH](https://github.com/jbikker/tinybvh)'s binned
78
+ SAH builder (`BVH::Build`). It computes in float64, so where split costs
79
+ nearly tie it can choose differently from TinyBVH's float32 build; tree
80
+ quality is the same. The TLAS and dynamic BLASes always use it.
81
+
82
+ ### TinyBVH WebAssembly
83
+
84
+ `engine.bvhBuilder = 'tinybvh'` builds static BLASes with TinyBVH compiled
85
+ to WebAssembly, about 1.3 times faster than the built-in builder. The module
86
+ (about 90 KB) is fetched on first use, so applications that keep the default
87
+ never load it. If it fails to load, the renderer warns and falls back to the
88
+ built-in builder.
89
+
90
+ `engine.bvhSpatialSplits = true` builds SBVHs. They lower traversal cost on
91
+ some scenes, which can make rendering noticeably faster, but build three to
92
+ five times slower.
93
+
94
+ BLASes are cached internally by geometry: share one `Geometry`
95
+ between meshes to share its BLAS.
96
+
97
+ ## Layouts
98
+
99
+ `engine.bvhLayout` applies to static TinyBVH BLASes, rebuilding them automatically when changed. All four
100
+ layouts work on WebGPU and WebGL 2.
101
+
102
+ | Layout | Notes |
103
+ | --- | --- |
104
+ | `'bvh2'` | Default; binary BVH |
105
+ | `'bvh4'` | 4-wide BVH |
106
+ | `'bvh-gpu'` | TinyBVH's `BVH_GPU` layout |
107
+ | `'cwbvh'` | Compressed 8-wide BVH; experimental, benefit depends on GPU and scene |
108
+
109
+ The built-in builder, dynamic geometry and TinyBVH displacement bounds use
110
+ `'bvh2'`. TinyBVH falls back to `'bvh-gpu'` when CWBVH cannot represent a
111
+ mesh. The geometry BVH cache is internal.
112
+
113
+ ## Deployment
114
+
115
+ The Worker entry ships with both the standalone build and the npm ESM package.
116
+ Serve it from the same origin and allow Workers in your content security
117
+ policy. The bundled TinyBVH wasm is checked on download (HTTP status and file
118
+ signature); if that fails, MuTracer warns once and retries the version-pinned
119
+ jsDelivr copy, then falls back to the built-in builder. See
120
+ [bundler notes](./getting-started.md#bundler-notes).
121
+
122
+ ## Implementation notes
123
+
124
+ - Source geometry stays usable on the main thread while its BLAS builds in a
125
+ Worker.
126
+ - Editing geometry or displacement settings while a build is in flight
127
+ discards the stale result.
128
+ - An invalid input affects only its mesh. Worker startup, messaging or runtime
129
+ failures retry with the same builder on the calling thread within the same
130
+ preparation call; TinyBVH failures retry with the built-in builder. Each
131
+ fallback warns once per engine.
132
+ - Concurrent preparation calls on one renderer are queued and check for missing BLASes when
133
+ they start, so they do not repeat completed builds.
134
+ - Height-map analysis, attribute generation, TLAS construction and per-frame
135
+ refits run on the calling thread.
136
+
137
+ ## Rebuilding the WebAssembly module
138
+
139
+ `src/tinybvh/tinybvh.wasm` is checked in. To rebuild it, install Emscripten and
140
+ run `npm run build:tinybvh` (or `npm run build:tinybvh:windows`). See
141
+ [`src/tinybvh/README.md`](../src/tinybvh/README.md).