@meimu/mutracer 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (529) hide show
  1. package/LICENSES/Classroom-CC0.txt +121 -0
  2. package/README.md +7 -7
  3. package/THIRD_PARTY_NOTICES.md +13 -8
  4. package/dist/assets/bvh.worker.js +1 -1
  5. package/dist/mutracer.umd.js +10421 -8363
  6. package/docs/api.md +202 -11
  7. package/docs/denoising.md +30 -15
  8. package/docs/materials.md +18 -27
  9. package/docs/performance.md +5 -2
  10. package/docs/progressive-rendering.md +32 -1
  11. package/docs/threejs.md +19 -10
  12. package/docs/updates.md +44 -2
  13. package/docs/viewer.md +41 -3
  14. package/lib/Display.d.ts +13 -2
  15. package/lib/Display.js +27 -6
  16. package/lib/Display.js.map +1 -1
  17. package/lib/Engine.d.ts +2 -0
  18. package/lib/Engine.js +52 -25
  19. package/lib/Engine.js.map +1 -1
  20. package/lib/Render.d.ts +44 -9
  21. package/lib/Render.js +115 -17
  22. package/lib/Render.js.map +1 -1
  23. package/lib/RenderLoop.d.ts +7 -1
  24. package/lib/RenderLoop.js +94 -13
  25. package/lib/RenderLoop.js.map +1 -1
  26. package/lib/main.d.ts +6 -3
  27. package/lib/main.js +1 -0
  28. package/lib/main.js.map +1 -1
  29. package/lib/math/access.d.ts +4 -0
  30. package/lib/math/access.js +10 -0
  31. package/lib/math/access.js.map +1 -0
  32. package/lib/math/mat3.d.ts +4 -0
  33. package/lib/math/mat3.js +54 -0
  34. package/lib/math/mat3.js.map +1 -0
  35. package/lib/math/mat4.d.ts +19 -0
  36. package/lib/math/mat4.js +413 -0
  37. package/lib/math/mat4.js.map +1 -0
  38. package/lib/math/storage.d.ts +6 -0
  39. package/lib/math/storage.js +22 -0
  40. package/lib/math/storage.js.map +1 -0
  41. package/lib/math/types.d.ts +3 -0
  42. package/lib/math/types.js +2 -0
  43. package/lib/math/types.js.map +1 -0
  44. package/lib/math/vec2.d.ts +13 -0
  45. package/lib/math/vec2.js +52 -0
  46. package/lib/math/vec2.js.map +1 -0
  47. package/lib/math/vec3.d.ts +23 -0
  48. package/lib/math/vec3.js +139 -0
  49. package/lib/math/vec3.js.map +1 -0
  50. package/lib/math.d.ts +5 -17
  51. package/lib/math.js +5 -55
  52. package/lib/math.js.map +1 -1
  53. package/lib/oidn.d.ts +1 -1
  54. package/lib/oidn.js +4 -2
  55. package/lib/oidn.js.map +1 -1
  56. package/lib/oidnBundledWeights.cdn.d.ts +2 -2
  57. package/lib/renderer/AovPrimitiveCache.d.ts +10 -0
  58. package/lib/renderer/AovPrimitiveCache.js +48 -0
  59. package/lib/renderer/AovPrimitiveCache.js.map +1 -0
  60. package/lib/renderer/Box3.d.ts +5 -0
  61. package/lib/renderer/Box3.js +9 -0
  62. package/lib/renderer/Box3.js.map +1 -0
  63. package/lib/renderer/GPUTraceQueue.d.ts +10 -0
  64. package/lib/renderer/GPUTraceQueue.js +31 -0
  65. package/lib/renderer/GPUTraceQueue.js.map +1 -0
  66. package/lib/renderer/MaterialData.d.ts +15 -0
  67. package/lib/renderer/MaterialData.js +61 -0
  68. package/lib/renderer/MaterialData.js.map +1 -0
  69. package/lib/renderer/MaterialTable.d.ts +11 -98
  70. package/lib/renderer/MaterialTable.js +34 -412
  71. package/lib/renderer/MaterialTable.js.map +1 -1
  72. package/lib/renderer/RenderingPipeline.d.ts +32 -13
  73. package/lib/renderer/RenderingPipeline.js +1 -17
  74. package/lib/renderer/RenderingPipeline.js.map +1 -1
  75. package/lib/renderer/TileRender.d.ts +0 -1
  76. package/lib/renderer/TileRender.js +14 -1
  77. package/lib/renderer/TileRender.js.map +1 -1
  78. package/lib/renderer/WGPUAov.d.ts +39 -0
  79. package/lib/renderer/WGPUAov.js +239 -0
  80. package/lib/renderer/WGPUAov.js.map +1 -0
  81. package/lib/renderer/WGPUBindlessMaterialData.d.ts +17 -0
  82. package/lib/renderer/WGPUBindlessMaterialData.js +48 -0
  83. package/lib/renderer/WGPUBindlessMaterialData.js.map +1 -0
  84. package/lib/renderer/WGPUBindlessTextures.d.ts +47 -0
  85. package/lib/renderer/WGPUBindlessTextures.js +180 -0
  86. package/lib/renderer/WGPUBindlessTextures.js.map +1 -0
  87. package/lib/renderer/WGPUBloomPass.js +17 -97
  88. package/lib/renderer/WGPUBloomPass.js.map +1 -1
  89. package/lib/renderer/WGPUComputePass.d.ts +1 -1
  90. package/lib/renderer/WGPUComputePass.js.map +1 -1
  91. package/lib/renderer/WGPUEnvMapDistribution.d.ts +12 -0
  92. package/lib/renderer/WGPUEnvMapDistribution.js +150 -0
  93. package/lib/renderer/WGPUEnvMapDistribution.js.map +1 -0
  94. package/lib/renderer/WGPUFullQuadPass.js +10 -9
  95. package/lib/renderer/WGPUFullQuadPass.js.map +1 -1
  96. package/lib/renderer/WGPUJNLMDenoiser.d.ts +1 -20
  97. package/lib/renderer/WGPUJNLMDenoiser.js +4 -267
  98. package/lib/renderer/WGPUJNLMDenoiser.js.map +1 -1
  99. package/lib/renderer/WGPURayTraceOutput.js +26 -17
  100. package/lib/renderer/WGPURayTraceOutput.js.map +1 -1
  101. package/lib/renderer/WGPURayTracePass.d.ts +36 -40
  102. package/lib/renderer/WGPURayTracePass.js +399 -548
  103. package/lib/renderer/WGPURayTracePass.js.map +1 -1
  104. package/lib/renderer/WGPURenderingPipeline.d.ts +5 -3
  105. package/lib/renderer/WGPURenderingPipeline.js +239 -60
  106. package/lib/renderer/WGPURenderingPipeline.js.map +1 -1
  107. package/lib/renderer/WGPUShaderCache.d.ts +2 -2
  108. package/lib/renderer/WGPUShaderCache.js +10 -5
  109. package/lib/renderer/WGPUShaderCache.js.map +1 -1
  110. package/lib/renderer/WGPUShaderCapabilities.d.ts +10 -0
  111. package/lib/renderer/WGPUShaderCapabilities.js +54 -0
  112. package/lib/renderer/WGPUShaderCapabilities.js.map +1 -0
  113. package/lib/renderer/WGPUSkyBaker.d.ts +13 -0
  114. package/lib/renderer/WGPUSkyBaker.js +85 -0
  115. package/lib/renderer/WGPUSkyBaker.js.map +1 -0
  116. package/lib/renderer/WebGLAov.d.ts +41 -0
  117. package/lib/renderer/WebGLAov.js +106 -0
  118. package/lib/renderer/WebGLAov.js.map +1 -0
  119. package/lib/renderer/WebGLFullQuadPass.d.ts +5 -3
  120. package/lib/renderer/WebGLFullQuadPass.js +18 -2
  121. package/lib/renderer/WebGLFullQuadPass.js.map +1 -1
  122. package/lib/renderer/WebGLJNLMDenoiser.d.ts +1 -1
  123. package/lib/renderer/WebGLJNLMDenoiser.js +83 -74
  124. package/lib/renderer/WebGLJNLMDenoiser.js.map +1 -1
  125. package/lib/renderer/WebGLRayTraceOutputPass.js +7 -4
  126. package/lib/renderer/WebGLRayTraceOutputPass.js.map +1 -1
  127. package/lib/renderer/WebGLRayTracePass.d.ts +12 -2
  128. package/lib/renderer/WebGLRayTracePass.js +83 -7
  129. package/lib/renderer/WebGLRayTracePass.js.map +1 -1
  130. package/lib/renderer/WebGLRenderingPipeline.js +116 -8
  131. package/lib/renderer/WebGLRenderingPipeline.js.map +1 -1
  132. package/lib/renderer/WebGLSkyBaker.d.ts +39 -0
  133. package/lib/renderer/WebGLSkyBaker.js +422 -0
  134. package/lib/renderer/WebGLSkyBaker.js.map +1 -0
  135. package/lib/renderer/WebGLSkySource.d.ts +9 -0
  136. package/lib/renderer/WebGLSkySource.js +28 -0
  137. package/lib/renderer/WebGLSkySource.js.map +1 -0
  138. package/lib/renderer/accumulationTarget.d.ts +5 -0
  139. package/lib/renderer/accumulationTarget.js.map +1 -1
  140. package/lib/renderer/aov.d.ts +42 -0
  141. package/lib/renderer/aov.js +50 -0
  142. package/lib/renderer/aov.js.map +1 -0
  143. package/lib/renderer/aovDisplay.d.ts +14 -0
  144. package/lib/renderer/aovDisplay.js +32 -0
  145. package/lib/renderer/aovDisplay.js.map +1 -0
  146. package/lib/renderer/aovScene.d.ts +21 -0
  147. package/lib/renderer/aovScene.js +139 -0
  148. package/lib/renderer/aovScene.js.map +1 -0
  149. package/lib/renderer/binnedSahBvh.js +2 -1
  150. package/lib/renderer/binnedSahBvh.js.map +1 -1
  151. package/lib/renderer/bvhAccel.d.ts +20 -10
  152. package/lib/renderer/bvhAccel.js +168 -58
  153. package/lib/renderer/bvhAccel.js.map +1 -1
  154. package/lib/renderer/bvhWorkerBuild.d.ts +1 -0
  155. package/lib/renderer/cameraSnapshot.js +2 -1
  156. package/lib/renderer/cameraSnapshot.js.map +1 -1
  157. package/lib/renderer/cameraUniform.d.ts +2 -0
  158. package/lib/renderer/cameraUniform.js +12 -0
  159. package/lib/renderer/cameraUniform.js.map +1 -0
  160. package/lib/renderer/committedScene.js +4 -0
  161. package/lib/renderer/committedScene.js.map +1 -1
  162. package/lib/renderer/denoiser.d.ts +3 -11
  163. package/lib/renderer/denoiser.js.map +1 -1
  164. package/lib/renderer/depthQuery.js +4 -1
  165. package/lib/renderer/depthQuery.js.map +1 -1
  166. package/lib/renderer/displacementPreparation.d.ts +11 -0
  167. package/lib/renderer/displacementPreparation.js +351 -0
  168. package/lib/renderer/displacementPreparation.js.map +1 -0
  169. package/lib/renderer/displacementRange.d.ts +1 -0
  170. package/lib/renderer/displacementRange.js +9 -0
  171. package/lib/renderer/displacementRange.js.map +1 -0
  172. package/lib/renderer/displayParityDiagnostics.d.ts +11 -0
  173. package/lib/renderer/displayParityDiagnostics.js +2 -0
  174. package/lib/renderer/displayParityDiagnostics.js.map +1 -0
  175. package/lib/renderer/envMapCreation.d.ts +9 -8
  176. package/lib/renderer/envMapCreation.js +36 -12
  177. package/lib/renderer/envMapCreation.js.map +1 -1
  178. package/lib/renderer/envMapDistribution.d.ts +12 -2
  179. package/lib/renderer/envMapDistribution.js +43 -34
  180. package/lib/renderer/envMapDistribution.js.map +1 -1
  181. package/lib/renderer/geometryBvhBounds.d.ts +4 -0
  182. package/lib/renderer/geometryBvhBounds.js +82 -0
  183. package/lib/renderer/geometryBvhBounds.js.map +1 -0
  184. package/lib/renderer/geometryUpdateState.d.ts +32 -0
  185. package/lib/renderer/geometryUpdateState.js +2 -0
  186. package/lib/renderer/geometryUpdateState.js.map +1 -0
  187. package/lib/renderer/geometryUpdates.d.ts +17 -9
  188. package/lib/renderer/geometryUpdates.js +92 -33
  189. package/lib/renderer/geometryUpdates.js.map +1 -1
  190. package/lib/renderer/glsl/aovDisplay.frag.d.ts +3 -0
  191. package/lib/renderer/glsl/aovDisplay.frag.js +54 -0
  192. package/lib/renderer/glsl/aovDisplay.frag.js.map +1 -0
  193. package/lib/renderer/glsl/aovReflectance.glsl.d.ts +2 -0
  194. package/lib/renderer/glsl/aovReflectance.glsl.js +87 -0
  195. package/lib/renderer/glsl/aovReflectance.glsl.js.map +1 -0
  196. package/lib/renderer/glsl/aovReflectanceSamples.glsl.d.ts +2 -0
  197. package/lib/renderer/glsl/aovReflectanceSamples.glsl.js +135 -0
  198. package/lib/renderer/glsl/aovReflectanceSamples.glsl.js.map +1 -0
  199. package/lib/renderer/glsl/aovTrace.frag.d.ts +2 -0
  200. package/lib/renderer/glsl/aovTrace.frag.js +121 -0
  201. package/lib/renderer/glsl/aovTrace.frag.js.map +1 -0
  202. package/lib/renderer/glsl/chunks/cameraRay.glsl.js +12 -12
  203. package/lib/renderer/glsl/chunks/envMap.glsl.js +80 -74
  204. package/lib/renderer/glsl/chunks/envMap.glsl.js.map +1 -1
  205. package/lib/renderer/glsl/chunks/intersect.glsl.js +437 -435
  206. package/lib/renderer/glsl/chunks/intersect.glsl.js.map +1 -1
  207. package/lib/renderer/glsl/chunks/materialBuffer.glsl.js +146 -145
  208. package/lib/renderer/glsl/chunks/materialBuffer.glsl.js.map +1 -1
  209. package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js +821 -821
  210. package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js.map +1 -1
  211. package/lib/renderer/glsl/chunks/rand.glsl.js +3 -3
  212. package/lib/renderer/glsl/chunks/random.glsl.js +6 -6
  213. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js +51 -51
  214. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js.map +1 -1
  215. package/lib/renderer/glsl/chunks/sampleLight.glsl.js +80 -80
  216. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js +108 -108
  217. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js.map +1 -1
  218. package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js +20 -17
  219. package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js.map +1 -1
  220. package/lib/renderer/glsl/chunks/sampling.glsl.js +93 -93
  221. package/lib/renderer/glsl/chunks/sobol.glsl.js +79 -79
  222. package/lib/renderer/glsl/chunks/textureLinear.glsl.js +5 -5
  223. package/lib/renderer/glsl/chunks/uvProjection.glsl.js +12 -12
  224. package/lib/renderer/glsl/chunks/uvProjection.glsl.js.map +1 -1
  225. package/lib/renderer/glsl/depthQuery.frag.js +7 -7
  226. package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js +17 -9
  227. package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js.map +1 -1
  228. package/lib/renderer/glsl/rayTrace.frag.js +191 -191
  229. package/lib/renderer/glsl/shadowCatcher.frag.js +25 -20
  230. package/lib/renderer/glsl/shadowCatcher.frag.js.map +1 -1
  231. package/lib/renderer/glsl/webglPipeline.frag.js +65 -60
  232. package/lib/renderer/glsl/webglPipeline.frag.js.map +1 -1
  233. package/lib/renderer/lightConstants.d.ts +10 -0
  234. package/lib/renderer/lightConstants.js +11 -0
  235. package/lib/renderer/lightConstants.js.map +1 -0
  236. package/lib/renderer/lightCore.d.ts +12 -0
  237. package/lib/renderer/lightCore.js +13 -0
  238. package/lib/renderer/lightCore.js.map +1 -0
  239. package/lib/renderer/lightSampling.d.ts +20 -17
  240. package/lib/renderer/lightSampling.js +123 -56
  241. package/lib/renderer/lightSampling.js.map +1 -1
  242. package/lib/renderer/lightsData.d.ts +21 -0
  243. package/lib/renderer/lightsData.js +192 -0
  244. package/lib/renderer/lightsData.js.map +1 -0
  245. package/lib/renderer/lightsUtil.d.ts +3 -26
  246. package/lib/renderer/lightsUtil.js +3 -153
  247. package/lib/renderer/lightsUtil.js.map +1 -1
  248. package/lib/renderer/materialBufferData.d.ts +70 -0
  249. package/lib/renderer/materialBufferData.js +2 -0
  250. package/lib/renderer/materialBufferData.js.map +1 -0
  251. package/lib/renderer/materialConstants.d.ts +11 -0
  252. package/lib/renderer/materialConstants.js +11 -0
  253. package/lib/renderer/materialConstants.js.map +1 -1
  254. package/lib/renderer/materialCore.d.ts +8 -0
  255. package/lib/renderer/materialCore.js +9 -0
  256. package/lib/renderer/materialCore.js.map +1 -0
  257. package/lib/renderer/materialEmission.d.ts +2 -2
  258. package/lib/renderer/materialEmission.js +3 -3
  259. package/lib/renderer/materialEmission.js.map +1 -1
  260. package/lib/renderer/materialLayout.d.ts +2 -101
  261. package/lib/renderer/materialLayout.js +110 -172
  262. package/lib/renderer/materialLayout.js.map +1 -1
  263. package/lib/renderer/materialLayoutSchema.d.ts +26 -0
  264. package/lib/renderer/materialLayoutSchema.js +172 -0
  265. package/lib/renderer/materialLayoutSchema.js.map +1 -0
  266. package/lib/renderer/materialParams.d.ts +69 -0
  267. package/lib/renderer/materialParams.js +272 -0
  268. package/lib/renderer/materialParams.js.map +1 -0
  269. package/lib/renderer/materialTextureSlots.d.ts +14 -324
  270. package/lib/renderer/materialTextureSlots.js +21 -8
  271. package/lib/renderer/materialTextureSlots.js.map +1 -1
  272. package/lib/renderer/materialTextures.d.ts +6 -0
  273. package/lib/renderer/{texturesFromMaterials.js → materialTextures.js} +1 -2
  274. package/lib/renderer/materialTextures.js.map +1 -0
  275. package/lib/renderer/mergeMeshesToGeometry.js +6 -147
  276. package/lib/renderer/mergeMeshesToGeometry.js.map +1 -1
  277. package/lib/renderer/meshInstances.d.ts +4 -21
  278. package/lib/renderer/meshInstances.js +10 -56
  279. package/lib/renderer/meshInstances.js.map +1 -1
  280. package/lib/renderer/oidnNetwork.d.ts +2 -2
  281. package/lib/renderer/oidnNetwork.js +1 -1
  282. package/lib/renderer/oidnNetwork.js.map +1 -1
  283. package/lib/renderer/openPbrEnergyLut.js +850 -846
  284. package/lib/renderer/openPbrEnergyLut.js.map +1 -1
  285. package/lib/renderer/ownedDenoiser.d.ts +9 -0
  286. package/lib/renderer/ownedDenoiser.js +2 -0
  287. package/lib/renderer/ownedDenoiser.js.map +1 -0
  288. package/lib/renderer/packedMeshInstances.d.ts +23 -0
  289. package/lib/renderer/packedMeshInstances.js +80 -0
  290. package/lib/renderer/packedMeshInstances.js.map +1 -0
  291. package/lib/renderer/prepareMeshBVH.d.ts +12 -47
  292. package/lib/renderer/prepareMeshBVH.js +21 -642
  293. package/lib/renderer/prepareMeshBVH.js.map +1 -1
  294. package/lib/renderer/proceduralEnvironmentPower.d.ts +3 -0
  295. package/lib/renderer/proceduralEnvironmentPower.js +8 -0
  296. package/lib/renderer/proceduralEnvironmentPower.js.map +1 -0
  297. package/lib/renderer/progressiveScheduler.d.ts +1 -0
  298. package/lib/renderer/progressiveScheduler.js +3 -0
  299. package/lib/renderer/progressiveScheduler.js.map +1 -1
  300. package/lib/renderer/renderPipeline.d.ts +3 -1
  301. package/lib/renderer/renderPipeline.js.map +1 -1
  302. package/lib/renderer/renderingLimits.d.ts +9 -0
  303. package/lib/renderer/renderingLimits.js +18 -0
  304. package/lib/renderer/renderingLimits.js.map +1 -0
  305. package/lib/renderer/sceneAssembly.d.ts +73 -0
  306. package/lib/renderer/sceneAssembly.js +109 -0
  307. package/lib/renderer/sceneAssembly.js.map +1 -0
  308. package/lib/renderer/sceneChangeCore.d.ts +39 -0
  309. package/lib/renderer/sceneChangeCore.js +307 -0
  310. package/lib/renderer/sceneChangeCore.js.map +1 -0
  311. package/lib/renderer/sceneChangeDetector.d.ts +3 -6
  312. package/lib/renderer/sceneChangeDetector.js +24 -150
  313. package/lib/renderer/sceneChangeDetector.js.map +1 -1
  314. package/lib/renderer/sceneLayoutSchema.d.ts +118 -0
  315. package/lib/renderer/sceneLayoutSchema.js +111 -0
  316. package/lib/renderer/sceneLayoutSchema.js.map +1 -0
  317. package/lib/renderer/sceneLightChanges.d.ts +3 -3
  318. package/lib/renderer/sceneLightChanges.js.map +1 -1
  319. package/lib/renderer/scenePreparation.d.ts +55 -0
  320. package/lib/renderer/scenePreparation.js +360 -0
  321. package/lib/renderer/scenePreparation.js.map +1 -0
  322. package/lib/renderer/scratchSampling.js +18 -18
  323. package/lib/renderer/scratchSampling.js.map +1 -1
  324. package/lib/renderer/shader.d.ts +2 -0
  325. package/lib/renderer/shader.js +2 -0
  326. package/lib/renderer/shader.js.map +1 -1
  327. package/lib/renderer/shaderCapabilities.d.ts +23 -0
  328. package/lib/renderer/shaderCapabilities.js +55 -0
  329. package/lib/renderer/shaderCapabilities.js.map +1 -0
  330. package/lib/renderer/shaderCapacity.d.ts +2 -0
  331. package/lib/renderer/shaderCapacity.js +5 -0
  332. package/lib/renderer/shaderCapacity.js.map +1 -0
  333. package/lib/renderer/skyModel.d.ts +9 -0
  334. package/lib/renderer/skyModel.js +10 -0
  335. package/lib/renderer/skyModel.js.map +1 -0
  336. package/lib/renderer/textureAtlas.d.ts +60 -0
  337. package/lib/renderer/textureAtlas.js +145 -0
  338. package/lib/renderer/textureAtlas.js.map +1 -0
  339. package/lib/renderer/textureAtlasPixels.d.ts +7 -0
  340. package/lib/renderer/textureAtlasPixels.js +68 -0
  341. package/lib/renderer/textureAtlasPixels.js.map +1 -0
  342. package/lib/renderer/util.d.ts +1 -1
  343. package/lib/renderer/util.js.map +1 -1
  344. package/lib/renderer/webgl.d.ts +9 -2
  345. package/lib/renderer/webgl.js +54 -9
  346. package/lib/renderer/webgl.js.map +1 -1
  347. package/lib/renderer/wgpuBindless.d.ts +26 -0
  348. package/lib/renderer/wgpuBindless.js +95 -0
  349. package/lib/renderer/wgpuBindless.js.map +1 -0
  350. package/lib/renderer/wgpuBindlessSource.d.ts +2 -0
  351. package/lib/renderer/wgpuBindlessSource.js +51 -0
  352. package/lib/renderer/wgpuBindlessSource.js.map +1 -0
  353. package/lib/renderer/wgpuMaterialConstants.d.ts +4 -0
  354. package/lib/renderer/wgpuMaterialConstants.js +52 -0
  355. package/lib/renderer/wgpuMaterialConstants.js.map +1 -0
  356. package/lib/renderer/wgpuSceneUniform.d.ts +42 -0
  357. package/lib/renderer/wgpuSceneUniform.js +125 -0
  358. package/lib/renderer/wgpuSceneUniform.js.map +1 -0
  359. package/lib/renderer/wgpuShaderSource.d.ts +15 -0
  360. package/lib/renderer/wgpuShaderSource.js +31 -0
  361. package/lib/renderer/wgpuShaderSource.js.map +1 -0
  362. package/lib/renderer/wgsl/aovDisplay.wgsl.d.ts +1 -0
  363. package/lib/renderer/wgsl/aovDisplay.wgsl.js +70 -0
  364. package/lib/renderer/wgsl/aovDisplay.wgsl.js.map +1 -0
  365. package/lib/renderer/wgsl/aovReflectance.wgsl.d.ts +2 -0
  366. package/lib/renderer/wgsl/aovReflectance.wgsl.js +98 -0
  367. package/lib/renderer/wgsl/aovReflectance.wgsl.js.map +1 -0
  368. package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.d.ts +2 -0
  369. package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.js +135 -0
  370. package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.js.map +1 -0
  371. package/lib/renderer/wgsl/aovResolve.wgsl.d.ts +5 -0
  372. package/lib/renderer/wgsl/aovResolve.wgsl.js +38 -0
  373. package/lib/renderer/wgsl/aovResolve.wgsl.js.map +1 -0
  374. package/lib/renderer/wgsl/aovSnapshot.wgsl.d.ts +4 -0
  375. package/lib/renderer/wgsl/aovSnapshot.wgsl.js +21 -0
  376. package/lib/renderer/wgsl/aovSnapshot.wgsl.js.map +1 -0
  377. package/lib/renderer/wgsl/aovTrace.wgsl.d.ts +2 -0
  378. package/lib/renderer/wgsl/aovTrace.wgsl.js +115 -0
  379. package/lib/renderer/wgsl/aovTrace.wgsl.js.map +1 -0
  380. package/lib/renderer/wgsl/bloom.wgsl.d.ts +13 -0
  381. package/lib/renderer/wgsl/bloom.wgsl.js +92 -0
  382. package/lib/renderer/wgsl/bloom.wgsl.js.map +1 -0
  383. package/lib/renderer/wgsl/chunks/common.wgsl.js +4 -4
  384. package/lib/renderer/wgsl/chunks/envMap.wgsl.d.ts +1 -1
  385. package/lib/renderer/wgsl/chunks/envMap.wgsl.js +43 -37
  386. package/lib/renderer/wgsl/chunks/envMap.wgsl.js.map +1 -1
  387. package/lib/renderer/wgsl/chunks/intersect.wgsl.d.ts +13 -1
  388. package/lib/renderer/wgsl/chunks/intersect.wgsl.js +743 -706
  389. package/lib/renderer/wgsl/chunks/intersect.wgsl.js.map +1 -1
  390. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js +16 -16
  391. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js.map +1 -1
  392. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.d.ts +3 -1
  393. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js +86 -83
  394. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js.map +1 -1
  395. package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js +855 -857
  396. package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js.map +1 -1
  397. package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js +139 -139
  398. package/lib/renderer/wgsl/chunks/rand.wgsl.js +3 -3
  399. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.d.ts +2 -1
  400. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js +42 -32
  401. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js.map +1 -1
  402. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.d.ts +1 -1
  403. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js +152 -148
  404. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js.map +1 -1
  405. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js +239 -232
  406. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js.map +1 -1
  407. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.d.ts +1 -1
  408. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js +26 -13
  409. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js.map +1 -1
  410. package/lib/renderer/wgsl/chunks/sampling.wgsl.js +91 -91
  411. package/lib/renderer/wgsl/chunks/shadowCatcherAccumulation.wgsl.d.ts +1 -1
  412. package/lib/renderer/wgsl/chunks/shadowCatcherAccumulation.wgsl.js +1 -0
  413. package/lib/renderer/wgsl/chunks/shadowCatcherAccumulation.wgsl.js.map +1 -1
  414. package/lib/renderer/wgsl/chunks/sobol.wgsl.js +83 -83
  415. package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js +12 -12
  416. package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js.map +1 -1
  417. package/lib/renderer/wgsl/compose.frag.wgsl.d.ts +8 -3
  418. package/lib/renderer/wgsl/compose.frag.wgsl.js +143 -118
  419. package/lib/renderer/wgsl/compose.frag.wgsl.js.map +1 -1
  420. package/lib/renderer/wgsl/customDenoise.wgsl.js +10 -10
  421. package/lib/renderer/wgsl/depthQuery.wgsl.js +7 -7
  422. package/lib/renderer/wgsl/jnlm.compute.d.ts +25 -0
  423. package/lib/renderer/wgsl/jnlm.compute.js +315 -0
  424. package/lib/renderer/wgsl/jnlm.compute.js.map +1 -0
  425. package/lib/renderer/wgsl/offlineAdaptive.compute.js +28 -28
  426. package/lib/renderer/wgsl/oidnAuxiliary.wgsl.d.ts +1 -0
  427. package/lib/renderer/wgsl/oidnAuxiliary.wgsl.js +17 -0
  428. package/lib/renderer/wgsl/oidnAuxiliary.wgsl.js.map +1 -0
  429. package/lib/renderer/wgsl/proceduralSky.compute.d.ts +1 -0
  430. package/lib/renderer/wgsl/proceduralSky.compute.js +198 -0
  431. package/lib/renderer/wgsl/proceduralSky.compute.js.map +1 -0
  432. package/lib/renderer/wgsl/rayTrace.compute.d.ts +17 -1
  433. package/lib/renderer/wgsl/rayTrace.compute.js +612 -393
  434. package/lib/renderer/wgsl/rayTrace.compute.js.map +1 -1
  435. package/lib/scene/Camera.js +7 -3
  436. package/lib/scene/Camera.js.map +1 -1
  437. package/lib/scene/EnvironmentLight.d.ts +5 -9
  438. package/lib/scene/EnvironmentLight.js +4 -14
  439. package/lib/scene/EnvironmentLight.js.map +1 -1
  440. package/lib/scene/EnvironmentLightState.d.ts +18 -0
  441. package/lib/scene/EnvironmentLightState.js +19 -0
  442. package/lib/scene/EnvironmentLightState.js.map +1 -0
  443. package/lib/scene/Geometry.d.ts +12 -6
  444. package/lib/scene/Geometry.js +37 -13
  445. package/lib/scene/Geometry.js.map +1 -1
  446. package/lib/scene/InstanceState.d.ts +39 -0
  447. package/lib/scene/InstanceState.js +77 -0
  448. package/lib/scene/InstanceState.js.map +1 -0
  449. package/lib/scene/InstancedMesh.d.ts +1 -1
  450. package/lib/scene/InstancedMesh.js +3 -0
  451. package/lib/scene/InstancedMesh.js.map +1 -1
  452. package/lib/scene/MaterialState.d.ts +209 -0
  453. package/lib/scene/MaterialState.js +231 -0
  454. package/lib/scene/MaterialState.js.map +1 -0
  455. package/lib/scene/Mesh.d.ts +4 -6
  456. package/lib/scene/Mesh.js +3 -11
  457. package/lib/scene/Mesh.js.map +1 -1
  458. package/lib/scene/MeshState.d.ts +20 -0
  459. package/lib/scene/MeshState.js +35 -0
  460. package/lib/scene/MeshState.js.map +1 -0
  461. package/lib/scene/OpenPBRMaterial.d.ts +7 -169
  462. package/lib/scene/OpenPBRMaterial.js +5 -223
  463. package/lib/scene/OpenPBRMaterial.js.map +1 -1
  464. package/lib/scene/PixelTexture.d.ts +6 -0
  465. package/lib/scene/PixelTexture.js +10 -0
  466. package/lib/scene/PixelTexture.js.map +1 -0
  467. package/lib/scene/ProceduralSky.d.ts +24 -0
  468. package/lib/scene/ProceduralSky.js +40 -0
  469. package/lib/scene/ProceduralSky.js.map +1 -0
  470. package/lib/scene/RectLight.d.ts +2 -13
  471. package/lib/scene/RectLight.js +3 -21
  472. package/lib/scene/RectLight.js.map +1 -1
  473. package/lib/scene/RectLightState.d.ts +31 -0
  474. package/lib/scene/RectLightState.js +26 -0
  475. package/lib/scene/RectLightState.js.map +1 -0
  476. package/lib/scene/Scene.d.ts +15 -4
  477. package/lib/scene/Scene.js.map +1 -1
  478. package/lib/scene/SceneNode.js +7 -6
  479. package/lib/scene/SceneNode.js.map +1 -1
  480. package/lib/scene/Texture.d.ts +10 -41
  481. package/lib/scene/Texture.js +4 -33
  482. package/lib/scene/Texture.js.map +1 -1
  483. package/lib/scene/TextureState.d.ts +35 -0
  484. package/lib/scene/TextureState.js +35 -0
  485. package/lib/scene/TextureState.js.map +1 -0
  486. package/lib/scene/attributeData.d.ts +4 -0
  487. package/lib/scene/attributeData.js +10 -0
  488. package/lib/scene/attributeData.js.map +1 -0
  489. package/lib/scene/lightState.d.ts +8 -0
  490. package/lib/scene/lightState.js +2 -0
  491. package/lib/scene/lightState.js.map +1 -0
  492. package/lib/scene/openPbrSchema.d.ts +7 -12
  493. package/lib/scene/openPbrSchema.js +273 -28
  494. package/lib/scene/openPbrSchema.js.map +1 -1
  495. package/lib/scene/skyParameters.d.ts +20 -0
  496. package/lib/scene/skyParameters.js +28 -0
  497. package/lib/scene/skyParameters.js.map +1 -0
  498. package/lib/scene/textureData.d.ts +9 -0
  499. package/lib/scene/textureData.js +2 -0
  500. package/lib/scene/textureData.js.map +1 -0
  501. package/lib/scene/texturePixels.d.ts +6 -0
  502. package/lib/scene/texturePixels.js +10 -0
  503. package/lib/scene/texturePixels.js.map +1 -0
  504. package/lib/settings/display.d.ts +33 -0
  505. package/lib/settings/display.js +7 -0
  506. package/lib/settings/display.js.map +1 -1
  507. package/lib/settings/render.d.ts +25 -3
  508. package/lib/settings/render.js +3 -1
  509. package/lib/settings/render.js.map +1 -1
  510. package/lib/tinybvh/tinybvh.wasm +0 -0
  511. package/lib/util/commonGeometry.js +7 -7
  512. package/lib/util/commonGeometry.js.map +1 -1
  513. package/lib/util/fromTHREE.d.ts +4 -1
  514. package/lib/util/fromTHREE.js +18 -5
  515. package/lib/util/fromTHREE.js.map +1 -1
  516. package/lib/util/geometry.js +42 -29
  517. package/lib/util/geometry.js.map +1 -1
  518. package/lib/util/loadRGBE.js +3 -4
  519. package/lib/util/loadRGBE.js.map +1 -1
  520. package/lib/util/studioLighting.d.ts +18 -0
  521. package/lib/util/studioLighting.js +36 -0
  522. package/lib/util/studioLighting.js.map +1 -0
  523. package/lib/version.d.ts +1 -1
  524. package/lib/version.js +1 -1
  525. package/lib/version.js.map +1 -1
  526. package/llms.txt +4 -0
  527. package/package.json +31 -5
  528. package/lib/renderer/texturesFromMaterials.d.ts +0 -6
  529. package/lib/renderer/texturesFromMaterials.js.map +0 -1
package/docs/threejs.md CHANGED
@@ -45,6 +45,10 @@ For an application-owned animation frame, update the animation mixer first,
45
45
  then call `loop.tick()`. With first-layer frame control, call `sync.update()`,
46
46
  `engine.update()`, `render.refine()` and `engine.display.present(render)` in order.
47
47
 
48
+ For a library-generated sky, pass `environment: new ProceduralSky()` in the
49
+ conversion or sync options. See [ProceduralSky](./api.md#proceduralsky) for
50
+ configuration and backend limits.
51
+
48
52
  ## What is converted
49
53
 
50
54
  | Three.js | MuTracer |
@@ -69,7 +73,7 @@ then call `loop.tick()`. With first-layer frame control, call `sync.update()`,
69
73
  | `RectAreaLight` | `RectLight` |
70
74
  | `AmbientLight` | `AmbientLight` |
71
75
  | `scene.environment` (equirectangular float `DataTexture`, e.g. from `HDRLoader`/`RGBELoader`) | `EnvironmentLight`; orientation follows Three.js, so a `DataTexture` with `flipY = false` has its first row at the bottom |
72
- | `scene.background` color / texture | Background; the environment itself when `background === environment` |
76
+ | `scene.background` color / texture | Explicit background, independent of environment lighting |
73
77
 
74
78
  Three.js `opacity` maps to `geometryOpacity`; thin-shell choices map to
75
79
  `geometryThinWalled`. Metadata accepts the five [canonical and compatibility
@@ -95,10 +99,15 @@ Material textures preserve independent `wrapS` and `wrapT`: repeat,
95
99
  clamp-to-edge and mirrored repeat. UV repeat and offset apply before wrapping;
96
100
  later wrap edits synchronize automatically. Displacement uses the same modes.
97
101
 
98
- `scene.environmentIntensity` controls environment lighting, including zero;
99
- `scene.environmentRotation` rotates it using the source Euler order. Both
100
- synchronize automatically. They do not change ambient lights or an explicitly
101
- assigned `scene.background` texture.
102
+ `scene.environmentIntensity` scales environment lighting (`0` disables it);
103
+ ambient lights and explicit backgrounds keep their own brightness.
104
+ `scene.backgroundIntensity` scales an explicit texture background; colors are
105
+ unaffected. `scene.environmentRotation` and `scene.backgroundRotation`
106
+ independently rotate environment lighting and explicit texture backgrounds. All
107
+ of these synchronize automatically; rotations preserve Euler order. An unset
108
+ background follows the environment. `mutracerGroundedSkybox` uses only its own
109
+ `rotation` (default `0`) and `intensity` (default `1`), ignoring
110
+ `scene.backgroundRotation` and `scene.backgroundIntensity`.
102
111
 
103
112
  Thin-film ranges keep their endpoint order, including minimum greater than
104
113
  maximum, and retain the converter's 0–20 µm endpoint clamp. The converter uses
@@ -108,12 +117,12 @@ or a source `THREE.Texture`. `THREESync` converts parameter edits without
108
117
  rewriting texture pixels. The iridescence strength texture is not supported;
109
118
  `thinFilmMap` represents thickness only.
110
119
 
111
- The six layer maps reuse the texture conversion cache, source UV channel,
112
- scale, offset and flipY. `mutracerOpenPBR` can override them with a MuTracer
120
+ The six layer maps preserve the source UV channel, scale, offset and `flipY`.
121
+ `mutracerOpenPBR` can override them with a MuTracer
113
122
  `Texture` or `THREE.Texture`; explicit `null` clears an imported map, while
114
- unknown JSON objects are ignored. `THREESync` follows texture edits without
115
- copying pixels. General `KHR_texture_transform` rotation remains unsupported.
116
- Clearcoat normals are deferred to the independent coat-frame implementation.
123
+ unknown JSON objects are ignored. `THREESync` follows texture edits.
124
+ General `KHR_texture_transform` rotation remains unsupported.
125
+ See [coat normal conversion](#coat-normal-conversion) for clearcoat normal maps.
117
126
  Anisotropy direction and source-model mapping are described [below](#anisotropy-source-conversion). The conversion preserves OpenPBR layering: glTF sheen
118
127
  layer order differs, and specular weight/color also affect metals in OpenPBR;
119
128
  these imports do not imply identical glTF BRDFs. A fully metallic material
package/docs/updates.md CHANGED
@@ -114,10 +114,52 @@ The notification range is validated.
114
114
  ## Materials, textures and lights
115
115
 
116
116
  Material parameter edits repack material parameters without touching geometry
117
- or BVHs. Emission edits also refresh light-sampling state, and texture edits
118
- rebuild the texture atlas. Displacement settings that move geometry require a
117
+ or BVHs. Emission edits also refresh light-sampling state. With atlas bindings,
118
+ texture edits rebuild the texture atlas. With [bindless bindings](./api.md#texture-bindings),
119
+ UV assignments, wrap and color-space edits update sampling metadata, while pixel edits
120
+ upload the changed images. Dimension, budget or shared storage-precision changes
121
+ can require more images to be uploaded. `Texture.markUpdated()` invalidates image
122
+ pixels as well as in-place UV edits. Displacement settings that move geometry require a
119
123
  [full mesh update](#full-mesh-updates).
120
124
 
125
+ WebGPU can compile a new path-tracing shader for the following changes. Feature
126
+ presence is scene-wide: adding another material or light that uses an already
127
+ supported feature does not by itself need another variant.
128
+
129
+ Within compatible transport settings and data layouts, WebGPU retains prepared
130
+ material, texture and lighting support for later edits. Turning a feature off
131
+ and back on can reuse that support. The base shader supports diffuse, dielectric
132
+ and metal materials: changing `baseMetalness` between 0 and 1 does not itself
133
+ require another shader. Coat and fuzz are prepared together on the first use of
134
+ either: switching between them or combining them does not itself require another
135
+ shader. Transmission, thin film and subsurface are prepared as needed; dispersion
136
+ and other transport/layout changes below can still require compilation.
137
+
138
+ | Change | When a different shader variant is needed |
139
+ | --- | --- |
140
+ | Material, texture or lighting features | Newly required support is not covered by a prepared shader: coat/fuzz, thin film, subsurface, transmission, shadow catchers, a texture type, an analytic-light type, sampled emissive triangles or environment illumination |
141
+ | Transport and transparency | Enabling/disabling medium or dispersion support, changing whether any non-opaque material exists, or changing whether deterministic primary BLEND splitting is needed |
142
+ | Shading and geometry structure | Changing required UV/tangent/coat-normal frames, displacement or material-bevel support, vertex/BVH layouts or required traversal capacity |
143
+ | Render settings | Changing `samplingPattern`, `bevelSamples`, or `alphaBlendStrategy` while BLEND materials exist |
144
+ | Texture capacity | Atlas: increasing the texture count beyond the current capacity. Both modes: first use or last removal of UV1 texture sampling also changes the shader |
145
+
146
+ With `alphaMode: 'auto'`, opacity, cutoff or alpha-map edits can change the
147
+ resolved transparency mode. Texture edits can also enable independent coat-normal
148
+ or anisotropy frames. These count as structural changes above.
149
+
150
+ Within an unchanged feature/structure combination, colors, roughness, metalness,
151
+ existing layer weights, light transforms/intensity, texture pixels and camera/output size
152
+ do not recompile the path tracer. Neither do changes to `bounces`,
153
+ `directLightCandidates`, clamping, `dispersionWavelengths` (1 or 3), the render's
154
+ bevel switch, sample count or seed. Data uploads, atlas/BVH work and accumulation
155
+ restarts may still be needed.
156
+
157
+ Returning to a cached compatible combination reuses its pipeline. Prepared
158
+ combinations may be discarded after many different edits; recreating the Engine
159
+ or recovering a lost device also requires preparing shaders again. Compilation time depends
160
+ on the feature combination, BVH layout, browser and GPU driver. Denoising and
161
+ post-processing passes have their own shaders and initialization costs.
162
+
121
163
  Analytic-light edits keep the environment map. Ambient and environment edits
122
164
  rebuild it. Rect-light texture edits require a full mesh update, because those
123
165
  textures live in the material atlas.
package/docs/viewer.md CHANGED
@@ -1,4 +1,42 @@
1
- # Sharing viewer settings
1
+ # Using the viewer
2
+
3
+ Open **Examples → MuTracer collection** for models curated for this viewer, or
4
+ **Examples → glTF Research Scenes** for the independently maintained
5
+ [glTF Research Scenes](https://github.com/ErfanMo77/gltf-research-scenes) collection.
6
+ Scenes download on demand from GitHub; cards show approximate download sizes
7
+ and link to each scene's source and license. Large scenes need more memory.
8
+ glTF Research Scenes load with **Ground shadow** off; you can enable it in Lighting.
9
+
10
+ On desktop, choose **Pin to right panel** in Examples to keep the collection
11
+ open while loading models. **Unpin examples** returns it to the popover.
12
+ The pinned layout is saved in this browser.
13
+
14
+ glTF/GLB imports include directional, point and spot lights and emissive meshes.
15
+ Benchmark scenes also load their sunlight and available environment maps.
16
+ Under **Lighting → Environment**, **Scene lighting** is available only when the
17
+ model provides lights or environment lighting. Choose it to use the imported
18
+ lighting alone, or select an HDRI or Studio to add lighting. Emissive materials
19
+ still work with HDRI and Studio. Environment maps add download time and are
20
+ resampled to at most 2K width. If a source map is missing, the model still opens
21
+ and the Lighting panel explains which map is unavailable; choose an environment
22
+ there to replace it.
23
+
24
+ glTF Research Scenes automatically use their first camera when available.
25
+ For other glTF/GLB imports with cameras, a toast offers **Apply camera** to
26
+ use the first camera; dismiss it to keep the Orbit view. You can select any
27
+ imported camera in the separate camera toolbar at the bottom right; it appears
28
+ only for models with cameras. Drag, pan or zoom after selecting a camera to
29
+ continue in **Orbit** from that view.
30
+ Hover over a camera in the scene tree and click its camera action to apply it
31
+ directly. **Fit to model** in the bottom toolbar (or **F**) returns to Orbit
32
+ and frames the model.
33
+ Reloading the current model restores your saved camera selection without
34
+ showing the prompt again.
35
+
36
+ Picking an object in the viewport reveals it in the scene tree and scrolls it
37
+ into view. Material rows start collapsed; expand a mesh to see its materials.
38
+
39
+ ## Sharing viewer settings
2
40
 
3
41
  Add settings to a viewer link to override the recipient's saved preferences.
4
42
  For example, open the viewer with HDR output enabled:
@@ -17,7 +55,7 @@ The viewer updates the URL as lighting, render and display settings change.
17
55
  Copy the address bar to share those settings and the selected example model.
18
56
  Settings also work in the hash, such as `#model=dragon&hdrOutputEnabled=true`.
19
57
 
20
- ## Options
58
+ ### Options
21
59
 
22
60
  Parameter names match the viewer settings and are case-sensitive:
23
61
 
@@ -42,7 +80,7 @@ can override a recipient's different preference. When the viewer updates the
42
80
  address, settings move into the hash; unrelated query parameters, including
43
81
  `?webgl`, are preserved.
44
82
 
45
- ## Caveats
83
+ ### Caveats
46
84
 
47
85
  HDR output requires WebGPU, an HDR display and a compatible browser. Unsupported
48
86
  devices fall back to SDR. `?webgl` forces WebGL 2, which does not support HDR output.
package/lib/Display.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { type AovIdComponent } from './renderer/aovDisplay.js';
2
+ export type { AovIdComponent } from './renderer/aovDisplay.js';
1
3
  import type Render from './Render.js';
2
4
  import type { ToneMapping, DisplayChannel } from './renderer/RenderingPipeline.js';
3
5
  import type { ColorRGB } from './types.js';
@@ -21,7 +23,11 @@ export interface DisplaySettings {
21
23
  /** Bloom luminance threshold. Default 1. */ bloomThreshold?: number;
22
24
  /** Bloom radius in 0–1. Default 0.6. */ bloomRadius?: number;
23
25
  /** Extended-range WebGPU presentation, ignored on WebGL. Default false. */ hdrOutputEnabled?: boolean;
24
- /** Display image channel. Default final. */ channel?: DisplayChannel;
26
+ /** Display image channel. Default final. AOV channels require explicit Render.aovs. */ channel?: DisplayChannel;
27
+ /** Finite float32 scene-unit depths mapped to black/white; 0 <= near < far. Default [0, 10]. */ aovDepthRange?: readonly [number, number];
28
+ /** Finite positive float32 scene-unit half-range around the origin for position RGB. Default 1. */ aovPositionScale?: number;
29
+ /** Finite positive float32 input-pixel displacement mapped to full motion brightness. Default 16. */ aovMotionScale?: number;
30
+ /** Stable ID lane to colorize. Default object. */ aovIdComponent?: AovIdComponent;
25
31
  /** Linear shadow-catcher color. Default black. */ shadowCatcherColor?: ColorRGB;
26
32
  /** Shadow-catcher opacity multiplier. Default 1. */ shadowCatcherAlpha?: number;
27
33
  }
@@ -52,12 +58,17 @@ export default class Display {
52
58
  /** Bloom luminance threshold. Default 1. */ bloomThreshold: number;
53
59
  /** Bloom radius in 0–1. Default 0.6. */ bloomRadius: number;
54
60
  /** Extended-range WebGPU presentation, ignored on WebGL. Default false. */ hdrOutputEnabled: boolean;
55
- /** Display image channel. Default final. */ channel: DisplayChannel;
61
+ /** Display image channel. Default final. AOV channels require explicit Render.aovs. */ channel: DisplayChannel;
62
+ /** Finite float32 scene-unit depths mapped to black/white; 0 <= near < far. Default [0, 10]. */ aovDepthRange: readonly [number, number];
63
+ /** Finite positive float32 scene-unit half-range around the origin for position RGB. Default 1. */ aovPositionScale: number;
64
+ /** Finite positive float32 input-pixel displacement mapped to full motion brightness. Default 16. */ aovMotionScale: number;
65
+ /** Stable ID lane to colorize. Default object. */ aovIdComponent: AovIdComponent;
56
66
  /** Linear shadow-catcher color. Default black. */ shadowCatcherColor: ColorRGB;
57
67
  /** Shadow-catcher opacity multiplier. Default 1. */ shadowCatcherAlpha: number;
58
68
  private constructor();
59
69
  /** Resizes the drawing buffer; scale-based renders resize at their next refine. */
60
70
  setSize(width: number, height: number): void;
71
+ private readonly _filterSettings;
61
72
  private readonly settings;
62
73
  private readonly _postProcesses;
63
74
  private _warnedPostProcess;
package/lib/Display.js CHANGED
@@ -1,5 +1,6 @@
1
+ import { displayAovKind, validateAovDisplay } from './renderer/aovDisplay.js';
1
2
  import { createCanvas } from './util/canvas.js';
2
- import { displaySettingsKey, applyDisplaySettings } from './settings/display.js';
3
+ import { displaySettingsKey, displayFilterSettingsKey, applyDisplaySettings } from './settings/display.js';
3
4
  /** Canvas presentation and shared display settings; obtained from engine.display. */
4
5
  export default class Display {
5
6
  engine;
@@ -15,7 +16,11 @@ export default class Display {
15
16
  /** Bloom luminance threshold. Default 1. */ bloomThreshold = 1;
16
17
  /** Bloom radius in 0–1. Default 0.6. */ bloomRadius = 0.6;
17
18
  /** Extended-range WebGPU presentation, ignored on WebGL. Default false. */ hdrOutputEnabled = false;
18
- /** Display image channel. Default final. */ channel = 'final';
19
+ /** Display image channel. Default final. AOV channels require explicit Render.aovs. */ channel = 'final';
20
+ /** Finite float32 scene-unit depths mapped to black/white; 0 <= near < far. Default [0, 10]. */ aovDepthRange = [0, 10];
21
+ /** Finite positive float32 scene-unit half-range around the origin for position RGB. Default 1. */ aovPositionScale = 1;
22
+ /** Finite positive float32 input-pixel displacement mapped to full motion brightness. Default 16. */ aovMotionScale = 16;
23
+ /** Stable ID lane to colorize. Default object. */ aovIdComponent = 'object';
19
24
  /** Linear shadow-catcher color. Default black. */ shadowCatcherColor = [0, 0, 0];
20
25
  /** Shadow-catcher opacity multiplier. Default 1. */ shadowCatcherAlpha = 1;
21
26
  constructor(engine, canvas) {
@@ -34,6 +39,7 @@ export default class Display {
34
39
  if (this.canvas.height !== height)
35
40
  this.canvas.height = height;
36
41
  }
42
+ _filterSettings = new WeakMap();
37
43
  settings = new WeakMap();
38
44
  /** @internal */ _configure(render) {
39
45
  if (render._engine !== this.engine)
@@ -41,12 +47,20 @@ export default class Display {
41
47
  const target = render._output;
42
48
  if (!target)
43
49
  return;
50
+ const kind = displayAovKind(this.channel);
51
+ if (!kind && !['final', 'normal', 'albedo', 'shadow', 'shadowCatcher'].includes(this.channel))
52
+ throw new RangeError('Unknown display channel');
53
+ if (kind && !render.aovs.includes(kind))
54
+ throw new Error(`AOV ${kind} is not enabled on the selected render`);
55
+ validateAovDisplay({ depthRange: this.aovDepthRange, positionScale: this.aovPositionScale, motionScale: this.aovMotionScale, idComponent: this.aovIdComponent });
44
56
  const key = displaySettingsKey(this);
57
+ const filterKey = displayFilterSettingsKey(this);
45
58
  const previous = this.settings.get(render);
46
59
  if (previous !== key) {
47
60
  this.settings.set(render, key);
48
- if (previous !== undefined)
61
+ if (previous !== undefined && this._filterSettings.get(render) !== filterKey)
49
62
  render._displayChanged();
63
+ this._filterSettings.set(render, filterKey);
50
64
  }
51
65
  target.activate();
52
66
  applyDisplaySettings(this, target);
@@ -72,7 +86,14 @@ export default class Display {
72
86
  if (render._engine !== this.engine)
73
87
  throw new Error('Render belongs to another engine.');
74
88
  const target = render._output;
75
- if (!target?.presentationComplete)
89
+ if (!target)
90
+ return;
91
+ const kind = displayAovKind(this.channel);
92
+ if (!kind && !target.presentationComplete)
93
+ return;
94
+ if (kind && !render.aovs.includes(kind))
95
+ throw new Error(`AOV ${kind} is not enabled on the selected render`);
96
+ if (kind && target.aovReady && !target.aovReady(kind))
76
97
  return;
77
98
  this._configure(render);
78
99
  target.drawPostProcess();
@@ -90,9 +111,9 @@ export default class Display {
90
111
  present(render) {
91
112
  if (render._engine !== this.engine)
92
113
  throw new Error('Render belongs to another engine.');
93
- const ready = this.channel === 'final' && render.fallback ? render._presentable : render._complete;
114
+ const ready = this.channel === 'final' && render.fallback ? render._presentable : render._completeFor(this.channel);
94
115
  const fallback = render.fallback;
95
- const selected = ready ? render : fallback && (this.channel === 'final' ? fallback._presentable : fallback._complete) ? fallback : undefined;
116
+ const selected = ready ? render : fallback && (this.channel === 'final' ? fallback._presentable : fallback._completeFor(this.channel)) ? fallback : undefined;
96
117
  if (!selected)
97
118
  return;
98
119
  const target = this.compose(selected);
@@ -1 +1 @@
1
- {"version":3,"file":"Display.js","sourceRoot":"","sources":["../src/Display.ts"],"names":[],"mappings":"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","sourcesContent":["import {createCanvas} from './util/canvas.js';\nimport type Engine from './Engine.js';\nimport type Render from './Render.js';\nimport type { ToneMapping, DisplayChannel } from './renderer/RenderingPipeline.js';\nimport type { ColorRGB } from './types.js';\nimport { displaySettingsKey, applyDisplaySettings } from './settings/display.js';\n/** Display image channels. Default final. */\nexport type {DisplayChannel} from './renderer/RenderingPipeline.js';\n/** Image encoding options for Display.toBlob. */\nexport interface BlobOptions {\n /** Browser image MIME type. Default image/png. */ type?: string;\n /** Encoder quality in 0–1. Default undefined uses the browser default. */ quality?: number;\n}\n/** Optional shared display settings; defaults match Display. */\nexport interface DisplaySettings {\n /** Tone mapping transform. Default agx. */ toneMapping?: ToneMapping;\n /** Linear exposure multiplier. Default 1. */ toneMappingExposure?: number;\n /** Contrast multiplier. Default 1. */ contrast?: number;\n /** Saturation multiplier. Default 1. */ saturation?: number;\n /** White balance temperature shift in -1–1. Default 0. */ temperature?: number;\n /** Green/magenta tint in -1–1. Default 0. */ tint?: number;\n /** Vignette strength in 0–1. Default 0. */ vignette?: number;\n /** Bloom intensity; 0 disables it. Default 0. */ bloomIntensity?: number;\n /** Bloom luminance threshold. Default 1. */ bloomThreshold?: number;\n /** Bloom radius in 0–1. Default 0.6. */ bloomRadius?: number;\n /** Extended-range WebGPU presentation, ignored on WebGL. Default false. */ hdrOutputEnabled?: boolean;\n /** Display image channel. Default final. */ channel?: DisplayChannel;\n /** Linear shadow-catcher color. Default black. */ shadowCatcherColor?: ColorRGB;\n /** Shadow-catcher opacity multiplier. Default 1. */ shadowCatcherAlpha?: number;\n}\n/** Borrowed WebGPU images for one synchronous display pass. */\nexport interface PostProcessContext {\n /** Engine device; may change after recovery. */ device: GPUDevice;\n /** Record commands here; the library finishes and submits it. */ encoder: GPUCommandEncoder;\n /** Read-only composed display image, top row first; no additional color conversion. */ input: GPUTexture;\n /** Fully write this image. Same format and dimensions as input; supports render, storage and copy writes. */ output: GPUTexture;\n /** Actual render width. */ width: number;\n /** Actual render height. */ height: number;\n /** Selected complete render, including a selected fallback. */ render: Render;\n}\n/** Synchronous display pass. Images and encoder are borrowed only during the call; do not retain or destroy them. */\nexport type PostProcess = (context: PostProcessContext) => void;\n/** Canvas presentation and shared display settings; obtained from engine.display. */\nexport default class Display {\n /** Display canvas. Default the supplied Engine canvas, or a new canvas (OffscreenCanvas without document). */ readonly canvas: HTMLCanvasElement | OffscreenCanvas;\n /** Tone mapping transform. Default agx. */ toneMapping: ToneMapping = 'agx';\n /** Linear exposure multiplier. Default 1. */ toneMappingExposure = 1;\n /** Contrast multiplier. Default 1. */ contrast = 1;\n /** Saturation multiplier. Default 1. */ saturation = 1;\n /** White balance temperature shift in -1–1. Default 0. */ temperature = 0;\n /** Green/magenta tint in -1–1. Default 0. */ tint = 0;\n /** Vignette strength in 0–1. Default 0. */ vignette = 0;\n /** Bloom intensity; 0 disables it. Default 0. */ bloomIntensity = 0;\n /** Bloom luminance threshold. Default 1. */ bloomThreshold = 1;\n /** Bloom radius in 0–1. Default 0.6. */ bloomRadius = 0.6;\n /** Extended-range WebGPU presentation, ignored on WebGL. Default false. */ hdrOutputEnabled = false;\n /** Display image channel. Default final. */ channel: DisplayChannel = 'final';\n /** Linear shadow-catcher color. Default black. */ shadowCatcherColor: ColorRGB = [0, 0, 0];\n /** Shadow-catcher opacity multiplier. Default 1. */ shadowCatcherAlpha = 1;\n private constructor(private readonly engine: Engine, canvas: HTMLCanvasElement | OffscreenCanvas) { this.canvas = canvas; }\n /** @internal */ static _create(engine: Engine, canvas: HTMLCanvasElement | OffscreenCanvas) { return new Display(engine, canvas); }\n /** Resizes the drawing buffer; scale-based renders resize at their next refine. */\n setSize(width: number, height: number) {\n if (!Number.isFinite(width) || !Number.isFinite(height) || width < 1 || height < 1) throw new Error('Display dimensions must be positive.');\n width = Math.round(width); height = Math.round(height);\n if (this.canvas.width !== width) this.canvas.width = width;\n if (this.canvas.height !== height) this.canvas.height = height;\n }\n private readonly settings = new WeakMap<Render, string>();\n /** @internal */ _configure(render: Render) {\n if (render._engine !== this.engine) throw new Error('Render belongs to another engine.');\n const target = render._output;\n if (!target) return;\n const key = displaySettingsKey(this);\n const previous = this.settings.get(render);\n if (previous !== key) {\n this.settings.set(render, key);\n if (previous !== undefined) render._displayChanged();\n }\n target.activate();\n applyDisplaySettings(this, target);\n }\n private readonly _postProcesses: {pass: PostProcess}[] = [];\n private _warnedPostProcess = false;\n /** Registers a display pass in order and returns an idempotent removal function. Default no passes. WebGPU only; WebGL skips passes with one warning. Runs after composition on every present/toBlob, without tracing or invalidating denoising. A thrown error discards the whole chain, presents the original image and emits engine error. */\n addPostProcess(pass: PostProcess): () => void {\n const entry = {pass};\n this._postProcesses.push(entry);\n if (this.engine.backend === 'webgl') this.warnPostProcess();\n return () => { const index = this._postProcesses.indexOf(entry); if (index >= 0) this._postProcesses.splice(index, 1); };\n }\n private warnPostProcess() {\n if (!this._warnedPostProcess) { this._warnedPostProcess = true; console.warn('Display post-processing requires WebGPU; passes are ignored on WebGL.'); }\n }\n private compose(render: Render) {\n if (render._engine !== this.engine) throw new Error('Render belongs to another engine.');\n const target = render._output;\n if (!target?.presentationComplete) return;\n this._configure(render);\n target.drawPostProcess();\n if (this._postProcesses.length && this.engine.backend === 'webgl') this.warnPostProcess();\n try { target.applyPostProcesses?.(this._postProcesses.map(entry => entry.pass), render); }\n catch (error) { this.engine._notifyError(error); }\n return target;\n }\n /** Presents a complete image or fallback. Keeps fallback visible until the first intermediate filter finishes. Does not trace. */\n present(render: Render): Render | undefined {\n if (render._engine !== this.engine) throw new Error('Render belongs to another engine.');\n const ready = this.channel === 'final' && render.fallback ? render._presentable : render._complete;\n const fallback = render.fallback;\n const selected = ready ? render : fallback && (this.channel === 'final' ? fallback._presentable : fallback._complete) ? fallback : undefined;\n if (!selected) return;\n const target = this.compose(selected);\n if (!target) return;\n this.engine._present(target);\n return selected;\n }\n /** Encodes this render at its actual dimensions using these settings; leaves the display canvas unchanged. */\n async toBlob(render: Render, options: BlobOptions = {}): Promise<Blob> {\n const target = this.compose(render);\n if (!target) throw new Error('Render has no complete image.');\n const image = await target.readPresentation();\n const canvas = createCanvas(image.width, image.height, 'convertToBlob' in this.canvas);\n const context = canvas.getContext('2d') as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null;\n if (!context) throw new Error('The image encoding context is not available.');\n const bytes = new Uint8ClampedArray(image.data.length);\n for (let i = 0; i < bytes.length; i++) bytes[i] = Math.round(Math.min(1, Math.max(0, image.data[i])) * 255);\n context.putImageData(new ImageData(bytes, image.width, image.height), 0, 0);\n if ('convertToBlob' in canvas) return canvas.convertToBlob({type: options.type ?? 'image/png', quality: options.quality});\n return new Promise((resolve, reject) => canvas.toBlob(blob => blob ? resolve(blob) : reject(new Error('The image could not be encoded')), options.type ?? 'image/png', options.quality));\n }\n}\n"]}
1
+ {"version":3,"file":"Display.js","sourceRoot":"","sources":["../src/Display.ts"],"names":[],"mappings":"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","sourcesContent":["import {displayAovKind, validateAovDisplay, type AovIdComponent} from './renderer/aovDisplay.js';\nexport type {AovIdComponent} from './renderer/aovDisplay.js';\nimport {createCanvas} from './util/canvas.js';\nimport type Engine from './Engine.js';\nimport type Render from './Render.js';\nimport type { ToneMapping, DisplayChannel } from './renderer/RenderingPipeline.js';\nimport type { ColorRGB } from './types.js';\nimport { displaySettingsKey, displayFilterSettingsKey, applyDisplaySettings } from './settings/display.js';\n/** Display image channels. Default final. */\nexport type {DisplayChannel} from './renderer/RenderingPipeline.js';\n/** Image encoding options for Display.toBlob. */\nexport interface BlobOptions {\n /** Browser image MIME type. Default image/png. */ type?: string;\n /** Encoder quality in 0–1. Default undefined uses the browser default. */ quality?: number;\n}\n/** Optional shared display settings; defaults match Display. */\nexport interface DisplaySettings {\n /** Tone mapping transform. Default agx. */ toneMapping?: ToneMapping;\n /** Linear exposure multiplier. Default 1. */ toneMappingExposure?: number;\n /** Contrast multiplier. Default 1. */ contrast?: number;\n /** Saturation multiplier. Default 1. */ saturation?: number;\n /** White balance temperature shift in -1–1. Default 0. */ temperature?: number;\n /** Green/magenta tint in -1–1. Default 0. */ tint?: number;\n /** Vignette strength in 0–1. Default 0. */ vignette?: number;\n /** Bloom intensity; 0 disables it. Default 0. */ bloomIntensity?: number;\n /** Bloom luminance threshold. Default 1. */ bloomThreshold?: number;\n /** Bloom radius in 0–1. Default 0.6. */ bloomRadius?: number;\n /** Extended-range WebGPU presentation, ignored on WebGL. Default false. */ hdrOutputEnabled?: boolean;\n /** Display image channel. Default final. AOV channels require explicit Render.aovs. */ channel?: DisplayChannel;\n /** Finite float32 scene-unit depths mapped to black/white; 0 <= near < far. Default [0, 10]. */ aovDepthRange?: readonly [number, number];\n /** Finite positive float32 scene-unit half-range around the origin for position RGB. Default 1. */ aovPositionScale?: number;\n /** Finite positive float32 input-pixel displacement mapped to full motion brightness. Default 16. */ aovMotionScale?: number;\n /** Stable ID lane to colorize. Default object. */ aovIdComponent?: AovIdComponent;\n /** Linear shadow-catcher color. Default black. */ shadowCatcherColor?: ColorRGB;\n /** Shadow-catcher opacity multiplier. Default 1. */ shadowCatcherAlpha?: number;\n}\n/** Borrowed WebGPU images for one synchronous display pass. */\nexport interface PostProcessContext {\n /** Engine device; may change after recovery. */ device: GPUDevice;\n /** Record commands here; the library finishes and submits it. */ encoder: GPUCommandEncoder;\n /** Read-only composed display image, top row first; no additional color conversion. */ input: GPUTexture;\n /** Fully write this image. Same format and dimensions as input; supports render, storage and copy writes. */ output: GPUTexture;\n /** Actual render width. */ width: number;\n /** Actual render height. */ height: number;\n /** Selected complete render, including a selected fallback. */ render: Render;\n}\n/** Synchronous display pass. Images and encoder are borrowed only during the call; do not retain or destroy them. */\nexport type PostProcess = (context: PostProcessContext) => void;\n/** Canvas presentation and shared display settings; obtained from engine.display. */\nexport default class Display {\n /** Display canvas. Default the supplied Engine canvas, or a new canvas (OffscreenCanvas without document). */ readonly canvas: HTMLCanvasElement | OffscreenCanvas;\n /** Tone mapping transform. Default agx. */ toneMapping: ToneMapping = 'agx';\n /** Linear exposure multiplier. Default 1. */ toneMappingExposure = 1;\n /** Contrast multiplier. Default 1. */ contrast = 1;\n /** Saturation multiplier. Default 1. */ saturation = 1;\n /** White balance temperature shift in -1–1. Default 0. */ temperature = 0;\n /** Green/magenta tint in -1–1. Default 0. */ tint = 0;\n /** Vignette strength in 0–1. Default 0. */ vignette = 0;\n /** Bloom intensity; 0 disables it. Default 0. */ bloomIntensity = 0;\n /** Bloom luminance threshold. Default 1. */ bloomThreshold = 1;\n /** Bloom radius in 0–1. Default 0.6. */ bloomRadius = 0.6;\n /** Extended-range WebGPU presentation, ignored on WebGL. Default false. */ hdrOutputEnabled = false;\n /** Display image channel. Default final. AOV channels require explicit Render.aovs. */ channel: DisplayChannel = 'final';\n /** Finite float32 scene-unit depths mapped to black/white; 0 <= near < far. Default [0, 10]. */ aovDepthRange: readonly [number, number] = [0, 10];\n /** Finite positive float32 scene-unit half-range around the origin for position RGB. Default 1. */ aovPositionScale = 1;\n /** Finite positive float32 input-pixel displacement mapped to full motion brightness. Default 16. */ aovMotionScale = 16;\n /** Stable ID lane to colorize. Default object. */ aovIdComponent: AovIdComponent = 'object';\n /** Linear shadow-catcher color. Default black. */ shadowCatcherColor: ColorRGB = [0, 0, 0];\n /** Shadow-catcher opacity multiplier. Default 1. */ shadowCatcherAlpha = 1;\n private constructor(private readonly engine: Engine, canvas: HTMLCanvasElement | OffscreenCanvas) { this.canvas = canvas; }\n /** @internal */ static _create(engine: Engine, canvas: HTMLCanvasElement | OffscreenCanvas) { return new Display(engine, canvas); }\n /** Resizes the drawing buffer; scale-based renders resize at their next refine. */\n setSize(width: number, height: number) {\n if (!Number.isFinite(width) || !Number.isFinite(height) || width < 1 || height < 1) throw new Error('Display dimensions must be positive.');\n width = Math.round(width); height = Math.round(height);\n if (this.canvas.width !== width) this.canvas.width = width;\n if (this.canvas.height !== height) this.canvas.height = height;\n }\n private readonly _filterSettings = new WeakMap<Render, string>();\n private readonly settings = new WeakMap<Render, string>();\n /** @internal */ _configure(render: Render) {\n if (render._engine !== this.engine) throw new Error('Render belongs to another engine.');\n const target = render._output;\n if (!target) return;\n const kind = displayAovKind(this.channel);\n if (!kind && !['final','normal','albedo','shadow','shadowCatcher'].includes(this.channel)) throw new RangeError('Unknown display channel');\n if (kind && !render.aovs.includes(kind)) throw new Error(`AOV ${kind} is not enabled on the selected render`);\n validateAovDisplay({depthRange: this.aovDepthRange, positionScale: this.aovPositionScale, motionScale: this.aovMotionScale, idComponent: this.aovIdComponent});\n const key = displaySettingsKey(this);\n const filterKey = displayFilterSettingsKey(this);\n const previous = this.settings.get(render);\n if (previous !== key) {\n this.settings.set(render, key);\n if (previous !== undefined && this._filterSettings.get(render) !== filterKey) render._displayChanged();\n this._filterSettings.set(render, filterKey);\n }\n target.activate();\n applyDisplaySettings(this, target);\n }\n private readonly _postProcesses: {pass: PostProcess}[] = [];\n private _warnedPostProcess = false;\n /** Registers a display pass in order and returns an idempotent removal function. Default no passes. WebGPU only; WebGL skips passes with one warning. Runs after composition on every present/toBlob, without tracing or invalidating denoising. A thrown error discards the whole chain, presents the original image and emits engine error. */\n addPostProcess(pass: PostProcess): () => void {\n const entry = {pass};\n this._postProcesses.push(entry);\n if (this.engine.backend === 'webgl') this.warnPostProcess();\n return () => { const index = this._postProcesses.indexOf(entry); if (index >= 0) this._postProcesses.splice(index, 1); };\n }\n private warnPostProcess() {\n if (!this._warnedPostProcess) { this._warnedPostProcess = true; console.warn('Display post-processing requires WebGPU; passes are ignored on WebGL.'); }\n }\n private compose(render: Render) {\n if (render._engine !== this.engine) throw new Error('Render belongs to another engine.');\n const target = render._output;\n if (!target) return;\n const kind = displayAovKind(this.channel);\n if (!kind && !target.presentationComplete) return;\n if (kind && !render.aovs.includes(kind)) throw new Error(`AOV ${kind} is not enabled on the selected render`);\n if (kind && target.aovReady && !target.aovReady(kind)) return;\n this._configure(render);\n target.drawPostProcess();\n if (this._postProcesses.length && this.engine.backend === 'webgl') this.warnPostProcess();\n try { target.applyPostProcesses?.(this._postProcesses.map(entry => entry.pass), render); }\n catch (error) { this.engine._notifyError(error); }\n return target;\n }\n /** Presents a complete image or fallback. Keeps fallback visible until the first intermediate filter finishes. Does not trace. */\n present(render: Render): Render | undefined {\n if (render._engine !== this.engine) throw new Error('Render belongs to another engine.');\n const ready = this.channel === 'final' && render.fallback ? render._presentable : render._completeFor(this.channel);\n const fallback = render.fallback;\n const selected = ready ? render : fallback && (this.channel === 'final' ? fallback._presentable : fallback._completeFor(this.channel)) ? fallback : undefined;\n if (!selected) return;\n const target = this.compose(selected);\n if (!target) return;\n this.engine._present(target);\n return selected;\n }\n /** Encodes this render at its actual dimensions using these settings; leaves the display canvas unchanged. */\n async toBlob(render: Render, options: BlobOptions = {}): Promise<Blob> {\n const target = this.compose(render);\n if (!target) throw new Error('Render has no complete image.');\n const image = await target.readPresentation();\n const canvas = createCanvas(image.width, image.height, 'convertToBlob' in this.canvas);\n const context = canvas.getContext('2d') as CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D | null;\n if (!context) throw new Error('The image encoding context is not available.');\n const bytes = new Uint8ClampedArray(image.data.length);\n for (let i = 0; i < bytes.length; i++) bytes[i] = Math.round(Math.min(1, Math.max(0, image.data[i])) * 255);\n context.putImageData(new ImageData(bytes, image.width, image.height), 0, 0);\n if ('convertToBlob' in canvas) return canvas.convertToBlob({type: options.type ?? 'image/png', quality: options.quality});\n return new Promise((resolve, reject) => canvas.toBlob(blob => blob ? resolve(blob) : reject(new Error('The image could not be encoded')), options.type ?? 'image/png', options.quality));\n }\n}\n"]}
package/lib/Engine.d.ts CHANGED
@@ -17,6 +17,7 @@ export interface EngineParams {
17
17
  /** Default display canvas. Default a new HTML canvas, or OffscreenCanvas without document. */ canvas?: HTMLCanvasElement | OffscreenCanvas;
18
18
  /** Backend selection. Default auto, with WebGL fallback. webgpu requires WebGPU. */ backend?: 'auto' | 'webgpu' | 'webgl';
19
19
  /** Caller-owned WebGPU device. Default undefined uses a shared device. Implies webgpu; incompatible with webgl. */ device?: GPUDevice;
20
+ /** Material texture bindings. Default atlas; auto tries WebGPU bindless textures and falls back to atlas when unavailable. Fixed at construction. */ textureBinding?: 'atlas' | 'auto';
20
21
  }
21
22
  /** Material-atlas device limits. */
22
23
  export interface TextureAtlasLimits {
@@ -89,6 +90,7 @@ export default class Engine {
89
90
  private _contextRestore?;
90
91
  private _gpuAdapterInfo?;
91
92
  private _backendChoice;
93
+ private readonly _textureBinding;
92
94
  private _initPromise?;
93
95
  private _info?;
94
96
  private _pipelineInitError?;
package/lib/Engine.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { bvhConfig, engineSettingsKey, workerCount, textureBudget } from './settings/engine.js';
2
2
  import { createCanvas } from './util/canvas.js';
3
3
  import { getRecommendedDeviceDescriptor, validateDevice } from './renderer/deviceRequirements.js';
4
+ import { probeBindless, resourceTableFeature } from './renderer/wgpuBindless.js';
4
5
  import { cameraSnapshot } from './renderer/cameraSnapshot.js';
5
6
  import Display from './Display.js';
6
7
  import { Events } from './util/events.js';
@@ -16,29 +17,41 @@ import { packDepthSampleArea } from './renderer/depthQuery.js';
16
17
  import { makeWGPURenderTargets } from './renderer/WGPURenderingPipeline.js';
17
18
  import { makeWebGLRenderTargets } from './renderer/WebGLRenderingPipeline.js';
18
19
  import { WebGLDevice as WebGLRenderer } from './renderer/webgl.js';
19
- let globalGPUDevice = null;
20
- let globalGPUAdapterInfo = null;
21
- let globalGPURequest;
22
- async function sharedDevice(gpu) {
23
- if (globalGPUDevice)
24
- return globalGPUDevice;
25
- if (!globalGPURequest) {
26
- const request = (async () => {
27
- const adapter = await gpu.requestAdapter({ powerPreference: 'high-performance' }) ?? await gpu.requestAdapter();
20
+ const sharedDevices = new Map();
21
+ async function sharedDevice(gpu, mode) {
22
+ let request = sharedDevices.get(mode);
23
+ if (!request) {
24
+ request = (async () => {
25
+ let adapter = await gpu.requestAdapter({ powerPreference: 'high-performance' }) ?? await gpu.requestAdapter();
28
26
  if (!adapter)
29
27
  throw new Error('No WebGPU adapter is available');
30
- const device = await adapter.requestDevice(getRecommendedDeviceDescriptor(adapter));
31
- globalGPUAdapterInfo = adapter.info ?? null;
32
- globalGPUDevice = device;
33
- void device.lost.then(() => { if (globalGPUDevice === device)
34
- globalGPUDevice = null; });
35
- return device;
28
+ const descriptor = getRecommendedDeviceDescriptor(adapter);
29
+ const support = mode === 'auto' ? resourceTableFeature(adapter.features) : undefined;
30
+ let device, fallbackReason;
31
+ try {
32
+ device = await adapter.requestDevice(support ? { ...descriptor, requiredFeatures: [...descriptor.requiredFeatures ?? [], support.feature] } : descriptor);
33
+ }
34
+ catch (error) {
35
+ if (!support)
36
+ throw error;
37
+ fallbackReason = error instanceof Error ? error.message : String(error);
38
+ const retry = await gpu.requestAdapter({ powerPreference: 'high-performance' }) ?? await gpu.requestAdapter();
39
+ if (!retry)
40
+ throw new Error('No WebGPU adapter is available for atlas fallback');
41
+ device = await retry.requestDevice(getRecommendedDeviceDescriptor(retry));
42
+ adapter = retry;
43
+ }
44
+ const current = request;
45
+ void device.lost.then(() => { if (sharedDevices.get(mode) === current)
46
+ sharedDevices.delete(mode); });
47
+ return { device, adapterInfo: adapter.info, fallbackReason };
36
48
  })();
37
- globalGPURequest = request;
38
- void request.finally(() => { if (globalGPURequest === request)
39
- globalGPURequest = undefined; }).catch(() => { });
49
+ sharedDevices.set(mode, request);
50
+ const current = request;
51
+ void request.catch(() => { if (sharedDevices.get(mode) === current)
52
+ sharedDevices.delete(mode); });
40
53
  }
41
- return globalGPURequest;
54
+ return request;
42
55
  }
43
56
  /** Shared device, committed scene/camera, CPU preparation and denoiser ownership. */
44
57
  export default class Engine {
@@ -79,6 +92,7 @@ export default class Engine {
79
92
  _contextRestore;
80
93
  _gpuAdapterInfo;
81
94
  _backendChoice;
95
+ _textureBinding;
82
96
  _initPromise;
83
97
  _info;
84
98
  _pipelineInitError;
@@ -121,6 +135,7 @@ export default class Engine {
121
135
  if (params.device && params.backend === 'webgl')
122
136
  throw new Error('A supplied GPUDevice cannot use the webgl backend.');
123
137
  this._suppliedDevice = params.device;
138
+ this._textureBinding = params.textureBinding ?? 'atlas';
124
139
  this._ownsDeviceSelection = !params.device;
125
140
  this._backendChoice = params.device ? 'webgpu' : params.backend ?? 'auto';
126
141
  this._sceneChangeDetector = new SceneChangeDetector();
@@ -335,16 +350,24 @@ export default class Engine {
335
350
  if (preferWebGPU && (this._suppliedDevice || (typeof navigator !== 'undefined' && navigator.gpu))) {
336
351
  try {
337
352
  const gpu = typeof navigator !== 'undefined' ? navigator.gpu : undefined;
338
- const gpuDevice = this._suppliedDevice ?? await sharedDevice(gpu);
353
+ const shared = this._suppliedDevice ? undefined : await sharedDevice(gpu, this._textureBinding);
354
+ const gpuDevice = this._suppliedDevice ?? shared.device;
339
355
  const gpuAdapterInfo = this._suppliedDevice
340
- ? gpuDevice.adapterInfo : globalGPUAdapterInfo;
356
+ ? gpuDevice.adapterInfo : shared?.adapterInfo;
357
+ const materialTextures = { requested: this._textureBinding };
358
+ if (this._textureBinding === 'auto') {
359
+ const support = resourceTableFeature(gpuDevice.features);
360
+ materialTextures.fallbackReason = shared?.fallbackReason ?? (support ? await probeBindless(gpuDevice, support) : 'Resource-table feature is not enabled on this device.');
361
+ if (!materialTextures.fallbackReason)
362
+ materialTextures.support = support;
363
+ }
341
364
  if (this._disposed)
342
365
  return;
343
366
  validateDevice(gpuDevice);
344
367
  this._gpuAdapterInfo = gpuAdapterInfo ?? undefined;
345
368
  this._gpuDevice = gpuDevice;
346
369
  this._pipeline = makeWGPURenderTargets(this.display.canvas, gpuDevice, {
347
- presentationFormat: gpu?.getPreferredCanvasFormat() ?? 'bgra8unorm'
370
+ presentationFormat: gpu?.getPreferredCanvasFormat() ?? 'bgra8unorm', materialTextures
348
371
  });
349
372
  this._watchDevice(gpuDevice);
350
373
  gpuCreated = true;
@@ -420,8 +443,6 @@ export default class Engine {
420
443
  void device.lost.then(info => {
421
444
  if (this._disposed || this._gpuDevice !== device)
422
445
  return;
423
- if (globalGPUDevice === device)
424
- globalGPUDevice = null;
425
446
  const recovering = this._ownsDeviceSelection;
426
447
  const error = new Error(`WebGPU device lost (${info.reason}): ${info.message || 'device is unavailable'}`);
427
448
  this._invalidateDevice(error, recovering);
@@ -515,7 +536,13 @@ export default class Engine {
515
536
  if (!this._pipeline && !this._lastBvhBuild)
516
537
  return;
517
538
  const values = this._pipeline?.getDiagnostics();
518
- return { ...values, bvh: { ...values?.bvh, lastBuild: this._lastBvhBuild }, backend: this.backend, adapterName: this._adapterName(), width: this.display.canvas.width, height: this.display.canvas.height,
539
+ const materialTextures = values?.materialTextures ?? (this._pipeline ? {
540
+ requested: this._textureBinding, active: 'atlas',
541
+ fallbackReason: this._textureBinding === 'auto' ? 'Bindless textures require a supported WebGPU device.' : undefined,
542
+ textureCount: values?.textureAtlas?.textureCount ?? 0, estimatedBytes: values?.textureAtlas?.estimatedBytes ?? 0,
543
+ scale: values?.textureAtlas?.scale ?? 1, metadataBytes: 0, resourceTableCapacity: 0, retiredBytes: 0
544
+ } : undefined);
545
+ return { ...values, materialTextures, bvh: { ...values?.bvh, lastBuild: this._lastBvhBuild }, backend: this.backend, adapterName: this._adapterName(), width: this.display.canvas.width, height: this.display.canvas.height,
519
546
  lastError: this.lastError?.message, webgpuFallbackReason: this._webgpuFallbackReason,
520
547
  presentedTarget: this._presented?.label, presentedComplete: this._presented?.presentationComplete ?? false };
521
548
  }