@meimu/mutracer 0.1.5 → 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 (526) 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 +10407 -8353
  6. package/docs/api.md +200 -10
  7. package/docs/denoising.md +30 -15
  8. package/docs/materials.md +1 -1
  9. package/docs/performance.md +5 -2
  10. package/docs/progressive-rendering.md +32 -1
  11. package/docs/threejs.md +14 -5
  12. package/docs/updates.md +44 -2
  13. package/docs/viewer.md +11 -6
  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 -550
  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 +82 -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 +429 -429
  206. package/lib/renderer/glsl/chunks/materialBuffer.glsl.js +144 -144
  207. package/lib/renderer/glsl/chunks/materialBuffer.glsl.js.map +1 -1
  208. package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js +801 -801
  209. package/lib/renderer/glsl/chunks/rand.glsl.js +3 -3
  210. package/lib/renderer/glsl/chunks/random.glsl.js +6 -6
  211. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js +49 -49
  212. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js.map +1 -1
  213. package/lib/renderer/glsl/chunks/sampleLight.glsl.js +80 -80
  214. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js +102 -102
  215. package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js +20 -17
  216. package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js.map +1 -1
  217. package/lib/renderer/glsl/chunks/sampling.glsl.js +93 -93
  218. package/lib/renderer/glsl/chunks/sobol.glsl.js +79 -79
  219. package/lib/renderer/glsl/chunks/textureLinear.glsl.js +5 -5
  220. package/lib/renderer/glsl/chunks/uvProjection.glsl.js +12 -12
  221. package/lib/renderer/glsl/chunks/uvProjection.glsl.js.map +1 -1
  222. package/lib/renderer/glsl/depthQuery.frag.js +7 -7
  223. package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js +17 -9
  224. package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js.map +1 -1
  225. package/lib/renderer/glsl/rayTrace.frag.js +191 -191
  226. package/lib/renderer/glsl/shadowCatcher.frag.js +25 -20
  227. package/lib/renderer/glsl/shadowCatcher.frag.js.map +1 -1
  228. package/lib/renderer/glsl/webglPipeline.frag.js +65 -60
  229. package/lib/renderer/glsl/webglPipeline.frag.js.map +1 -1
  230. package/lib/renderer/lightConstants.d.ts +10 -0
  231. package/lib/renderer/lightConstants.js +11 -0
  232. package/lib/renderer/lightConstants.js.map +1 -0
  233. package/lib/renderer/lightCore.d.ts +12 -0
  234. package/lib/renderer/lightCore.js +13 -0
  235. package/lib/renderer/lightCore.js.map +1 -0
  236. package/lib/renderer/lightSampling.d.ts +20 -17
  237. package/lib/renderer/lightSampling.js +123 -56
  238. package/lib/renderer/lightSampling.js.map +1 -1
  239. package/lib/renderer/lightsData.d.ts +21 -0
  240. package/lib/renderer/lightsData.js +192 -0
  241. package/lib/renderer/lightsData.js.map +1 -0
  242. package/lib/renderer/lightsUtil.d.ts +3 -26
  243. package/lib/renderer/lightsUtil.js +3 -153
  244. package/lib/renderer/lightsUtil.js.map +1 -1
  245. package/lib/renderer/materialBufferData.d.ts +70 -0
  246. package/lib/renderer/materialBufferData.js +2 -0
  247. package/lib/renderer/materialBufferData.js.map +1 -0
  248. package/lib/renderer/materialConstants.d.ts +11 -0
  249. package/lib/renderer/materialConstants.js +11 -0
  250. package/lib/renderer/materialConstants.js.map +1 -1
  251. package/lib/renderer/materialCore.d.ts +8 -0
  252. package/lib/renderer/materialCore.js +9 -0
  253. package/lib/renderer/materialCore.js.map +1 -0
  254. package/lib/renderer/materialEmission.d.ts +2 -2
  255. package/lib/renderer/materialEmission.js +3 -3
  256. package/lib/renderer/materialEmission.js.map +1 -1
  257. package/lib/renderer/materialLayout.d.ts +2 -101
  258. package/lib/renderer/materialLayout.js +110 -172
  259. package/lib/renderer/materialLayout.js.map +1 -1
  260. package/lib/renderer/materialLayoutSchema.d.ts +26 -0
  261. package/lib/renderer/materialLayoutSchema.js +172 -0
  262. package/lib/renderer/materialLayoutSchema.js.map +1 -0
  263. package/lib/renderer/materialParams.d.ts +69 -0
  264. package/lib/renderer/materialParams.js +272 -0
  265. package/lib/renderer/materialParams.js.map +1 -0
  266. package/lib/renderer/materialTextureSlots.d.ts +14 -324
  267. package/lib/renderer/materialTextureSlots.js +21 -8
  268. package/lib/renderer/materialTextureSlots.js.map +1 -1
  269. package/lib/renderer/materialTextures.d.ts +6 -0
  270. package/lib/renderer/{texturesFromMaterials.js → materialTextures.js} +1 -2
  271. package/lib/renderer/materialTextures.js.map +1 -0
  272. package/lib/renderer/mergeMeshesToGeometry.js +6 -147
  273. package/lib/renderer/mergeMeshesToGeometry.js.map +1 -1
  274. package/lib/renderer/meshInstances.d.ts +4 -21
  275. package/lib/renderer/meshInstances.js +10 -56
  276. package/lib/renderer/meshInstances.js.map +1 -1
  277. package/lib/renderer/oidnNetwork.d.ts +2 -2
  278. package/lib/renderer/oidnNetwork.js +1 -1
  279. package/lib/renderer/oidnNetwork.js.map +1 -1
  280. package/lib/renderer/openPbrEnergyLut.js +850 -846
  281. package/lib/renderer/openPbrEnergyLut.js.map +1 -1
  282. package/lib/renderer/ownedDenoiser.d.ts +9 -0
  283. package/lib/renderer/ownedDenoiser.js +2 -0
  284. package/lib/renderer/ownedDenoiser.js.map +1 -0
  285. package/lib/renderer/packedMeshInstances.d.ts +23 -0
  286. package/lib/renderer/packedMeshInstances.js +80 -0
  287. package/lib/renderer/packedMeshInstances.js.map +1 -0
  288. package/lib/renderer/prepareMeshBVH.d.ts +12 -47
  289. package/lib/renderer/prepareMeshBVH.js +21 -642
  290. package/lib/renderer/prepareMeshBVH.js.map +1 -1
  291. package/lib/renderer/proceduralEnvironmentPower.d.ts +3 -0
  292. package/lib/renderer/proceduralEnvironmentPower.js +8 -0
  293. package/lib/renderer/proceduralEnvironmentPower.js.map +1 -0
  294. package/lib/renderer/progressiveScheduler.d.ts +1 -0
  295. package/lib/renderer/progressiveScheduler.js +3 -0
  296. package/lib/renderer/progressiveScheduler.js.map +1 -1
  297. package/lib/renderer/renderPipeline.d.ts +3 -1
  298. package/lib/renderer/renderPipeline.js.map +1 -1
  299. package/lib/renderer/renderingLimits.d.ts +9 -0
  300. package/lib/renderer/renderingLimits.js +18 -0
  301. package/lib/renderer/renderingLimits.js.map +1 -0
  302. package/lib/renderer/sceneAssembly.d.ts +73 -0
  303. package/lib/renderer/sceneAssembly.js +109 -0
  304. package/lib/renderer/sceneAssembly.js.map +1 -0
  305. package/lib/renderer/sceneChangeCore.d.ts +39 -0
  306. package/lib/renderer/sceneChangeCore.js +307 -0
  307. package/lib/renderer/sceneChangeCore.js.map +1 -0
  308. package/lib/renderer/sceneChangeDetector.d.ts +3 -6
  309. package/lib/renderer/sceneChangeDetector.js +24 -150
  310. package/lib/renderer/sceneChangeDetector.js.map +1 -1
  311. package/lib/renderer/sceneLayoutSchema.d.ts +118 -0
  312. package/lib/renderer/sceneLayoutSchema.js +111 -0
  313. package/lib/renderer/sceneLayoutSchema.js.map +1 -0
  314. package/lib/renderer/sceneLightChanges.d.ts +3 -3
  315. package/lib/renderer/sceneLightChanges.js.map +1 -1
  316. package/lib/renderer/scenePreparation.d.ts +55 -0
  317. package/lib/renderer/scenePreparation.js +360 -0
  318. package/lib/renderer/scenePreparation.js.map +1 -0
  319. package/lib/renderer/scratchSampling.js +18 -18
  320. package/lib/renderer/scratchSampling.js.map +1 -1
  321. package/lib/renderer/shader.d.ts +2 -0
  322. package/lib/renderer/shader.js +2 -0
  323. package/lib/renderer/shader.js.map +1 -1
  324. package/lib/renderer/shaderCapabilities.d.ts +23 -0
  325. package/lib/renderer/shaderCapabilities.js +55 -0
  326. package/lib/renderer/shaderCapabilities.js.map +1 -0
  327. package/lib/renderer/shaderCapacity.d.ts +2 -0
  328. package/lib/renderer/shaderCapacity.js +5 -0
  329. package/lib/renderer/shaderCapacity.js.map +1 -0
  330. package/lib/renderer/skyModel.d.ts +9 -0
  331. package/lib/renderer/skyModel.js +10 -0
  332. package/lib/renderer/skyModel.js.map +1 -0
  333. package/lib/renderer/textureAtlas.d.ts +60 -0
  334. package/lib/renderer/textureAtlas.js +145 -0
  335. package/lib/renderer/textureAtlas.js.map +1 -0
  336. package/lib/renderer/textureAtlasPixels.d.ts +7 -0
  337. package/lib/renderer/textureAtlasPixels.js +68 -0
  338. package/lib/renderer/textureAtlasPixels.js.map +1 -0
  339. package/lib/renderer/util.d.ts +1 -1
  340. package/lib/renderer/util.js.map +1 -1
  341. package/lib/renderer/webgl.d.ts +9 -2
  342. package/lib/renderer/webgl.js +54 -9
  343. package/lib/renderer/webgl.js.map +1 -1
  344. package/lib/renderer/wgpuBindless.d.ts +26 -0
  345. package/lib/renderer/wgpuBindless.js +95 -0
  346. package/lib/renderer/wgpuBindless.js.map +1 -0
  347. package/lib/renderer/wgpuBindlessSource.d.ts +2 -0
  348. package/lib/renderer/wgpuBindlessSource.js +51 -0
  349. package/lib/renderer/wgpuBindlessSource.js.map +1 -0
  350. package/lib/renderer/wgpuMaterialConstants.d.ts +4 -0
  351. package/lib/renderer/wgpuMaterialConstants.js +52 -0
  352. package/lib/renderer/wgpuMaterialConstants.js.map +1 -0
  353. package/lib/renderer/wgpuSceneUniform.d.ts +42 -0
  354. package/lib/renderer/wgpuSceneUniform.js +125 -0
  355. package/lib/renderer/wgpuSceneUniform.js.map +1 -0
  356. package/lib/renderer/wgpuShaderSource.d.ts +15 -0
  357. package/lib/renderer/wgpuShaderSource.js +31 -0
  358. package/lib/renderer/wgpuShaderSource.js.map +1 -0
  359. package/lib/renderer/wgsl/aovDisplay.wgsl.d.ts +1 -0
  360. package/lib/renderer/wgsl/aovDisplay.wgsl.js +70 -0
  361. package/lib/renderer/wgsl/aovDisplay.wgsl.js.map +1 -0
  362. package/lib/renderer/wgsl/aovReflectance.wgsl.d.ts +2 -0
  363. package/lib/renderer/wgsl/aovReflectance.wgsl.js +98 -0
  364. package/lib/renderer/wgsl/aovReflectance.wgsl.js.map +1 -0
  365. package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.d.ts +2 -0
  366. package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.js +135 -0
  367. package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.js.map +1 -0
  368. package/lib/renderer/wgsl/aovResolve.wgsl.d.ts +5 -0
  369. package/lib/renderer/wgsl/aovResolve.wgsl.js +38 -0
  370. package/lib/renderer/wgsl/aovResolve.wgsl.js.map +1 -0
  371. package/lib/renderer/wgsl/aovSnapshot.wgsl.d.ts +4 -0
  372. package/lib/renderer/wgsl/aovSnapshot.wgsl.js +21 -0
  373. package/lib/renderer/wgsl/aovSnapshot.wgsl.js.map +1 -0
  374. package/lib/renderer/wgsl/aovTrace.wgsl.d.ts +2 -0
  375. package/lib/renderer/wgsl/aovTrace.wgsl.js +115 -0
  376. package/lib/renderer/wgsl/aovTrace.wgsl.js.map +1 -0
  377. package/lib/renderer/wgsl/bloom.wgsl.d.ts +13 -0
  378. package/lib/renderer/wgsl/bloom.wgsl.js +92 -0
  379. package/lib/renderer/wgsl/bloom.wgsl.js.map +1 -0
  380. package/lib/renderer/wgsl/chunks/common.wgsl.js +4 -4
  381. package/lib/renderer/wgsl/chunks/envMap.wgsl.d.ts +1 -1
  382. package/lib/renderer/wgsl/chunks/envMap.wgsl.js +43 -37
  383. package/lib/renderer/wgsl/chunks/envMap.wgsl.js.map +1 -1
  384. package/lib/renderer/wgsl/chunks/intersect.wgsl.d.ts +13 -1
  385. package/lib/renderer/wgsl/chunks/intersect.wgsl.js +742 -705
  386. package/lib/renderer/wgsl/chunks/intersect.wgsl.js.map +1 -1
  387. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js +16 -16
  388. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js.map +1 -1
  389. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.d.ts +3 -1
  390. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js +84 -82
  391. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js.map +1 -1
  392. package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js +855 -857
  393. package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js.map +1 -1
  394. package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js +139 -139
  395. package/lib/renderer/wgsl/chunks/rand.wgsl.js +3 -3
  396. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.d.ts +2 -1
  397. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js +42 -32
  398. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js.map +1 -1
  399. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.d.ts +1 -1
  400. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js +152 -148
  401. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js.map +1 -1
  402. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js +239 -232
  403. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js.map +1 -1
  404. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.d.ts +1 -1
  405. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js +26 -13
  406. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js.map +1 -1
  407. package/lib/renderer/wgsl/chunks/sampling.wgsl.js +91 -91
  408. package/lib/renderer/wgsl/chunks/shadowCatcherAccumulation.wgsl.d.ts +1 -1
  409. package/lib/renderer/wgsl/chunks/shadowCatcherAccumulation.wgsl.js +1 -0
  410. package/lib/renderer/wgsl/chunks/shadowCatcherAccumulation.wgsl.js.map +1 -1
  411. package/lib/renderer/wgsl/chunks/sobol.wgsl.js +83 -83
  412. package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js +12 -12
  413. package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js.map +1 -1
  414. package/lib/renderer/wgsl/compose.frag.wgsl.d.ts +8 -3
  415. package/lib/renderer/wgsl/compose.frag.wgsl.js +143 -118
  416. package/lib/renderer/wgsl/compose.frag.wgsl.js.map +1 -1
  417. package/lib/renderer/wgsl/customDenoise.wgsl.js +10 -10
  418. package/lib/renderer/wgsl/depthQuery.wgsl.js +7 -7
  419. package/lib/renderer/wgsl/jnlm.compute.d.ts +25 -0
  420. package/lib/renderer/wgsl/jnlm.compute.js +315 -0
  421. package/lib/renderer/wgsl/jnlm.compute.js.map +1 -0
  422. package/lib/renderer/wgsl/offlineAdaptive.compute.js +28 -28
  423. package/lib/renderer/wgsl/oidnAuxiliary.wgsl.d.ts +1 -0
  424. package/lib/renderer/wgsl/oidnAuxiliary.wgsl.js +17 -0
  425. package/lib/renderer/wgsl/oidnAuxiliary.wgsl.js.map +1 -0
  426. package/lib/renderer/wgsl/proceduralSky.compute.d.ts +1 -0
  427. package/lib/renderer/wgsl/proceduralSky.compute.js +198 -0
  428. package/lib/renderer/wgsl/proceduralSky.compute.js.map +1 -0
  429. package/lib/renderer/wgsl/rayTrace.compute.d.ts +17 -1
  430. package/lib/renderer/wgsl/rayTrace.compute.js +612 -393
  431. package/lib/renderer/wgsl/rayTrace.compute.js.map +1 -1
  432. package/lib/scene/Camera.js +7 -3
  433. package/lib/scene/Camera.js.map +1 -1
  434. package/lib/scene/EnvironmentLight.d.ts +5 -9
  435. package/lib/scene/EnvironmentLight.js +4 -14
  436. package/lib/scene/EnvironmentLight.js.map +1 -1
  437. package/lib/scene/EnvironmentLightState.d.ts +18 -0
  438. package/lib/scene/EnvironmentLightState.js +19 -0
  439. package/lib/scene/EnvironmentLightState.js.map +1 -0
  440. package/lib/scene/Geometry.d.ts +12 -6
  441. package/lib/scene/Geometry.js +37 -13
  442. package/lib/scene/Geometry.js.map +1 -1
  443. package/lib/scene/InstanceState.d.ts +39 -0
  444. package/lib/scene/InstanceState.js +77 -0
  445. package/lib/scene/InstanceState.js.map +1 -0
  446. package/lib/scene/InstancedMesh.d.ts +1 -1
  447. package/lib/scene/InstancedMesh.js +3 -0
  448. package/lib/scene/InstancedMesh.js.map +1 -1
  449. package/lib/scene/MaterialState.d.ts +209 -0
  450. package/lib/scene/MaterialState.js +231 -0
  451. package/lib/scene/MaterialState.js.map +1 -0
  452. package/lib/scene/Mesh.d.ts +4 -6
  453. package/lib/scene/Mesh.js +3 -11
  454. package/lib/scene/Mesh.js.map +1 -1
  455. package/lib/scene/MeshState.d.ts +20 -0
  456. package/lib/scene/MeshState.js +35 -0
  457. package/lib/scene/MeshState.js.map +1 -0
  458. package/lib/scene/OpenPBRMaterial.d.ts +6 -168
  459. package/lib/scene/OpenPBRMaterial.js +5 -223
  460. package/lib/scene/OpenPBRMaterial.js.map +1 -1
  461. package/lib/scene/PixelTexture.d.ts +6 -0
  462. package/lib/scene/PixelTexture.js +10 -0
  463. package/lib/scene/PixelTexture.js.map +1 -0
  464. package/lib/scene/ProceduralSky.d.ts +24 -0
  465. package/lib/scene/ProceduralSky.js +40 -0
  466. package/lib/scene/ProceduralSky.js.map +1 -0
  467. package/lib/scene/RectLight.d.ts +2 -13
  468. package/lib/scene/RectLight.js +3 -21
  469. package/lib/scene/RectLight.js.map +1 -1
  470. package/lib/scene/RectLightState.d.ts +31 -0
  471. package/lib/scene/RectLightState.js +26 -0
  472. package/lib/scene/RectLightState.js.map +1 -0
  473. package/lib/scene/Scene.d.ts +15 -4
  474. package/lib/scene/Scene.js.map +1 -1
  475. package/lib/scene/SceneNode.js +7 -6
  476. package/lib/scene/SceneNode.js.map +1 -1
  477. package/lib/scene/Texture.d.ts +10 -41
  478. package/lib/scene/Texture.js +4 -33
  479. package/lib/scene/Texture.js.map +1 -1
  480. package/lib/scene/TextureState.d.ts +35 -0
  481. package/lib/scene/TextureState.js +35 -0
  482. package/lib/scene/TextureState.js.map +1 -0
  483. package/lib/scene/attributeData.d.ts +4 -0
  484. package/lib/scene/attributeData.js +10 -0
  485. package/lib/scene/attributeData.js.map +1 -0
  486. package/lib/scene/lightState.d.ts +8 -0
  487. package/lib/scene/lightState.js +2 -0
  488. package/lib/scene/lightState.js.map +1 -0
  489. package/lib/scene/openPbrSchema.d.ts +7 -12
  490. package/lib/scene/openPbrSchema.js +273 -28
  491. package/lib/scene/openPbrSchema.js.map +1 -1
  492. package/lib/scene/skyParameters.d.ts +20 -0
  493. package/lib/scene/skyParameters.js +28 -0
  494. package/lib/scene/skyParameters.js.map +1 -0
  495. package/lib/scene/textureData.d.ts +9 -0
  496. package/lib/scene/textureData.js +2 -0
  497. package/lib/scene/textureData.js.map +1 -0
  498. package/lib/scene/texturePixels.d.ts +6 -0
  499. package/lib/scene/texturePixels.js +10 -0
  500. package/lib/scene/texturePixels.js.map +1 -0
  501. package/lib/settings/display.d.ts +33 -0
  502. package/lib/settings/display.js +7 -0
  503. package/lib/settings/display.js.map +1 -1
  504. package/lib/settings/render.d.ts +25 -3
  505. package/lib/settings/render.js +3 -1
  506. package/lib/settings/render.js.map +1 -1
  507. package/lib/tinybvh/tinybvh.wasm +0 -0
  508. package/lib/util/commonGeometry.js +7 -7
  509. package/lib/util/commonGeometry.js.map +1 -1
  510. package/lib/util/fromTHREE.d.ts +4 -1
  511. package/lib/util/fromTHREE.js +18 -5
  512. package/lib/util/fromTHREE.js.map +1 -1
  513. package/lib/util/geometry.js +42 -29
  514. package/lib/util/geometry.js.map +1 -1
  515. package/lib/util/loadRGBE.js +3 -4
  516. package/lib/util/loadRGBE.js.map +1 -1
  517. package/lib/util/studioLighting.d.ts +18 -0
  518. package/lib/util/studioLighting.js +36 -0
  519. package/lib/util/studioLighting.js.map +1 -0
  520. package/lib/version.d.ts +1 -1
  521. package/lib/version.js +1 -1
  522. package/lib/version.js.map +1 -1
  523. package/llms.txt +4 -0
  524. package/package.json +31 -5
  525. package/lib/renderer/texturesFromMaterials.d.ts +0 -6
  526. package/lib/renderer/texturesFromMaterials.js.map +0 -1
@@ -131,16 +131,17 @@ export class WGPUFullQuadPass {
131
131
  }
132
132
  }
133
133
  setOutputParams(outputParams) {
134
+ const wasScreen = !!this._renderToScreen;
134
135
  this._renderToScreen = undefined;
135
136
  const outputsChanged = Object.keys(outputParams).some((key) => !isTextureParamsEqual(outputParams[key], this._outputParams[key] || {}));
136
137
  this._needsUpdateOutputTextures ||= outputsChanged;
137
- this._needsUpdatePipeline ||= outputsChanged;
138
- if (outputsChanged)
138
+ this._needsUpdatePipeline ||= outputsChanged || wasScreen;
139
+ if (outputsChanged || wasScreen)
139
140
  this._fsCode = '';
140
141
  this._outputParams = outputParams;
141
142
  }
142
143
  setRenderToScreen(screenTexture, presentationFormat) {
143
- if (this._renderToScreen &&
144
+ if (!this._renderToScreen ||
144
145
  this._renderToScreen.presentationFormat !== presentationFormat) {
145
146
  this._needsUpdatePipeline = true;
146
147
  this._fsCode = '';
@@ -273,7 +274,7 @@ ${hasInputs
273
274
  ${this._uniforms
274
275
  .map((uniform, idx) => `@group(${hasInputs ? 1 : 0}) @binding(${idx}) var<uniform> ${uniform.label}: ${uniform.type};`)
275
276
  .join('\n')}
276
- struct pd {
277
+ struct qa {
277
278
  ${this._outputs
278
279
  .map((name, idx) => `@location(${idx}) ${name}: vec4f,`)
279
280
  .join('\n')}
@@ -282,11 +283,11 @@ ${scratchWGSLFunctions(this._reserveCapacity ? this._regionNames : inputs.filter
282
283
  ${this._fsDefine ?? ''}
283
284
  @fragment
284
285
  fn main(
285
- @builtin(position) fH: vec4f
286
- ) -> pd {
287
- let uv = vec2i(floor(fH.xy));
288
- let uv2 = fH.xy / viewportSize;
289
- var output: pd;
286
+ @builtin(position) coord: vec4f
287
+ ) -> qa {
288
+ let uv = vec2i(floor(coord.xy));
289
+ let uv2 = coord.xy / viewportSize;
290
+ var output: qa;
290
291
  ${this._fsMain}
291
292
  return output;
292
293
  }
@@ -1 +1 @@
1
- {"version":3,"file":"WGPUFullQuadPass.js","sourceRoot":"","sources":["../../src/renderer/WGPUFullQuadPass.ts"],"names":[],"mappings":"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","sourcesContent":["import {scratchWGSLFunctions} from './scratchSampling.js';\nimport {setTextureRegion, textureRegion} from './textureRegion.js';\nimport { getTargetShaderCache } from './WGPUShaderCache.js';\nimport { textureBytes } from './gpuMemory.js';\nexport const fullScreenQuadVertexShaderWGSL = /*wgsl */ `\n@vertex\nfn main(\n @builtin(vertex_index) vertexIndex: u32\n) -> @builtin(position) vec4f {\n const pos = array(\n vec2(-1.0, -1.0), vec2(1.0, -1.0), vec2(-1.0, 1.0),\n vec2(-1.0, 1.0), vec2(1.0, -1.0), vec2(1.0, 1.0),\n );\n\n return vec4<f32>(pos[vertexIndex], 0.0, 1.0);\n}\n`;\n\nfunction isTextureParamsEqual(\n params: WGPUFullQuadPassOutput,\n other: WGPUFullQuadPassOutput\n) {\n return params.format === other.format;\n}\n\nexport function getUniformBuffer(\n value: any,\n type: Uniform['type']\n): Float32Array | Int32Array | Uint32Array {\n if (\n value instanceof Float32Array ||\n value instanceof Int32Array ||\n value instanceof Uint32Array\n ) {\n return value;\n }\n\n if (typeof value === 'number') {\n value = [value];\n }\n\n if (type === 'i32' || type.endsWith('i')) {\n return new Int32Array(value);\n } else if (type === 'u32' || type.endsWith('u')) {\n return new Uint32Array(value);\n } else {\n return new Float32Array(value);\n }\n}\n\nexport interface Uniform {\n label: string;\n type:\n | `array<vec4u, ${number}>`\n | 'f32'\n | 'i32'\n | 'u32'\n | 'vec3f'\n | 'vec4f'\n | 'vec2f'\n | 'vec2i'\n | 'vec3i'\n | 'vec4i'\n | 'vec2u'\n | 'vec3u'\n | 'vec4u';\n data: Float32Array | Int32Array | Uint32Array | number | number[];\n}\n\nexport interface WGPUFullQuadPassOutput {\n format: GPUTextureFormat;\n}\nexport class WGPUFullQuadPass<I extends string, O extends string> {\n private _label;\n\n private _device;\n private _outputTextures: Record<string, GPUTexture> = {};\n private _outputParams: Record<string, WGPUFullQuadPassOutput> = {};\n\n private _pipeline!: GPURenderPipeline;\n private _bindGroups: GPUBindGroup[] = [];\n private _needsUpdatePipeline = true;\n private _needsUpdateOutputTextures = true;\n /**\n * When render to canvas\n */\n private _renderToScreen?: {\n screenTexture: GPUTexture;\n presentationFormat: GPUTextureFormat;\n };\n private _inputs: string[] = [];\n private _inputViewDimensions: Partial<\n Record<I, GPUTextureViewDimension>\n > = {};\n private _outputs: string[] = [];\n private _uniforms: Uniform[] = [];\n private _uniformsMap: Record<string, Uniform> = {};\n private _uniformBuffers: Record<string, GPUBuffer> = {};\n\n private _samplers: Record<string, GPUSampler> = {};\n\n private _capacityWidth = 0;\n private _capacityHeight = 0;\n private _reserveCapacity = false;\n private _regionNames: string[] = [];\n private _width = 10;\n private _height = 10;\n\n private _fsCode = '';\n private readonly _fsMain;\n private readonly _fsDefine;\n\n private _textureWillBeRead;\n\n constructor(\n label: string,\n device: GPUDevice,\n opts: {\n inputs: I[];\n inputViewDimensions?: Partial<Record<I, GPUTextureViewDimension>>;\n outputs: O[];\n samplers?: Record<string, GPUSampler>;\n fsMain: string;\n fsDefine?: string;\n uniforms?: Uniform[];\n textureWillBeRead?: boolean;\n }\n ) {\n this._label = label;\n this._device = device;\n this._fsMain = opts.fsMain;\n this._fsDefine = opts.fsDefine;\n this._inputs = opts.inputs;\n this._inputViewDimensions = opts.inputViewDimensions || {};\n this._outputs = opts.outputs;\n this._uniforms = (opts.uniforms || []).concat({\n label: 'viewportSize',\n type: 'vec2f',\n data: [0, 0]\n });\n this._samplers = opts.samplers || {};\n this._uniformsMap = this._uniforms.reduce((map, uniform) => {\n map[uniform.label] = uniform;\n return map;\n }, {} as Record<string, Uniform>);\n this._textureWillBeRead = opts.textureWillBeRead || false;\n\n this._uniforms.forEach((uniform) => {\n const data = getUniformBuffer(uniform.data, uniform.type);\n this._uniformBuffers[uniform.label] = device.createBuffer({\n label: this._label,\n size: data.byteLength,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n });\n this._device.queue.writeBuffer(\n this._uniformBuffers[uniform.label],\n 0,\n data\n );\n });\n }\n\n /** Keep physical outputs large enough for every render while varying the logical viewport. */\n reserveCapacity() {\n if (this._reserveCapacity) return;\n this._reserveCapacity = true;\n this._capacityWidth = this._width; this._capacityHeight = this._height;\n const textures = this._inputs.filter(name => !this._inputViewDimensions[name as I] || this._inputViewDimensions[name as I] === '2d');\n this._regionNames = textures;\n if (textures.length) {\n const uniform: Uniform = {label: 'imageRegions', type: `array<vec4u, ${textures.length}>`, data: new Uint32Array(textures.length * 4)};\n this._uniforms.push(uniform); this._uniformsMap[uniform.label] = uniform;\n this._uniformBuffers[uniform.label] = this._device.createBuffer({label: `${this._label}.${uniform.label}`, size: textures.length * 16, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST});\n }\n this._needsUpdatePipeline = true; this._fsCode = '';\n }\n setSize(width: number, height: number) {\n width = Math.max(1, Math.ceil(width));\n height = Math.max(1, Math.ceil(height));\n const sizeChanged = width !== this._width || height !== this._height;\n this._width = width;\n this._height = height;\n if (sizeChanged) {\n const nextWidth = Math.max(this._capacityWidth, width);\n const nextHeight = Math.max(this._capacityHeight, height);\n this._needsUpdateOutputTextures ||= !this._reserveCapacity || nextWidth !== this._capacityWidth || nextHeight !== this._capacityHeight;\n this._capacityWidth = nextWidth; this._capacityHeight = nextHeight;\n this._needsUpdatePipeline = true;\n\n this.setUniform('viewportSize', [width, height]);\n }\n }\n\n setOutputParams(outputParams: Record<O, WGPUFullQuadPassOutput>) {\n this._renderToScreen = undefined;\n const outputsChanged = Object.keys(outputParams).some(\n (key) =>\n !isTextureParamsEqual(\n (outputParams as any)[key],\n this._outputParams[key] || ({} as WGPUFullQuadPassOutput)\n )\n );\n this._needsUpdateOutputTextures ||= outputsChanged;\n this._needsUpdatePipeline ||= outputsChanged;\n if (outputsChanged) this._fsCode = '';\n this._outputParams = outputParams;\n }\n\n setRenderToScreen(\n screenTexture: GPUTexture,\n presentationFormat: GPUTextureFormat\n ) {\n if (\n this._renderToScreen &&\n this._renderToScreen.presentationFormat !== presentationFormat\n ) {\n this._needsUpdatePipeline = true;\n this._fsCode = '';\n }\n this._renderToScreen = {\n screenTexture,\n presentationFormat\n };\n }\n\n setUniform(label: string, data: Uniform['data']) {\n const buffer = this._uniformBuffers[label];\n this._device.queue.writeBuffer(\n buffer,\n 0,\n getUniformBuffer(data, this._uniformsMap[label].type)\n );\n }\n\n private readonly _retainedOutputs = new Set<GPUTexture>();\n retainOutput(texture: GPUTexture) { if (Object.values(this._outputTextures).includes(texture)) this._retainedOutputs.add(texture); }\n releaseOutput(texture: GPUTexture) {\n if (!this._retainedOutputs.delete(texture)) return;\n if (!Object.values(this._outputTextures).includes(texture)) {\n void this._device.queue.onSubmittedWorkDone().catch(() => undefined).then(() => texture.destroy());\n }\n }\n\n getOutput(name: O) {\n return this._outputTextures[name];\n }\n\n getMemoryBytes() {\n return Object.values(this._uniformBuffers).reduce((sum, buffer) => sum + buffer.size, 0)\n + Array.from(new Set([...Object.values(this._outputTextures), ...this._retainedOutputs]))\n .reduce((sum, texture) => sum + textureBytes(texture), 0);\n }\n\n dispose() {\n Object.keys(this._uniformBuffers).forEach((key) => {\n (this._uniformBuffers as any)[key].destroy();\n });\n new Set([...Object.values(this._outputTextures), ...this._retainedOutputs]).forEach(texture => texture.destroy());\n this._retainedOutputs.clear();\n }\n\n private _createTexture(params: WGPUFullQuadPassOutput) {\n return this._device.createTexture({\n label: this._label,\n size: {\n width: this._reserveCapacity ? this._capacityWidth : this._width,\n height: this._reserveCapacity ? this._capacityHeight : this._height,\n depthOrArrayLayers: 1\n },\n format: params.format,\n usage:\n GPUTextureUsage.RENDER_ATTACHMENT |\n GPUTextureUsage.TEXTURE_BINDING |\n (this._textureWillBeRead ? GPUTextureUsage.COPY_SRC : 0)\n });\n }\n\n private _updateOutputTextures(excludes?: string[]) {\n const outputParams = this._outputParams;\n for (const key in outputParams) {\n if (excludes?.includes(key)) {\n continue;\n }\n const params = outputParams[key];\n if (!this._retainedOutputs.has(this._outputTextures[key])) this._outputTextures[key]?.destroy();\n this._outputTextures[key] = this._createTexture(params);\n }\n }\n\n private _updatePipeline() {\n if (!this._needsUpdatePipeline) {\n return;\n }\n this._needsUpdatePipeline = false;\n\n const outputParams = this._outputParams;\n const device = this._device;\n const fsCode = this._getFullFs();\n if (fsCode === this._fsCode) {\n return;\n }\n const { screenTexture, presentationFormat } = this._renderToScreen || {};\n this._fsCode = fsCode;\n this._pipeline = getTargetShaderCache(device).createRenderPipeline({\n label: this._label,\n layout: 'auto',\n vertex: {\n module: getTargetShaderCache(device).createShaderModule({\n label: this._label,\n code: fullScreenQuadVertexShaderWGSL\n }),\n entryPoint: 'main'\n },\n fragment: {\n module: getTargetShaderCache(device).createShaderModule({\n label: this._label,\n code: fsCode\n }),\n entryPoint: 'main',\n targets: screenTexture\n ? [\n {\n format: presentationFormat!\n }\n ]\n : this._outputs.map((key) => ({\n format: (outputParams as any)[key].format\n }))\n },\n primitive: {\n topology: 'triangle-list'\n }\n });\n this._updateBindGroups();\n }\n\n private _getFullFs() {\n const inputs = this._inputs;\n const inputsLen = inputs.length;\n const hasInputs = inputsLen > 0;\n const fs = /* wgsl */ `\n${inputs\n .sort()\n .map(\n (textureName, idx) => {\n const viewDimension = this._inputViewDimensions[textureName as I];\n const textureType = viewDimension === '3d' ? 'texture_3d' : 'texture_2d';\n return `@group(0) @binding(${idx}) var ${textureName}: ${textureType}<f32>;`;\n }\n )\n .join('\\n')}\n\n${\n hasInputs\n ? Object.keys(this._samplers)\n .sort()\n .map(\n (samplerName, idx) =>\n `@group(0) @binding(${\n idx + inputsLen\n }) var ${samplerName}: sampler;`\n )\n .join('\\n')\n : ''\n}\n${this._uniforms\n .map(\n (uniform, idx) =>\n `@group(${hasInputs ? 1 : 0}) @binding(${idx}) var<uniform> ${\n uniform.label\n }: ${uniform.type};`\n )\n .join('\\n')}\nstruct FSOutput {\n${this._outputs\n .map((name, idx) => `@location(${idx}) ${name}: vec4f,`)\n .join('\\n')}\n}\n${scratchWGSLFunctions(\n this._reserveCapacity ? this._regionNames : inputs.filter(name =>\n !this._inputViewDimensions[name as I] || this._inputViewDimensions[name as I] === '2d'),\n Object.keys(this._samplers), this._reserveCapacity\n)}\n${this._fsDefine ?? ''}\n@fragment\nfn main(\n @builtin(position) coord: vec4f\n) -> FSOutput {\n let uv = vec2i(floor(coord.xy));\n let uv2 = coord.xy / viewportSize;\n var output: FSOutput;\n${this._fsMain}\n return output;\n}\n`;\n\n return fs;\n }\n\n private _updateBindGroups() {\n const bindGroups: GPUBindGroup[] = [];\n const device = this._device;\n const uniformBindGroupIndex = this._inputs.length > 0 ? 1 : 0;\n if (this._uniforms.length > 0) {\n bindGroups[uniformBindGroupIndex] = device.createBindGroup({\n label: this._label,\n layout: this._pipeline.getBindGroupLayout(uniformBindGroupIndex),\n entries: this._uniforms.map(\n (uniform, idx) =>\n ({\n binding: idx,\n resource: {\n buffer: this._uniformBuffers[uniform.label]\n }\n } satisfies GPUBindGroupEntry)\n )\n });\n }\n\n this._bindGroups = bindGroups;\n }\n\n createPass(\n commandEncoder: GPUCommandEncoder,\n inputs: Record<I, GPUTexture>,\n\n /**\n * Explict outputs. Used for buffers reuse.\n */\n outputs?: Record<O, GPUTexture>\n ) {\n if (this._needsUpdateOutputTextures && !this._renderToScreen) {\n this._updateOutputTextures(Object.keys(outputs || {}));\n this._needsUpdateOutputTextures = false;\n }\n\n if (this._regionNames.length) {\n const values = new Uint32Array(this._regionNames.length * 4);\n for (const [index, name] of this._regionNames.entries()) {\n const region = textureRegion(inputs[name as I]);\n values.set([region.width, region.height], index * 4);\n }\n this.setUniform('imageRegions', values);\n }\n for (const texture of Object.values(this._outputTextures)) setTextureRegion(texture, this._width, this._height);\n this._updatePipeline();\n\n const inputsLen = this._inputs.length;\n if (inputsLen > 0) {\n this._bindGroups[0] = this._device.createBindGroup({\n label: this._label,\n layout: this._pipeline.getBindGroupLayout(0),\n entries: [\n ...this._inputs.map((textureName, idx) => ({\n binding: idx,\n resource: inputs[textureName as I].createView(\n this._inputViewDimensions[textureName as I]\n ? { dimension: this._inputViewDimensions[textureName as I] }\n : undefined\n )\n })),\n ...Object.keys(this._samplers).map((samplerName, idx) => ({\n binding: idx + inputsLen,\n resource: this._samplers[samplerName]\n }))\n ]\n });\n }\n\n const outputTextures = {\n // Pick the texture from outputTextures first.\n ...this._outputTextures,\n ...outputs\n } as Record<string, GPUTexture>;\n // Begin the render pass\n const renderPass = commandEncoder.beginRenderPass({\n colorAttachments: this._renderToScreen\n ? [\n {\n view: this._renderToScreen.screenTexture.createView(),\n clearValue: { r: 0, g: 0, b: 0, a: 0 },\n storeOp: 'store',\n loadOp: 'clear'\n }\n ]\n : this._outputs.map(\n (textureName) =>\n ({\n view: outputTextures[textureName].createView(),\n clearValue: { r: 0, g: 0, b: 0, a: 0 },\n loadOp: 'clear',\n storeOp: 'store'\n } satisfies GPURenderPassColorAttachment)\n )\n });\n\n // Draw a full quad\n renderPass.setViewport(0, 0, this._width, this._height, 0, 1);\n renderPass.setScissorRect(0, 0, this._width, this._height);\n renderPass.setPipeline(this._pipeline);\n // Bind groups\n this._bindGroups.forEach((bindGroup, idx) => {\n renderPass.setBindGroup(idx, bindGroup);\n });\n renderPass.draw(6, 1, 0, 0);\n // End the render pass\n renderPass.end();\n }\n}\n"]}
1
+ {"version":3,"file":"WGPUFullQuadPass.js","sourceRoot":"","sources":["../../src/renderer/WGPUFullQuadPass.ts"],"names":[],"mappings":"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","sourcesContent":["import {scratchWGSLFunctions} from './scratchSampling.js';\nimport {setTextureRegion, textureRegion} from './textureRegion.js';\nimport { getTargetShaderCache } from './WGPUShaderCache.js';\nimport { textureBytes } from './gpuMemory.js';\nexport const fullScreenQuadVertexShaderWGSL = /*wgsl */ `\n@vertex\nfn main(\n @builtin(vertex_index) vertexIndex: u32\n) -> @builtin(position) vec4f {\n const pos = array(\n vec2(-1.0, -1.0), vec2(1.0, -1.0), vec2(-1.0, 1.0),\n vec2(-1.0, 1.0), vec2(1.0, -1.0), vec2(1.0, 1.0),\n );\n\n return vec4<f32>(pos[vertexIndex], 0.0, 1.0);\n}\n`;\n\nfunction isTextureParamsEqual(\n params: WGPUFullQuadPassOutput,\n other: WGPUFullQuadPassOutput\n) {\n return params.format === other.format;\n}\n\nexport function getUniformBuffer(\n value: any,\n type: Uniform['type']\n): Float32Array | Int32Array | Uint32Array {\n if (\n value instanceof Float32Array ||\n value instanceof Int32Array ||\n value instanceof Uint32Array\n ) {\n return value;\n }\n\n if (typeof value === 'number') {\n value = [value];\n }\n\n if (type === 'i32' || type.endsWith('i')) {\n return new Int32Array(value);\n } else if (type === 'u32' || type.endsWith('u')) {\n return new Uint32Array(value);\n } else {\n return new Float32Array(value);\n }\n}\n\nexport interface Uniform {\n label: string;\n type:\n | `array<vec4u, ${number}>`\n | 'f32'\n | 'i32'\n | 'u32'\n | 'vec3f'\n | 'vec4f'\n | 'vec2f'\n | 'vec2i'\n | 'vec3i'\n | 'vec4i'\n | 'vec2u'\n | 'vec3u'\n | 'vec4u';\n data: Float32Array | Int32Array | Uint32Array | number | number[];\n}\n\nexport interface WGPUFullQuadPassOutput {\n format: GPUTextureFormat;\n}\nexport class WGPUFullQuadPass<I extends string, O extends string> {\n private _label;\n\n private _device;\n private _outputTextures: Record<string, GPUTexture> = {};\n private _outputParams: Record<string, WGPUFullQuadPassOutput> = {};\n\n private _pipeline!: GPURenderPipeline;\n private _bindGroups: GPUBindGroup[] = [];\n private _needsUpdatePipeline = true;\n private _needsUpdateOutputTextures = true;\n /**\n * When render to canvas\n */\n private _renderToScreen?: {\n screenTexture: GPUTexture;\n presentationFormat: GPUTextureFormat;\n };\n private _inputs: string[] = [];\n private _inputViewDimensions: Partial<\n Record<I, GPUTextureViewDimension>\n > = {};\n private _outputs: string[] = [];\n private _uniforms: Uniform[] = [];\n private _uniformsMap: Record<string, Uniform> = {};\n private _uniformBuffers: Record<string, GPUBuffer> = {};\n\n private _samplers: Record<string, GPUSampler> = {};\n\n private _capacityWidth = 0;\n private _capacityHeight = 0;\n private _reserveCapacity = false;\n private _regionNames: string[] = [];\n private _width = 10;\n private _height = 10;\n\n private _fsCode = '';\n private readonly _fsMain;\n private readonly _fsDefine;\n\n private _textureWillBeRead;\n\n constructor(\n label: string,\n device: GPUDevice,\n opts: {\n inputs: I[];\n inputViewDimensions?: Partial<Record<I, GPUTextureViewDimension>>;\n outputs: O[];\n samplers?: Record<string, GPUSampler>;\n fsMain: string;\n fsDefine?: string;\n uniforms?: Uniform[];\n textureWillBeRead?: boolean;\n }\n ) {\n this._label = label;\n this._device = device;\n this._fsMain = opts.fsMain;\n this._fsDefine = opts.fsDefine;\n this._inputs = opts.inputs;\n this._inputViewDimensions = opts.inputViewDimensions || {};\n this._outputs = opts.outputs;\n this._uniforms = (opts.uniforms || []).concat({\n label: 'viewportSize',\n type: 'vec2f',\n data: [0, 0]\n });\n this._samplers = opts.samplers || {};\n this._uniformsMap = this._uniforms.reduce((map, uniform) => {\n map[uniform.label] = uniform;\n return map;\n }, {} as Record<string, Uniform>);\n this._textureWillBeRead = opts.textureWillBeRead || false;\n\n this._uniforms.forEach((uniform) => {\n const data = getUniformBuffer(uniform.data, uniform.type);\n this._uniformBuffers[uniform.label] = device.createBuffer({\n label: this._label,\n size: data.byteLength,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n });\n this._device.queue.writeBuffer(\n this._uniformBuffers[uniform.label],\n 0,\n data\n );\n });\n }\n\n /** Keep physical outputs large enough for every render while varying the logical viewport. */\n reserveCapacity() {\n if (this._reserveCapacity) return;\n this._reserveCapacity = true;\n this._capacityWidth = this._width; this._capacityHeight = this._height;\n const textures = this._inputs.filter(name => !this._inputViewDimensions[name as I] || this._inputViewDimensions[name as I] === '2d');\n this._regionNames = textures;\n if (textures.length) {\n const uniform: Uniform = {label: 'imageRegions', type: `array<vec4u, ${textures.length}>`, data: new Uint32Array(textures.length * 4)};\n this._uniforms.push(uniform); this._uniformsMap[uniform.label] = uniform;\n this._uniformBuffers[uniform.label] = this._device.createBuffer({label: `${this._label}.${uniform.label}`, size: textures.length * 16, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST});\n }\n this._needsUpdatePipeline = true; this._fsCode = '';\n }\n setSize(width: number, height: number) {\n width = Math.max(1, Math.ceil(width));\n height = Math.max(1, Math.ceil(height));\n const sizeChanged = width !== this._width || height !== this._height;\n this._width = width;\n this._height = height;\n if (sizeChanged) {\n const nextWidth = Math.max(this._capacityWidth, width);\n const nextHeight = Math.max(this._capacityHeight, height);\n this._needsUpdateOutputTextures ||= !this._reserveCapacity || nextWidth !== this._capacityWidth || nextHeight !== this._capacityHeight;\n this._capacityWidth = nextWidth; this._capacityHeight = nextHeight;\n this._needsUpdatePipeline = true;\n\n this.setUniform('viewportSize', [width, height]);\n }\n }\n\n setOutputParams(outputParams: Record<O, WGPUFullQuadPassOutput>) {\n const wasScreen = !!this._renderToScreen;\n this._renderToScreen = undefined;\n const outputsChanged = Object.keys(outputParams).some(\n (key) =>\n !isTextureParamsEqual(\n (outputParams as any)[key],\n this._outputParams[key] || ({} as WGPUFullQuadPassOutput)\n )\n );\n this._needsUpdateOutputTextures ||= outputsChanged;\n this._needsUpdatePipeline ||= outputsChanged || wasScreen;\n if (outputsChanged || wasScreen) this._fsCode = '';\n this._outputParams = outputParams;\n }\n\n setRenderToScreen(\n screenTexture: GPUTexture,\n presentationFormat: GPUTextureFormat\n ) {\n if (\n !this._renderToScreen ||\n this._renderToScreen.presentationFormat !== presentationFormat\n ) {\n this._needsUpdatePipeline = true;\n this._fsCode = '';\n }\n this._renderToScreen = {\n screenTexture,\n presentationFormat\n };\n }\n\n setUniform(label: string, data: Uniform['data']) {\n const buffer = this._uniformBuffers[label];\n this._device.queue.writeBuffer(\n buffer,\n 0,\n getUniformBuffer(data, this._uniformsMap[label].type)\n );\n }\n\n private readonly _retainedOutputs = new Set<GPUTexture>();\n retainOutput(texture: GPUTexture) { if (Object.values(this._outputTextures).includes(texture)) this._retainedOutputs.add(texture); }\n releaseOutput(texture: GPUTexture) {\n if (!this._retainedOutputs.delete(texture)) return;\n if (!Object.values(this._outputTextures).includes(texture)) {\n void this._device.queue.onSubmittedWorkDone().catch(() => undefined).then(() => texture.destroy());\n }\n }\n\n getOutput(name: O) {\n return this._outputTextures[name];\n }\n\n getMemoryBytes() {\n return Object.values(this._uniformBuffers).reduce((sum, buffer) => sum + buffer.size, 0)\n + Array.from(new Set([...Object.values(this._outputTextures), ...this._retainedOutputs]))\n .reduce((sum, texture) => sum + textureBytes(texture), 0);\n }\n\n dispose() {\n Object.keys(this._uniformBuffers).forEach((key) => {\n (this._uniformBuffers as any)[key].destroy();\n });\n new Set([...Object.values(this._outputTextures), ...this._retainedOutputs]).forEach(texture => texture.destroy());\n this._retainedOutputs.clear();\n }\n\n private _createTexture(params: WGPUFullQuadPassOutput) {\n return this._device.createTexture({\n label: this._label,\n size: {\n width: this._reserveCapacity ? this._capacityWidth : this._width,\n height: this._reserveCapacity ? this._capacityHeight : this._height,\n depthOrArrayLayers: 1\n },\n format: params.format,\n usage:\n GPUTextureUsage.RENDER_ATTACHMENT |\n GPUTextureUsage.TEXTURE_BINDING |\n (this._textureWillBeRead ? GPUTextureUsage.COPY_SRC : 0)\n });\n }\n\n private _updateOutputTextures(excludes?: string[]) {\n const outputParams = this._outputParams;\n for (const key in outputParams) {\n if (excludes?.includes(key)) {\n continue;\n }\n const params = outputParams[key];\n if (!this._retainedOutputs.has(this._outputTextures[key])) this._outputTextures[key]?.destroy();\n this._outputTextures[key] = this._createTexture(params);\n }\n }\n\n private _updatePipeline() {\n if (!this._needsUpdatePipeline) {\n return;\n }\n this._needsUpdatePipeline = false;\n\n const outputParams = this._outputParams;\n const device = this._device;\n const fsCode = this._getFullFs();\n if (fsCode === this._fsCode) {\n return;\n }\n const { screenTexture, presentationFormat } = this._renderToScreen || {};\n this._fsCode = fsCode;\n this._pipeline = getTargetShaderCache(device).createRenderPipeline({\n label: this._label,\n layout: 'auto',\n vertex: {\n module: getTargetShaderCache(device).createShaderModule({\n label: this._label,\n code: fullScreenQuadVertexShaderWGSL\n }),\n entryPoint: 'main'\n },\n fragment: {\n module: getTargetShaderCache(device).createShaderModule({\n label: this._label,\n code: fsCode\n }),\n entryPoint: 'main',\n targets: screenTexture\n ? [\n {\n format: presentationFormat!\n }\n ]\n : this._outputs.map((key) => ({\n format: (outputParams as any)[key].format\n }))\n },\n primitive: {\n topology: 'triangle-list'\n }\n });\n this._updateBindGroups();\n }\n\n private _getFullFs() {\n const inputs = this._inputs;\n const inputsLen = inputs.length;\n const hasInputs = inputsLen > 0;\n const fs = /* wgsl */ `\n${inputs\n .sort()\n .map(\n (textureName, idx) => {\n const viewDimension = this._inputViewDimensions[textureName as I];\n const textureType = viewDimension === '3d' ? 'texture_3d' : 'texture_2d';\n return `@group(0) @binding(${idx}) var ${textureName}: ${textureType}<f32>;`;\n }\n )\n .join('\\n')}\n\n${\n hasInputs\n ? Object.keys(this._samplers)\n .sort()\n .map(\n (samplerName, idx) =>\n `@group(0) @binding(${\n idx + inputsLen\n }) var ${samplerName}: sampler;`\n )\n .join('\\n')\n : ''\n}\n${this._uniforms\n .map(\n (uniform, idx) =>\n `@group(${hasInputs ? 1 : 0}) @binding(${idx}) var<uniform> ${\n uniform.label\n }: ${uniform.type};`\n )\n .join('\\n')}\nstruct FSOutput {\n${this._outputs\n .map((name, idx) => `@location(${idx}) ${name}: vec4f,`)\n .join('\\n')}\n}\n${scratchWGSLFunctions(\n this._reserveCapacity ? this._regionNames : inputs.filter(name =>\n !this._inputViewDimensions[name as I] || this._inputViewDimensions[name as I] === '2d'),\n Object.keys(this._samplers), this._reserveCapacity\n)}\n${this._fsDefine ?? ''}\n@fragment\nfn main(\n @builtin(position) coord: vec4f\n) -> FSOutput {\n let uv = vec2i(floor(coord.xy));\n let uv2 = coord.xy / viewportSize;\n var output: FSOutput;\n${this._fsMain}\n return output;\n}\n`;\n\n return fs;\n }\n\n private _updateBindGroups() {\n const bindGroups: GPUBindGroup[] = [];\n const device = this._device;\n const uniformBindGroupIndex = this._inputs.length > 0 ? 1 : 0;\n if (this._uniforms.length > 0) {\n bindGroups[uniformBindGroupIndex] = device.createBindGroup({\n label: this._label,\n layout: this._pipeline.getBindGroupLayout(uniformBindGroupIndex),\n entries: this._uniforms.map(\n (uniform, idx) =>\n ({\n binding: idx,\n resource: {\n buffer: this._uniformBuffers[uniform.label]\n }\n } satisfies GPUBindGroupEntry)\n )\n });\n }\n\n this._bindGroups = bindGroups;\n }\n\n createPass(\n commandEncoder: GPUCommandEncoder,\n inputs: Record<I, GPUTexture>,\n\n /**\n * Explict outputs. Used for buffers reuse.\n */\n outputs?: Record<O, GPUTexture>\n ) {\n if (this._needsUpdateOutputTextures && !this._renderToScreen) {\n this._updateOutputTextures(Object.keys(outputs || {}));\n this._needsUpdateOutputTextures = false;\n }\n\n if (this._regionNames.length) {\n const values = new Uint32Array(this._regionNames.length * 4);\n for (const [index, name] of this._regionNames.entries()) {\n const region = textureRegion(inputs[name as I]);\n values.set([region.width, region.height], index * 4);\n }\n this.setUniform('imageRegions', values);\n }\n for (const texture of Object.values(this._outputTextures)) setTextureRegion(texture, this._width, this._height);\n this._updatePipeline();\n\n const inputsLen = this._inputs.length;\n if (inputsLen > 0) {\n this._bindGroups[0] = this._device.createBindGroup({\n label: this._label,\n layout: this._pipeline.getBindGroupLayout(0),\n entries: [\n ...this._inputs.map((textureName, idx) => ({\n binding: idx,\n resource: inputs[textureName as I].createView(\n this._inputViewDimensions[textureName as I]\n ? { dimension: this._inputViewDimensions[textureName as I] }\n : undefined\n )\n })),\n ...Object.keys(this._samplers).map((samplerName, idx) => ({\n binding: idx + inputsLen,\n resource: this._samplers[samplerName]\n }))\n ]\n });\n }\n\n const outputTextures = {\n // Pick the texture from outputTextures first.\n ...this._outputTextures,\n ...outputs\n } as Record<string, GPUTexture>;\n // Begin the render pass\n const renderPass = commandEncoder.beginRenderPass({\n colorAttachments: this._renderToScreen\n ? [\n {\n view: this._renderToScreen.screenTexture.createView(),\n clearValue: { r: 0, g: 0, b: 0, a: 0 },\n storeOp: 'store',\n loadOp: 'clear'\n }\n ]\n : this._outputs.map(\n (textureName) =>\n ({\n view: outputTextures[textureName].createView(),\n clearValue: { r: 0, g: 0, b: 0, a: 0 },\n loadOp: 'clear',\n storeOp: 'store'\n } satisfies GPURenderPassColorAttachment)\n )\n });\n\n // Draw a full quad\n renderPass.setViewport(0, 0, this._width, this._height, 0, 1);\n renderPass.setScissorRect(0, 0, this._width, this._height);\n renderPass.setPipeline(this._pipeline);\n // Bind groups\n this._bindGroups.forEach((bindGroup, idx) => {\n renderPass.setBindGroup(idx, bindGroup);\n });\n renderPass.draw(6, 1, 0, 0);\n // End the render pass\n renderPass.end();\n }\n}\n"]}
@@ -1,25 +1,6 @@
1
1
  import { type JNLMFilterShape } from './jnlm.js';
2
+ export { createJNLMFilterWGSL, jnlmGuideWGSL, jnlmVarianceWGSL, jnlmLoadColorWGSL, JNLM_WORKGROUP_SIZE } from './wgsl/jnlm.compute.js';
2
3
  /** WebGPU passes of the JNLM denoiser described in `jnlm.ts`. */
3
- export declare const JNLM_WORKGROUP_SIZE = 8;
4
- /**
5
- * Pass 1: the guide mean and the variance of that mean from the accumulated
6
- * moments. Ray buffers are stored bottom-up; guides use texture rows.
7
- */
8
- export declare const jnlmGuideWGSL: string;
9
- /**
10
- * Pass 2: smooth the noisy per-pixel variance over 3 x 3 pixels. Pixels with
11
- * a single sample take the spatial variance of their neighborhood instead.
12
- */
13
- export declare const jnlmVarianceWGSL = "\n\nstruct JNLMParams {\n size: vec2u,\n colorSensitivity: f32,\n // Pixel spacing of the search window and patches in this pass.\n dilation: f32,\n}\n@group(0) @binding(0) var<uniform> params: JNLMParams;\n\n@group(0) @binding(1) var<storage, read> rawGuide: array<vec2f>;\n@group(0) @binding(2) var<storage, read_write> guide: array<vec2f>;\n\n@compute @workgroup_size(8, 8, 1)\nfn main(@builtin(global_invocation_id) id: vec3u) {\n let size = params.size;\n if (id.x >= size.x || id.y >= size.y) { return; }\n let center = rawGuide[id.x + id.y * size.x];\n var varianceSum = 0.0;\n var varianceCount = 0.0;\n var meanSum = 0.0;\n var meanSquareSum = 0.0;\n for (var dy = -1; dy <= 1; dy++) {\n for (var dx = -1; dx <= 1; dx++) {\n let q = clamp(vec2i(id.xy) + vec2i(dx, dy), vec2i(0), vec2i(size) - 1);\n let value = rawGuide[u32(q.x) + u32(q.y) * size.x];\n meanSum += value.x;\n meanSquareSum += value.x * value.x;\n if (value.y >= 0.0) {\n varianceSum += value.y;\n varianceCount += 1.0;\n }\n }\n }\n var variance: f32;\n if (center.y >= 0.0) {\n variance = varianceSum / varianceCount;\n } else {\n let spatialMean = meanSum / 9.0;\n variance = max(meanSquareSum / 9.0 - spatialMean * spatialMean, 0.0) * 9.0 / 8.0;\n }\n guide[id.x + id.y * size.x] = vec2f(center.x, variance);\n}\n";
14
- /** Copies the composed image into the filter's color buffer. */
15
- export declare const jnlmLoadColorWGSL = "\n\nstruct JNLMParams {\n size: vec2u,\n colorSensitivity: f32,\n // Pixel spacing of the search window and patches in this pass.\n dilation: f32,\n}\n@group(0) @binding(0) var<uniform> params: JNLMParams;\n\n@group(0) @binding(1) var colorTex: texture_2d<f32>;\n@group(0) @binding(2) var<storage, read_write> outColor: array<vec4f>;\n\n@compute @workgroup_size(8, 8, 1)\nfn main(@builtin(global_invocation_id) id: vec3u) {\n if (id.x >= params.size.x || id.y >= params.size.y) { return; }\n outColor[id.x + id.y * params.size.x] = textureLoad(colorTex, vec2i(id.xy), 0);\n}\n";
16
- /**
17
- * Pass 3: the joint NL-means filter of the composed image. It also filters
18
- * the guide with the same weights, with the variance of the weighted mean,
19
- * for a following pass. The albedo regression corrects color only, keeping
20
- * uncertain fitted texture responses out of the matching guide.
21
- */
22
- export declare function createJNLMFilterWGSL({ searchRadius, patchRadius, albedoBandwidth, normalBandwidth }?: JNLMFilterShape): string;
23
4
  export interface JNLMInputs {
24
5
  width: number;
25
6
  height: number;
@@ -1,267 +1,7 @@
1
1
  import { getTargetShaderCache } from './WGPUShaderCache.js';
2
- import shadowCatcherAccumulationWGSL from './wgsl/chunks/shadowCatcherAccumulation.wgsl.js';
3
- import { JNLM_DEFAULT_COLOR_SENSITIVITY, JNLM_DEFAULT_SHAPE, JNLM_ALBEDO_FLOOR, JNLM_ALBEDO_REGULARIZATION, JNLM_COVERAGE_BANDWIDTH, JNLM_MAX_ITERATIONS, jnlmPassDilation } from './jnlm.js';
4
- /** WebGPU passes of the JNLM denoiser described in `jnlm.ts`. */
5
- export const JNLM_WORKGROUP_SIZE = 8;
6
- const paramsWGSL = /* wgsl */ `
7
- struct JNLMParams {
8
- size: vec2u,
9
- colorSensitivity: f32,
10
-
11
- dilation: f32,
12
- }
13
- @group(0) @binding(0) var<uniform> params: JNLMParams;
14
- `;
15
- /**
16
- * Pass 1: the guide mean and the variance of that mean from the accumulated
17
- * moments. Ray buffers are stored bottom-up; guides use texture rows.
18
- */
19
- export const jnlmGuideWGSL = /* wgsl */ `
20
- ${paramsWGSL}
21
- ${shadowCatcherAccumulationWGSL}
22
- @group(0) @binding(1) var<storage, read> accumulation: array<ShadowCatcherAccumulation>;
23
- @group(0) @binding(2) var<storage, read> normalBuffer: array<vec4f>;
24
- @group(0) @binding(3) var<storage, read_write> rawGuide: array<vec2f>;
25
-
26
- @compute @workgroup_size(${JNLM_WORKGROUP_SIZE}, ${JNLM_WORKGROUP_SIZE}, 1)
27
- fn main(@builtin(global_invocation_id) id: vec3u) {
28
- let size = params.size;
29
- if (id.x >= size.x || id.y >= size.y) { return; }
30
- let ua = id.x + (size.y - 1u - id.y) * size.x;
31
- let n = normalBuffer[ua].a;
32
- let moments = accumulation[ua].moments;
33
- let mean = moments.x / max(n, 1.0);
34
-
35
- var variance = -1.0;
36
- if (n >= 2.0) {
37
- variance = max(moments.y - n * mean * mean, 0.0) / (n * (n - 1.0));
38
- }
39
- rawGuide[id.x + id.y * size.x] = vec2f(mean, variance);
40
- }
41
- `;
42
- /**
43
- * Pass 2: smooth the noisy per-pixel variance over 3 x 3 pixels. Pixels with
44
- * a single sample take the spatial variance of their neighborhood instead.
45
- */
46
- export const jnlmVarianceWGSL = /* wgsl */ `
47
- ${paramsWGSL}
48
- @group(0) @binding(1) var<storage, read> rawGuide: array<vec2f>;
49
- @group(0) @binding(2) var<storage, read_write> guide: array<vec2f>;
50
-
51
- @compute @workgroup_size(${JNLM_WORKGROUP_SIZE}, ${JNLM_WORKGROUP_SIZE}, 1)
52
- fn main(@builtin(global_invocation_id) id: vec3u) {
53
- let size = params.size;
54
- if (id.x >= size.x || id.y >= size.y) { return; }
55
- let center = rawGuide[id.x + id.y * size.x];
56
- var lu = 0.0;
57
- var jc = 0.0;
58
- var mY = 0.0;
59
- var iX = 0.0;
60
- for (var dy = -1; dy <= 1; dy++) {
61
- for (var dx = -1; dx <= 1; dx++) {
62
- let q = clamp(vec2i(id.xy) + vec2i(dx, dy), vec2i(0), vec2i(size) - 1);
63
- let value = rawGuide[u32(q.x) + u32(q.y) * size.x];
64
- mY += value.x;
65
- iX += value.x * value.x;
66
- if (value.y >= 0.0) {
67
- lu += value.y;
68
- jc += 1.0;
69
- }
70
- }
71
- }
72
- var variance: f32;
73
- if (center.y >= 0.0) {
74
- variance = lu / jc;
75
- } else {
76
- let lt = mY / 9.0;
77
- variance = max(iX / 9.0 - lt * lt, 0.0) * 9.0 / 8.0;
78
- }
79
- guide[id.x + id.y * size.x] = vec2f(center.x, variance);
80
- }
81
- `;
82
- /** Copies the composed image into the filter's color buffer. */
83
- export const jnlmLoadColorWGSL = /* wgsl */ `
84
- ${paramsWGSL}
85
- @group(0) @binding(1) var colorTex: texture_2d<f32>;
86
- @group(0) @binding(2) var<storage, read_write> outColor: array<vec4f>;
87
-
88
- @compute @workgroup_size(${JNLM_WORKGROUP_SIZE}, ${JNLM_WORKGROUP_SIZE}, 1)
89
- fn main(@builtin(global_invocation_id) id: vec3u) {
90
- if (id.x >= params.size.x || id.y >= params.size.y) { return; }
91
- outColor[id.x + id.y * params.size.x] = textureLoad(colorTex, vec2i(id.xy), 0);
92
- }
93
- `;
94
- /**
95
- * Pass 3: the joint NL-means filter of the composed image. It also filters
96
- * the guide with the same weights, with the variance of the weighted mean,
97
- * for a following pass. The albedo regression corrects color only, keeping
98
- * uncertain fitted texture responses out of the matching guide.
99
- */
100
- export function createJNLMFilterWGSL({ searchRadius, patchRadius, albedoBandwidth, normalBandwidth } = JNLM_DEFAULT_SHAPE) {
101
- const patchSize = (2 * patchRadius + 1) ** 2;
102
- return /* wgsl */ `
103
- ${paramsWGSL}
104
- @group(0) @binding(1) var<storage, read> guide: array<vec2f>;
105
- @group(0) @binding(2) var<storage, read> color: array<vec4f>;
106
- @group(0) @binding(3) var albedoTex: texture_2d<f32>;
107
- @group(0) @binding(4) var normalTex: texture_2d<f32>;
108
- @group(0) @binding(5) var<storage, read_write> outColor: array<vec4f>;
109
- @group(0) @binding(6) var<storage, read_write> outGuide: array<vec2f>;
110
- @group(0) @binding(7) var shadowCatcherTex: texture_2d<f32>;
111
-
112
- const SEARCH_RADIUS = ${searchRadius};
113
- const PATCH_RADIUS = ${patchRadius};
114
- const PATCH_SIZE = ${patchSize};
115
-
116
- const VARIANCE_CANCELLATION = 1.0;
117
-
118
- const INV_ALBEDO_BANDWIDTH2 = ${(1 / albedoBandwidth ** 2).toFixed(6)};
119
- const INV_COVERAGE_BANDWIDTH2 = ${(1 / JNLM_COVERAGE_BANDWIDTH ** 2).toFixed(6)};
120
- const INV_NORMAL_BANDWIDTH2 = ${(1 / normalBandwidth ** 2).toFixed(6)};
121
-
122
-
123
- const CENTER_WEIGHT_MIN = 0.01;
124
-
125
- fn hg(p: vec2i) -> u32 {
126
- let q = clamp(p, vec2i(0), vec2i(params.size) - 1);
127
- return u32(q.x) + u32(q.y) * params.size.x;
128
- }
129
-
130
- fn lw(q: vec2i, bs: vec4f, gT: vec3f) -> f32 {
131
- let albedo = textureLoad(albedoTex, q, 0);
132
-
133
-
134
- let pf = max((albedo.rgb + bs.rgb) * 0.5, vec3f(${JNLM_ALBEDO_FLOOR}));
135
- let ld = (albedo.rgb - bs.rgb) / pf;
136
- let iU = albedo.a - bs.a;
137
- let lp = textureLoad(normalTex, q, 0).rgb - gT;
138
- return max(
139
- dot(ld, ld) * INV_ALBEDO_BANDWIDTH2
140
- + iU * iU * INV_COVERAGE_BANDWIDTH2,
141
- dot(lp, lp) * INV_NORMAL_BANDWIDTH2
142
- );
143
- }
144
-
145
- fn premultiplied(c: vec4f) -> vec4f {
146
- return vec4f(c.rgb * c.a, c.a);
147
- }
148
-
149
- @compute @workgroup_size(${JNLM_WORKGROUP_SIZE}, ${JNLM_WORKGROUP_SIZE}, 1)
150
- fn main(@builtin(global_invocation_id) id: vec3u) {
151
- let size = vec2i(params.size);
152
- let p = vec2i(id.xy);
153
- if (p.x >= size.x || p.y >= size.y) { return; }
154
- let step = i32(params.dilation);
155
- let bs = textureLoad(albedoTex, p, 0);
156
- let fD = textureLoad(normalTex, p, 0);
157
- let gT = fD.rgb;
158
- let index = hg(p);
159
-
160
-
161
- if (fD.a <= 0.0 && textureLoad(shadowCatcherTex, p, 0).r <= 0.0) {
162
- outColor[index] = color[index];
163
- outGuide[index] = guide[index];
164
- return;
165
- }
166
-
167
- var lf: array<vec2f, PATCH_SIZE>;
168
- var k = 0;
169
- for (var dy = -PATCH_RADIUS; dy <= PATCH_RADIUS; dy++) {
170
- for (var dx = -PATCH_RADIUS; dx <= PATCH_RADIUS; dx++) {
171
- lf[k] = guide[hg(p + vec2i(dx, dy) * step)];
172
- k++;
173
- }
174
- }
175
- let k2 = params.colorSensitivity * params.colorSensitivity;
176
-
177
- var sum = vec4f(0.0);
178
- let gW = max(bs.rgb, vec3f(${JNLM_ALBEDO_FLOOR}));
179
- var mp = vec3f(0.0);
180
- var gy = vec3f(0.0);
181
- var hs = vec3f(0.0);
182
- var ps = 0.0;
183
- var gA = 0.0;
184
- var nU = 0.0;
185
- var kM = 0.0;
186
- for (var sy = -SEARCH_RADIUS; sy <= SEARCH_RADIUS; sy++) {
187
- for (var sx = -SEARCH_RADIUS; sx <= SEARCH_RADIUS; sx++) {
188
- let q = p + vec2i(sx, sy) * step;
189
- if (
190
- (sx == 0 && sy == 0) ||
191
- q.x < 0 || q.y < 0 || q.x >= size.x || q.y >= size.y
192
- ) { continue; }
193
-
194
- let features = lw(q, bs, gT);
195
- if (features > 16.0) { continue; }
196
-
197
- var fY = 0.0;
198
- k = 0;
199
- for (var dy = -PATCH_RADIUS; dy <= PATCH_RADIUS; dy++) {
200
- for (var dx = -PATCH_RADIUS; dx <= PATCH_RADIUS; dx++) {
201
- let a = lf[k];
202
- let b = guide[hg(q + vec2i(dx, dy) * step)];
203
- let qU = a.x - b.x;
204
- fY += (qU * qU
205
- - VARIANCE_CANCELLATION * (a.y + min(a.y, b.y)))
206
- / (1e-10 + k2 * (a.y + b.y));
207
- k++;
208
- }
209
- }
210
- fY /= f32(PATCH_SIZE);
211
-
212
- let weight = exp(-max(max(fY, 0.0), features));
213
- let index = hg(q);
214
- let c = color[index];
215
- let g = guide[index];
216
-
217
- let a = (textureLoad(albedoTex, q, 0).rgb - bs.rgb) / gW;
218
- let value = premultiplied(c);
219
- sum += value * weight;
220
- mp += a * weight;
221
- gy += a * a * weight;
222
- hs += a * value.rgb * weight;
223
- ps += g.x * weight;
224
- gA += g.y * weight * weight;
225
- nU += weight;
226
- kM = max(kM, weight);
227
- }
228
- }
229
-
230
-
231
-
232
- let center = color[index];
233
- let le = guide[index];
234
- let dG = max(kM, CENTER_WEIGHT_MIN);
235
- let totalWeight = nU + dG;
236
- let tM = premultiplied(center);
237
- let mean = (sum + tM * dG) / totalWeight;
238
-
239
-
240
- let ez = mp / totalWeight;
241
- let lA = max(gy / totalWeight - ez * ez, vec3f(0.0));
242
- let qu = hs / totalWeight - ez * mean.rgb;
243
-
244
-
245
-
246
- let qE = bs.rgb + ez * gW;
247
- let oz = mean.rgb * gW / max(qE, vec3f(${JNLM_ALBEDO_FLOOR}));
248
- let vB = clamp(qu / (lA + vec3f(${JNLM_ALBEDO_REGULARIZATION})), vec3f(0.0), oz);
249
- let rD = mean.rgb - vB * ez;
250
- let filtered = vec4f(max(rD, vec3f(0.0)), max(mean.a, 0.0));
251
- let rgb = select(
252
- center.rgb,
253
- filtered.rgb / max(filtered.a, 1e-6),
254
- filtered.a > 1e-6
255
- );
256
- outColor[index] = vec4f(rgb, filtered.a);
257
- outGuide[index] = vec2f(
258
- (ps + le.x * dG) / totalWeight,
259
- (gA + le.y * dG * dG)
260
- / (totalWeight * totalWeight)
261
- );
262
- }
263
- `;
264
- }
2
+ import { JNLM_MAX_ITERATIONS } from './jnlm.js';
3
+ import { JNLM_WORKGROUP_SIZE, jnlmGuideWGSL, jnlmVarianceWGSL, jnlmLoadColorWGSL, createJNLMFilterWGSL, packJNLMParameters } from './wgsl/jnlm.compute.js';
4
+ export { createJNLMFilterWGSL, jnlmGuideWGSL, jnlmVarianceWGSL, jnlmLoadColorWGSL, JNLM_WORKGROUP_SIZE } from './wgsl/jnlm.compute.js';
265
5
  const MAX_ITERATIONS = JNLM_MAX_ITERATIONS;
266
6
  export class WGPUJNLMDenoisePass {
267
7
  _device;
@@ -337,12 +77,9 @@ export class WGPUJNLMDenoisePass {
337
77
  const { width, height, shape } = inputs;
338
78
  this._ensureBuffers(width, height);
339
79
  const iterations = Math.min(Math.max(Math.round(shape.iterations), 1), MAX_ITERATIONS);
340
- const sensitivity = JNLM_DEFAULT_COLOR_SENSITIVITY * Math.max(inputs.strength, 1e-3);
341
80
  this._paramsBuffers.forEach((buffer, i) => {
342
- const params = new ArrayBuffer(16);
343
- new Uint32Array(params, 0, 2).set([width, height]);
344
81
  // Buffer i (from 1) is filter pass i - 1; index 0 is the prepasses.
345
- new Float32Array(params, 8, 2).set([sensitivity, jnlmPassDilation(Math.max(i - 1, 0))]);
82
+ const params = packJNLMParameters(width, height, inputs.strength, Math.max(i - 1, 0));
346
83
  this._device.queue.writeBuffer(buffer, 0, params);
347
84
  });
348
85
  const device = this._device;
@@ -1 +1 @@
1
- {"version":3,"file":"WGPUJNLMDenoiser.js","sourceRoot":"","sources":["../../src/renderer/WGPUJNLMDenoiser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,6BAA6B,MAAM,iDAAiD,CAAC;AAE5F,OAAO,EACL,8BAA8B,EAC9B,kBAAkB,EAClB,iBAAiB,EACjB,0BAA0B,EAC1B,uBAAuB,EACvB,mBAAmB,EACnB,gBAAgB,EAEjB,MAAM,WAAW,CAAC;AAEnB,iEAAiE;AAEjE,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAErC,MAAM,UAAU,GAAG,UAAU,CAAC;;;;;;;;CAQ7B,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CAAC;EACtC,UAAU;EACV,6BAA6B;;;;;2BAKJ,mBAAmB,KAAK,mBAAmB;;;;;;;;;;;;;;;CAerE,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CAAC;EACzC,UAAU;;;;2BAIe,mBAAmB,KAAK,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BrE,CAAC;AAEF,gEAAgE;AAChE,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAC;EAC1C,UAAU;;;;2BAIe,mBAAmB,KAAK,mBAAmB;;;;;CAKrE,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,EACnC,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,eAAe,KACxC,kBAAkB;IACrC,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,WAAW,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;IAC7C,OAAO,UAAU,CAAC;EAClB,UAAU;;;;;;;;;wBASY,YAAY;uBACb,WAAW;qBACb,SAAS;;;;gCAIE,CAAC,CAAC,GAAG,eAAe,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;kCACnC,CAAC,CAAC,GAAG,uBAAuB,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;gCAC/C,CAAC,CAAC,GAAG,eAAe,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;;;;;;;;;;;;;;kDAcE,iBAAiB;;;;;;;;;;;;;;;2BAe7D,mBAAmB,KAAK,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BA6BnB,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yCAqEG,iBAAiB;kCAC5B,0BAA0B;;;;;;;;;;;;;;;CAerF,CAAC;AACF,CAAC;AAmBD,MAAM,cAAc,GAAG,mBAAmB,CAAC;AAE3C,MAAM,OAAO,mBAAmB;IACtB,OAAO,CAAY;IACnB,cAAc,GAAgB,EAAE,CAAC;IACjC,cAAc,CAAqB;IACnC,iBAAiB,CAAqB;IACtC,kBAAkB,CAAqB;IACvC,eAAe,CAAsB;IACrC,eAAe,GAAG,EAAE,CAAC;IACrB,OAAO,GAAgB,EAAE,CAAC;IAC1B,OAAO,GAAgB,EAAE,CAAC;IAC1B,MAAM,GAAG,CAAC,CAAC;IACX,OAAO,GAAG,CAAC,CAAC;IAEpB,YAAY,MAAiB;QAC3B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,sEAAsE;QACtE,iCAAiC;QACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,cAAc,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;gBAC3C,KAAK,EAAE,aAAa;gBACpB,IAAI,EAAE,EAAE;gBACR,KAAK,EAAE,cAAc,CAAC,OAAO,GAAG,cAAc,CAAC,QAAQ;aACxD,CAAC,CAAC,CAAC;QACN,CAAC;QACD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;QACxE,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,eAAe,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAC;QACjF,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;IACvF,CAAC;IAEO,eAAe,CAAC,KAAa,EAAE,IAAY;QACjD,OAAO,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,qBAAqB,CAAC;YAC9D,KAAK;YACL,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,MAAM,EAAE,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,kBAAkB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;gBAC9E,UAAU,EAAE,MAAM;aACnB;SACF,CAAC,CAAC;IACL,CAAC;IAEO,kBAAkB,CAAC,KAAsB;QAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,eAAe,IAAI,GAAG,KAAK,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1D,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC;YACxF,IAAI,CAAC,eAAe,GAAG,GAAG,CAAC;QAC7B,CAAC;QACD,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAED,eAAe,KAAI,CAAC;IACZ,cAAc,CAAC,KAAa,EAAE,MAAc;QAClD,IAAI,KAAK,IAAI,IAAI,CAAC,MAAM,IAAI,MAAM,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM;YAAE,OAAO;QAClF,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9E,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;QAC9B,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,KAAa,EAAE,EAAE,CACpD,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;YACxB,KAAK;YACL,IAAI,EAAE,MAAM,GAAG,KAAK;YACpB,KAAK,EAAE,cAAc,CAAC,OAAO,GAAG,cAAc,CAAC,QAAQ;SACxD,CAAC,CAAC;QACL,IAAI,CAAC,OAAO,GAAG,CAAC,YAAY,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,YAAY,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,CAAC;QAClF,IAAI,CAAC,OAAO,GAAG,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,CAAC,EAAE,YAAY,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC;QACpF,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACxB,CAAC;IAEO,eAAe;QACrB,KAAK,MAAM,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;YAAE,MAAM,CAAC,OAAO,EAAE,CAAC;QAC1E,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACpB,CAAC;IAED,2EAA2E;IAC3E,MAAM,CAAC,OAA0B,EAAE,MAAkB;QACnD,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;QACxC,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACnC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QACvF,MAAM,WAAW,GAAG,8BAA8B,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACrF,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACxC,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,EAAE,CAAC,CAAC;YACnC,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;YACnD,oEAAoE;YACpE,IAAI,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACxF,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC;QAC5B,MAAM,cAAc,GAAG,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,CACX,QAA4B,EAC5B,YAAuB,EACvB,SAA+B,EAC/B,EAAE,CACF,MAAM,CAAC,eAAe,CAAC;YACrB,MAAM,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAAC;YACtC,OAAO,EAAE;gBACP,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE;gBAClD,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;aAClE;SACF,CAAC,CAAC;QACL,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;QACtC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,MAAM,GAAyC;YACnD,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,OAAO,EAAE;oBACvD,EAAE,MAAM,EAAE,MAAM,CAAC,YAAY,EAAE;oBAC/B,EAAE,MAAM,EAAE,MAAM,CAAC,kBAAkB,EAAE;oBACrC,EAAE,MAAM,EAAE,MAAM,EAAE;iBACnB,CAAC,CAAC;YACH,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,OAAO,EAAE;oBAC7D,EAAE,MAAM,EAAE,MAAM,EAAE;oBAClB,EAAE,MAAM,EAAE,MAAM,EAAE;iBACnB,CAAC,CAAC;YACH,CAAC,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,OAAO,EAAE;oBAC/D,MAAM,CAAC,KAAK,CAAC,UAAU,EAAE;oBACzB,EAAE,MAAM,EAAE,MAAM,EAAE;iBACnB,CAAC,CAAC;SACJ,CAAC;QACF,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QAC9C,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QAC9C,MAAM,iBAAiB,GAAG,MAAM,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC;QAC5D,IAAI,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9B,IAAI,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,CAAC,IAAI,CAAC,CAAC,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE;oBACxE,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE;oBACrB,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE;oBACrB,UAAU;oBACV,UAAU;oBACV,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE;oBACrB,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE;oBACrB,iBAAiB;iBAClB,CAAC,CAAC,CAAC,CAAC;YACL,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAChC,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAClC,CAAC;QACD,MAAM,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;QACjE,KAAK,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,MAAM,EAAE,CAAC;YAC3C,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC3B,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;YAChC,IAAI,CAAC,kBAAkB,CACrB,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,mBAAmB,CAAC,EACtC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,mBAAmB,CAAC,CACxC,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,GAAG,EAAE,CAAC;QACX,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC;IAED,cAAc;QACZ,OAAO,CAAC,GAAG,IAAI,CAAC,cAAc,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;aAC9D,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,OAAO;QACL,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,cAAc;YAAE,MAAM,CAAC,OAAO,EAAE,CAAC;QAC3D,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC;CACF","sourcesContent":["import { getTargetShaderCache } from './WGPUShaderCache.js';\nimport shadowCatcherAccumulationWGSL from './wgsl/chunks/shadowCatcherAccumulation.wgsl.js';\n\nimport {\n JNLM_DEFAULT_COLOR_SENSITIVITY,\n JNLM_DEFAULT_SHAPE,\n JNLM_ALBEDO_FLOOR,\n JNLM_ALBEDO_REGULARIZATION,\n JNLM_COVERAGE_BANDWIDTH,\n JNLM_MAX_ITERATIONS,\n jnlmPassDilation,\n type JNLMFilterShape\n} from './jnlm.js';\n\n/** WebGPU passes of the JNLM denoiser described in `jnlm.ts`. */\n\nexport const JNLM_WORKGROUP_SIZE = 8;\n\nconst paramsWGSL = /* wgsl */ `\nstruct JNLMParams {\n size: vec2u,\n colorSensitivity: f32,\n // Pixel spacing of the search window and patches in this pass.\n dilation: f32,\n}\n@group(0) @binding(0) var<uniform> params: JNLMParams;\n`;\n\n/**\n * Pass 1: the guide mean and the variance of that mean from the accumulated\n * moments. Ray buffers are stored bottom-up; guides use texture rows.\n */\nexport const jnlmGuideWGSL = /* wgsl */ `\n${paramsWGSL}\n${shadowCatcherAccumulationWGSL}\n@group(0) @binding(1) var<storage, read> accumulation: array<ShadowCatcherAccumulation>;\n@group(0) @binding(2) var<storage, read> normalBuffer: array<vec4f>;\n@group(0) @binding(3) var<storage, read_write> rawGuide: array<vec2f>;\n\n@compute @workgroup_size(${JNLM_WORKGROUP_SIZE}, ${JNLM_WORKGROUP_SIZE}, 1)\nfn main(@builtin(global_invocation_id) id: vec3u) {\n let size = params.size;\n if (id.x >= size.x || id.y >= size.y) { return; }\n let rayIndex = id.x + (size.y - 1u - id.y) * size.x;\n let n = normalBuffer[rayIndex].a;\n let moments = accumulation[rayIndex].moments;\n let mean = moments.x / max(n, 1.0);\n // Variance of the mean, or -1 when one sample cannot estimate it.\n var variance = -1.0;\n if (n >= 2.0) {\n variance = max(moments.y - n * mean * mean, 0.0) / (n * (n - 1.0));\n }\n rawGuide[id.x + id.y * size.x] = vec2f(mean, variance);\n}\n`;\n\n/**\n * Pass 2: smooth the noisy per-pixel variance over 3 x 3 pixels. Pixels with\n * a single sample take the spatial variance of their neighborhood instead.\n */\nexport const jnlmVarianceWGSL = /* wgsl */ `\n${paramsWGSL}\n@group(0) @binding(1) var<storage, read> rawGuide: array<vec2f>;\n@group(0) @binding(2) var<storage, read_write> guide: array<vec2f>;\n\n@compute @workgroup_size(${JNLM_WORKGROUP_SIZE}, ${JNLM_WORKGROUP_SIZE}, 1)\nfn main(@builtin(global_invocation_id) id: vec3u) {\n let size = params.size;\n if (id.x >= size.x || id.y >= size.y) { return; }\n let center = rawGuide[id.x + id.y * size.x];\n var varianceSum = 0.0;\n var varianceCount = 0.0;\n var meanSum = 0.0;\n var meanSquareSum = 0.0;\n for (var dy = -1; dy <= 1; dy++) {\n for (var dx = -1; dx <= 1; dx++) {\n let q = clamp(vec2i(id.xy) + vec2i(dx, dy), vec2i(0), vec2i(size) - 1);\n let value = rawGuide[u32(q.x) + u32(q.y) * size.x];\n meanSum += value.x;\n meanSquareSum += value.x * value.x;\n if (value.y >= 0.0) {\n varianceSum += value.y;\n varianceCount += 1.0;\n }\n }\n }\n var variance: f32;\n if (center.y >= 0.0) {\n variance = varianceSum / varianceCount;\n } else {\n let spatialMean = meanSum / 9.0;\n variance = max(meanSquareSum / 9.0 - spatialMean * spatialMean, 0.0) * 9.0 / 8.0;\n }\n guide[id.x + id.y * size.x] = vec2f(center.x, variance);\n}\n`;\n\n/** Copies the composed image into the filter's color buffer. */\nexport const jnlmLoadColorWGSL = /* wgsl */ `\n${paramsWGSL}\n@group(0) @binding(1) var colorTex: texture_2d<f32>;\n@group(0) @binding(2) var<storage, read_write> outColor: array<vec4f>;\n\n@compute @workgroup_size(${JNLM_WORKGROUP_SIZE}, ${JNLM_WORKGROUP_SIZE}, 1)\nfn main(@builtin(global_invocation_id) id: vec3u) {\n if (id.x >= params.size.x || id.y >= params.size.y) { return; }\n outColor[id.x + id.y * params.size.x] = textureLoad(colorTex, vec2i(id.xy), 0);\n}\n`;\n\n/**\n * Pass 3: the joint NL-means filter of the composed image. It also filters\n * the guide with the same weights, with the variance of the weighted mean,\n * for a following pass. The albedo regression corrects color only, keeping\n * uncertain fitted texture responses out of the matching guide.\n */\nexport function createJNLMFilterWGSL({\n searchRadius, patchRadius, albedoBandwidth, normalBandwidth\n}: JNLMFilterShape = JNLM_DEFAULT_SHAPE) {\n const patchSize = (2 * patchRadius + 1) ** 2;\n return /* wgsl */ `\n${paramsWGSL}\n@group(0) @binding(1) var<storage, read> guide: array<vec2f>;\n@group(0) @binding(2) var<storage, read> color: array<vec4f>;\n@group(0) @binding(3) var albedoTex: texture_2d<f32>;\n@group(0) @binding(4) var normalTex: texture_2d<f32>;\n@group(0) @binding(5) var<storage, read_write> outColor: array<vec4f>;\n@group(0) @binding(6) var<storage, read_write> outGuide: array<vec2f>;\n@group(0) @binding(7) var shadowCatcherTex: texture_2d<f32>;\n\nconst SEARCH_RADIUS = ${searchRadius};\nconst PATCH_RADIUS = ${patchRadius};\nconst PATCH_SIZE = ${patchSize};\n// Variance cancellation strength alpha of the paper.\nconst VARIANCE_CANCELLATION = 1.0;\n// Inverse squared feature bandwidths. Normals are encoded as n * 0.5 + 0.5.\nconst INV_ALBEDO_BANDWIDTH2 = ${(1 / albedoBandwidth ** 2).toFixed(6)};\nconst INV_COVERAGE_BANDWIDTH2 = ${(1 / JNLM_COVERAGE_BANDWIDTH ** 2).toFixed(6)};\nconst INV_NORMAL_BANDWIDTH2 = ${(1 / normalBandwidth ** 2).toFixed(6)};\n// Lower bound of the center weight, so a pixel unlike all of its neighbors\n// (a thin highlight) is kept rather than replaced by them.\nconst CENTER_WEIGHT_MIN = 0.01;\n\nfn pixelIndex(p: vec2i) -> u32 {\n let q = clamp(p, vec2i(0), vec2i(params.size) - 1);\n return u32(q.x) + u32(q.y) * params.size.x;\n}\n\nfn featureDistance(q: vec2i, centerAlbedo: vec4f, centerNormal: vec3f) -> f32 {\n let albedo = textureLoad(albedoTex, q, 0);\n // Absolute differences in linear albedo erase low-contrast dark textures.\n // Measure RGB contrast relative to both pixels; keep coverage absolute.\n let albedoScale = max((albedo.rgb + centerAlbedo.rgb) * 0.5, vec3f(${JNLM_ALBEDO_FLOOR}));\n let albedoDelta = (albedo.rgb - centerAlbedo.rgb) / albedoScale;\n let coverageDelta = albedo.a - centerAlbedo.a;\n let normalDelta = textureLoad(normalTex, q, 0).rgb - centerNormal;\n return max(\n dot(albedoDelta, albedoDelta) * INV_ALBEDO_BANDWIDTH2\n + coverageDelta * coverageDelta * INV_COVERAGE_BANDWIDTH2,\n dot(normalDelta, normalDelta) * INV_NORMAL_BANDWIDTH2\n );\n}\n\nfn premultiplied(c: vec4f) -> vec4f {\n return vec4f(c.rgb * c.a, c.a);\n}\n\n@compute @workgroup_size(${JNLM_WORKGROUP_SIZE}, ${JNLM_WORKGROUP_SIZE}, 1)\nfn main(@builtin(global_invocation_id) id: vec3u) {\n let size = vec2i(params.size);\n let p = vec2i(id.xy);\n if (p.x >= size.x || p.y >= size.y) { return; }\n let step = i32(params.dilation);\n let centerAlbedo = textureLoad(albedoTex, p, 0);\n let centerNormalTexel = textureLoad(normalTex, p, 0);\n let centerNormal = centerNormalTexel.rgb;\n let index = pixelIndex(p);\n // Primary misses show the background directly. It has no features that\n // protect its detail and no noise beyond antialiasing, so keep it.\n if (centerNormalTexel.a <= 0.0 && textureLoad(shadowCatcherTex, p, 0).r <= 0.0) {\n outColor[index] = color[index];\n outGuide[index] = guide[index];\n return;\n }\n\n var centerPatch: array<vec2f, PATCH_SIZE>;\n var k = 0;\n for (var dy = -PATCH_RADIUS; dy <= PATCH_RADIUS; dy++) {\n for (var dx = -PATCH_RADIUS; dx <= PATCH_RADIUS; dx++) {\n centerPatch[k] = guide[pixelIndex(p + vec2i(dx, dy) * step)];\n k++;\n }\n }\n let k2 = params.colorSensitivity * params.colorSensitivity;\n\n var sum = vec4f(0.0);\n let featureScale = max(centerAlbedo.rgb, vec3f(${JNLM_ALBEDO_FLOOR}));\n var featureSum = vec3f(0.0);\n var featureSquareSum = vec3f(0.0);\n var featureColorSum = vec3f(0.0);\n var guideSum = 0.0;\n var guideVarianceSum = 0.0;\n var weightSum = 0.0;\n var maxWeight = 0.0;\n for (var sy = -SEARCH_RADIUS; sy <= SEARCH_RADIUS; sy++) {\n for (var sx = -SEARCH_RADIUS; sx <= SEARCH_RADIUS; sx++) {\n let q = p + vec2i(sx, sy) * step;\n if (\n (sx == 0 && sy == 0) ||\n q.x < 0 || q.y < 0 || q.x >= size.x || q.y >= size.y\n ) { continue; }\n\n let features = featureDistance(q, centerAlbedo, centerNormal);\n if (features > 16.0) { continue; }\n\n var colorDistance = 0.0;\n k = 0;\n for (var dy = -PATCH_RADIUS; dy <= PATCH_RADIUS; dy++) {\n for (var dx = -PATCH_RADIUS; dx <= PATCH_RADIUS; dx++) {\n let a = centerPatch[k];\n let b = guide[pixelIndex(q + vec2i(dx, dy) * step)];\n let delta = a.x - b.x;\n colorDistance += (delta * delta\n - VARIANCE_CANCELLATION * (a.y + min(a.y, b.y)))\n / (1e-10 + k2 * (a.y + b.y));\n k++;\n }\n }\n colorDistance /= f32(PATCH_SIZE);\n\n let weight = exp(-max(max(colorDistance, 0.0), features));\n let index = pixelIndex(q);\n let c = color[index];\n let g = guide[index];\n // Filter premultiplied color so coverage and color stay consistent.\n let a = (textureLoad(albedoTex, q, 0).rgb - centerAlbedo.rgb) / featureScale;\n let value = premultiplied(c);\n sum += value * weight;\n featureSum += a * weight;\n featureSquareSum += a * a * weight;\n featureColorSum += a * value.rgb * weight;\n guideSum += g.x * weight;\n guideVarianceSum += g.y * weight * weight;\n weightSum += weight;\n maxWeight = max(maxWeight, weight);\n }\n }\n\n // Weight the center like its most similar neighbor (Buades et al. 2005)\n // instead of 1, so isolated outliers are not kept unfiltered.\n let center = color[index];\n let centerGuide = guide[index];\n let centerWeight = max(maxWeight, CENTER_WEIGHT_MIN);\n let totalWeight = weightSum + centerWeight;\n let centerValue = premultiplied(center);\n let mean = (sum + centerValue * centerWeight) / totalWeight;\n // Fit each color channel against relative albedo with the same JNLM weights.\n // Centering at this pixel avoids cancellation when the feature is constant.\n let meanFeature = featureSum / totalWeight;\n let featureVariance = max(featureSquareSum / totalWeight - meanFeature * meanFeature, vec3f(0.0));\n let covariance = featureColorSum / totalWeight - meanFeature * mean.rgb;\n // A 1% contrast ridge stabilizes flat guides. Bound the response between no\n // texture dependence and multiplicative albedo modulation; specular color\n // with an unrelated albedo falls back to the weighted mean.\n let meanAlbedo = centerAlbedo.rgb + meanFeature * featureScale;\n let maximumSlope = mean.rgb * featureScale / max(meanAlbedo, vec3f(${JNLM_ALBEDO_FLOOR}));\n let slope = clamp(covariance / (featureVariance + vec3f(${JNLM_ALBEDO_REGULARIZATION})), vec3f(0.0), maximumSlope);\n let corrected = mean.rgb - slope * meanFeature;\n let filtered = vec4f(max(corrected, vec3f(0.0)), max(mean.a, 0.0));\n let rgb = select(\n center.rgb,\n filtered.rgb / max(filtered.a, 1e-6),\n filtered.a > 1e-6\n );\n outColor[index] = vec4f(rgb, filtered.a);\n outGuide[index] = vec2f(\n (guideSum + centerGuide.x * centerWeight) / totalWeight,\n (guideVarianceSum + centerGuide.y * centerWeight * centerWeight)\n / (totalWeight * totalWeight)\n );\n}\n`;\n}\n\nexport interface JNLMInputs {\n width: number;\n height: number;\n /** Normalized shadow-catcher mask; red is the catcher coverage. */\n shadowCatcher: GPUTexture;\n /** Ray-trace auxiliary accumulation holding the guide moments. */\n accumulation: GPUBuffer;\n /** Ray-trace normal accumulation; its alpha is the per-pixel sample count. */\n normalAccumulation: GPUBuffer;\n /** Composed linear image to filter. */\n color: GPUTexture;\n albedo: GPUTexture;\n normal: GPUTexture;\n strength: number;\n shape: JNLMFilterShape;\n}\n\nconst MAX_ITERATIONS = JNLM_MAX_ITERATIONS;\n\nexport class WGPUJNLMDenoisePass {\n private _device: GPUDevice;\n private _paramsBuffers: GPUBuffer[] = [];\n private _guidePipeline: GPUComputePipeline;\n private _variancePipeline: GPUComputePipeline;\n private _loadColorPipeline: GPUComputePipeline;\n private _filterPipeline?: GPUComputePipeline;\n private _filterShapeKey = '';\n private _guides: GPUBuffer[] = [];\n private _colors: GPUBuffer[] = [];\n private _width = 0;\n private _height = 0;\n\n constructor(device: GPUDevice) {\n this._device = device;\n // One uniform buffer per pass: every pass of an encoder sees the last\n // writeBuffer() of a shared one.\n for (let i = 0; i <= MAX_ITERATIONS; i++) {\n this._paramsBuffers.push(device.createBuffer({\n label: 'JNLM params',\n size: 16,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n }));\n }\n this._guidePipeline = this._createPipeline('JNLM guide', jnlmGuideWGSL);\n this._variancePipeline = this._createPipeline('JNLM variance', jnlmVarianceWGSL);\n this._loadColorPipeline = this._createPipeline('JNLM load color', jnlmLoadColorWGSL);\n }\n\n private _createPipeline(label: string, code: string) {\n return getTargetShaderCache(this._device).createComputePipeline({\n label,\n layout: 'auto',\n compute: {\n module: getTargetShaderCache(this._device).createShaderModule({ label, code }),\n entryPoint: 'main'\n }\n });\n }\n\n private _getFilterPipeline(shape: JNLMFilterShape) {\n const key = JSON.stringify(shape);\n if (!this._filterPipeline || key !== this._filterShapeKey) {\n this._filterPipeline = this._createPipeline('JNLM filter', createJNLMFilterWGSL(shape));\n this._filterShapeKey = key;\n }\n return this._filterPipeline;\n }\n\n reserveCapacity() {}\n private _ensureBuffers(width: number, height: number) {\n if (width <= this._width && height <= this._height && this._colors.length) return;\n width = Math.max(width, this._width); height = Math.max(height, this._height);\n this._destroyBuffers();\n const pixels = width * height;\n const createBuffer = (label: string, bytes: number) =>\n this._device.createBuffer({\n label,\n size: pixels * bytes,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC\n });\n this._guides = [createBuffer('JNLM guide A', 8), createBuffer('JNLM guide B', 8)];\n this._colors = [createBuffer('JNLM color A', 16), createBuffer('JNLM color B', 16)];\n this._width = width;\n this._height = height;\n }\n\n private _destroyBuffers() {\n for (const buffer of [...this._guides, ...this._colors]) buffer.destroy();\n this._guides = [];\n this._colors = [];\n }\n\n /** Encodes the denoiser and returns the RGBA32F output in texture rows. */\n encode(encoder: GPUCommandEncoder, inputs: JNLMInputs): GPUBuffer {\n const { width, height, shape } = inputs;\n this._ensureBuffers(width, height);\n const iterations = Math.min(Math.max(Math.round(shape.iterations), 1), MAX_ITERATIONS);\n const sensitivity = JNLM_DEFAULT_COLOR_SENSITIVITY * Math.max(inputs.strength, 1e-3);\n this._paramsBuffers.forEach((buffer, i) => {\n const params = new ArrayBuffer(16);\n new Uint32Array(params, 0, 2).set([width, height]);\n // Buffer i (from 1) is filter pass i - 1; index 0 is the prepasses.\n new Float32Array(params, 8, 2).set([sensitivity, jnlmPassDilation(Math.max(i - 1, 0))]);\n this._device.queue.writeBuffer(buffer, 0, params);\n });\n\n const device = this._device;\n const filterPipeline = this._getFilterPipeline(shape);\n const bind = (\n pipeline: GPUComputePipeline,\n paramsBuffer: GPUBuffer,\n resources: GPUBindingResource[]\n ) =>\n device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: { buffer: paramsBuffer } },\n ...resources.map((resource, i) => ({ binding: i + 1, resource }))\n ]\n });\n const [guideA, guideB] = this._guides;\n const [colorA, colorB] = this._colors;\n const prepass = this._paramsBuffers[0];\n const passes: [GPUComputePipeline, GPUBindGroup][] = [\n [this._guidePipeline, bind(this._guidePipeline, prepass, [\n { buffer: inputs.accumulation },\n { buffer: inputs.normalAccumulation },\n { buffer: guideB }\n ])],\n [this._variancePipeline, bind(this._variancePipeline, prepass, [\n { buffer: guideB },\n { buffer: guideA }\n ])],\n [this._loadColorPipeline, bind(this._loadColorPipeline, prepass, [\n inputs.color.createView(),\n { buffer: colorA }\n ])]\n ];\n const albedoView = inputs.albedo.createView();\n const normalView = inputs.normal.createView();\n const shadowCatcherView = inputs.shadowCatcher.createView();\n let guides = [guideA, guideB];\n let colors = [colorA, colorB];\n for (let i = 1; i <= iterations; i++) {\n passes.push([filterPipeline, bind(filterPipeline, this._paramsBuffers[i], [\n { buffer: guides[0] },\n { buffer: colors[0] },\n albedoView,\n normalView,\n { buffer: colors[1] },\n { buffer: guides[1] },\n shadowCatcherView\n ])]);\n guides = [guides[1], guides[0]];\n colors = [colors[1], colors[0]];\n }\n const pass = encoder.beginComputePass({ label: 'JNLM denoise' });\n for (const [pipeline, bindGroup] of passes) {\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, bindGroup);\n pass.dispatchWorkgroups(\n Math.ceil(width / JNLM_WORKGROUP_SIZE),\n Math.ceil(height / JNLM_WORKGROUP_SIZE)\n );\n }\n pass.end();\n return colors[0];\n }\n\n getMemoryBytes() {\n return [...this._paramsBuffers, ...this._guides, ...this._colors]\n .reduce((sum, buffer) => sum + buffer.size, 0);\n }\n\n dispose() {\n for (const buffer of this._paramsBuffers) buffer.destroy();\n this._destroyBuffers();\n }\n}\n"]}
1
+ {"version":3,"file":"WGPUJNLMDenoiser.js","sourceRoot":"","sources":["../../src/renderer/WGPUJNLMDenoiser.ts"],"names":[],"mappings":"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","sourcesContent":["import {getTargetShaderCache} from './WGPUShaderCache.js';\nimport {JNLM_MAX_ITERATIONS, type JNLMFilterShape} from './jnlm.js';\nimport {\n JNLM_WORKGROUP_SIZE, jnlmGuideWGSL, jnlmVarianceWGSL, jnlmLoadColorWGSL,\n createJNLMFilterWGSL, packJNLMParameters\n} from './wgsl/jnlm.compute.js';\nexport {createJNLMFilterWGSL, jnlmGuideWGSL, jnlmVarianceWGSL, jnlmLoadColorWGSL, JNLM_WORKGROUP_SIZE} from './wgsl/jnlm.compute.js';\n\n/** WebGPU passes of the JNLM denoiser described in `jnlm.ts`. */\n\nexport interface JNLMInputs {\n width: number;\n height: number;\n /** Normalized shadow-catcher mask; red is the catcher coverage. */\n shadowCatcher: GPUTexture;\n /** Ray-trace auxiliary accumulation holding the guide moments. */\n accumulation: GPUBuffer;\n /** Ray-trace normal accumulation; its alpha is the per-pixel sample count. */\n normalAccumulation: GPUBuffer;\n /** Composed linear image to filter. */\n color: GPUTexture;\n albedo: GPUTexture;\n normal: GPUTexture;\n strength: number;\n shape: JNLMFilterShape;\n}\n\nconst MAX_ITERATIONS = JNLM_MAX_ITERATIONS;\n\nexport class WGPUJNLMDenoisePass {\n private _device: GPUDevice;\n private _paramsBuffers: GPUBuffer[] = [];\n private _guidePipeline: GPUComputePipeline;\n private _variancePipeline: GPUComputePipeline;\n private _loadColorPipeline: GPUComputePipeline;\n private _filterPipeline?: GPUComputePipeline;\n private _filterShapeKey = '';\n private _guides: GPUBuffer[] = [];\n private _colors: GPUBuffer[] = [];\n private _width = 0;\n private _height = 0;\n\n constructor(device: GPUDevice) {\n this._device = device;\n // One uniform buffer per pass: every pass of an encoder sees the last\n // writeBuffer() of a shared one.\n for (let i = 0; i <= MAX_ITERATIONS; i++) {\n this._paramsBuffers.push(device.createBuffer({\n label: 'JNLM params',\n size: 16,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n }));\n }\n this._guidePipeline = this._createPipeline('JNLM guide', jnlmGuideWGSL);\n this._variancePipeline = this._createPipeline('JNLM variance', jnlmVarianceWGSL);\n this._loadColorPipeline = this._createPipeline('JNLM load color', jnlmLoadColorWGSL);\n }\n\n private _createPipeline(label: string, code: string) {\n return getTargetShaderCache(this._device).createComputePipeline({\n label,\n layout: 'auto',\n compute: {\n module: getTargetShaderCache(this._device).createShaderModule({ label, code }),\n entryPoint: 'main'\n }\n });\n }\n\n private _getFilterPipeline(shape: JNLMFilterShape) {\n const key = JSON.stringify(shape);\n if (!this._filterPipeline || key !== this._filterShapeKey) {\n this._filterPipeline = this._createPipeline('JNLM filter', createJNLMFilterWGSL(shape));\n this._filterShapeKey = key;\n }\n return this._filterPipeline;\n }\n\n reserveCapacity() {}\n private _ensureBuffers(width: number, height: number) {\n if (width <= this._width && height <= this._height && this._colors.length) return;\n width = Math.max(width, this._width); height = Math.max(height, this._height);\n this._destroyBuffers();\n const pixels = width * height;\n const createBuffer = (label: string, bytes: number) =>\n this._device.createBuffer({\n label,\n size: pixels * bytes,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC\n });\n this._guides = [createBuffer('JNLM guide A', 8), createBuffer('JNLM guide B', 8)];\n this._colors = [createBuffer('JNLM color A', 16), createBuffer('JNLM color B', 16)];\n this._width = width;\n this._height = height;\n }\n\n private _destroyBuffers() {\n for (const buffer of [...this._guides, ...this._colors]) buffer.destroy();\n this._guides = [];\n this._colors = [];\n }\n\n /** Encodes the denoiser and returns the RGBA32F output in texture rows. */\n encode(encoder: GPUCommandEncoder, inputs: JNLMInputs): GPUBuffer {\n const { width, height, shape } = inputs;\n this._ensureBuffers(width, height);\n const iterations = Math.min(Math.max(Math.round(shape.iterations), 1), MAX_ITERATIONS);\n this._paramsBuffers.forEach((buffer, i) => {\n // Buffer i (from 1) is filter pass i - 1; index 0 is the prepasses.\n const params = packJNLMParameters(width, height, inputs.strength, Math.max(i - 1, 0));\n this._device.queue.writeBuffer(buffer, 0, params);\n });\n\n const device = this._device;\n const filterPipeline = this._getFilterPipeline(shape);\n const bind = (\n pipeline: GPUComputePipeline,\n paramsBuffer: GPUBuffer,\n resources: GPUBindingResource[]\n ) =>\n device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: { buffer: paramsBuffer } },\n ...resources.map((resource, i) => ({ binding: i + 1, resource }))\n ]\n });\n const [guideA, guideB] = this._guides;\n const [colorA, colorB] = this._colors;\n const prepass = this._paramsBuffers[0];\n const passes: [GPUComputePipeline, GPUBindGroup][] = [\n [this._guidePipeline, bind(this._guidePipeline, prepass, [\n { buffer: inputs.accumulation },\n { buffer: inputs.normalAccumulation },\n { buffer: guideB }\n ])],\n [this._variancePipeline, bind(this._variancePipeline, prepass, [\n { buffer: guideB },\n { buffer: guideA }\n ])],\n [this._loadColorPipeline, bind(this._loadColorPipeline, prepass, [\n inputs.color.createView(),\n { buffer: colorA }\n ])]\n ];\n const albedoView = inputs.albedo.createView();\n const normalView = inputs.normal.createView();\n const shadowCatcherView = inputs.shadowCatcher.createView();\n let guides = [guideA, guideB];\n let colors = [colorA, colorB];\n for (let i = 1; i <= iterations; i++) {\n passes.push([filterPipeline, bind(filterPipeline, this._paramsBuffers[i], [\n { buffer: guides[0] },\n { buffer: colors[0] },\n albedoView,\n normalView,\n { buffer: colors[1] },\n { buffer: guides[1] },\n shadowCatcherView\n ])]);\n guides = [guides[1], guides[0]];\n colors = [colors[1], colors[0]];\n }\n const pass = encoder.beginComputePass({ label: 'JNLM denoise' });\n for (const [pipeline, bindGroup] of passes) {\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, bindGroup);\n pass.dispatchWorkgroups(\n Math.ceil(width / JNLM_WORKGROUP_SIZE),\n Math.ceil(height / JNLM_WORKGROUP_SIZE)\n );\n }\n pass.end();\n return colors[0];\n }\n\n getMemoryBytes() {\n return [...this._paramsBuffers, ...this._guides, ...this._colors]\n .reduce((sum, buffer) => sum + buffer.size, 0);\n }\n\n dispose() {\n for (const buffer of this._paramsBuffers) buffer.destroy();\n this._destroyBuffers();\n }\n}\n"]}