@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
@@ -0,0 +1,281 @@
1
+ # Materials
2
+
3
+ `OpenPBRMaterial` implements the
4
+ [OpenPBR 1.1](https://academysoftwarefoundation.github.io/OpenPBR/) surface.
5
+ Property names use camelCase OpenPBR inputs plus compatibility names. Colors are
6
+ linear RGB. Pass optional properties to `new OpenPBRMaterial(params)`; omitted
7
+ properties use the defaults below and in TSDoc.
8
+
9
+ ```ts
10
+ import { OpenPBRMaterial } from '@meimu/mutracer';
11
+
12
+ const glass = new OpenPBRMaterial();
13
+ glass.transmissionWeight = 1;
14
+ glass.specularRoughness = 0;
15
+ glass.transmissionColor = [0.72, 0.9, 1];
16
+ glass.transmissionDepth = 0.5;
17
+
18
+ const gold = new OpenPBRMaterial({
19
+ baseColor: [1.0, 0.78, 0.34],
20
+ baseMetalness: 1,
21
+ specularRoughness: 0.2
22
+ });
23
+ ```
24
+
25
+ Edit a material that is already rendering in place; the next `engine.update()`
26
+ detects the change (see [scene updates](./updates.md#materials-textures-and-lights)
27
+ for costs):
28
+
29
+ ```ts
30
+ gold.specularRoughness = 0.4;
31
+ gold.baseColor[1] = 0.7;
32
+ ```
33
+
34
+ Materials occupy GPU slots by object identity: share one material object to
35
+ share its slot. Separate objects with equal values take separate slots, but
36
+ the textures they reference still share atlas space.
37
+
38
+ ## Inputs
39
+
40
+ | Layer | Inputs (default) |
41
+ | --- | --- |
42
+ | Base | `baseWeight` (1), `baseColor` (0.8), `baseDiffuseRoughness` (0), `baseMetalness` (0) |
43
+ | Specular | `specularWeight` (1), `specularColor` (1), `specularRoughness` (0.3), `specularIor` (1.5), `specularRoughnessAnisotropy` (0) |
44
+ | Transmission | `transmissionWeight` (0), `transmissionColor` (1), `transmissionDepth` (0), `transmissionScatter` (0), `transmissionScatterAnisotropy` (0), `transmissionDispersionScale` (0), `transmissionDispersionAbbeNumber` (20) |
45
+ | Subsurface | `subsurfaceWeight` (0), `subsurfaceColor` (0.8), `subsurfaceRadius` (1), `subsurfaceRadiusScale` ([1, 0.5, 0.25]), `subsurfaceScatterAnisotropy` (0) |
46
+ | Fuzz | `fuzzWeight` (0), `fuzzColor` (1), `fuzzRoughness` (0.5) |
47
+ | Coat | `coatWeight` (0), `coatColor` (1), `coatRoughness` (0), `coatRoughnessAnisotropy` (0), `coatIor` (1.6), `coatDarkening` (1) |
48
+ | Thin film | `thinFilmWeight` (0), `thinFilmThickness` (0.5 µm), `thinFilmIor` (1.4), `thinFilmThicknessMinimum` (0 µm), `thinFilmMapChannel` (`r`) |
49
+ | Emission | `emissionColor` (1), `emissionLuminance` (0) |
50
+ | Geometry | `geometryOpacity` (1), `geometryThinWalled` (false), `doubleSided` (false) |
51
+
52
+ Units: `transmissionDepth` and `subsurfaceRadius` are in scene units;
53
+ `thinFilmThickness` is in micrometres (`0.45` = 450 nm).
54
+
55
+ `baseWeight` scales diffuse reflection and the metallic normal-incidence color
56
+ (`baseWeight * baseColor`). Dielectric specular, transmission and subsurface
57
+ retain their own strengths. For metals, `specularColor` tints the F82 Fresnel
58
+ curve near grazing angles and `specularWeight` scales the entire reflection,
59
+ including thin-film reflection. At their default values, F82 reduces to Schlick.
60
+
61
+ Native `specularRoughnessAnisotropy` and `coatRoughnessAnisotropy` use the OpenPBR GGX mapping:
62
+ `alphaT = roughness² * sqrt(2 / (1 + (1 - anisotropy)²))` and
63
+ `alphaB = (1 - anisotropy) * alphaT`, with the renderer's minimum alpha.
64
+ Both layers use the geometry tangent; a separate coat tangent is not available.
65
+ A rough coat broadens the underlying metal, dielectric reflection and transmission
66
+ using `mix(rB, min(1, rB^4 + 2*rC^4)^0.25, coatWeight)` before the GGX mapping.
67
+
68
+ `coatColor` is the squared transmittance at normal incidence. Each passage
69
+ through the coat applies `sqrt(coatColor)` raised to the inverse refracted
70
+ cosine. Coat reflection stays uncolored; reflection from the base crosses the
71
+ coat twice, and transmission crosses it once. `coatDarkening` controls the
72
+ extra darkening from internal reflections, while absorption remains active at
73
+ zero. The base is attenuated by the coat directional albedo on the view side
74
+ and by an internal-reflection factor estimated from the base slab albedos.
75
+ Partial coat coverage is mixed independently for each passage.
76
+ Thin film lies below the coat: its exterior IOR is `mix(1, coatIor, coatWeight)`
77
+ and its dielectric substrate uses the adjusted absolute base IOR. A solid
78
+ inside hit exchanges these media; uncoated films retain their existing behavior.
79
+ Emission uses a normal-incidence single passage: it is multiplied by
80
+ `mix(1, sqrt(coatColor), coatWeight)`. Without `coatWeightMap`, the same attenuated emission determines
81
+ emissive-light selection and hit MIS weights. This approximation has no angular
82
+ dependence and does not apply coat darkening or fuzz attenuation to emission.
83
+ Unlit and shadow-catching materials keep their existing emission behavior.
84
+
85
+ The base reflection beneath a coat uses the surrounding IOR
86
+ `mix(1, coatIor, coatWeight)`. `specularWeight` adjusts the base IOR relative
87
+ to that medium; refraction uses the resulting absolute base IOR relative to air.
88
+ Solid back-face exits ignore the coat IOR; thin walls use the exterior rule
89
+ on either side. Reflection inverts a coat-to-base ratio below one when the
90
+ base IOR is at least one, avoiding false total internal reflection caused by
91
+ the approximate coat model. Dispersion adjusts the base IOR before these rules.
92
+
93
+ `fuzzColor` colors the fuzz reflection only. Fuzz attenuates the underlying
94
+ material using its white directional albedo, so colored fuzz does not tint
95
+ the substrate through the attenuation term.
96
+
97
+ **Interior media.** Transmission describes a homogeneous volume:
98
+ `transmissionColor` is the color that survives one `transmissionDepth`, and
99
+ `transmissionScatter` is the scattering albedo. With `transmissionDepth = 0`
100
+ the tint is applied at the surface. Subsurface is a separate layer driven by its
101
+ color and per-channel radius. When both are active, their coefficients combine
102
+ into one volume. Dispersion (`transmissionDispersionScale > 0`) samples
103
+ wavelengths spectrally.
104
+
105
+ ## Compatibility names
106
+
107
+ The canonical names below share storage with the deprecated names. Both work in
108
+ constructor parameters, property reads/writes and Three.js metadata. If both
109
+ are supplied together, equal values are accepted and conflicting values throw.
110
+ Edits through either spelling are detected by the next `engine.update()`; see [scene updates](./updates.md).
111
+
112
+ | Canonical name | Deprecated compatibility name | Default |
113
+ | --- | --- | --- |
114
+ | `specularRoughnessAnisotropy` | `specularAnisotropy` | `0` |
115
+ | `coatRoughnessAnisotropy` | `coatAnisotropy` | `0` |
116
+ | `subsurfaceScatterAnisotropy` | `subsurfaceAnisotropy` | `0` |
117
+ | `geometryOpacity` | `opacity` | `1` |
118
+ | `geometryThinWalled` | `thinWalled` | `false` |
119
+
120
+ `materialKeys`, `materialParamKeys`, hashes and snapshots keep the compatibility
121
+ storage names and order; aliases add no GPU fields. `Object.keys()` and JSON
122
+ include the stored compatibility names only. The canonical accessors are not
123
+ an alternate serialization format.
124
+
125
+ ## Textures
126
+
127
+ | Property | Channel | Notes |
128
+ | --- | --- | --- |
129
+ | `map` | RGB (sRGB), A | Multiplies `baseColor`; alpha use set by `mapAlphaUsage` |
130
+ | `alphaMap` | G | Opacity, as in Three.js |
131
+ | `normalMap`, `normalScale` | RGB | Tangent space; tangents are generated when missing |
132
+ | `metallicRoughnessMap` | G = roughness, B = metalness | glTF convention |
133
+ | `roughnessMap` | G | |
134
+ | `metalnessMap` | B | |
135
+ | `emissiveMap` | RGB | Multiplies `emissionColor` |
136
+ | `transmissionMap` | R | Multiplies `transmissionWeight` |
137
+ | `thinFilmMap` | R by default; selectable R/G/B/A | Linear thickness range |
138
+ | `displacementMap` | R | See [displacement](#displacement) |
139
+ | `coatWeightMap` | Linear R | Multiplies `coatWeight`, including emission absorption |
140
+ | `coatRoughnessMap` | Linear G | Multiplies `coatRoughness` before base roughening |
141
+ | `coatNormalMap`, `coatNormalScale` | Linear RGB | Independent tangent-space coat normal; see [coat normals](#coat-normals) |
142
+ | `fuzzColorMap` | sRGB RGB | Decoded color multiplies `fuzzColor` |
143
+ | `fuzzRoughnessMap` | Linear A | Multiplies `fuzzRoughness` |
144
+ | `specularWeightMap` | Linear A | Multiplies `specularWeight`, for dielectric and metal |
145
+ | `specularColorMap` | sRGB RGB | Decoded color multiplies `specularColor`, for dielectric and metal |
146
+
147
+ All six layer maps default to `undefined`. They resolve before coat roughening
148
+ and BSDF preparation. Images may be shared between color and data slots;
149
+ sRGB decoding happens only at color sample sites. See [anisotropy directions](#anisotropy-directions)
150
+ for the RG/B slot and [coat normals](#coat-normals) for the independent normal input.
151
+
152
+ With `coatWeightMap`, emission absorption uses the sampled coverage at each
153
+ surface/mesh-light point. Light selection and emissive-hit MIS use raw constant
154
+ emission luminance as a conservative proposal; absorption is applied once to
155
+ the contribution. Black texture points can retain a positive sampling PDF.
156
+ Removing the map restores the constant-coat packing path.
157
+
158
+ `Texture.uvScale`, `uvOffset` and `uvChannel` (0 or 1) transform UVs per
159
+ texture. For geometry without usable UVs, set `uvProjection` to
160
+ `'triplanar'`, `'spherical'` or `'cylindrical'` with `uvProjectionScale` (default `[1, 1]`).
161
+
162
+ With `thinFilmMap`, thickness interpolates from `thinFilmThicknessMinimum` to
163
+ `thinFilmThickness` using the linear `thinFilmMapChannel`. The default minimum
164
+ 0 and channel `r` keep the original R-times-thickness behavior. Without a map,
165
+ only `thinFilmThickness` is used. Endpoints are nonnegative and may be reversed,
166
+ including a positive minimum and zero maximum. Nonfinite endpoints use their
167
+ defaults; invalid channels throw during construction or packing.
168
+
169
+ Call `texture.markUpdated()` after editing pixels or UV-array elements;
170
+ assigning a new texture, image or UV array is detected automatically.
171
+
172
+ ## Alpha
173
+
174
+ `alphaMode` is `'auto'` (default; derived from the alpha inputs), `'opaque'`,
175
+ `'mask'` (alpha test against `alphaCutoff`) or `'blend'`. `mapAlphaUsage`
176
+ selects how `map`'s alpha channel is used:
177
+ `'opaque'` (default), `'alpha'` or `'transmission'`. Blended primary rays follow
178
+ `render.alphaBlendStrategy`. Both WebGPU and WebGL 2 apply these modes to
179
+ surface hits and shadow rays: `opaque` ignores opacity and alpha textures;
180
+ `mask` resolves coverage to 0 below `alphaCutoff` and 1 at or above it;
181
+ `blend` retains fractional coverage. In `auto`, a positive cutoff selects
182
+ `mask`; otherwise opacity below 1, alpha use of `map`, or an `alphaMap`
183
+ selects `blend`. With none of these inputs, `auto` selects `opaque`.
184
+
185
+ ## Renderer extensions
186
+
187
+ | Property | Description |
188
+ | --- | --- |
189
+ | `shadowCatcher` | Invisible ground that only receives shadows; composite over a transparent background |
190
+ | `unlit` | Shows emission without scattering or lighting other surfaces |
191
+ | `bevelSize` | Rounded-edge shading radius in scene units; `0` disables (see below) |
192
+
193
+ **Shader bevel.** `bevelSize > 0` rounds hard edges in shading only, without
194
+ changing geometry or silhouettes. It samples nearby surface normals of the same
195
+ instance, similar to Blender Cycles' Bevel node. `render.bevelSamples`
196
+ trades noise for speed. A radius of 0.5–2% of the model size is a reasonable
197
+ start.
198
+
199
+ ## Displacement
200
+
201
+ `displacementMap` (red channel) with `displacementScale` (local units)
202
+ ray-marches the height field in the shader. `displacementStepSize` controls the
203
+ ray-marching step (default `0.01`). No extra triangles are generated.
204
+ `displacementUvProjection` (default `'none'`) and `displacementUvProjectionScale`
205
+ (default `1`) control height-map coordinates.
206
+
207
+ The remaining `displacement*` properties are documented in the type declarations.
208
+
209
+ ## Known limitations
210
+
211
+ Data-backed material atlases require RGBA8 `Uint8Array` sources. WebGL 2 can
212
+ currently resolve zero for data-backed material maps; use DOM image or canvas
213
+ sources on that backend. Float data remains supported for environments.
214
+
215
+ Rough thin-wall glass can appear too dark because its reflection/transmission
216
+ model includes only single microfacet scattering. Adobe's reference has no
217
+ thin-wall transmission multiple-scattering compensation; this approximation
218
+ is exact for smooth windows but loses energy as roughness increases.
219
+
220
+ ## Implementation notes
221
+
222
+ The BSDF evaluates fuzz, coat, metal, dielectric specular, transmission,
223
+ diffuse and subsurface as separate lobes, with energy compensation tables and
224
+ thin-film interference adapted from
225
+ [Adobe's OpenPBR BSDF](https://github.com/adobe/openpbr-bsdf). Small
226
+ differences from offline references remain, from finite path depth, RGB
227
+ thin-film evaluation and texture filtering.
228
+
229
+ Metal reflection includes the reference's additional microfacet multiple
230
+ scattering, scaled by the square of the average F82 reflectance. Its energy
231
+ tables use the original isotropic roughness, also for anisotropic materials,
232
+ so strong anisotropy can retain a small energy error. Solid transmission also
233
+ includes the reference dielectric multiple-scattering lobe, using its
234
+ refraction IOR for both reflected and transmitted compensation. It uses the
235
+ original isotropic alpha and turns off below roughness 0.04. Its transmission
236
+ scale follows the reference; single refraction retains the renderer's existing
237
+ radiance IOR scaling. The combined model can retain an energy error, including
238
+ with coat, and the finite path-event budget can truncate deep glass paths.
239
+
240
+ ## Coat normals
241
+
242
+ Set `coatNormalMap` to give the coat a tangent-space normal independently of
243
+ `normalMap`. The renderer decodes linear RGB as `2 * RGB - 1`, multiplies XY
244
+ by `coatNormalScale`, then normalizes. The scale defaults to `[1, 1]` and can
245
+ be negative or zero. A missing map (the default), zero coat weight or zero sampled coat coverage retains the existing shared
246
+ shading normal, including the base normal map.
247
+
248
+ The coat TBN starts from the interpolated geometry normal before base normal
249
+ mapping. It uses the coat texture's UV0/UV1 selection and geometric
250
+ tangent handedness; generated tangents use UV1 differentials when that set is
251
+ selected. Degenerate frames and zero decoded vectors use stable fallbacks.
252
+ The texture's scale, offset and `flipY` follow the ordinary atlas sampling
253
+ rules. As with other slots, sharing an image never changes its color space.
254
+
255
+ Base lobes keep their base frame. Coat reflection, its sampling PDF, directional
256
+ albedo and passage absorption use the coat frame; the renderer combines their
257
+ responses and densities for the same world direction. Each frame is corrected
258
+ against the geometric/view hemisphere independently. Triangle normals still
259
+ control reflection versus transmission, medium boundaries and ray offsets.
260
+ A coat reflection can contribute below the base shading hemisphere when it
261
+ remains above the coat and geometric hemispheres. As before, solid interior
262
+ hits omit coat reflection; thin surfaces are treated as exterior hits.
263
+
264
+ Strongly tilted shading normals lose some lobe support when clipped to the
265
+ geometric hemisphere. A unit white environment can therefore render below
266
+ unit radiance; the renderer does not renormalize the clipped lobes.
267
+
268
+ Replacing the map or editing its scale is detected by `engine.update()`. Call
269
+ `texture.markUpdated()` after pixel or UV-array element edits; see [scene updates](./updates.md).
270
+ These edits update material parameters/textures without rebuilding geometry. Normal maps do not alter
271
+ emission's existing normal-incidence absorption or light-selection proposals.
272
+
273
+ ## Anisotropy directions
274
+
275
+ Set `specularAnisotropyRotation` or provide `anisotropyMap` to orient the base specular lobe. The map reads linear `2 * RG - 1`, normalizes the direction, multiplies strength by B, and then applies the rotation. A decoded squared length at or below `1e-4` falls back to `(1, 0)` before rotation (including the two central RGBA8 codes). Without a map the direction is `(1, 0)` and the strength multiplier is one. The rotation defaults to zero; the map defaults to undefined.
276
+
277
+ `coatAnisotropyRotation` defaults to zero and uses the geometry tangent independently of the base map. Base and coat evaluation, sampling and PDF use their respective directions. The coat uses the shared shading normal unless `coatNormalMap` selects an [independent normal](#coat-normals). Zero strength ignores the new direction and retains the original isotropic path.
278
+
279
+ Provided tangent XYZ and optional W handedness are preserved. For XYZ tangents the sign comes from triangle UV derivatives. Missing or degenerate tangents use UV derivatives and then a stable orthonormal fallback; missing tangents produce one diagnostic per geometry. The direction texture's selected UV set is used for derivative fallback, including UV1. A provided XYZW tangent remains authoritative. Directions are reorthogonalized against the final shading normal, including normal maps and back faces, and instance transforms preserve mirrored handedness. UV scale, offset and flipY affect texel lookup; they do not rotate the encoded direction.
280
+
281
+ The direction and strength inputs use native OpenPBR semantics by default. For imported glTF/Three.js strength, select `specularAnisotropyModel: 'gltf'`; the same roughness and strength properties then retain source values. Source scalar inputs are clamped to [0, 1] before texture factors; non-finite source roughness/strength fall back to 0.3/0. Native scalar handling is unchanged. Zero source strength preserves the original roughness path. The conversion matches the GGX alpha axes before existing minimum-alpha clamping; Fresnel, masking, multiple scattering and OpenPBR coating remain the library's model. See [the conversion rules](./threejs.md#anisotropy-source-conversion).
@@ -0,0 +1,85 @@
1
+ # Performance
2
+
3
+ A tuning checklist. Each item links to the page with the details.
4
+
5
+ ## Resolution and samples
6
+
7
+ - Rays per sample scale with pixel count. Cap the device pixel ratio
8
+ (`Math.min(devicePixelRatio, 2)`, or lower on mobile).
9
+ - Set `maxSamples` for the quality you need. With a denoiser, 64–256 spp is
10
+ usually enough; without one, 1000+ for clean results.
11
+ - Start with `bounces` 3–5. Raise it for glass, subsurface scattering or
12
+ interiors lit indirectly, not everywhere.
13
+ - `clamping` removes fireflies at the cost of bias; use the smallest value
14
+ that works.
15
+
16
+ ## Responsiveness
17
+
18
+ - Use a preview Render with cheaper quality and optional adaptiveResolution:
19
+ `{targetFrameMs: 20, minScale: .25}`, plus resolutionScale .5. Choose it during
20
+ motion and configure final.fallback once; see [progressive rendering](./progressive-rendering.md).
21
+ - timeBudgetMs (default 21) bounds each render's tile cost. Raise it for exports.
22
+ - allowMultipleSamplesPerFrame adds several samples per refine when time permits.
23
+ - For exports, `render.converge` with `targetBatchTimeMs` adapts batch sizes
24
+ to the GPU; omit `previewIntervalMs` for maximum throughput.
25
+
26
+ ## Scene setup
27
+
28
+ - Share `Geometry`, `OpenPBRMaterial` and `Texture` objects. Shared geometry
29
+ shares its BLAS and GPU buffers.
30
+ - For large scenes, try `engine.bvhBuilder = 'tinybvh'` and build BVHs up
31
+ front with optional `await engine.prepare(nextScene)`. Tune `bvhWorkerCount` for
32
+ parallel construction across geometries; see [BVH](./bvh.md).
33
+ - With Three.js, keep one `THREESync(engine, {scene, camera, controls})` for the whole session rather than
34
+ converting again with `fromTHREEScene`.
35
+ - Textures share an atlas bounded by `textureAtlasBudgetBytes`; larger textures
36
+ are downscaled. Check `engine.getDiagnostics()?.textureAtlas`.
37
+
38
+ ## Animation and editing
39
+
40
+ See [scene updates](./updates.md) for the cost of each kind of edit.
41
+
42
+ - Edit `mesh.transform` in place: transform changes only refit instances.
43
+ - For vertex animation, keep the arrays, set `geometry.dynamic = true` and call
44
+ `geometry.markVerticesUpdated()`, not `markUpdated()`.
45
+ - Avoid [full mesh updates](./updates.md#full-mesh-updates) per frame:
46
+ replacing arrays, changing displacement, or adding new geometry.
47
+ - Three.js skinning and morph targets run on the CPU; cost grows with
48
+ vertices, bone influences and material groups. An unchanged pose is free.
49
+ - Each `InstancedMesh` instance adds one top-level BVH instance per material
50
+ group. Native instance colors share the same materials.
51
+
52
+ ## Lighting
53
+
54
+ - Prefer `RectLight` and `SphereLight` to small emissive meshes: analytic
55
+ lights are sampled directly and converge faster.
56
+ - Scenes with many lights benefit from more `directLightCandidates` (WebGPU).
57
+ - A bright, small sun in an environment map is importance sampled, but a
58
+ `DirectionalLight` is cleaner when the sun is the key light.
59
+
60
+ ## Shader compilation
61
+
62
+ The path-tracing shaders are large. The first frame can take several seconds
63
+ to compile on some platforms (`'compiling'`). Materials
64
+ with displacement or alpha, and some renderer options, select shader variants
65
+ that compile on first use. Show a status while compiling, as the examples do.
66
+
67
+ ## Diagnostics
68
+
69
+ `engine.getDiagnostics()` reports the backend and adapter, shader
70
+ compilation times, BVH statistics, light sampling setup and GPU trace timing.
71
+ `presentedTarget` is the presented render label after the first complete image
72
+ (`undefined` beforehand); `presentedComplete` is initially `false`.
73
+ `targets` lists each resident accumulation's `label`, `width`, `height` and
74
+ allocated GPU payload `bytes`, including its retained outputs. It excludes shared scene data and temporary image passes, shader/driver overhead,
75
+ and resources queued for release. Each render retains accumulation buffers,
76
+ resolved outputs, its last complete composition and its valid denoised result.
77
+ Post-processing, readback and denoising scratch resources are shared by the engine;
78
+ their allocated capacity grows to the largest required dimensions.
79
+
80
+ Preview and final keep independent outputs. Switching uses their complete
81
+ images without reallocating them; final's first tiled sample keeps preview on
82
+ screen until it completes. Adaptive resolution may rebuild only the preview
83
+ target; its previous complete image remains available through the rebuild.
84
+ Targets are created lazily and remain resident until disposed. Resolution,
85
+ quality and interaction exceptions are explicit application choices.
@@ -0,0 +1,87 @@
1
+ # GPU output and display passes
2
+
3
+ After a render has a complete sample, borrow its WebGPU textures with
4
+ `render.getOutputTexture('hdr')` or `render.getOutputTexture('display')`.
5
+ To add an overlay or another display effect, register a synchronous pass:
6
+
7
+ ```ts
8
+ const remove = engine.display.addPostProcess(ctx => {
9
+ // Record a render or compute pass on ctx.encoder.
10
+ // Read ctx.input and fully write ctx.output, including alpha.
11
+ // Use ctx.output.format when creating the pipeline.
12
+ drawOverlay(ctx);
13
+ });
14
+ engine.display.present(final);
15
+ const png = await engine.display.toBlob(final);
16
+ remove(); // Safe to call again.
17
+ ```
18
+
19
+ Passes run in registration order on every `present()` and `toBlob()`, after
20
+ composition and denoising. They receive the selected complete render, including
21
+ fallbacks, at its actual dimensions. Export uses the same chain without resizing
22
+ or changing the display canvas. `readPixels()` never runs these passes.
23
+
24
+ For a complete overlay implementation, see
25
+ [`createCrosshairPass`](../examples/shared/crosshairPass.ts). It loads the input
26
+ with `textureLoad`, draws a white crosshair in display space and writes every
27
+ output pixel. The [basic example](../examples/basic.ts) enables it with `?overlay`:
28
+
29
+ ```ts
30
+ import { createCrosshairPass } from './shared/crosshairPass';
31
+ const removeCrosshair = engine.display.addPostProcess(createCrosshairPass());
32
+ ```
33
+
34
+ A changing overlay can read application state in its callback. `RenderLoop`
35
+ stops presenting after convergence, so explicitly call `display.present(final)`
36
+ when that state changes. This refreshes the overlay without tracing more samples.
37
+
38
+ ## Options and image semantics
39
+
40
+ `getOutputTexture(kind)` requires `'hdr'` or `'display'`; both return undefined
41
+ on WebGL, before a complete sample or after disposal. There are no passes by
42
+ default. `addPostProcess(pass)` returns an idempotent unregister function.
43
+ `PostProcess` and `PostProcessContext` are exported types.
44
+
45
+ | Image | Meaning |
46
+ | --- | --- |
47
+ | HDR | Native resolved linear ray RGB, before denoising, exposure, grading, tone mapping, vignette, bloom or display background/catcher composition. Same normalization and raw path-coverage alpha as `DenoiseInput.color` |
48
+ | Display | Latest composed display channel, including denoising and the display pass chain; encoded display RGB and straight alpha (diagnostic channels retain their native values) |
49
+
50
+ Images have their first row at the top. HDR currently uses `rgba16float`;
51
+ ordinary display uses `rgba8unorm`, extended-range output uses `rgba16float`,
52
+ and diagnostic channels may use their native format. Inspect `texture.format`
53
+ and dimensions rather than assuming a format. Extended-range display RGB is
54
+ still encoded for presentation; it is not the original HDR ray color.
55
+
56
+ HDR RGB divides by primary hits when there are hits, otherwise by sample count.
57
+ For an opaque flat background, `readPixels('hdr')` additionally multiplies RGB
58
+ by primary-hit coverage for partially hit pixels, restoring the per-sample
59
+ average. Thus that CPU readback can differ from the borrowed native HDR texture.
60
+ See [custom denoiser image semantics](./denoising.md#custom-denoisers).
61
+
62
+ ## Caveats
63
+
64
+ Textures are borrowed and read-only. Do not retain, write or destroy returned
65
+ textures. Their validity ends at the render's next `refine()`/`converge()`, or
66
+ the display's next `present()`/`setSize()`; restart, disposal and device loss
67
+ also invalidate them. Fully transparent PNG pixels have no preserved RGB
68
+ value after the browser canvas encoding/decoding round trip. Submit your reads before that boundary. Callback images
69
+ and encoder are borrowed only during the synchronous callback; record all work
70
+ there and let MuTracer finish and submit the encoder. Do not submit separate
71
+ work, mutate input or retain the output. Device recovery may replace the device,
72
+ so cache pipelines by both device and output format.
73
+
74
+ The output supports `RENDER_ATTACHMENT`, `STORAGE_BINDING`, `TEXTURE_BINDING`
75
+ and copy usage. Each pass must fully write it; previous contents are unspecified.
76
+ The input and output never alias. WebGL skips all registered passes and warns
77
+ once per display. A synchronous callback exception skips the remaining passes,
78
+ discards the chain's recorded commands, displays the original composed image
79
+ and emits the engine `error` event. GPU validation errors remain WebGPU errors;
80
+ the callback must record valid commands.
81
+
82
+ ## Implementation notes
83
+
84
+ The composed image is kept separately, so a thrown callback cannot leave a
85
+ partly processed result.
86
+ Display passes do not enter denoiser inputs, change samples or invalidate cached
87
+ filter results. HDR-stage callbacks are outside this API.
@@ -0,0 +1,160 @@
1
+ # Progressive rendering
2
+
3
+ Use RenderLoop for interactive preview and final rendering; use the first layer
4
+ when your application needs explicit selection and frame budgets.
5
+
6
+ ```ts
7
+ const sync = new THREESync(engine, {scene: threeScene, camera: threeCamera, controls});
8
+ const loop = new RenderLoop(engine, {sync});
9
+ loop.start();
10
+ ```
11
+
12
+ ## Loop policy
13
+
14
+ Each tick updates syncs and commits engine inputs, then calls select, refines the
15
+ selected render and presents it. Active syncs select preview by default. Isolated
16
+ edits start final immediately; consecutive changes without explicit sync activity
17
+ hold preview for idleMs (default 150 ms). When interaction ends, final starts after
18
+ the current preview completes; its fallback remains visible until final completes a sample.
19
+ With intermediate denoising enabled, it stays visible until the first filtered final image is ready.
20
+
21
+ ```ts
22
+ loop.select = ({changing}) => changing || slider.dragging ? 'preview' : 'final';
23
+ loop.on('status', ({status, previous}) => updateStatus(status));
24
+ loop.on('sample', ({samples, frameTimeMs}) => updateSamples(samples));
25
+ ```
26
+
27
+ Loop status is previewing when the displayed target is preview, including fallback
28
+ presentation and the wait for the first complete final image. Starting to trace
29
+ final tiles does not change that status until final is actually presented.
30
+ Preview samples never emit loop sample events or count toward loop
31
+ samples. Intermediate final filtering reports converging; only terminal filtering
32
+ reports denoising. After finishing, unchanged ticks update syncs and the engine
33
+ without GPU submissions. Display or render settings edits resume necessary work.
34
+
35
+ During interaction, the loop finishes the current preview sample before applying
36
+ the latest scene/camera edits, keeping previews responsive during continuous input.
37
+
38
+ start pauses on hidden pages; stop preserves images. Use tick with your own frame
39
+ loop, or start, which ignores manual tick calls with one warning. loop.converge
40
+ pauses interactive ticks, converges/presents final and resumes if still started.
41
+
42
+ coalesceSceneUpdates defaults to false. When enabled, preview inference defers
43
+ engine commits while syncs keep collecting edits. The last presented image stays
44
+ visible until the next filtered preview is ready. Completed inference is presented
45
+ before the latest camera/scene is committed together. Interaction ending during
46
+ inference waits for that result before final starts. With it disabled, changes
47
+ immediately invalidate old inference. Once final is available, unused fallback
48
+ inference does not delay it or switch presentation back to preview.
49
+ Render.denoising includes intermediate
50
+ inference without changing status semantics. Denoising does not enable preview;
51
+ preview: false always disables it.
52
+
53
+ ## Explicit frame control
54
+
55
+ Create one `Engine` for a scene and camera, then one `Render` per output. The
56
+ engine owns shared GPU scene data; a render owns its image and complete sample
57
+ count. `Display` owns canvas presentation and display settings.
58
+
59
+ ```ts
60
+ import { Engine, Render } from '@meimu/mutracer';
61
+ const engine = new Engine({ canvas });
62
+ engine.scene = scene;
63
+ engine.camera = camera;
64
+ const preview = new Render(engine, {
65
+ resolutionScale: .5,
66
+ timeBudgetMs: 80,
67
+ adaptiveResolution: { targetFrameMs: 80, minScale: .125 },
68
+ bounces: 2, bevel: false, dispersionWavelengths: 1,
69
+ directLightCandidates: 2,
70
+ });
71
+ const final = new Render(engine, { fallback: preview });
72
+ function frame() {
73
+ engine.update();
74
+ const current = dragging ? preview : final;
75
+ current.refine();
76
+ engine.display.present(current);
77
+ requestAnimationFrame(frame);
78
+ }
79
+ frame();
80
+ ```
81
+
82
+ `engine.update()` is the only external edit detection and commit point. Until
83
+ it runs, object edits and scene/camera replacement have no effect on tracing.
84
+ Call it once after updating your scene and controls, even when several renders
85
+ are refined that frame. See [scene updates](updates.md) for notifications.
86
+
87
+ ## Reading and exporting
88
+
89
+ A fixed-size render does not need to be displayed. Its camera defaults to the
90
+ committed engine camera, with automatic aspect based on its target dimensions.
91
+ An explicitly supplied camera aspect is preserved.
92
+
93
+ ```ts
94
+ const image = new Render(engine, { width: 256, height: 256 });
95
+ engine.update();
96
+ await image.converge({ samples: 64, sampleSequenceOffset: 0 });
97
+ const hdr = await image.readPixels('hdr'); // this image, regardless of other activity
98
+ const blob = await engine.display.toBlob(image);
99
+ image.dispose();
100
+ ```
101
+
102
+ `toBlob` uses the specified render's actual dimensions and the display's
103
+ settings. It does not resize or change the display canvas. `converge` accepts a
104
+ camera override, copied on entry, without replacing `engine.camera`. If engine
105
+ input revisions change during a convergence task, the task rejects. Only that
106
+ render rejects `refine()` while convergence is running; other renders remain
107
+ usable.
108
+
109
+ ## Options and ownership
110
+
111
+ - RenderLoop: preview/final selection, syncs, idleMs and coalesceSceneUpdates.
112
+ - Engine: backend, scene/camera, BVH preparation and texture atlas budget.
113
+ - Display: size, tone mapping, color grading, bloom, HDR output, channel and
114
+ shadow-catcher color/opacity. Editing these does not restart accumulation.
115
+ - Render: resolution, samples, path quality, alpha handling, execution budget,
116
+ fallback and denoiser. `transmissiveOutputAlphaMin` belongs to Render because
117
+ it is evaluated along individual paths, so changing it restarts that render.
118
+
119
+ RenderLoop creates a half-resolution preview with adaptive scale .125–.5,
120
+ 80 ms budget, 2 bounces, no bevel, one wavelength and two light candidates;
121
+ other settings use Render defaults. Pass preview settings, a Render or false.
122
+ Preview resolution drops when interaction is slow and recovers gradually when
123
+ performance improves. Final resolution stays independent of preview adaptation.
124
+ Pass final settings or a Render; newly created finals use preview as fallback.
125
+ Supplied Render/Sync objects must belong to this engine. loop.dispose releases
126
+ only renders it created; dispose supplied renders, syncs and controls yourself.
127
+
128
+ The default render scale is 1 and adaptive resolution is disabled. Alternatively,
129
+ provide both fixed width and height at construction; fixed dimensions cannot be
130
+ changed through `resolutionScale`. `width` and `height` report the actual GPU
131
+ image, including WebGPU's 16-pixel alignment. See [API options](api.md).
132
+
133
+ Keep the display canvas at the viewport's drawing-buffer size and set
134
+ `resolutionScale` on each render independently. Lowering final's scale does not
135
+ lower preview's scale; resizing the display canvas affects both.
136
+
137
+ Call `render.setDenoiser({ type: 'jnlm', schedule: 'converged' })` with JNLM or an OIDN
138
+ configuration. The schedules are `converged` (default), `progressive` (first
139
+ sample, then 4, 8, 16, … with a ten-second limit), and `every-sample`. Same-engine
140
+ renders share equal filter configurations and OIDN weight downloads. The engine
141
+ releases a network when its last render lease is released. OIDN is ignored with
142
+ a warning on WebGL; JNLM works on both backends.
143
+
144
+ ## Caveats
145
+
146
+ A fallback has only one level and must belong to the same engine. If the first
147
+ full sample is predicted to exceed the frame budget, `refine` supplies a sample
148
+ to a stale fallback before continuing. A current fallback is reused; a fast
149
+ final sample does not render the fallback. `present` selects the requested
150
+ complete image, then its complete fallback, and otherwise leaves the canvas
151
+ unchanged. It never traces.
152
+
153
+ `prepare(nextScene)` performs optional CPU BVH preparation without disturbing
154
+ the current GPU scene. Setting `engine.scene` and calling `update` commits a
155
+ scene switch for every render. Only one GPU scene resides in an engine.
156
+
157
+ Dispose renders when no longer needed; `engine.dispose()` releases every render
158
+ and shared resource. Initialization and asynchronous filter failures use the
159
+ engine's `error` event. `Render.status` is independent for each output; the
160
+ first-layer API leaves frame selection and application UI status to the caller.
@@ -0,0 +1,40 @@
1
+ # Sampling patterns
2
+
3
+ `render.samplingPattern` selects the sample sequence. Changing it restarts
4
+ accumulation. The denoiser never changes it.
5
+
6
+ | Pattern | Use |
7
+ | --- | --- |
8
+ | `'sobol'` (default) | General use, and with any denoiser. Owen-scrambled Sobol; converges well per pixel with spatially decorrelated error |
9
+ | `'zsobol'` | Low sample counts **without** a denoiser. Morton-ordered Sobol with blue-noise error |
10
+ | `'random'` | PCG white noise; an independent Monte Carlo reference |
11
+
12
+ ```ts
13
+ render.samplingPattern = 'zsobol';
14
+ ```
15
+
16
+ ## Caveats
17
+
18
+ - **ZSobol budget**: ZSobol sizes its pattern from `maxSamples`, rounded up to
19
+ a power of two and capped at 65536 (unlimited rendering uses the cap).
20
+ Changing the rounded budget restarts accumulation. The first sample always
21
+ has blue-noise error; later prefixes of a large budget cannot all keep it.
22
+ - **Determinism**: offline sequences are deterministic, including
23
+ `sampleSequenceOffset`. Use disjoint offset ranges for animation frames.
24
+ - **Backends**: WebGPU and WebGL 2 can differ in floating-point rounding even
25
+ with identical sequence points.
26
+ - **Fireflies**: very narrow specular lobes under directional lights can
27
+ produce rare, large contributions with any pattern. Sampling does not clamp
28
+ them; use `render.clamping` if needed.
29
+
30
+ ## Implementation notes
31
+
32
+ - `sobol` uses Burley's Owen-scrambled 2D Sobol sequences, scrambled
33
+ independently per pixel and domain.
34
+ - ZSobol is blue-noise-first: sample zero uses a one-sample ZSobol pattern,
35
+ and later samples use an independent scramble for the remaining budget.
36
+ - On WebGPU each pixel follows its own sequence, so adaptive sampling and
37
+ preview tiles do not skip sequence points.
38
+ - Camera, aperture, light, BSDF and phase sampling use separate dimensions;
39
+ spectral wavelengths reuse them to reduce colored noise. Interactive resets
40
+ keep seed zero for stable screen-relative noise.