@meimu/mutracer 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/CHANGELOG.md +222 -0
  2. package/LICENSES/FidelityFX-FSR.txt +19 -0
  3. package/LICENSES/pbrt-v4-Apache-2.0.txt +202 -0
  4. package/THIRD_PARTY_NOTICES.md +18 -4
  5. package/dist/assets/bvh.worker.js +1 -1
  6. package/dist/mutracer.umd.js +6260 -5580
  7. package/docs/api.md +45 -18
  8. package/docs/materials.md +4 -2
  9. package/docs/performance.md +7 -0
  10. package/docs/post-processing.md +62 -9
  11. package/docs/progressive-rendering.md +3 -0
  12. package/docs/sampling.md +4 -0
  13. package/docs/technical/acceleration.md +52 -0
  14. package/docs/technical/aovs.md +79 -0
  15. package/docs/technical/caustics.md +109 -0
  16. package/docs/technical/continuous-spectrum.md +29 -0
  17. package/docs/technical/display-upscale.md +82 -0
  18. package/docs/technical/openpbr.md +99 -0
  19. package/docs/technical/pbrt-import.md +168 -0
  20. package/docs/technical/tiling.md +74 -0
  21. package/docs/technical/webgl.md +53 -0
  22. package/docs/viewer.md +11 -1
  23. package/lib/Display.d.ts +19 -5
  24. package/lib/Display.js +10 -7
  25. package/lib/Display.js.map +1 -1
  26. package/lib/Engine.d.ts +2 -1
  27. package/lib/Engine.js +30 -2
  28. package/lib/Engine.js.map +1 -1
  29. package/lib/Render.d.ts +20 -11
  30. package/lib/Render.js +32 -7
  31. package/lib/Render.js.map +1 -1
  32. package/lib/main.d.ts +3 -1
  33. package/lib/main.js +1 -0
  34. package/lib/main.js.map +1 -1
  35. package/lib/oidn.d.ts +1 -1
  36. package/lib/renderer/AovPrimitiveCache.js +39 -8
  37. package/lib/renderer/AovPrimitiveCache.js.map +1 -1
  38. package/lib/renderer/DisplayPostProcess.d.ts +8 -3
  39. package/lib/renderer/DisplayPostProcess.js +51 -18
  40. package/lib/renderer/DisplayPostProcess.js.map +1 -1
  41. package/lib/renderer/MaterialData.js +7 -2
  42. package/lib/renderer/MaterialData.js.map +1 -1
  43. package/lib/renderer/RenderingPipeline.d.ts +7 -1
  44. package/lib/renderer/RenderingPipeline.js.map +1 -1
  45. package/lib/renderer/TileRender.d.ts +2 -2
  46. package/lib/renderer/TileRender.js +128 -7
  47. package/lib/renderer/TileRender.js.map +1 -1
  48. package/lib/renderer/WGPUAov.d.ts +6 -1
  49. package/lib/renderer/WGPUAov.js +108 -14
  50. package/lib/renderer/WGPUAov.js.map +1 -1
  51. package/lib/renderer/WGPUCanvasSurface.js +12 -1
  52. package/lib/renderer/WGPUCanvasSurface.js.map +1 -1
  53. package/lib/renderer/WGPUEnvMapDistribution.js +19 -19
  54. package/lib/renderer/WGPUFullQuadPass.js +3 -3
  55. package/lib/renderer/WGPURayTraceOutput.js +12 -12
  56. package/lib/renderer/WGPURayTracePass.d.ts +17 -4
  57. package/lib/renderer/WGPURayTracePass.js +194 -71
  58. package/lib/renderer/WGPURayTracePass.js.map +1 -1
  59. package/lib/renderer/WGPURenderingPipeline.js +46 -40
  60. package/lib/renderer/WGPURenderingPipeline.js.map +1 -1
  61. package/lib/renderer/WebGLAov.js +3 -3
  62. package/lib/renderer/WebGLAov.js.map +1 -1
  63. package/lib/renderer/WebGLFullQuadPass.d.ts +1 -1
  64. package/lib/renderer/WebGLFullQuadPass.js +8 -2
  65. package/lib/renderer/WebGLFullQuadPass.js.map +1 -1
  66. package/lib/renderer/WebGLJNLMDenoiser.js +66 -66
  67. package/lib/renderer/WebGLJNLMDenoiser.js.map +1 -1
  68. package/lib/renderer/WebGLRayTraceOutputPass.js +4 -4
  69. package/lib/renderer/WebGLRayTracePass.d.ts +14 -10
  70. package/lib/renderer/WebGLRayTracePass.js +115 -111
  71. package/lib/renderer/WebGLRayTracePass.js.map +1 -1
  72. package/lib/renderer/WebGLRenderingPipeline.js +10 -3
  73. package/lib/renderer/WebGLRenderingPipeline.js.map +1 -1
  74. package/lib/renderer/WebGLSkyBaker.js +57 -57
  75. package/lib/renderer/aov.d.ts +13 -1
  76. package/lib/renderer/aov.js +21 -2
  77. package/lib/renderer/aov.js.map +1 -1
  78. package/lib/renderer/aovDisplay.js +2 -2
  79. package/lib/renderer/aovDisplay.js.map +1 -1
  80. package/lib/renderer/binnedSahBvh.d.ts +2 -1
  81. package/lib/renderer/binnedSahBvh.js +24 -17
  82. package/lib/renderer/binnedSahBvh.js.map +1 -1
  83. package/lib/renderer/bvhAccel.d.ts +3 -1
  84. package/lib/renderer/bvhAccel.js +36 -6
  85. package/lib/renderer/bvhAccel.js.map +1 -1
  86. package/lib/renderer/cameraUniform.d.ts +1 -1
  87. package/lib/renderer/cameraUniform.js +6 -2
  88. package/lib/renderer/cameraUniform.js.map +1 -1
  89. package/lib/renderer/compactVertices.d.ts +14 -0
  90. package/lib/renderer/compactVertices.js +124 -0
  91. package/lib/renderer/compactVertices.js.map +1 -0
  92. package/lib/renderer/easu.d.ts +11 -0
  93. package/lib/renderer/easu.js +156 -0
  94. package/lib/renderer/easu.js.map +1 -0
  95. package/lib/renderer/geometryUpdateState.d.ts +1 -0
  96. package/lib/renderer/geometryUpdateState.js.map +1 -1
  97. package/lib/renderer/geometryUpdates.js +3 -2
  98. package/lib/renderer/geometryUpdates.js.map +1 -1
  99. package/lib/renderer/glsl/aovDisplay.frag.js +5 -5
  100. package/lib/renderer/glsl/aovReflectance.glsl.js +35 -35
  101. package/lib/renderer/glsl/aovReflectanceSamples.glsl.js +1 -1
  102. package/lib/renderer/glsl/aovTrace.frag.js +44 -36
  103. package/lib/renderer/glsl/aovTrace.frag.js.map +1 -1
  104. package/lib/renderer/glsl/chunks/cameraProjection.glsl.d.ts +2 -0
  105. package/lib/renderer/glsl/chunks/cameraProjection.glsl.js +16 -0
  106. package/lib/renderer/glsl/chunks/cameraProjection.glsl.js.map +1 -0
  107. package/lib/renderer/glsl/chunks/cameraRay.glsl.d.ts +1 -1
  108. package/lib/renderer/glsl/chunks/cameraRay.glsl.js +9 -16
  109. package/lib/renderer/glsl/chunks/cameraRay.glsl.js.map +1 -1
  110. package/lib/renderer/glsl/chunks/emissiveLight.glsl.js +8 -8
  111. package/lib/renderer/glsl/chunks/envMap.glsl.js +67 -67
  112. package/lib/renderer/glsl/chunks/intersect.glsl.js +390 -375
  113. package/lib/renderer/glsl/chunks/intersect.glsl.js.map +1 -1
  114. package/lib/renderer/glsl/chunks/materialBuffer.glsl.js +120 -120
  115. package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js +562 -562
  116. package/lib/renderer/glsl/chunks/rand.glsl.js +3 -3
  117. package/lib/renderer/glsl/chunks/random.glsl.js +4 -4
  118. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js +37 -35
  119. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js.map +1 -1
  120. package/lib/renderer/glsl/chunks/sampleLight.glsl.js +70 -74
  121. package/lib/renderer/glsl/chunks/sampleLight.glsl.js.map +1 -1
  122. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.d.ts +1 -1
  123. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js +107 -88
  124. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js.map +1 -1
  125. package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js +11 -11
  126. package/lib/renderer/glsl/chunks/sampling.glsl.js +77 -77
  127. package/lib/renderer/glsl/chunks/sobol.glsl.js +70 -70
  128. package/lib/renderer/glsl/chunks/spectralPrefix.glsl.d.ts +6 -0
  129. package/lib/renderer/glsl/chunks/spectralPrefix.glsl.js +47 -0
  130. package/lib/renderer/glsl/chunks/spectralPrefix.glsl.js.map +1 -0
  131. package/lib/renderer/glsl/chunks/textureLinear.glsl.js +5 -5
  132. package/lib/renderer/glsl/chunks/uvProjection.glsl.js +11 -11
  133. package/lib/renderer/glsl/depthQuery.frag.js +12 -6
  134. package/lib/renderer/glsl/depthQuery.frag.js.map +1 -1
  135. package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js +10 -10
  136. package/lib/renderer/glsl/rayTrace.frag.js +233 -170
  137. package/lib/renderer/glsl/rayTrace.frag.js.map +1 -1
  138. package/lib/renderer/glsl/shadowCatcher.frag.js +10 -9
  139. package/lib/renderer/glsl/shadowCatcher.frag.js.map +1 -1
  140. package/lib/renderer/glsl/webglPipeline.frag.js +58 -58
  141. package/lib/renderer/gpuMemory.js +1 -1
  142. package/lib/renderer/gpuMemory.js.map +1 -1
  143. package/lib/renderer/openPbrEnergyLut.d.ts +2 -1
  144. package/lib/renderer/openPbrEnergyLut.js +18 -1
  145. package/lib/renderer/openPbrEnergyLut.js.map +1 -1
  146. package/lib/renderer/pathLimits.d.ts +5 -4
  147. package/lib/renderer/pathLimits.js +6 -5
  148. package/lib/renderer/pathLimits.js.map +1 -1
  149. package/lib/renderer/prepareMeshBVH.d.ts +2 -0
  150. package/lib/renderer/prepareMeshBVH.js +5 -3
  151. package/lib/renderer/prepareMeshBVH.js.map +1 -1
  152. package/lib/renderer/progressiveScheduler.js +1 -1
  153. package/lib/renderer/progressiveScheduler.js.map +1 -1
  154. package/lib/renderer/renderPipeline.d.ts +4 -0
  155. package/lib/renderer/renderPipeline.js +1 -0
  156. package/lib/renderer/renderPipeline.js.map +1 -1
  157. package/lib/renderer/researchTransport.d.ts +1 -1
  158. package/lib/renderer/researchTransport.js.map +1 -1
  159. package/lib/renderer/sceneAssembly.d.ts +1 -1
  160. package/lib/renderer/sceneAssembly.js +4 -3
  161. package/lib/renderer/sceneAssembly.js.map +1 -1
  162. package/lib/renderer/sceneChangeDetector.d.ts +1 -1
  163. package/lib/renderer/sceneChangeDetector.js +3 -1
  164. package/lib/renderer/sceneChangeDetector.js.map +1 -1
  165. package/lib/renderer/sceneLayoutSchema.d.ts +1 -0
  166. package/lib/renderer/sceneLayoutSchema.js +2 -2
  167. package/lib/renderer/sceneLayoutSchema.js.map +1 -1
  168. package/lib/renderer/scenePreparation.d.ts +3 -2
  169. package/lib/renderer/scenePreparation.js +18 -2
  170. package/lib/renderer/scenePreparation.js.map +1 -1
  171. package/lib/renderer/scratchSampling.js +6 -6
  172. package/lib/renderer/spectrum.js +2 -2
  173. package/lib/renderer/staticBvhPreparation.d.ts +9 -0
  174. package/lib/renderer/staticBvhPreparation.js +8 -2
  175. package/lib/renderer/staticBvhPreparation.js.map +1 -1
  176. package/lib/renderer/surfaceHit.d.ts +10 -0
  177. package/lib/renderer/surfaceHit.js +22 -0
  178. package/lib/renderer/surfaceHit.js.map +1 -0
  179. package/lib/renderer/tangentRequirements.d.ts +2 -0
  180. package/lib/renderer/tangentRequirements.js +7 -0
  181. package/lib/renderer/tangentRequirements.js.map +1 -0
  182. package/lib/renderer/textureAtlas.d.ts +4 -0
  183. package/lib/renderer/textureAtlas.js +48 -2
  184. package/lib/renderer/textureAtlas.js.map +1 -1
  185. package/lib/renderer/webgl.js +4 -0
  186. package/lib/renderer/webgl.js.map +1 -1
  187. package/lib/renderer/webglVertexAttributes.d.ts +17 -0
  188. package/lib/renderer/webglVertexAttributes.js +44 -0
  189. package/lib/renderer/webglVertexAttributes.js.map +1 -0
  190. package/lib/renderer/wgpuBindlessSource.js +2 -2
  191. package/lib/renderer/wgpuMaterialConstants.js +4 -3
  192. package/lib/renderer/wgpuMaterialConstants.js.map +1 -1
  193. package/lib/renderer/wgpuSceneUniform.js +2 -2
  194. package/lib/renderer/wgpuSceneUniform.js.map +1 -1
  195. package/lib/renderer/wgpuShaderSource.d.ts +15 -0
  196. package/lib/renderer/wgpuShaderSource.js +1 -1
  197. package/lib/renderer/wgpuShaderSource.js.map +1 -1
  198. package/lib/renderer/wgsl/aovCompact.wgsl.d.ts +4 -0
  199. package/lib/renderer/wgsl/aovCompact.wgsl.js +26 -0
  200. package/lib/renderer/wgsl/aovCompact.wgsl.js.map +1 -0
  201. package/lib/renderer/wgsl/aovDisplay.wgsl.js +9 -9
  202. package/lib/renderer/wgsl/aovReflectance.wgsl.js +39 -39
  203. package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.js +1 -1
  204. package/lib/renderer/wgsl/aovResolve.wgsl.d.ts +4 -0
  205. package/lib/renderer/wgsl/aovResolve.wgsl.js +21 -2
  206. package/lib/renderer/wgsl/aovResolve.wgsl.js.map +1 -1
  207. package/lib/renderer/wgsl/aovSnapshot.wgsl.js +2 -2
  208. package/lib/renderer/wgsl/aovSnapshot.wgsl.js.map +1 -1
  209. package/lib/renderer/wgsl/aovTrace.wgsl.js +31 -31
  210. package/lib/renderer/wgsl/aovTraceDisplay.wgsl.d.ts +2 -0
  211. package/lib/renderer/wgsl/aovTraceDisplay.wgsl.js +56 -0
  212. package/lib/renderer/wgsl/aovTraceDisplay.wgsl.js.map +1 -0
  213. package/lib/renderer/wgsl/bloom.wgsl.js +18 -18
  214. package/lib/renderer/wgsl/causticLight.compute.d.ts +1 -1
  215. package/lib/renderer/wgsl/causticLight.compute.js +121 -119
  216. package/lib/renderer/wgsl/causticLight.compute.js.map +1 -1
  217. package/lib/renderer/wgsl/chunks/background.wgsl.js +46 -46
  218. package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js +4 -4
  219. package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js +3 -3
  220. package/lib/renderer/wgsl/chunks/caustics.wgsl.js +3 -3
  221. package/lib/renderer/wgsl/chunks/common.wgsl.js +4 -4
  222. package/lib/renderer/wgsl/chunks/envMap.wgsl.js +30 -30
  223. package/lib/renderer/wgsl/chunks/intersect.wgsl.d.ts +6 -2
  224. package/lib/renderer/wgsl/chunks/intersect.wgsl.js +550 -542
  225. package/lib/renderer/wgsl/chunks/intersect.wgsl.js.map +1 -1
  226. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.d.ts +1 -1
  227. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js +18 -16
  228. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js.map +1 -1
  229. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.d.ts +2 -1
  230. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js +70 -69
  231. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js.map +1 -1
  232. package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js +593 -593
  233. package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js +118 -118
  234. package/lib/renderer/wgsl/chunks/rand.wgsl.js +3 -3
  235. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.d.ts +4 -1
  236. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js +32 -26
  237. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js.map +1 -1
  238. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js +114 -114
  239. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.d.ts +1 -1
  240. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js +159 -137
  241. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js.map +1 -1
  242. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js +8 -8
  243. package/lib/renderer/wgsl/chunks/sampling.wgsl.js +74 -74
  244. package/lib/renderer/wgsl/chunks/sobol.wgsl.js +74 -74
  245. package/lib/renderer/wgsl/chunks/spectralPrefix.wgsl.d.ts +6 -0
  246. package/lib/renderer/wgsl/chunks/spectralPrefix.wgsl.js +66 -0
  247. package/lib/renderer/wgsl/chunks/spectralPrefix.wgsl.js.map +1 -0
  248. package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js +11 -11
  249. package/lib/renderer/wgsl/chunks/vertexAttributes.wgsl.d.ts +2 -0
  250. package/lib/renderer/wgsl/chunks/vertexAttributes.wgsl.js +61 -0
  251. package/lib/renderer/wgsl/chunks/vertexAttributes.wgsl.js.map +1 -0
  252. package/lib/renderer/wgsl/compose.frag.wgsl.d.ts +2 -0
  253. package/lib/renderer/wgsl/compose.frag.wgsl.js +99 -97
  254. package/lib/renderer/wgsl/compose.frag.wgsl.js.map +1 -1
  255. package/lib/renderer/wgsl/customDenoise.wgsl.js +10 -10
  256. package/lib/renderer/wgsl/depthQuery.wgsl.d.ts +1 -1
  257. package/lib/renderer/wgsl/depthQuery.wgsl.js +11 -2
  258. package/lib/renderer/wgsl/depthQuery.wgsl.js.map +1 -1
  259. package/lib/renderer/wgsl/easu.wgsl.d.ts +2 -0
  260. package/lib/renderer/wgsl/easu.wgsl.js +80 -0
  261. package/lib/renderer/wgsl/easu.wgsl.js.map +1 -0
  262. package/lib/renderer/wgsl/easuDetail.wgsl.d.ts +21 -0
  263. package/lib/renderer/wgsl/easuDetail.wgsl.js +230 -0
  264. package/lib/renderer/wgsl/easuDetail.wgsl.js.map +1 -0
  265. package/lib/renderer/wgsl/jnlm.compute.js +74 -74
  266. package/lib/renderer/wgsl/jnlm.compute.js.map +1 -1
  267. package/lib/renderer/wgsl/offlineAdaptive.compute.js +26 -26
  268. package/lib/renderer/wgsl/oidnAuxiliary.wgsl.js +3 -3
  269. package/lib/renderer/wgsl/photonMap.compute.js +89 -89
  270. package/lib/renderer/wgsl/proceduralSky.compute.js +61 -61
  271. package/lib/renderer/wgsl/rayTrace.compute.d.ts +14 -0
  272. package/lib/renderer/wgsl/rayTrace.compute.js +395 -333
  273. package/lib/renderer/wgsl/rayTrace.compute.js.map +1 -1
  274. package/lib/scene/Scene.js.map +1 -1
  275. package/lib/settings/render.d.ts +11 -0
  276. package/lib/settings/render.js +1 -0
  277. package/lib/settings/render.js.map +1 -1
  278. package/lib/util/fromTHREE.js +21 -14
  279. package/lib/util/fromTHREE.js.map +1 -1
  280. package/lib/version.d.ts +1 -1
  281. package/lib/version.js +1 -1
  282. package/lib/version.js.map +1 -1
  283. package/package.json +5 -2
  284. package/lib/oidnBundledWeights.cdn.d.ts +0 -2
  285. package/lib/oidnBundledWeights.cdn.js +0 -5
  286. package/lib/oidnBundledWeights.cdn.js.map +0 -1
  287. package/lib/renderer/bvh.worker.d.ts +0 -1
  288. package/lib/renderer/bvh.worker.js +0 -16
  289. package/lib/renderer/bvh.worker.js.map +0 -1
  290. package/lib/renderer/bvhWorkerBuild.d.ts +0 -13
  291. package/lib/renderer/bvhWorkerBuild.js +0 -17
  292. package/lib/renderer/bvhWorkerBuild.js.map +0 -1
  293. package/lib/renderer/lightCore.d.ts +0 -12
  294. package/lib/renderer/lightCore.js +0 -13
  295. package/lib/renderer/lightCore.js.map +0 -1
  296. package/lib/renderer/materialCore.d.ts +0 -8
  297. package/lib/renderer/materialCore.js +0 -9
  298. package/lib/renderer/materialCore.js.map +0 -1
  299. package/lib/scene/PixelTexture.d.ts +0 -6
  300. package/lib/scene/PixelTexture.js +0 -10
  301. package/lib/scene/PixelTexture.js.map +0 -1
  302. package/lib/util/studioLighting.d.ts +0 -18
  303. package/lib/util/studioLighting.js +0 -36
  304. package/lib/util/studioLighting.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import displayShader from './glsl/aovDisplay.frag.js';
2
2
  import { WebGLFullQuadPass } from './WebGLFullQuadPass.js';
3
- import { AOV_KINDS } from './aov.js';
3
+ import { aovLaneKind } from './aov.js';
4
4
  import { AOV_ID_COMPONENTS, validateAovDisplay } from './aovDisplay.js';
5
5
  import { AovHistory } from './aov.js';
6
6
  import { Texture2D, FrameBuffer } from './webgl.js';
@@ -54,7 +54,7 @@ export class WebGLAov {
54
54
  this.displayPass ??= new WebGLFullQuadPass('AOV display', this.renderer, { shader: displayShader, outputs: ['color'] });
55
55
  const pass = this.displayPass;
56
56
  pass.setSize(this.width, this.height);
57
- pass.setUniforms({ kind: AOV_KINDS.indexOf(kind), samples: this.samples, mapping: [...options.depthRange, options.positionScale, options.motionScale], idComponent: AOV_ID_COMPONENTS.indexOf(options.idComponent) });
57
+ pass.setUniforms({ kind: aovLaneKind(kind), samples: this.samples, mapping: [...options.depthRange, options.positionScale, options.motionScale], idComponent: AOV_ID_COMPONENTS.indexOf(options.idComponent) });
58
58
  pass.createPass({ ...this.accumulation[(this.samples - 1) % 2], identity: this.center.id, motion: this.center.motion });
59
59
  return pass.getOutput('color');
60
60
  }
@@ -62,7 +62,7 @@ export class WebGLAov {
62
62
  const gl = this.renderer.gl, framebuffer = new FrameBuffer(), width = this.width, height = this.height;
63
63
  try {
64
64
  const accumulated = this.accumulation[(this.samples - 1) % 2];
65
- const name = kind === 'depth' || kind === 'roughness' ? 'geometry' : kind === 'diffuseAlbedo' ? 'diffuse' : kind === 'specularAlbedo' ? 'specular' : 'position';
65
+ const name = kind === 'depth' || kind === 'roughness' ? 'geometry' : aovLaneKind(kind) === 3 ? 'diffuse' : aovLaneKind(kind) === 4 ? 'specular' : 'position';
66
66
  framebuffer.bind(this.renderer, [kind === 'id' ? this.center.id : kind === 'motion' ? this.center.motion : accumulated[name]]);
67
67
  if (kind === 'id') {
68
68
  const source = new Uint32Array(width * height * 4), data = new Uint32Array(source.length);
@@ -1 +1 @@
1
- {"version":3,"file":"WebGLAov.js","sourceRoot":"","sources":["../../src/renderer/WebGLAov.ts"],"names":[],"mappings":"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","sourcesContent":["import displayShader from './glsl/aovDisplay.frag.js';\nimport {WebGLFullQuadPass} from './WebGLFullQuadPass.js';\nimport {AOV_KINDS} from './aov.js';\nimport {AOV_ID_COMPONENTS, validateAovDisplay, type AovDisplayOptions} from './aovDisplay.js';\nimport {AovHistory, type AovKind, type AovFrameSnapshot} from './aov.js';\nimport {Texture2D, FrameBuffer, type WebGLDevice} from './webgl.js';\nimport {readRgbaPixels} from './WebGLReadback.js';\nconst names = ['geometry','position','diffuse','specular'] as const;\nexport class WebGLAov {\n private displayPass?: WebGLFullQuadPass<string,'color'>;\n readonly history=new AovHistory();\n width=0; height=0; samples=0; centerReady=false; frame?: AovFrameSnapshot;\n readonly accumulation: Record<typeof names[number],Texture2D>[]=[];\n previousCenter: {id:Texture2D; motion:Texture2D} | undefined;\n center: {id:Texture2D; motion:Texture2D} | undefined;\n scene = new Texture2D({type: 5125, minFilter:9728,magFilter:9728});\n constructor(readonly renderer: WebGLDevice) {}\n reset(){if(this.centerReady){const swap=this.previousCenter;this.previousCenter=this.center;this.center=swap;}this.samples=0;this.centerReady=false;this.frame=undefined;}\n resize(width:number,height:number){\n if(width===this.width && height===this.height)return;\n this.dispose();this.history.clear();this.reset();this.width=width;this.height=height;\n const options={width,height,type:5126,minFilter:9728,magFilter:9728};\n for(let i=0;i<2;i++)this.accumulation.push(Object.fromEntries(names.map(n=>[n,new Texture2D(options)])) as Record<typeof names[number],Texture2D>);\n this.previousCenter={id:new Texture2D({...options,type:5125}),motion:new Texture2D(options)};\n this.center={id:new Texture2D({...options,type:5125}),motion:new Texture2D(options)};\n }\n setScene(words:Uint32Array){\n const width=Math.min(1024,Math.max(1,Math.ceil(words.length/4))),height=Math.ceil(words.length/(width*4));\n const data=new Uint32Array(width*height*4);data.set(words);\n this.scene.source={data,width,height};\n }\n visualize(kind:AovKind,options:AovDisplayOptions):Texture2D {\n if(!this.samples || !this.center)throw new Error('AOV output is not ready');\n validateAovDisplay(options);\n this.displayPass??=new WebGLFullQuadPass('AOV display',this.renderer,{shader:displayShader,outputs:['color']});\n const pass=this.displayPass;pass.setSize(this.width,this.height);pass.setUniforms({kind:AOV_KINDS.indexOf(kind),samples:this.samples,mapping:[...options.depthRange,options.positionScale,options.motionScale],idComponent:AOV_ID_COMPONENTS.indexOf(options.idComponent)});\n pass.createPass({...this.accumulation[(this.samples-1)%2],identity:this.center.id,motion:this.center.motion});return pass.getOutput('color');\n }\n async read(kind:AovKind){\n const gl=this.renderer.gl, framebuffer=new FrameBuffer(), width=this.width,height=this.height;\n try{\n const accumulated=this.accumulation[(this.samples-1)%2];\n const name=kind==='depth'||kind==='roughness'?'geometry':kind==='diffuseAlbedo'?'diffuse':kind==='specularAlbedo'?'specular':'position';\n framebuffer.bind(this.renderer,[kind==='id'?this.center!.id:kind==='motion'?this.center!.motion:accumulated[name]]);\n if(kind==='id'){\n const source=new Uint32Array(width*height*4),data=new Uint32Array(source.length);\n gl.readPixels(0,0,width,height,gl.RGBA_INTEGER,gl.UNSIGNED_INT,source);\n for(let y=0;y<height;y++)data.set(source.subarray((height-1-y)*width*4,(height-y)*width*4),y*width*4);\n return {width,height,data};\n }\n const data=readRgbaPixels(gl,width,height,false);\n if(kind==='motion'){for(let o=2;o<data.length;o+=4)data[o]=0;return {width,height,data};}\n framebuffer.bind(this.renderer,[accumulated.position]);const coverage=readRgbaPixels(gl,width,height,false);\n for(let p=0;p<width*height;p++){\n const o=p*4,hits=coverage[o+3],inv=hits>0?1/hits:0,alpha=hits/Math.max(1,this.samples);\n if(kind==='depth')data.set([data[o]*inv,0,0,alpha],o);\n else if(kind==='roughness')data.set([data[o+1]*inv,data[o+2]*inv,data[o+3]*inv,alpha],o);\n else if(kind==='position')data.set([data[o]*inv,data[o+1]*inv,data[o+2]*inv,alpha],o);\n else{const count=data[o+3],scale=count>0?1/count:0;data.set([data[o]*scale,data[o+1]*scale,data[o+2]*scale,count/Math.max(1,this.samples)],o);}\n }\n return {width,height,data};\n }finally{framebuffer.dispose(this.renderer);}\n }\n get bytes(){return this.width*this.height*(2*64+64+(this.displayPass?4:0))+this.scene.width*this.scene.height*16;}\n dispose(){this.displayPass?.dispose();this.displayPass=undefined;const gl=this.renderer.gl;for(const set of this.accumulation)for(const texture of Object.values(set))texture.dispose(gl);this.accumulation.length=0;this.center?.id.dispose(gl);this.center?.motion.dispose(gl);this.center=undefined;this.previousCenter?.id.dispose(gl);this.previousCenter?.motion.dispose(gl);this.previousCenter=undefined;this.scene.dispose(gl);}\n}\n"]}
1
+ {"version":3,"file":"WebGLAov.js","sourceRoot":"","sources":["../../src/renderer/WebGLAov.ts"],"names":[],"mappings":"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","sourcesContent":["import displayShader from './glsl/aovDisplay.frag.js';\nimport {WebGLFullQuadPass} from './WebGLFullQuadPass.js';\nimport {aovLaneKind} from './aov.js';\nimport {AOV_ID_COMPONENTS, validateAovDisplay, type AovDisplayOptions} from './aovDisplay.js';\nimport {AovHistory, type AovKind, type AovFrameSnapshot} from './aov.js';\nimport {Texture2D, FrameBuffer, type WebGLDevice} from './webgl.js';\nimport {readRgbaPixels} from './WebGLReadback.js';\nconst names = ['geometry','position','diffuse','specular'] as const;\nexport class WebGLAov {\n private displayPass?: WebGLFullQuadPass<string,'color'>;\n readonly history=new AovHistory();\n width=0; height=0; samples=0; centerReady=false; frame?: AovFrameSnapshot;\n readonly accumulation: Record<typeof names[number],Texture2D>[]=[];\n previousCenter: {id:Texture2D; motion:Texture2D} | undefined;\n center: {id:Texture2D; motion:Texture2D} | undefined;\n scene = new Texture2D({type: 5125, minFilter:9728,magFilter:9728});\n constructor(readonly renderer: WebGLDevice) {}\n reset(){if(this.centerReady){const swap=this.previousCenter;this.previousCenter=this.center;this.center=swap;}this.samples=0;this.centerReady=false;this.frame=undefined;}\n resize(width:number,height:number){\n if(width===this.width && height===this.height)return;\n this.dispose();this.history.clear();this.reset();this.width=width;this.height=height;\n const options={width,height,type:5126,minFilter:9728,magFilter:9728};\n for(let i=0;i<2;i++)this.accumulation.push(Object.fromEntries(names.map(n=>[n,new Texture2D(options)])) as Record<typeof names[number],Texture2D>);\n this.previousCenter={id:new Texture2D({...options,type:5125}),motion:new Texture2D(options)};\n this.center={id:new Texture2D({...options,type:5125}),motion:new Texture2D(options)};\n }\n setScene(words:Uint32Array){\n const width=Math.min(1024,Math.max(1,Math.ceil(words.length/4))),height=Math.ceil(words.length/(width*4));\n const data=new Uint32Array(width*height*4);data.set(words);\n this.scene.source={data,width,height};\n }\n visualize(kind:AovKind,options:AovDisplayOptions):Texture2D {\n if(!this.samples || !this.center)throw new Error('AOV output is not ready');\n validateAovDisplay(options);\n this.displayPass??=new WebGLFullQuadPass('AOV display',this.renderer,{shader:displayShader,outputs:['color']});\n const pass=this.displayPass;pass.setSize(this.width,this.height);pass.setUniforms({kind:aovLaneKind(kind),samples:this.samples,mapping:[...options.depthRange,options.positionScale,options.motionScale],idComponent:AOV_ID_COMPONENTS.indexOf(options.idComponent)});\n pass.createPass({...this.accumulation[(this.samples-1)%2],identity:this.center.id,motion:this.center.motion});return pass.getOutput('color');\n }\n async read(kind:AovKind){\n const gl=this.renderer.gl, framebuffer=new FrameBuffer(), width=this.width,height=this.height;\n try{\n const accumulated=this.accumulation[(this.samples-1)%2];\n const name=kind==='depth'||kind==='roughness'?'geometry':aovLaneKind(kind)===3?'diffuse':aovLaneKind(kind)===4?'specular':'position';\n framebuffer.bind(this.renderer,[kind==='id'?this.center!.id:kind==='motion'?this.center!.motion:accumulated[name]]);\n if(kind==='id'){\n const source=new Uint32Array(width*height*4),data=new Uint32Array(source.length);\n gl.readPixels(0,0,width,height,gl.RGBA_INTEGER,gl.UNSIGNED_INT,source);\n for(let y=0;y<height;y++)data.set(source.subarray((height-1-y)*width*4,(height-y)*width*4),y*width*4);\n return {width,height,data};\n }\n const data=readRgbaPixels(gl,width,height,false);\n if(kind==='motion'){for(let o=2;o<data.length;o+=4)data[o]=0;return {width,height,data};}\n framebuffer.bind(this.renderer,[accumulated.position]);const coverage=readRgbaPixels(gl,width,height,false);\n for(let p=0;p<width*height;p++){\n const o=p*4,hits=coverage[o+3],inv=hits>0?1/hits:0,alpha=hits/Math.max(1,this.samples);\n if(kind==='depth')data.set([data[o]*inv,0,0,alpha],o);\n else if(kind==='roughness')data.set([data[o+1]*inv,data[o+2]*inv,data[o+3]*inv,alpha],o);\n else if(kind==='position')data.set([data[o]*inv,data[o+1]*inv,data[o+2]*inv,alpha],o);\n else{const count=data[o+3],scale=count>0?1/count:0;data.set([data[o]*scale,data[o+1]*scale,data[o+2]*scale,count/Math.max(1,this.samples)],o);}\n }\n return {width,height,data};\n }finally{framebuffer.dispose(this.renderer);}\n }\n get bytes(){return this.width*this.height*(2*64+64+(this.displayPass?4:0))+this.scene.width*this.scene.height*16;}\n dispose(){this.displayPass?.dispose();this.displayPass=undefined;const gl=this.renderer.gl;for(const set of this.accumulation)for(const texture of Object.values(set))texture.dispose(gl);this.accumulation.length=0;this.center?.id.dispose(gl);this.center?.motion.dispose(gl);this.center=undefined;this.previousCenter?.id.dispose(gl);this.previousCenter?.motion.dispose(gl);this.previousCenter=undefined;this.scene.dispose(gl);}\n}\n"]}
@@ -43,7 +43,7 @@ export declare class WebGLFullQuadPass<I extends string, O extends string> {
43
43
  outputs?: O[];
44
44
  outputParams?: Partial<Record<O, WebGLFullQuadPassOutput>>;
45
45
  });
46
- setShader(shader: FragmentShader): void;
46
+ setShader(shader: FragmentShader, discardUniforms?: readonly string[], discardDefines?: readonly string[]): void;
47
47
  reserveCapacity(): void;
48
48
  private _samplingShader;
49
49
  setSize(width: number, height: number): void;
@@ -37,9 +37,15 @@ export class WebGLFullQuadPass {
37
37
  options.outputParams?.[name] || {}
38
38
  ])));
39
39
  }
40
- setShader(shader) {
40
+ setShader(shader, discardUniforms = [], discardDefines = []) {
41
+ const uniforms = { ...shader.uniforms, ...this._bindings.uniforms };
42
+ const defines = { ...shader.defines, ...this._bindings.defines };
43
+ for (const name of discardUniforms)
44
+ delete uniforms[name];
45
+ for (const name of discardDefines)
46
+ delete defines[name];
41
47
  this._sourceShader = shader;
42
- this._bindings = new WebGLProgramBindings(this._samplingShader(shader, this._reserveCapacity, { ...shader.uniforms, ...this._bindings.uniforms }, this._bindings.defines));
48
+ this._bindings = new WebGLProgramBindings(this._samplingShader(shader, this._reserveCapacity, uniforms, defines));
43
49
  }
44
50
  reserveCapacity() {
45
51
  if (this._reserveCapacity)
@@ -1 +1 @@
1
- {"version":3,"file":"WebGLFullQuadPass.js","sourceRoot":"","sources":["../../src/renderer/WebGLFullQuadPass.ts"],"names":[],"mappings":"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","sourcesContent":["import {scratchGLSLFunctions} from './scratchSampling.js';\nimport {setTextureRegion, textureRegion} from './textureRegion.js';\nimport { FragmentShader, type ShaderDefineValue } from './shader.js';\nimport {\n FrameBuffer,\n WebGLDevice,\n Texture2D,\n type TextureOptions,\n WebGLProgramBindings\n} from './webgl.js';\n\nexport interface WebGLFullQuadPassOutput extends TextureOptions {}\n\nexport interface WebGLPassOptions {\n clear?: boolean;\n blend?: boolean;\n viewport?: { x: number; y: number; width: number; height: number };\n scissor?: { x: number; y: number; width: number; height: number };\n}\n\n/**\n * Explicit WebGL 2.0 render pass matching the lifecycle of WGPUFullQuadPass.\n * It owns its output textures and framebuffer; there is no render graph.\n */\nexport class WebGLFullQuadPass<I extends string, O extends string> {\n private readonly _renderer: WebGLDevice;\n private _bindings: WebGLProgramBindings;\n private _sourceShader: FragmentShader;\n private readonly _outputs: O[];\n private readonly _frameBuffer = new FrameBuffer();\n private _outputTextures = {} as Record<O, Texture2D>;\n private readonly _targetOutputs = new Map<object, Record<O, Texture2D>>();\n useTarget(target: object) {\n let outputs = this._targetOutputs.get(target);\n if (!outputs) this._targetOutputs.set(target, outputs = {} as Record<O, Texture2D>);\n this._outputTextures = outputs;\n }\n\n private _outputParams = {} as Record<O, WebGLFullQuadPassOutput>;\n private _reserveCapacity = false;\n private _capacityWidth = 1;\n private _capacityHeight = 1;\n private _width = 1;\n private _height = 1;\n private _renderToScreen = false;\n\n constructor(\n _label: string,\n renderer: WebGLDevice,\n options: {\n shader: FragmentShader;\n outputs?: O[];\n outputParams?: Partial<Record<O, WebGLFullQuadPassOutput>>;\n }\n ) {\n this._renderer = renderer;\n this._sourceShader = options.shader;\n this._bindings = new WebGLProgramBindings(this._samplingShader(options.shader));\n this._outputs = options.outputs || (options.shader.outputs as O[]);\n this.setOutputParams(\n Object.fromEntries(\n this._outputs.map((name) => [\n name,\n options.outputParams?.[name] || {}\n ])\n ) as Record<O, WebGLFullQuadPassOutput>\n );\n }\n\n setShader(shader: FragmentShader) {\n this._sourceShader = shader;\n this._bindings = new WebGLProgramBindings(this._samplingShader(\n shader, this._reserveCapacity, {...shader.uniforms, ...this._bindings.uniforms}, this._bindings.defines\n ));\n }\n\n reserveCapacity() {\n if (this._reserveCapacity) return;\n this._reserveCapacity = true;\n this._bindings = new WebGLProgramBindings(this._samplingShader(\n this._sourceShader, true, this._bindings.uniforms, this._bindings.defines\n ));\n }\n\n private _samplingShader(\n shader: FragmentShader,\n scratch = false,\n uniforms = shader.uniforms,\n defines = shader.defines\n ) {\n const textures = Object.keys(shader.uniforms).filter(name => shader.uniforms[name].type === 'sampler2D');\n uniforms = {...uniforms};\n if (scratch) for (const name of textures) uniforms[`${name}RegionSize`] = {type: 'ivec2', value: [1, 1]};\n const sampled = new FragmentShader({name: shader.name, outputs: shader.outputs, outputTypes: shader.outputTypes, defines, uniforms,\n includes: [{defines: {}, uniforms: {}, main: '', functions: [() => scratchGLSLFunctions(textures, scratch), ...shader.functions]}],\n main: shader.main});\n sampled.parallelCompile = shader.parallelCompile;\n return sampled;\n }\n\n setSize(width: number, height: number) {\n if (this._width === width && this._height === height) return;\n this._width = Math.max(1, width);\n this._height = Math.max(1, height);\n this._capacityWidth = Math.max(this._capacityWidth, this._width);\n this._capacityHeight = Math.max(this._capacityHeight, this._height);\n this.setUniform('viewportSize', [this._width, this._height]);\n }\n\n setOutputs(outputs: readonly O[]) {\n for (const name of this._outputs) if (!outputs.includes(name)) {\n this._outputTextures[name]?.dispose(this._renderer.gl); delete this._outputTextures[name];\n }\n this._outputs.splice(0, this._outputs.length, ...outputs);\n }\n setOutputParams(params: Record<O, WebGLFullQuadPassOutput>) {\n this._outputParams = params;\n }\n\n setRenderToScreen(renderToScreen = true) {\n this._renderToScreen = renderToScreen;\n }\n\n setUniform(label: string, data: unknown) {\n return this._bindings.set(label, data);\n }\n\n setUniforms(values: Record<string, unknown>) {\n this._bindings.setUniforms(values);\n }\n\n getUniform(label: string) {\n return this._bindings.get(label);\n }\n\n setDefines(\n defines: Record<\n string,\n ShaderDefineValue | undefined\n >\n ) {\n let changed = false;\n for (const [name, value] of Object.entries(defines)) {\n const oldValue = this._bindings.defines[name];\n if (!value) {\n if (name in this._bindings.defines) {\n this._bindings.deleteDefine(name);\n changed = true;\n }\n } else if (oldValue !== value) {\n this._bindings.setDefine(name, value);\n changed = true;\n }\n }\n return changed;\n }\n\n private readonly _retainedOutputs = new Set<Texture2D>();\n retainOutput(texture: Texture2D) { if (Object.values(this._outputTextures).includes(texture)) this._retainedOutputs.add(texture); }\n releaseOutput(texture: Texture2D) {\n if (!this._retainedOutputs.delete(texture)) return;\n if (!Object.values(this._outputTextures).includes(texture)) texture.dispose(this._renderer.gl);\n }\n\n // Internal fixed-accumulation loader; transfer ownership to the selected target.\n loadDiagnosticOutputs(outputs: Partial<Record<O, Texture2D>>) {\n for (const name of Object.keys(outputs) as O[]) {\n this._outputTextures[name]?.dispose(this._renderer.gl);\n this._outputTextures[name] = outputs[name]!;\n }\n }\n\n getOutput(name: O) {\n return this._outputTextures[name];\n }\n\n private _prepareOutputs(explicitOutputs?: Partial<Record<O, Texture2D>>) {\n const gl = this._renderer.gl;\n for (const name of this._outputs) {\n const explicit = explicitOutputs?.[name];\n const current = this._outputTextures[name];\n const retainedResize = current && this._retainedOutputs.has(current) &&\n (current.width !== this._width || current.height !== this._height);\n const texture =\n explicit ||\n (retainedResize ? new Texture2D(this._outputParams[name]) : undefined) ||\n this._outputTextures[name] ||\n new Texture2D(this._outputParams[name]);\n texture.ensureStorage(\n gl,\n this._reserveCapacity ? this._capacityWidth : this._width,\n this._reserveCapacity ? this._capacityHeight : this._height,\n this._outputParams[name]\n );\n this._outputTextures[name] = texture;\n setTextureRegion(texture, this._width, this._height);\n }\n }\n\n isProgramReady(inputs?: Record<I, Texture2D>) {\n if (inputs) this._bindings.setUniforms(inputs);\n return this._renderer.isProgramCompiled(this._bindings.getProgram(this._renderer));\n }\n\n createPass(\n inputs: Record<I, Texture2D>,\n explicitOutputs?: Partial<Record<O, Texture2D>>,\n options: WebGLPassOptions = {}\n ) {\n const renderer = this._renderer;\n const gl = renderer.gl;\n\n if (this._renderToScreen) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n } else {\n this._prepareOutputs(explicitOutputs);\n this._frameBuffer.bind(\n renderer,\n this._outputs.map((name) => this._outputTextures[name])\n );\n }\n\n const viewport = options.viewport || {\n x: 0,\n y: 0,\n width: this._width,\n height: this._height\n };\n renderer.setViewport(\n viewport.x,\n viewport.y,\n viewport.width,\n viewport.height\n );\n\n // Clear the full accumulation target before enabling the tile scissor.\n // Otherwise every tile outside the first one retains stale camera data.\n if (options.clear) {\n gl.disable(gl.SCISSOR_TEST);\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n }\n\n if (options.scissor) {\n gl.enable(gl.SCISSOR_TEST);\n gl.scissor(\n options.scissor.x,\n options.scissor.y,\n options.scissor.width,\n options.scissor.height\n );\n } else {\n gl.disable(gl.SCISSOR_TEST);\n }\n\n if (this._reserveCapacity) for (const [name, texture] of Object.entries(inputs) as [string, Texture2D][]) {\n const region = textureRegion(texture);\n this.setUniform(`${name}RegionSize`, [region.width, region.height]);\n }\n this._bindings.setUniforms(inputs);\n if (!this._bindings.bind(renderer)) {\n gl.disable(gl.SCISSOR_TEST);\n return false;\n }\n gl.disable(gl.DEPTH_TEST);\n if (options.blend) {\n gl.enable(gl.BLEND);\n gl.blendEquation(gl.FUNC_ADD);\n gl.blendFunc(gl.ONE, gl.ONE);\n } else {\n gl.disable(gl.BLEND);\n }\n gl.drawArrays(gl.TRIANGLES, 0, 3);\n gl.disable(gl.SCISSOR_TEST);\n return true;\n }\n\n releaseTarget(target: object) {\n const outputs = this._targetOutputs.get(target);\n if (!outputs) return;\n this._targetOutputs.delete(target);\n for (const texture of (Object.values(outputs) as Texture2D[])) texture.dispose(this._renderer.gl);\n if (outputs === this._outputTextures) this._outputTextures = {} as Record<O, Texture2D>;\n }\n\n getMemoryBytes(target?: object): number {\n const outputs = target ? this._targetOutputs.get(target) ?? {} : this._outputTextures;\n return Array.from(new Set([...Object.values(outputs) as Texture2D[], ...this._retainedOutputs]))\n .reduce((sum, texture) => sum + texture.getMemoryBytes(), 0);\n }\n\n dispose() {\n const gl = this._renderer.gl;\n (Array.from(new Set([this._outputTextures, ...this._targetOutputs.values()])).flatMap(outputs => Object.values(outputs)) as Texture2D[]).forEach((texture) =>\n texture.dispose(gl)\n );\n this._retainedOutputs.forEach(texture => texture.dispose(gl));\n this._retainedOutputs.clear();\n this._frameBuffer.dispose(this._renderer);\n }\n}\n"]}
1
+ {"version":3,"file":"WebGLFullQuadPass.js","sourceRoot":"","sources":["../../src/renderer/WebGLFullQuadPass.ts"],"names":[],"mappings":"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","sourcesContent":["import {scratchGLSLFunctions} from './scratchSampling.js';\nimport {setTextureRegion, textureRegion} from './textureRegion.js';\nimport { FragmentShader, type ShaderDefineValue } from './shader.js';\nimport {\n FrameBuffer,\n WebGLDevice,\n Texture2D,\n type TextureOptions,\n WebGLProgramBindings\n} from './webgl.js';\n\nexport interface WebGLFullQuadPassOutput extends TextureOptions {}\n\nexport interface WebGLPassOptions {\n clear?: boolean;\n blend?: boolean;\n viewport?: { x: number; y: number; width: number; height: number };\n scissor?: { x: number; y: number; width: number; height: number };\n}\n\n/**\n * Explicit WebGL 2.0 render pass matching the lifecycle of WGPUFullQuadPass.\n * It owns its output textures and framebuffer; there is no render graph.\n */\nexport class WebGLFullQuadPass<I extends string, O extends string> {\n private readonly _renderer: WebGLDevice;\n private _bindings: WebGLProgramBindings;\n private _sourceShader: FragmentShader;\n private readonly _outputs: O[];\n private readonly _frameBuffer = new FrameBuffer();\n private _outputTextures = {} as Record<O, Texture2D>;\n private readonly _targetOutputs = new Map<object, Record<O, Texture2D>>();\n useTarget(target: object) {\n let outputs = this._targetOutputs.get(target);\n if (!outputs) this._targetOutputs.set(target, outputs = {} as Record<O, Texture2D>);\n this._outputTextures = outputs;\n }\n\n private _outputParams = {} as Record<O, WebGLFullQuadPassOutput>;\n private _reserveCapacity = false;\n private _capacityWidth = 1;\n private _capacityHeight = 1;\n private _width = 1;\n private _height = 1;\n private _renderToScreen = false;\n\n constructor(\n _label: string,\n renderer: WebGLDevice,\n options: {\n shader: FragmentShader;\n outputs?: O[];\n outputParams?: Partial<Record<O, WebGLFullQuadPassOutput>>;\n }\n ) {\n this._renderer = renderer;\n this._sourceShader = options.shader;\n this._bindings = new WebGLProgramBindings(this._samplingShader(options.shader));\n this._outputs = options.outputs || (options.shader.outputs as O[]);\n this.setOutputParams(\n Object.fromEntries(\n this._outputs.map((name) => [\n name,\n options.outputParams?.[name] || {}\n ])\n ) as Record<O, WebGLFullQuadPassOutput>\n );\n }\n\n setShader(shader: FragmentShader, discardUniforms: readonly string[] = [], discardDefines: readonly string[] = []) {\n const uniforms = {...shader.uniforms, ...this._bindings.uniforms};\n const defines = {...shader.defines, ...this._bindings.defines};\n for (const name of discardUniforms) delete uniforms[name];\n for (const name of discardDefines) delete defines[name];\n this._sourceShader = shader;\n this._bindings = new WebGLProgramBindings(this._samplingShader(\n shader, this._reserveCapacity, uniforms, defines\n ));\n }\n\n reserveCapacity() {\n if (this._reserveCapacity) return;\n this._reserveCapacity = true;\n this._bindings = new WebGLProgramBindings(this._samplingShader(\n this._sourceShader, true, this._bindings.uniforms, this._bindings.defines\n ));\n }\n\n private _samplingShader(\n shader: FragmentShader,\n scratch = false,\n uniforms = shader.uniforms,\n defines = shader.defines\n ) {\n const textures = Object.keys(shader.uniforms).filter(name => shader.uniforms[name].type === 'sampler2D');\n uniforms = {...uniforms};\n if (scratch) for (const name of textures) uniforms[`${name}RegionSize`] = {type: 'ivec2', value: [1, 1]};\n const sampled = new FragmentShader({name: shader.name, outputs: shader.outputs, outputTypes: shader.outputTypes, defines, uniforms,\n includes: [{defines: {}, uniforms: {}, main: '', functions: [() => scratchGLSLFunctions(textures, scratch), ...shader.functions]}],\n main: shader.main});\n sampled.parallelCompile = shader.parallelCompile;\n return sampled;\n }\n\n setSize(width: number, height: number) {\n if (this._width === width && this._height === height) return;\n this._width = Math.max(1, width);\n this._height = Math.max(1, height);\n this._capacityWidth = Math.max(this._capacityWidth, this._width);\n this._capacityHeight = Math.max(this._capacityHeight, this._height);\n this.setUniform('viewportSize', [this._width, this._height]);\n }\n\n setOutputs(outputs: readonly O[]) {\n for (const name of this._outputs) if (!outputs.includes(name)) {\n this._outputTextures[name]?.dispose(this._renderer.gl); delete this._outputTextures[name];\n }\n this._outputs.splice(0, this._outputs.length, ...outputs);\n }\n setOutputParams(params: Record<O, WebGLFullQuadPassOutput>) {\n this._outputParams = params;\n }\n\n setRenderToScreen(renderToScreen = true) {\n this._renderToScreen = renderToScreen;\n }\n\n setUniform(label: string, data: unknown) {\n return this._bindings.set(label, data);\n }\n\n setUniforms(values: Record<string, unknown>) {\n this._bindings.setUniforms(values);\n }\n\n getUniform(label: string) {\n return this._bindings.get(label);\n }\n\n setDefines(\n defines: Record<\n string,\n ShaderDefineValue | undefined\n >\n ) {\n let changed = false;\n for (const [name, value] of Object.entries(defines)) {\n const oldValue = this._bindings.defines[name];\n if (!value) {\n if (name in this._bindings.defines) {\n this._bindings.deleteDefine(name);\n changed = true;\n }\n } else if (oldValue !== value) {\n this._bindings.setDefine(name, value);\n changed = true;\n }\n }\n return changed;\n }\n\n private readonly _retainedOutputs = new Set<Texture2D>();\n retainOutput(texture: Texture2D) { if (Object.values(this._outputTextures).includes(texture)) this._retainedOutputs.add(texture); }\n releaseOutput(texture: Texture2D) {\n if (!this._retainedOutputs.delete(texture)) return;\n if (!Object.values(this._outputTextures).includes(texture)) texture.dispose(this._renderer.gl);\n }\n\n // Internal fixed-accumulation loader; transfer ownership to the selected target.\n loadDiagnosticOutputs(outputs: Partial<Record<O, Texture2D>>) {\n for (const name of Object.keys(outputs) as O[]) {\n this._outputTextures[name]?.dispose(this._renderer.gl);\n this._outputTextures[name] = outputs[name]!;\n }\n }\n\n getOutput(name: O) {\n return this._outputTextures[name];\n }\n\n private _prepareOutputs(explicitOutputs?: Partial<Record<O, Texture2D>>) {\n const gl = this._renderer.gl;\n for (const name of this._outputs) {\n const explicit = explicitOutputs?.[name];\n const current = this._outputTextures[name];\n const retainedResize = current && this._retainedOutputs.has(current) &&\n (current.width !== this._width || current.height !== this._height);\n const texture =\n explicit ||\n (retainedResize ? new Texture2D(this._outputParams[name]) : undefined) ||\n this._outputTextures[name] ||\n new Texture2D(this._outputParams[name]);\n texture.ensureStorage(\n gl,\n this._reserveCapacity ? this._capacityWidth : this._width,\n this._reserveCapacity ? this._capacityHeight : this._height,\n this._outputParams[name]\n );\n this._outputTextures[name] = texture;\n setTextureRegion(texture, this._width, this._height);\n }\n }\n\n isProgramReady(inputs?: Record<I, Texture2D>) {\n if (inputs) this._bindings.setUniforms(inputs);\n return this._renderer.isProgramCompiled(this._bindings.getProgram(this._renderer));\n }\n\n createPass(\n inputs: Record<I, Texture2D>,\n explicitOutputs?: Partial<Record<O, Texture2D>>,\n options: WebGLPassOptions = {}\n ) {\n const renderer = this._renderer;\n const gl = renderer.gl;\n\n if (this._renderToScreen) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n } else {\n this._prepareOutputs(explicitOutputs);\n this._frameBuffer.bind(\n renderer,\n this._outputs.map((name) => this._outputTextures[name])\n );\n }\n\n const viewport = options.viewport || {\n x: 0,\n y: 0,\n width: this._width,\n height: this._height\n };\n renderer.setViewport(\n viewport.x,\n viewport.y,\n viewport.width,\n viewport.height\n );\n\n // Clear the full accumulation target before enabling the tile scissor.\n // Otherwise every tile outside the first one retains stale camera data.\n if (options.clear) {\n gl.disable(gl.SCISSOR_TEST);\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n }\n\n if (options.scissor) {\n gl.enable(gl.SCISSOR_TEST);\n gl.scissor(\n options.scissor.x,\n options.scissor.y,\n options.scissor.width,\n options.scissor.height\n );\n } else {\n gl.disable(gl.SCISSOR_TEST);\n }\n\n if (this._reserveCapacity) for (const [name, texture] of Object.entries(inputs) as [string, Texture2D][]) {\n const region = textureRegion(texture);\n this.setUniform(`${name}RegionSize`, [region.width, region.height]);\n }\n this._bindings.setUniforms(inputs);\n if (!this._bindings.bind(renderer)) {\n gl.disable(gl.SCISSOR_TEST);\n return false;\n }\n gl.disable(gl.DEPTH_TEST);\n if (options.blend) {\n gl.enable(gl.BLEND);\n gl.blendEquation(gl.FUNC_ADD);\n gl.blendFunc(gl.ONE, gl.ONE);\n } else {\n gl.disable(gl.BLEND);\n }\n gl.drawArrays(gl.TRIANGLES, 0, 3);\n gl.disable(gl.SCISSOR_TEST);\n return true;\n }\n\n releaseTarget(target: object) {\n const outputs = this._targetOutputs.get(target);\n if (!outputs) return;\n this._targetOutputs.delete(target);\n for (const texture of (Object.values(outputs) as Texture2D[])) texture.dispose(this._renderer.gl);\n if (outputs === this._outputTextures) this._outputTextures = {} as Record<O, Texture2D>;\n }\n\n getMemoryBytes(target?: object): number {\n const outputs = target ? this._targetOutputs.get(target) ?? {} : this._outputTextures;\n return Array.from(new Set([...Object.values(outputs) as Texture2D[], ...this._retainedOutputs]))\n .reduce((sum, texture) => sum + texture.getMemoryBytes(), 0);\n }\n\n dispose() {\n const gl = this._renderer.gl;\n (Array.from(new Set([this._outputTextures, ...this._targetOutputs.values()])).flatMap(outputs => Object.values(outputs)) as Texture2D[]).forEach((texture) =>\n texture.dispose(gl)\n );\n this._retainedOutputs.forEach(texture => texture.dispose(gl));\n this._retainedOutputs.clear();\n this._frameBuffer.dispose(this._renderer);\n }\n}\n"]}
@@ -45,27 +45,27 @@ void main() {
45
45
  ivec2 p = ivec2(gl_FragCoord.xy);
46
46
  ivec2 size = rawGuideTexRegion();
47
47
  vec2 center = load_rawGuideTex(p, 0).xy;
48
- float lM = 0.0;
49
- float je = 0.0;
50
- float nM = 0.0;
51
- float iV = 0.0;
48
+ float mF = 0.0;
49
+ float jI = 0.0;
50
+ float oL = 0.0;
51
+ float jB = 0.0;
52
52
  for (int dy = -1; dy <= 1; dy++) {
53
53
  for (int dx = -1; dx <= 1; dx++) {
54
54
  vec2 value = load_rawGuideTex(clamp(p + ivec2(dx, dy), ivec2(0), size - 1), 0).xy;
55
- nM += value.x;
56
- iV += value.x * value.x;
55
+ oL += value.x;
56
+ jB += value.x * value.x;
57
57
  if (value.y >= 0.0) {
58
- lM += value.y;
59
- je += 1.0;
58
+ mF += value.y;
59
+ jI += 1.0;
60
60
  }
61
61
  }
62
62
  }
63
63
  float variance;
64
64
  if (center.y >= 0.0) {
65
- variance = lM / je;
65
+ variance = mF / jI;
66
66
  } else {
67
- float lL = nM / 9.0;
68
- variance = max(iV / 9.0 - lL * lL, 0.0) * 9.0 / 8.0;
67
+ float mE = oL / 9.0;
68
+ variance = max(jB / 9.0 - mE * mE, 0.0) * 9.0 / 8.0;
69
69
  }
70
70
  out_guide = vec4(center.x, variance, 0.0, 1.0);
71
71
  }`
@@ -110,38 +110,38 @@ return load_guideTex(clamp(p, ivec2(0), imageSize - 1), 0).xy;
110
110
  }
111
111
 
112
112
 
113
- vec4 sI(ivec2 p) {
113
+ vec4 ns(ivec2 p) {
114
114
  vec4 c = load_colorTex(p, 0);
115
115
  if (decodeInput) c.rgb = mix(pow((max(c.rgb, 0.0) + 0.055) / 1.055, vec3(2.4)),
116
116
  c.rgb / 12.92, lessThanEqual(c.rgb, vec3(0.04045)));
117
117
  return vec4(c.rgb * c.a, c.a);
118
118
  }
119
119
 
120
- float lP(ivec2 q, vec4 bo, vec3 gO) {
120
+ float mJ(ivec2 q, vec4 bp, vec3 hk) {
121
121
  vec4 albedo = load_albedoTex(q, 0);
122
122
 
123
123
 
124
- vec3 pY = max((albedo.rgb + bo.rgb) * 0.5, vec3(${JNLM_ALBEDO_FLOOR}));
125
- vec3 lu = (albedo.rgb - bo.rgb) / pY;
126
- float iQ = albedo.a - bo.a;
127
- vec3 lG = load_normalTex(q, 0).rgb - gO;
124
+ vec3 rc = max((albedo.rgb + bp.rgb) * 0.5, vec3(${JNLM_ALBEDO_FLOOR}));
125
+ vec3 mn = (albedo.rgb - bp.rgb) / rc;
126
+ float jv = albedo.a - bp.a;
127
+ vec3 my = load_normalTex(q, 0).rgb - hk;
128
128
  return max(
129
- dot(lu, lu) * INV_ALBEDO_BANDWIDTH2
130
- + iQ * iQ * INV_COVERAGE_BANDWIDTH2,
131
- dot(lG, lG) * INV_NORMAL_BANDWIDTH2
129
+ dot(mn, mn) * INV_ALBEDO_BANDWIDTH2
130
+ + jv * jv * INV_COVERAGE_BANDWIDTH2,
131
+ dot(my, my) * INV_NORMAL_BANDWIDTH2
132
132
  );
133
133
  }
134
134
 
135
135
  void main() {
136
136
  imageSize = guideTexRegion();
137
137
  ivec2 p = ivec2(gl_FragCoord.xy);
138
- vec4 bo = load_albedoTex(p, 0);
139
- vec4 fC = load_normalTex(p, 0);
140
- vec3 gO = fC.rgb;
138
+ vec4 bp = load_albedoTex(p, 0);
139
+ vec4 fO = load_normalTex(p, 0);
140
+ vec3 hk = fO.rgb;
141
141
 
142
142
 
143
- if (fC.a <= 0.0 && load_shadowCatcherTex(p, 0).r <= 0.0) {
144
- vec4 c = sI(p);
143
+ if (fO.a <= 0.0 && load_shadowCatcherTex(p, 0).r <= 0.0) {
144
+ vec4 c = ns(p);
145
145
  vec3 rgb = c.rgb / max(c.a, 1e-6);
146
146
  if (encodeOutput) rgb = mix(1.055 * pow(max(rgb, 0.0), vec3(1.0 / 2.4)) - 0.055,
147
147
  rgb * 12.92, lessThanEqual(rgb, vec3(0.0031308)));
@@ -150,25 +150,25 @@ out_guide = vec4(loadGuide(p), 0.0, 1.0);
150
150
  return;
151
151
  }
152
152
 
153
- vec2 lA[PATCH_SIZE];
153
+ vec2 mq[PATCH_SIZE];
154
154
  int k = 0;
155
155
  for (int dy = -PATCH_RADIUS; dy <= PATCH_RADIUS; dy++) {
156
156
  for (int dx = -PATCH_RADIUS; dx <= PATCH_RADIUS; dx++) {
157
- lA[k] = loadGuide(p + ivec2(dx, dy) * dilation);
157
+ mq[k] = loadGuide(p + ivec2(dx, dy) * dilation);
158
158
  k++;
159
159
  }
160
160
  }
161
161
  float k2 = colorSensitivity * colorSensitivity;
162
162
 
163
163
  vec4 sum = vec4(0.0);
164
- vec3 gR = max(bo.rgb, vec3(${JNLM_ALBEDO_FLOOR}));
165
- vec3 mQ = vec3(0.0);
166
- vec3 gv = vec3(0.0);
167
- vec3 hm = vec3(0.0);
168
- float qf = 0.0;
169
- float gx = 0.0;
170
- float oE = 0.0;
171
- float kX = 0.0;
164
+ vec3 hn = max(bp.rgb, vec3(${JNLM_ALBEDO_FLOOR}));
165
+ vec3 nS = vec3(0.0);
166
+ vec3 gP = vec3(0.0);
167
+ vec3 hH = vec3(0.0);
168
+ float rn = 0.0;
169
+ float gR = 0.0;
170
+ float pK = 0.0;
171
+ float lR = 0.0;
172
172
  for (int sy = -SEARCH_RADIUS; sy <= SEARCH_RADIUS; sy++) {
173
173
  for (int sx = -SEARCH_RADIUS; sx <= SEARCH_RADIUS; sx++) {
174
174
  ivec2 q = p + ivec2(sx, sy) * dilation;
@@ -176,60 +176,60 @@ if (
176
176
  (sx == 0 && sy == 0) ||
177
177
  q.x < 0 || q.y < 0 || q.x >= imageSize.x || q.y >= imageSize.y
178
178
  ) continue;
179
- float features = lP(q, bo, gO);
179
+ float features = mJ(q, bp, hk);
180
180
  if (features > 16.0) continue;
181
181
 
182
- float fW = 0.0;
182
+ float gn = 0.0;
183
183
  k = 0;
184
184
  for (int dy = -PATCH_RADIUS; dy <= PATCH_RADIUS; dy++) {
185
185
  for (int dx = -PATCH_RADIUS; dx <= PATCH_RADIUS; dx++) {
186
- vec2 a = lA[k];
186
+ vec2 a = mq[k];
187
187
  vec2 b = loadGuide(q + ivec2(dx, dy) * dilation);
188
- float rV = a.x - b.x;
189
- fW += (rV * rV
188
+ float tn = a.x - b.x;
189
+ gn += (tn * tn
190
190
  - VARIANCE_CANCELLATION * (a.y + min(a.y, b.y)))
191
191
  / (1e-10 + k2 * (a.y + b.y));
192
192
  k++;
193
193
  }
194
194
  }
195
- fW /= float(PATCH_SIZE);
195
+ gn /= float(PATCH_SIZE);
196
196
 
197
- float weight = exp(-max(max(fW, 0.0), features));
197
+ float weight = exp(-max(max(gn, 0.0), features));
198
198
  vec2 g = loadGuide(q);
199
199
 
200
- vec3 a = (load_albedoTex(q, 0).rgb - bo.rgb) / gR;
201
- vec4 value = sI(q);
200
+ vec3 a = (load_albedoTex(q, 0).rgb - bp.rgb) / hn;
201
+ vec4 value = ns(q);
202
202
  sum += value * weight;
203
- mQ += a * weight;
204
- gv += a * a * weight;
205
- hm += a * value.rgb * weight;
206
- qf += g.x * weight;
207
- gx += g.y * weight * weight;
208
- oE += weight;
209
- kX = max(kX, weight);
203
+ nS += a * weight;
204
+ gP += a * a * weight;
205
+ hH += a * value.rgb * weight;
206
+ rn += g.x * weight;
207
+ gR += g.y * weight * weight;
208
+ pK += weight;
209
+ lR = max(lR, weight);
210
210
  }
211
211
  }
212
212
 
213
213
 
214
214
 
215
- vec4 center = sI(p);
216
- vec2 lw = loadGuide(p);
217
- float dE = max(kX, CENTER_WEIGHT_MIN);
218
- float totalWeight = oE + dE;
219
- vec4 mean = (sum + center * dE) / totalWeight;
215
+ vec4 center = ns(p);
216
+ vec2 mp = loadGuide(p);
217
+ float dG = max(lR, CENTER_WEIGHT_MIN);
218
+ float totalWeight = pK + dG;
219
+ vec4 mean = (sum + center * dG) / totalWeight;
220
220
 
221
221
 
222
- vec3 er = mQ / totalWeight;
223
- vec3 lQ = max(gv / totalWeight - er * er, vec3(0.0));
224
- vec3 rq = hm / totalWeight - er * mean.rgb;
222
+ vec3 eA = nS / totalWeight;
223
+ vec3 mK = max(gP / totalWeight - eA * eA, vec3(0.0));
224
+ vec3 sH = hH / totalWeight - eA * mean.rgb;
225
225
 
226
226
 
227
227
 
228
- vec3 rD = bo.rgb + er * gR;
229
- vec3 pd = mean.rgb * gR / max(rD, vec3(${JNLM_ALBEDO_FLOOR}));
230
- vec3 xI = clamp(rq / (lQ + vec3(${JNLM_ALBEDO_REGULARIZATION})), vec3(0.0), pd);
231
- vec3 sz = mean.rgb - xI * er;
232
- vec4 filtered = vec4(max(sz, vec3(0.0)), max(mean.a, 0.0));
228
+ vec3 gt = bp.rgb + eA * hn;
229
+ vec3 qm = mean.rgb * hn / max(gt, vec3(${JNLM_ALBEDO_FLOOR}));
230
+ vec3 slope = clamp(sH / (mK + vec3(${JNLM_ALBEDO_REGULARIZATION})), vec3(0.0), qm);
231
+ vec3 tY = mean.rgb - slope * eA;
232
+ vec4 filtered = vec4(max(tY, vec3(0.0)), max(mean.a, 0.0));
233
233
  vec3 rgb = filtered.a > 1e-6
234
234
  ? filtered.rgb / max(filtered.a, 1e-6)
235
235
  : center.rgb / max(center.a, 1e-6);
@@ -237,8 +237,8 @@ if (encodeOutput) rgb = mix(1.055 * pow(max(rgb, 0.0), vec3(1.0 / 2.4)) - 0.055,
237
237
  rgb * 12.92, lessThanEqual(rgb, vec3(0.0031308)));
238
238
  out_color = vec4(rgb, filtered.a);
239
239
  out_guide = vec4(
240
- (qf + lw.x * dE) / totalWeight,
241
- (gx + lw.y * dE * dE)
240
+ (rn + mp.x * dG) / totalWeight,
241
+ (gR + mp.y * dG * dG)
242
242
  / (totalWeight * totalWeight),
243
243
  0.0,
244
244
  1.0
@@ -1 +1 @@
1
- {"version":3,"file":"WebGLJNLMDenoiser.js","sourceRoot":"","sources":["../../src/renderer/WebGLJNLMDenoiser.ts"],"names":[],"mappings":"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","sourcesContent":["import { FragmentShader, glsl, Shader } from './shader.js';\nimport { constants, WebGLDevice, Texture2D } from './webgl.js';\nimport { WebGLFullQuadPass } from './WebGLFullQuadPass.js';\nimport {\n JNLM_DEFAULT_COLOR_SENSITIVITY,\n JNLM_ALBEDO_FLOOR,\n JNLM_ALBEDO_REGULARIZATION,\n JNLM_DEFAULT_SHAPE,\n JNLM_COVERAGE_BANDWIDTH,\n JNLM_MAX_ITERATIONS,\n jnlmPassDilation,\n type JNLMFilterShape\n} from './jnlm.js';\n\n/**\n * WebGL 2 passes of the JNLM denoiser described in `jnlm.ts`, matching\n * WGPUJNLMDenoiser. Textures replace its storage buffers.\n */\n\n/**\n * The guide mean and the variance of that mean. The main and catcher trace\n * passes each accumulate (sum, sum of squares, count) for their own samples.\n */\nconst guideFragment = new FragmentShader({\n name: 'jnlmGuide',\n outputs: ['guide'],\n uniforms: {\n momentsTex: Shader.uniform('sampler2D'),\n catcherMomentsTex: Shader.uniform('sampler2D')\n },\n main: glsl`\nvoid main() {\n ivec2 p = ivec2(gl_FragCoord.xy);\n vec4 moments = load_momentsTex(p, 0) + load_catcherMomentsTex(p, 0);\n float n = moments.z;\n float mean = moments.x / max(n, 1.0);\n // Variance of the mean, or -1 when one sample cannot estimate it.\n float variance = n >= 2.0\n ? max(moments.y - n * mean * mean, 0.0) / (n * (n - 1.0))\n : -1.0;\n out_guide = vec4(mean, variance, 0.0, 1.0);\n}`\n});\n\n/**\n * Smooths the noisy per-pixel variance over 3 x 3 pixels. Pixels with a\n * single sample take the spatial variance of their neighborhood instead.\n */\nconst varianceFragment = new FragmentShader({\n name: 'jnlmVariance',\n outputs: ['guide'],\n uniforms: {\n rawGuideTex: Shader.uniform('sampler2D')\n },\n main: glsl`\nvoid main() {\n ivec2 p = ivec2(gl_FragCoord.xy);\n ivec2 size = rawGuideTexRegion();\n vec2 center = load_rawGuideTex(p, 0).xy;\n float varianceSum = 0.0;\n float varianceCount = 0.0;\n float meanSum = 0.0;\n float meanSquareSum = 0.0;\n for (int dy = -1; dy <= 1; dy++) {\n for (int dx = -1; dx <= 1; dx++) {\n vec2 value = load_rawGuideTex(clamp(p + ivec2(dx, dy), ivec2(0), size - 1), 0).xy;\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 float variance;\n if (center.y >= 0.0) {\n variance = varianceSum / varianceCount;\n } else {\n float spatialMean = meanSum / 9.0;\n variance = max(meanSquareSum / 9.0 - spatialMean * spatialMean, 0.0) * 9.0 / 8.0;\n }\n out_guide = vec4(center.x, variance, 0.0, 1.0);\n}`\n});\n\n/**\n * One joint NL-means pass; see createJNLMFilterWGSL. The first pass decodes\n * the display-encoded composition to linear light, the last encodes it again.\n */\nconst filterFragment = new FragmentShader({\n name: 'jnlmFilter',\n outputs: ['color', 'guide'],\n defines: {\n SEARCH_RADIUS: JNLM_DEFAULT_SHAPE.searchRadius,\n PATCH_RADIUS: JNLM_DEFAULT_SHAPE.patchRadius,\n INV_ALBEDO_BANDWIDTH2: (1 / JNLM_DEFAULT_SHAPE.albedoBandwidth ** 2).toFixed(6),\n INV_NORMAL_BANDWIDTH2: (1 / JNLM_DEFAULT_SHAPE.normalBandwidth ** 2).toFixed(6)\n },\n uniforms: {\n guideTex: Shader.uniform('sampler2D'),\n colorTex: Shader.uniform('sampler2D'),\n albedoTex: Shader.uniform('sampler2D'),\n normalTex: Shader.uniform('sampler2D'),\n shadowCatcherTex: Shader.uniform('sampler2D'),\n colorSensitivity: Shader.uniform('float', JNLM_DEFAULT_COLOR_SENSITIVITY),\n dilation: Shader.uniform('int', 1),\n decodeInput: Shader.uniform('bool', 0),\n encodeOutput: Shader.uniform('bool', 0)\n },\n main: glsl`\n#define PATCH_SIZE ((2 * PATCH_RADIUS + 1) * (2 * PATCH_RADIUS + 1))\n// Variance cancellation strength alpha of the paper.\n#define VARIANCE_CANCELLATION 1.0\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.\n#define CENTER_WEIGHT_MIN 0.01\n#define INV_COVERAGE_BANDWIDTH2 ${(1 / JNLM_COVERAGE_BANDWIDTH ** 2).toFixed(6)}\n\nivec2 imageSize;\n\nvec2 loadGuide(ivec2 p) {\n return load_guideTex(clamp(p, ivec2(0), imageSize - 1), 0).xy;\n}\n\n// Premultiplied linear color.\nvec4 loadColor(ivec2 p) {\n vec4 c = load_colorTex(p, 0);\n if (decodeInput) c.rgb = mix(pow((max(c.rgb, 0.0) + 0.055) / 1.055, vec3(2.4)),\n c.rgb / 12.92, lessThanEqual(c.rgb, vec3(0.04045)));\n return vec4(c.rgb * c.a, c.a);\n}\n\nfloat featureDistance(ivec2 q, vec4 centerAlbedo, vec3 centerNormal) {\n vec4 albedo = load_albedoTex(q, 0);\n // Match WebGPU: protect relative RGB contrast, including dark textures,\n // while keeping coverage differences in absolute units.\n vec3 albedoScale = max((albedo.rgb + centerAlbedo.rgb) * 0.5, vec3(${JNLM_ALBEDO_FLOOR}));\n vec3 albedoDelta = (albedo.rgb - centerAlbedo.rgb) / albedoScale;\n float coverageDelta = albedo.a - centerAlbedo.a;\n vec3 normalDelta = load_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\nvoid main() {\n imageSize = guideTexRegion();\n ivec2 p = ivec2(gl_FragCoord.xy);\n vec4 centerAlbedo = load_albedoTex(p, 0);\n vec4 centerNormalTexel = load_normalTex(p, 0);\n vec3 centerNormal = centerNormalTexel.rgb;\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 && load_shadowCatcherTex(p, 0).r <= 0.0) {\n vec4 c = loadColor(p);\n vec3 rgb = c.rgb / max(c.a, 1e-6);\n if (encodeOutput) rgb = mix(1.055 * pow(max(rgb, 0.0), vec3(1.0 / 2.4)) - 0.055,\n rgb * 12.92, lessThanEqual(rgb, vec3(0.0031308)));\n out_color = vec4(rgb, c.a);\n out_guide = vec4(loadGuide(p), 0.0, 1.0);\n return;\n }\n\n vec2 centerPatch[PATCH_SIZE];\n int k = 0;\n for (int dy = -PATCH_RADIUS; dy <= PATCH_RADIUS; dy++) {\n for (int dx = -PATCH_RADIUS; dx <= PATCH_RADIUS; dx++) {\n centerPatch[k] = loadGuide(p + ivec2(dx, dy) * dilation);\n k++;\n }\n }\n float k2 = colorSensitivity * colorSensitivity;\n\n vec4 sum = vec4(0.0);\n vec3 featureScale = max(centerAlbedo.rgb, vec3(${JNLM_ALBEDO_FLOOR}));\n vec3 featureSum = vec3(0.0);\n vec3 featureSquareSum = vec3(0.0);\n vec3 featureColorSum = vec3(0.0);\n float guideSum = 0.0;\n float guideVarianceSum = 0.0;\n float weightSum = 0.0;\n float maxWeight = 0.0;\n for (int sy = -SEARCH_RADIUS; sy <= SEARCH_RADIUS; sy++) {\n for (int sx = -SEARCH_RADIUS; sx <= SEARCH_RADIUS; sx++) {\n ivec2 q = p + ivec2(sx, sy) * dilation;\n if (\n (sx == 0 && sy == 0) ||\n q.x < 0 || q.y < 0 || q.x >= imageSize.x || q.y >= imageSize.y\n ) continue;\n float features = featureDistance(q, centerAlbedo, centerNormal);\n if (features > 16.0) continue;\n\n float colorDistance = 0.0;\n k = 0;\n for (int dy = -PATCH_RADIUS; dy <= PATCH_RADIUS; dy++) {\n for (int dx = -PATCH_RADIUS; dx <= PATCH_RADIUS; dx++) {\n vec2 a = centerPatch[k];\n vec2 b = loadGuide(q + ivec2(dx, dy) * dilation);\n float 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 /= float(PATCH_SIZE);\n\n float weight = exp(-max(max(colorDistance, 0.0), features));\n vec2 g = loadGuide(q);\n // Filter premultiplied color so coverage and color stay consistent.\n vec3 a = (load_albedoTex(q, 0).rgb - centerAlbedo.rgb) / featureScale;\n vec4 value = loadColor(q);\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 vec4 center = loadColor(p);\n vec2 centerGuide = loadGuide(p);\n float centerWeight = max(maxWeight, CENTER_WEIGHT_MIN);\n float totalWeight = weightSum + centerWeight;\n vec4 mean = (sum + center * 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 vec3 meanFeature = featureSum / totalWeight;\n vec3 featureVariance = max(featureSquareSum / totalWeight - meanFeature * meanFeature, vec3(0.0));\n vec3 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 vec3 meanAlbedo = centerAlbedo.rgb + meanFeature * featureScale;\n vec3 maximumSlope = mean.rgb * featureScale / max(meanAlbedo, vec3(${JNLM_ALBEDO_FLOOR}));\n vec3 slope = clamp(covariance / (featureVariance + vec3(${JNLM_ALBEDO_REGULARIZATION})), vec3(0.0), maximumSlope);\n vec3 corrected = mean.rgb - slope * meanFeature;\n vec4 filtered = vec4(max(corrected, vec3(0.0)), max(mean.a, 0.0));\n vec3 rgb = filtered.a > 1e-6\n ? filtered.rgb / max(filtered.a, 1e-6)\n : center.rgb / max(center.a, 1e-6);\n if (encodeOutput) rgb = mix(1.055 * pow(max(rgb, 0.0), vec3(1.0 / 2.4)) - 0.055,\n rgb * 12.92, lessThanEqual(rgb, vec3(0.0031308)));\n out_color = vec4(rgb, filtered.a);\n out_guide = vec4(\n (guideSum + centerGuide.x * centerWeight) / totalWeight,\n (guideVarianceSum + centerGuide.y * centerWeight * centerWeight)\n / (totalWeight * totalWeight),\n 0.0,\n 1.0\n );\n}`\n});\n\nexport interface WebGLJNLMInputs {\n width: number;\n height: number;\n /** Main trace pass moments: guide sum, sum of squares and count. */\n moments: Texture2D;\n /** Catcher trace pass moments, when the scene has a shadow catcher. */\n catcherMoments?: Texture2D;\n /** Display-encoded composition to filter. */\n color: Texture2D;\n albedo: Texture2D;\n normal: Texture2D;\n /** Normalized shadow-catcher mask; red is the catcher coverage. */\n shadowCatcher: Texture2D;\n strength: number;\n shape: JNLMFilterShape;\n}\n\nconst floatOutput = {\n type: constants.FLOAT,\n minFilter: constants.NEAREST,\n magFilter: constants.NEAREST\n};\n\nexport class WebGLJNLMDenoisePass {\n private _renderer: WebGLDevice;\n private _guidePass: WebGLFullQuadPass<'momentsTex' | 'catcherMomentsTex', 'guide'>;\n private _variancePass: WebGLFullQuadPass<'rawGuideTex', 'guide'>;\n // Two instances so consecutive passes ping-pong between their outputs.\n private _filterPasses: WebGLFullQuadPass<\n 'guideTex' | 'colorTex' | 'albedoTex' | 'normalTex' | 'shadowCatcherTex',\n 'color' | 'guide'\n >[];\n\n constructor(renderer: WebGLDevice) {\n this._renderer = renderer;\n this._guidePass = new WebGLFullQuadPass('jnlmGuide', renderer, {\n shader: guideFragment,\n outputParams: { guide: floatOutput }\n });\n this._variancePass = new WebGLFullQuadPass('jnlmVariance', renderer, {\n shader: varianceFragment,\n outputParams: { guide: floatOutput }\n });\n this._filterPasses = [0, 1].map(() =>\n new WebGLFullQuadPass('jnlmFilter', renderer, {\n shader: filterFragment,\n outputParams: {\n color: { type: constants.HALF_FLOAT },\n guide: floatOutput\n }\n })\n );\n }\n\n /** Runs the denoiser and returns the display-encoded result. */\n render(inputs: WebGLJNLMInputs, trace?: string[]): Texture2D {\n const { width, height, shape } = inputs;\n const passes = [this._guidePass, this._variancePass, ...this._filterPasses];\n passes.forEach((pass) => pass.setSize(width, height));\n this._guidePass.createPass({\n momentsTex: inputs.moments,\n catcherMomentsTex: inputs.catcherMoments ?? this._renderer.emptyTexture\n });\n this._variancePass.createPass({ rawGuideTex: this._guidePass.getOutput('guide') });\n\n const sensitivity = JNLM_DEFAULT_COLOR_SENSITIVITY * Math.max(inputs.strength, 1e-3);\n const iterations = Math.min(JNLM_MAX_ITERATIONS, Math.max(1, Math.round(shape.iterations)));\n let guide = this._variancePass.getOutput('guide');\n let color = inputs.color;\n for (let i = 0; i < iterations; i++) {\n const pass = this._filterPasses[i % 2];\n pass.setDefines({\n SEARCH_RADIUS: shape.searchRadius,\n // Numeric zero removes a define in the WebGL shader builder.\n PATCH_RADIUS: String(shape.patchRadius),\n INV_ALBEDO_BANDWIDTH2: (1 / shape.albedoBandwidth ** 2).toFixed(6),\n INV_NORMAL_BANDWIDTH2: (1 / shape.normalBandwidth ** 2).toFixed(6)\n });\n pass.setUniforms({\n colorSensitivity: sensitivity,\n dilation: jnlmPassDilation(i),\n decodeInput: i === 0,\n encodeOutput: i === iterations - 1\n });\n if (trace) {\n if (i === 0) trace.push('Decode:DisplayLinear', 'Denoise:DisplayLinear');\n if (i === iterations - 1) trace.push('Encode:DisplayEncoded');\n }\n pass.createPass({\n guideTex: guide,\n colorTex: color,\n albedoTex: inputs.albedo,\n normalTex: inputs.normal,\n shadowCatcherTex: inputs.shadowCatcher\n });\n guide = pass.getOutput('guide');\n color = pass.getOutput('color');\n }\n return color;\n }\n\n reserveCapacity() {\n [this._guidePass, this._variancePass, ...this._filterPasses].forEach(pass => pass.reserveCapacity());\n }\n\n retainOutput(texture: Texture2D) { this._filterPasses.forEach(pass => pass.retainOutput(texture)); }\n releaseOutput(texture: Texture2D) { this._filterPasses.forEach(pass => pass.releaseOutput(texture)); }\n\n getMemoryBytes() {\n return [this._guidePass, this._variancePass, ...this._filterPasses]\n .reduce((sum, pass) => sum + pass.getMemoryBytes(), 0);\n }\n\n dispose() {\n [this._guidePass, this._variancePass, ...this._filterPasses].forEach((pass) =>\n pass.dispose()\n );\n }\n}\n"]}
1
+ {"version":3,"file":"WebGLJNLMDenoiser.js","sourceRoot":"","sources":["../../src/renderer/WebGLJNLMDenoiser.ts"],"names":[],"mappings":"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","sourcesContent":["import { FragmentShader, glsl, Shader } from './shader.js';\nimport { constants, WebGLDevice, Texture2D } from './webgl.js';\nimport { WebGLFullQuadPass } from './WebGLFullQuadPass.js';\nimport {\n JNLM_DEFAULT_COLOR_SENSITIVITY,\n JNLM_ALBEDO_FLOOR,\n JNLM_ALBEDO_REGULARIZATION,\n JNLM_DEFAULT_SHAPE,\n JNLM_COVERAGE_BANDWIDTH,\n JNLM_MAX_ITERATIONS,\n jnlmPassDilation,\n type JNLMFilterShape\n} from './jnlm.js';\n\n/**\n * WebGL 2 passes of the JNLM denoiser described in `jnlm.ts`, matching\n * WGPUJNLMDenoiser. Textures replace its storage buffers.\n */\n\n/**\n * The guide mean and the variance of that mean. The main and catcher trace\n * passes each accumulate (sum, sum of squares, count) for their own samples.\n */\nconst guideFragment = new FragmentShader({\n name: 'jnlmGuide',\n outputs: ['guide'],\n uniforms: {\n momentsTex: Shader.uniform('sampler2D'),\n catcherMomentsTex: Shader.uniform('sampler2D')\n },\n main: glsl`\nvoid main() {\n ivec2 p = ivec2(gl_FragCoord.xy);\n vec4 moments = load_momentsTex(p, 0) + load_catcherMomentsTex(p, 0);\n float n = moments.z;\n float mean = moments.x / max(n, 1.0);\n // Variance of the mean, or -1 when one sample cannot estimate it.\n float variance = n >= 2.0\n ? max(moments.y - n * mean * mean, 0.0) / (n * (n - 1.0))\n : -1.0;\n out_guide = vec4(mean, variance, 0.0, 1.0);\n}`\n});\n\n/**\n * Smooths the noisy per-pixel variance over 3 x 3 pixels. Pixels with a\n * single sample take the spatial variance of their neighborhood instead.\n */\nconst varianceFragment = new FragmentShader({\n name: 'jnlmVariance',\n outputs: ['guide'],\n uniforms: {\n rawGuideTex: Shader.uniform('sampler2D')\n },\n main: glsl`\nvoid main() {\n ivec2 p = ivec2(gl_FragCoord.xy);\n ivec2 size = rawGuideTexRegion();\n vec2 center = load_rawGuideTex(p, 0).xy;\n float varianceSum = 0.0;\n float varianceCount = 0.0;\n float meanSum = 0.0;\n float meanSquareSum = 0.0;\n for (int dy = -1; dy <= 1; dy++) {\n for (int dx = -1; dx <= 1; dx++) {\n vec2 value = load_rawGuideTex(clamp(p + ivec2(dx, dy), ivec2(0), size - 1), 0).xy;\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 float variance;\n if (center.y >= 0.0) {\n variance = varianceSum / varianceCount;\n } else {\n float spatialMean = meanSum / 9.0;\n variance = max(meanSquareSum / 9.0 - spatialMean * spatialMean, 0.0) * 9.0 / 8.0;\n }\n out_guide = vec4(center.x, variance, 0.0, 1.0);\n}`\n});\n\n/**\n * One joint NL-means pass; see createJNLMFilterWGSL. The first pass decodes\n * the display-encoded composition to linear light, the last encodes it again.\n */\nconst filterFragment = new FragmentShader({\n name: 'jnlmFilter',\n outputs: ['color', 'guide'],\n defines: {\n SEARCH_RADIUS: JNLM_DEFAULT_SHAPE.searchRadius,\n PATCH_RADIUS: JNLM_DEFAULT_SHAPE.patchRadius,\n INV_ALBEDO_BANDWIDTH2: (1 / JNLM_DEFAULT_SHAPE.albedoBandwidth ** 2).toFixed(6),\n INV_NORMAL_BANDWIDTH2: (1 / JNLM_DEFAULT_SHAPE.normalBandwidth ** 2).toFixed(6)\n },\n uniforms: {\n guideTex: Shader.uniform('sampler2D'),\n colorTex: Shader.uniform('sampler2D'),\n albedoTex: Shader.uniform('sampler2D'),\n normalTex: Shader.uniform('sampler2D'),\n shadowCatcherTex: Shader.uniform('sampler2D'),\n colorSensitivity: Shader.uniform('float', JNLM_DEFAULT_COLOR_SENSITIVITY),\n dilation: Shader.uniform('int', 1),\n decodeInput: Shader.uniform('bool', 0),\n encodeOutput: Shader.uniform('bool', 0)\n },\n main: glsl`\n#define PATCH_SIZE ((2 * PATCH_RADIUS + 1) * (2 * PATCH_RADIUS + 1))\n// Variance cancellation strength alpha of the paper.\n#define VARIANCE_CANCELLATION 1.0\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.\n#define CENTER_WEIGHT_MIN 0.01\n#define INV_COVERAGE_BANDWIDTH2 ${(1 / JNLM_COVERAGE_BANDWIDTH ** 2).toFixed(6)}\n\nivec2 imageSize;\n\nvec2 loadGuide(ivec2 p) {\n return load_guideTex(clamp(p, ivec2(0), imageSize - 1), 0).xy;\n}\n\n// Premultiplied linear color.\nvec4 loadColor(ivec2 p) {\n vec4 c = load_colorTex(p, 0);\n if (decodeInput) c.rgb = mix(pow((max(c.rgb, 0.0) + 0.055) / 1.055, vec3(2.4)),\n c.rgb / 12.92, lessThanEqual(c.rgb, vec3(0.04045)));\n return vec4(c.rgb * c.a, c.a);\n}\n\nfloat featureDistance(ivec2 q, vec4 centerAlbedo, vec3 centerNormal) {\n vec4 albedo = load_albedoTex(q, 0);\n // Match WebGPU: protect relative RGB contrast, including dark textures,\n // while keeping coverage differences in absolute units.\n vec3 albedoScale = max((albedo.rgb + centerAlbedo.rgb) * 0.5, vec3(${JNLM_ALBEDO_FLOOR}));\n vec3 albedoDelta = (albedo.rgb - centerAlbedo.rgb) / albedoScale;\n float coverageDelta = albedo.a - centerAlbedo.a;\n vec3 normalDelta = load_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\nvoid main() {\n imageSize = guideTexRegion();\n ivec2 p = ivec2(gl_FragCoord.xy);\n vec4 centerAlbedo = load_albedoTex(p, 0);\n vec4 centerNormalTexel = load_normalTex(p, 0);\n vec3 centerNormal = centerNormalTexel.rgb;\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 && load_shadowCatcherTex(p, 0).r <= 0.0) {\n vec4 c = loadColor(p);\n vec3 rgb = c.rgb / max(c.a, 1e-6);\n if (encodeOutput) rgb = mix(1.055 * pow(max(rgb, 0.0), vec3(1.0 / 2.4)) - 0.055,\n rgb * 12.92, lessThanEqual(rgb, vec3(0.0031308)));\n out_color = vec4(rgb, c.a);\n out_guide = vec4(loadGuide(p), 0.0, 1.0);\n return;\n }\n\n vec2 centerPatch[PATCH_SIZE];\n int k = 0;\n for (int dy = -PATCH_RADIUS; dy <= PATCH_RADIUS; dy++) {\n for (int dx = -PATCH_RADIUS; dx <= PATCH_RADIUS; dx++) {\n centerPatch[k] = loadGuide(p + ivec2(dx, dy) * dilation);\n k++;\n }\n }\n float k2 = colorSensitivity * colorSensitivity;\n\n vec4 sum = vec4(0.0);\n vec3 featureScale = max(centerAlbedo.rgb, vec3(${JNLM_ALBEDO_FLOOR}));\n vec3 featureSum = vec3(0.0);\n vec3 featureSquareSum = vec3(0.0);\n vec3 featureColorSum = vec3(0.0);\n float guideSum = 0.0;\n float guideVarianceSum = 0.0;\n float weightSum = 0.0;\n float maxWeight = 0.0;\n for (int sy = -SEARCH_RADIUS; sy <= SEARCH_RADIUS; sy++) {\n for (int sx = -SEARCH_RADIUS; sx <= SEARCH_RADIUS; sx++) {\n ivec2 q = p + ivec2(sx, sy) * dilation;\n if (\n (sx == 0 && sy == 0) ||\n q.x < 0 || q.y < 0 || q.x >= imageSize.x || q.y >= imageSize.y\n ) continue;\n float features = featureDistance(q, centerAlbedo, centerNormal);\n if (features > 16.0) continue;\n\n float colorDistance = 0.0;\n k = 0;\n for (int dy = -PATCH_RADIUS; dy <= PATCH_RADIUS; dy++) {\n for (int dx = -PATCH_RADIUS; dx <= PATCH_RADIUS; dx++) {\n vec2 a = centerPatch[k];\n vec2 b = loadGuide(q + ivec2(dx, dy) * dilation);\n float 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 /= float(PATCH_SIZE);\n\n float weight = exp(-max(max(colorDistance, 0.0), features));\n vec2 g = loadGuide(q);\n // Filter premultiplied color so coverage and color stay consistent.\n vec3 a = (load_albedoTex(q, 0).rgb - centerAlbedo.rgb) / featureScale;\n vec4 value = loadColor(q);\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 vec4 center = loadColor(p);\n vec2 centerGuide = loadGuide(p);\n float centerWeight = max(maxWeight, CENTER_WEIGHT_MIN);\n float totalWeight = weightSum + centerWeight;\n vec4 mean = (sum + center * 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 vec3 meanFeature = featureSum / totalWeight;\n vec3 featureVariance = max(featureSquareSum / totalWeight - meanFeature * meanFeature, vec3(0.0));\n vec3 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 vec3 meanAlbedo = centerAlbedo.rgb + meanFeature * featureScale;\n vec3 maximumSlope = mean.rgb * featureScale / max(meanAlbedo, vec3(${JNLM_ALBEDO_FLOOR}));\n vec3 slope = clamp(covariance / (featureVariance + vec3(${JNLM_ALBEDO_REGULARIZATION})), vec3(0.0), maximumSlope);\n vec3 corrected = mean.rgb - slope * meanFeature;\n vec4 filtered = vec4(max(corrected, vec3(0.0)), max(mean.a, 0.0));\n vec3 rgb = filtered.a > 1e-6\n ? filtered.rgb / max(filtered.a, 1e-6)\n : center.rgb / max(center.a, 1e-6);\n if (encodeOutput) rgb = mix(1.055 * pow(max(rgb, 0.0), vec3(1.0 / 2.4)) - 0.055,\n rgb * 12.92, lessThanEqual(rgb, vec3(0.0031308)));\n out_color = vec4(rgb, filtered.a);\n out_guide = vec4(\n (guideSum + centerGuide.x * centerWeight) / totalWeight,\n (guideVarianceSum + centerGuide.y * centerWeight * centerWeight)\n / (totalWeight * totalWeight),\n 0.0,\n 1.0\n );\n}`\n});\n\nexport interface WebGLJNLMInputs {\n width: number;\n height: number;\n /** Main trace pass moments: guide sum, sum of squares and count. */\n moments: Texture2D;\n /** Catcher trace pass moments, when the scene has a shadow catcher. */\n catcherMoments?: Texture2D;\n /** Display-encoded composition to filter. */\n color: Texture2D;\n albedo: Texture2D;\n normal: Texture2D;\n /** Normalized shadow-catcher mask; red is the catcher coverage. */\n shadowCatcher: Texture2D;\n strength: number;\n shape: JNLMFilterShape;\n}\n\nconst floatOutput = {\n type: constants.FLOAT,\n minFilter: constants.NEAREST,\n magFilter: constants.NEAREST\n};\n\nexport class WebGLJNLMDenoisePass {\n private _renderer: WebGLDevice;\n private _guidePass: WebGLFullQuadPass<'momentsTex' | 'catcherMomentsTex', 'guide'>;\n private _variancePass: WebGLFullQuadPass<'rawGuideTex', 'guide'>;\n // Two instances so consecutive passes ping-pong between their outputs.\n private _filterPasses: WebGLFullQuadPass<\n 'guideTex' | 'colorTex' | 'albedoTex' | 'normalTex' | 'shadowCatcherTex',\n 'color' | 'guide'\n >[];\n\n constructor(renderer: WebGLDevice) {\n this._renderer = renderer;\n this._guidePass = new WebGLFullQuadPass('jnlmGuide', renderer, {\n shader: guideFragment,\n outputParams: { guide: floatOutput }\n });\n this._variancePass = new WebGLFullQuadPass('jnlmVariance', renderer, {\n shader: varianceFragment,\n outputParams: { guide: floatOutput }\n });\n this._filterPasses = [0, 1].map(() =>\n new WebGLFullQuadPass('jnlmFilter', renderer, {\n shader: filterFragment,\n outputParams: {\n color: { type: constants.HALF_FLOAT },\n guide: floatOutput\n }\n })\n );\n }\n\n /** Runs the denoiser and returns the display-encoded result. */\n render(inputs: WebGLJNLMInputs, trace?: string[]): Texture2D {\n const { width, height, shape } = inputs;\n const passes = [this._guidePass, this._variancePass, ...this._filterPasses];\n passes.forEach((pass) => pass.setSize(width, height));\n this._guidePass.createPass({\n momentsTex: inputs.moments,\n catcherMomentsTex: inputs.catcherMoments ?? this._renderer.emptyTexture\n });\n this._variancePass.createPass({ rawGuideTex: this._guidePass.getOutput('guide') });\n\n const sensitivity = JNLM_DEFAULT_COLOR_SENSITIVITY * Math.max(inputs.strength, 1e-3);\n const iterations = Math.min(JNLM_MAX_ITERATIONS, Math.max(1, Math.round(shape.iterations)));\n let guide = this._variancePass.getOutput('guide');\n let color = inputs.color;\n for (let i = 0; i < iterations; i++) {\n const pass = this._filterPasses[i % 2];\n pass.setDefines({\n SEARCH_RADIUS: shape.searchRadius,\n // Numeric zero removes a define in the WebGL shader builder.\n PATCH_RADIUS: String(shape.patchRadius),\n INV_ALBEDO_BANDWIDTH2: (1 / shape.albedoBandwidth ** 2).toFixed(6),\n INV_NORMAL_BANDWIDTH2: (1 / shape.normalBandwidth ** 2).toFixed(6)\n });\n pass.setUniforms({\n colorSensitivity: sensitivity,\n dilation: jnlmPassDilation(i),\n decodeInput: i === 0,\n encodeOutput: i === iterations - 1\n });\n if (trace) {\n if (i === 0) trace.push('Decode:DisplayLinear', 'Denoise:DisplayLinear');\n if (i === iterations - 1) trace.push('Encode:DisplayEncoded');\n }\n pass.createPass({\n guideTex: guide,\n colorTex: color,\n albedoTex: inputs.albedo,\n normalTex: inputs.normal,\n shadowCatcherTex: inputs.shadowCatcher\n });\n guide = pass.getOutput('guide');\n color = pass.getOutput('color');\n }\n return color;\n }\n\n reserveCapacity() {\n [this._guidePass, this._variancePass, ...this._filterPasses].forEach(pass => pass.reserveCapacity());\n }\n\n retainOutput(texture: Texture2D) { this._filterPasses.forEach(pass => pass.retainOutput(texture)); }\n releaseOutput(texture: Texture2D) { this._filterPasses.forEach(pass => pass.releaseOutput(texture)); }\n\n getMemoryBytes() {\n return [this._guidePass, this._variancePass, ...this._filterPasses]\n .reduce((sum, pass) => sum + pass.getMemoryBytes(), 0);\n }\n\n dispose() {\n [this._guidePass, this._variancePass, ...this._filterPasses].forEach((pass) =>\n pass.dispose()\n );\n }\n}\n"]}
@@ -42,11 +42,11 @@ vec4 mask = sample_shadowCatcherTex(v_Texcoord);
42
42
  vec4 background = sample_catcherBackgroundTex(v_Texcoord);
43
43
  float hit = sample_albedoTex(v_Texcoord).a;
44
44
 
45
- float qZ = max(sample_normalTex(v_Texcoord).a, 1.0) / sampleCount;
46
- float iT = max(hit - mask.b * qZ, 0.0);
45
+ float sq = max(sample_normalTex(v_Texcoord).a, 1.0) / sampleCount;
46
+ float jz = max(hit - mask.b * sq, 0.0);
47
47
  out_foreground = vec4(
48
- (light.rgb - background.rgb * qZ)
49
- / (iT > 0.0 ? iT : sampleCount),
48
+ (light.rgb - background.rgb * sq)
49
+ / (jz > 0.0 ? jz : sampleCount),
50
50
  clamp((light.a - background.a) / sampleCount, 0.0, 1.0)
51
51
  );
52
52
  out_catcherBackground = background / sampleCount;