@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
@@ -0,0 +1,66 @@
1
+ // Browser-only checkpoint source. Native and nonspectral generation omit it.
2
+ // Structured-sample caches are pure dimension lookups; only PCG, hashed draws
3
+ // and the two current-bounce indices need restoring.
4
+ export function spectralPrefixWgsl(shareSecondary = true) {
5
+ return /* wgsl */ `
6
+ struct eE {
7
+ ready: bool,
8
+ result: vec4f,
9
+ aux: RayTraceAuxiliary,
10
+ rng: vec4u,
11
+ counter: u32,
12
+ bounce: u32,
13
+ vertex: u32,
14
+ }
15
+ var<private> eB: array<eE, 2>;
16
+ var<private> spActive: bool;
17
+ var<private> sd: bool;
18
+ var<private> spChannel: i32;
19
+ var<private> lg: f32;
20
+ var<private> qz: i32;
21
+ var<private> fC: i32 = -1;
22
+
23
+ fn wY(channel: i32, wavelength: f32, xF: bool) {
24
+ sd = SPECTRAL && rtUniform.dispersionWavelengths != 1${shareSecondary ? '' : ' && false'};
25
+ spChannel = channel; lg = wavelength;
26
+ spActive = sd && !xF;
27
+ qz = 0;
28
+ }
29
+ fn gf(ma: OpenPbrResolvedMaterial) -> bool {
30
+ return ma.transmissionDispersionScale > 0.0 && ma.specularIor != 1.0;
31
+ }
32
+ fn qA(path: ptr<function, Path>, si: ptr<function, SurfaceInteraction>) {
33
+ spActive = false;
34
+ (*path).li = sampling_spectral_rgb_filter((*path).li, spChannel);
35
+ (*si).spectralChannel = spChannel; (*si).wavelength = lg;
36
+ }
37
+ fn rN(slot: i32, aux: ptr<function, RayTraceAuxiliary>) -> vec4f {
38
+ let oM = eB[slot];
39
+ *aux = oM.aux;
40
+ s0 = oM.rng; hashedCounter = oM.counter;
41
+ samplingBounce = oM.bounce; bounceIndex = oM.vertex;
42
+ return vec4f(sampling_spectral_rgb_filter(oM.result.rgb, spChannel), oM.result.a);
43
+ }
44
+ fn spFinish(slot: i32, result: vec4f, aux: RayTraceAuxiliary) -> vec4f {
45
+ if (!spActive) { return result; }
46
+ if (spChannel == 1) {
47
+ eB[slot] = eE(true, result, aux, s0, hashedCounter, samplingBounce, bounceIndex);
48
+ }
49
+ return vec4f(sampling_spectral_rgb_filter(result.rgb, spChannel), result.a);
50
+ }
51
+ `;
52
+ }
53
+ export const prefixRandomBindings = {
54
+ rng: ['vec4u', 's0'], counter: ['u32', 'hashedCounter'],
55
+ bounce: ['u32', 'samplingBounce'], vertex: ['u32', 'bounceIndex']
56
+ };
57
+ export function prefixCheckpoint(name, bindings) {
58
+ return `struct ${name}State {\n${Object.entries(bindings).map(([key, [type]]) => ` ${key}: ${type},`).join('\n')}\n}\nvar<private> ${name}: ${name}State;\n`;
59
+ }
60
+ export function prefixSave(name, bindings) {
61
+ return Object.entries(bindings).map(([key, [, value]]) => `${name}.${key} = ${value};`).join('\n');
62
+ }
63
+ export function prefixRestore(name, bindings) {
64
+ return Object.entries(bindings).map(([key, [, value]]) => `${value} = ${name}.${key};`).join('\n');
65
+ }
66
+ //# sourceMappingURL=spectralPrefix.wgsl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spectralPrefix.wgsl.js","sourceRoot":"","sources":["../../../../src/renderer/wgsl/chunks/spectralPrefix.wgsl.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,8EAA8E;AAC9E,qDAAqD;AACrD,MAAM,UAAU,kBAAkB,CAAC,cAAc,GAAG,IAAI;IAAI,OAAO,UAAU,CAAC;;;;;;;;;;;;;;;;;;;uDAmBd,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BhG,CAAC;AAAC,CAAC;AAGJ,MAAM,CAAC,MAAM,oBAAoB,GAAmB;IAClD,GAAG,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,eAAe,CAAC;IACvD,MAAM,EAAE,CAAC,KAAK,EAAE,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC;CAClE,CAAC;AACF,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,QAAwB;IACrE,OAAO,UAAU,IAAI,YAAY,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,IAAI,KAAK,IAAI,UAAU,CAAC;AAChK,CAAC;AACD,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,QAAwB;IAC/D,OAAO,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,IAAI,GAAG,MAAM,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrG,CAAC;AACD,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,QAAwB;IAClE,OAAO,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,MAAM,IAAI,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrG,CAAC","sourcesContent":["// Browser-only checkpoint source. Native and nonspectral generation omit it.\n// Structured-sample caches are pure dimension lookups; only PCG, hashed draws\n// and the two current-bounce indices need restoring.\nexport function spectralPrefixWgsl(shareSecondary = true) { return /* wgsl */ `\nstruct SpectralCompleted {\n ready: bool,\n result: vec4f,\n aux: RayTraceAuxiliary,\n rng: vec4u,\n counter: u32,\n bounce: u32,\n vertex: u32,\n}\nvar<private> spCompleted: array<SpectralCompleted, 2>;\nvar<private> spActive: bool;\nvar<private> spEnabled: bool;\nvar<private> spChannel: i32;\nvar<private> spWavelength: f32;\nvar<private> spCall: i32;\nvar<private> spForkCall: i32 = -1;\n\nfn spBegin(channel: i32, wavelength: f32, primaryFork: bool) {\n spEnabled = SPECTRAL && rtUniform.dispersionWavelengths != 1${shareSecondary ? '' : ' && false'};\n spChannel = channel; spWavelength = wavelength;\n spActive = spEnabled && !primaryFork;\n spCall = 0;\n}\nfn spDisperses(ma: OpenPbrResolvedMaterial) -> bool {\n return ma.transmissionDispersionScale > 0.0 && ma.specularIor != 1.0;\n}\nfn spFork(path: ptr<function, Path>, si: ptr<function, SurfaceInteraction>) {\n spActive = false;\n (*path).li = sampling_spectral_rgb_filter((*path).li, spChannel);\n (*si).spectralChannel = spChannel; (*si).wavelength = spWavelength;\n}\nfn spReplay(slot: i32, aux: ptr<function, RayTraceAuxiliary>) -> vec4f {\n let saved = spCompleted[slot];\n *aux = saved.aux;\n s0 = saved.rng; hashedCounter = saved.counter;\n samplingBounce = saved.bounce; bounceIndex = saved.vertex;\n return vec4f(sampling_spectral_rgb_filter(saved.result.rgb, spChannel), saved.result.a);\n}\nfn spFinish(slot: i32, result: vec4f, aux: RayTraceAuxiliary) -> vec4f {\n if (!spActive) { return result; }\n if (spChannel == 1) {\n spCompleted[slot] = SpectralCompleted(true, result, aux, s0, hashedCounter, samplingBounce, bounceIndex);\n }\n return vec4f(sampling_spectral_rgb_filter(result.rgb, spChannel), result.a);\n}\n`; }\n\nexport type PrefixBindings = Record<string, [type: string, expression: string]>;\nexport const prefixRandomBindings: PrefixBindings = {\n rng: ['vec4u', 's0'], counter: ['u32', 'hashedCounter'],\n bounce: ['u32', 'samplingBounce'], vertex: ['u32', 'bounceIndex']\n};\nexport function prefixCheckpoint(name: string, bindings: PrefixBindings) {\n return `struct ${name}State {\\n${Object.entries(bindings).map(([key, [type]]) => ` ${key}: ${type},`).join('\\n')}\\n}\\nvar<private> ${name}: ${name}State;\\n`;\n}\nexport function prefixSave(name: string, bindings: PrefixBindings) {\n return Object.entries(bindings).map(([key, [, value]]) => `${name}.${key} = ${value};`).join('\\n');\n}\nexport function prefixRestore(name: string, bindings: PrefixBindings) {\n return Object.entries(bindings).map(([key, [, value]]) => `${value} = ${name}.${key};`).join('\\n');\n}\n"]}
@@ -7,12 +7,12 @@ let theta = atan2(n.x, n.z) / (2.0 * PI) + 0.5;
7
7
  let phi = acos(n.y) / PI;
8
8
  return vec2f(theta, 1.0 - phi);
9
9
  }
10
- fn iO(pos: vec3f, normal: vec3f) -> vec2f {
11
- let dg = abs(normal);
10
+ fn jq(pos: vec3f, normal: vec3f) -> vec2f {
11
+ let dj = abs(normal);
12
12
  var uv = vec2f(0.0);
13
- if (dg.x > dg.y && dg.x > dg.z) {
13
+ if (dj.x > dj.y && dj.x > dj.z) {
14
14
  uv = pos.yz;
15
- } else if (dg.y > dg.x && dg.y > dg.z) {
15
+ } else if (dj.y > dj.x && dj.y > dj.z) {
16
16
  uv = pos.xz;
17
17
  } else {
18
18
  uv = pos.xy;
@@ -23,18 +23,18 @@ return uv;
23
23
 
24
24
 
25
25
 
26
- fn hA(pos: vec3f, normal: vec3f) -> vec2f {
26
+ fn hW(pos: vec3f, normal: vec3f) -> vec2f {
27
27
  let theta = atan2(pos.z, pos.x) / (2.0 * PI) + 0.5;
28
28
  return vec2f(theta, pos.y);
29
29
  }
30
30
 
31
- fn gE(fg: i32, pos: vec3f, normal: vec3f) -> vec2f {
32
- if (fg == ${uvProjectionConstants.triplanar}) {
33
- return iO(pos, normal);
34
- } else if (fg == ${uvProjectionConstants.spherical}) {
31
+ fn gW(fu: i32, pos: vec3f, normal: vec3f) -> vec2f {
32
+ if (fu == ${uvProjectionConstants.triplanar}) {
33
+ return jq(pos, normal);
34
+ } else if (fu == ${uvProjectionConstants.spherical}) {
35
35
  return sphericalProjection(pos);
36
- } else if (fg == ${uvProjectionConstants.cylindrical}) {
37
- return hA(pos, normal);
36
+ } else if (fu == ${uvProjectionConstants.cylindrical}) {
37
+ return hW(pos, normal);
38
38
  }
39
39
  return vec2f(0.0);
40
40
  }
@@ -0,0 +1,2 @@
1
+ /** Readers share word offsets with compactVertices; legacy hosts keep vec4-slot offsets. */
2
+ export declare function vertexAttributeReaders(compact: boolean, frames: boolean): string;
@@ -0,0 +1,61 @@
1
+ /** Readers share word offsets with compactVertices; legacy hosts keep vec4-slot offsets. */
2
+ export function vertexAttributeReaders(compact, frames) {
3
+ if (!compact)
4
+ return /* wgsl */ `
5
+ fn vertexPosition(i:i32)->vec3f {return attrBuffers[i*ATTR_STRIDE+POSITION_OFF].xyz;}
6
+ fn vertexNormal(i:i32)->vec3f {return attrBuffers[i*ATTR_STRIDE+NORMAL_OFF].xyz;}
7
+ fn hd(i:i32)->vec2f {return attrBuffers[i*ATTR_STRIDE+UV_OFF].xy;}
8
+ fn hV(i:i32)->vec2f {return attrBuffers[i*ATTR_STRIDE+UV1_OFF].xy;}
9
+ fn vertexColor(i:i32)->vec3f {return attrBuffers[i*ATTR_STRIDE+COLOR_OFF].xyz;}
10
+ fn gC(i:i32)->vec4f {return ${frames ? 'attrBuffers[i*ATTR_STRIDE+TANGENT_OFF]' : 'vec4f(attrBuffers[i*ATTR_STRIDE+TANGENT_OFF],0.0)'};}
11
+ `;
12
+ return /* wgsl */ `
13
+ fn tI(a:i32,b:i32,maximum:f32)->vec3f {
14
+ if (a == -i32(maximum)-1 && b == -i32(maximum)-1) {return vec3f(0.0);}
15
+ var v=vec3f(f32(a)/maximum,f32(b)/maximum,0.0);
16
+ v.z=1.0-abs(v.x)-abs(v.y);
17
+ if(v.z<0.0) {v=vec3f((vec2f(1.0)-abs(v.yx))*select(vec2f(-1.0),vec2f(1.0),v.xy>=vec2f(0.0)),v.z);}
18
+ return normalize(v);
19
+ }
20
+ fn vertexPosition(i:i32)->vec3f {
21
+ let o=i*ATTR_STRIDE+POSITION_OFF;
22
+ return bitcast<vec3f>(vec3u(attrBuffers[o],attrBuffers[o+1],attrBuffers[o+2]));
23
+ }
24
+ fn vertexNormal(i:i32)->vec3f {
25
+ let o=i*ATTR_STRIDE+NORMAL_OFF;
26
+ if(NORMAL_FLOAT) {return bitcast<vec3f>(vec3u(attrBuffers[o],attrBuffers[o+1],attrBuffers[o+2]));}
27
+ let w=attrBuffers[o];
28
+ return tI(i32(w<<16u)>>16,i32(w)>>16,32767.0);
29
+ }
30
+ fn hd(i:i32)->vec2f {
31
+ if(!HAS_VERTEX_UV) {return vec2f(0.0);}
32
+ let o=i*ATTR_STRIDE+UV_OFF;
33
+ return bitcast<vec2f>(vec2u(attrBuffers[o],attrBuffers[o+1]));
34
+ }
35
+ fn hV(i:i32)->vec2f {
36
+ if(!HAS_VERTEX_UV) {return vec2f(0.0);}
37
+ let o=i*ATTR_STRIDE+UV1_OFF;
38
+ return bitcast<vec2f>(vec2u(attrBuffers[o],attrBuffers[o+1]));
39
+ }
40
+ fn vertexColor(i:i32)->vec3f {
41
+ if(!USE_VERTEX_COLOR) {return vec3f(1.0);}
42
+ let o=i*ATTR_STRIDE+COLOR_OFF;
43
+ if(COLOR_FLOAT) {return bitcast<vec3f>(vec3u(attrBuffers[o],attrBuffers[o+1],attrBuffers[o+2]));}
44
+ return unpack4x8unorm(attrBuffers[o]).xyz;
45
+ }
46
+ fn gC(i:i32)->vec4f {
47
+ if(!HAS_VERTEX_TANGENT) {return vec4f(0.0);}
48
+ let w=attrBuffers[i*ATTR_STRIDE+TANGENT_OFF];
49
+ let direction=tI(i32(w<<17u)>>17,i32(w<<2u)>>17,16383.0);
50
+ let AN=array<f32,4>(0.0,1.0,-1.0,2.0);
51
+ return vec4f(direction,AN[w>>30u]);
52
+ }
53
+ fn pJ(fallback:i32,record:i32)->i32 {
54
+ if(!HAS_TRIANGLE_MATERIAL) {return fallback;}
55
+ let material=attrBuffers[MATERIALINDEX_OFF+record];
56
+ if(material==0u) {return fallback;}
57
+ return i32(material-1u);
58
+ }
59
+ `;
60
+ }
61
+ //# sourceMappingURL=vertexAttributes.wgsl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vertexAttributes.wgsl.js","sourceRoot":"","sources":["../../../../src/renderer/wgsl/chunks/vertexAttributes.wgsl.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,MAAM,UAAU,sBAAsB,CAAC,OAAgB,EAAE,MAAe;IACtE,IAAI,CAAC,OAAO;QAAE,OAAO,UAAU,CAAC;;;;;;8BAMO,MAAM,CAAC,CAAC,CAAC,wCAAwC,CAAC,CAAC,CAAC,mDAAmD;CAC/I,CAAC;IACA,OAAO,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+CnB,CAAC;AACF,CAAC","sourcesContent":["/** Readers share word offsets with compactVertices; legacy hosts keep vec4-slot offsets. */\nexport function vertexAttributeReaders(compact: boolean, frames: boolean) {\n if (!compact) return /* wgsl */ `\nfn vertexPosition(i:i32)->vec3f {return attrBuffers[i*ATTR_STRIDE+POSITION_OFF].xyz;}\nfn vertexNormal(i:i32)->vec3f {return attrBuffers[i*ATTR_STRIDE+NORMAL_OFF].xyz;}\nfn vertexUv(i:i32)->vec2f {return attrBuffers[i*ATTR_STRIDE+UV_OFF].xy;}\nfn vertexUv1(i:i32)->vec2f {return attrBuffers[i*ATTR_STRIDE+UV1_OFF].xy;}\nfn vertexColor(i:i32)->vec3f {return attrBuffers[i*ATTR_STRIDE+COLOR_OFF].xyz;}\nfn vertexTangent(i:i32)->vec4f {return ${frames ? 'attrBuffers[i*ATTR_STRIDE+TANGENT_OFF]' : 'vec4f(attrBuffers[i*ATTR_STRIDE+TANGENT_OFF],0.0)'};}\n`;\n return /* wgsl */ `\nfn octDirection(a:i32,b:i32,maximum:f32)->vec3f {\n if (a == -i32(maximum)-1 && b == -i32(maximum)-1) {return vec3f(0.0);}\n var v=vec3f(f32(a)/maximum,f32(b)/maximum,0.0);\n v.z=1.0-abs(v.x)-abs(v.y);\n if(v.z<0.0) {v=vec3f((vec2f(1.0)-abs(v.yx))*select(vec2f(-1.0),vec2f(1.0),v.xy>=vec2f(0.0)),v.z);}\n return normalize(v);\n}\nfn vertexPosition(i:i32)->vec3f {\n let o=i*ATTR_STRIDE+POSITION_OFF;\n return bitcast<vec3f>(vec3u(attrBuffers[o],attrBuffers[o+1],attrBuffers[o+2]));\n}\nfn vertexNormal(i:i32)->vec3f {\n let o=i*ATTR_STRIDE+NORMAL_OFF;\n if(NORMAL_FLOAT) {return bitcast<vec3f>(vec3u(attrBuffers[o],attrBuffers[o+1],attrBuffers[o+2]));}\n let w=attrBuffers[o];\n return octDirection(i32(w<<16u)>>16,i32(w)>>16,32767.0);\n}\nfn vertexUv(i:i32)->vec2f {\n if(!HAS_VERTEX_UV) {return vec2f(0.0);}\n let o=i*ATTR_STRIDE+UV_OFF;\n return bitcast<vec2f>(vec2u(attrBuffers[o],attrBuffers[o+1]));\n}\nfn vertexUv1(i:i32)->vec2f {\n if(!HAS_VERTEX_UV) {return vec2f(0.0);}\n let o=i*ATTR_STRIDE+UV1_OFF;\n return bitcast<vec2f>(vec2u(attrBuffers[o],attrBuffers[o+1]));\n}\nfn vertexColor(i:i32)->vec3f {\n if(!USE_VERTEX_COLOR) {return vec3f(1.0);}\n let o=i*ATTR_STRIDE+COLOR_OFF;\n if(COLOR_FLOAT) {return bitcast<vec3f>(vec3u(attrBuffers[o],attrBuffers[o+1],attrBuffers[o+2]));}\n return unpack4x8unorm(attrBuffers[o]).xyz;\n}\nfn vertexTangent(i:i32)->vec4f {\n if(!HAS_VERTEX_TANGENT) {return vec4f(0.0);}\n let w=attrBuffers[i*ATTR_STRIDE+TANGENT_OFF];\n let direction=octDirection(i32(w<<17u)>>17,i32(w<<2u)>>17,16383.0);\n let signs=array<f32,4>(0.0,1.0,-1.0,2.0);\n return vec4f(direction,signs[w>>30u]);\n}\nfn triangleMaterial(fallback:i32,record:i32)->i32 {\n if(!HAS_TRIANGLE_MATERIAL) {return fallback;}\n let material=attrBuffers[MATERIALINDEX_OFF+record];\n if(material==0u) {return fallback;}\n return i32(material-1u);\n}\n`;\n}\n"]}
@@ -1,3 +1,5 @@
1
+ /** Mode indices understood by applyToneMapping. */
2
+ export declare const TONE_MAPPING_MODES: Readonly<Record<string, number>>;
1
3
  export declare const linearToSrgbDefine = "\nfn linearToSrgb(color: vec3f) -> vec3f {\n let linear = max(color, vec3f(0.0));\n let low = linear * 12.92;\n let high = 1.055 * pow(linear, vec3f(1.0 / 2.4)) - 0.055;\n return select(high, low, linear <= vec3f(0.0031308));\n}\n";
2
4
  export declare const composeDefine = "\n\nfn linearToneMapping(color: vec3f) -> vec3f {\n return clamp(color, vec3f(0.0), vec3f(1.0));\n}\nfn reinhardToneMapping(color: vec3f) -> vec3f {\n return clamp(color / (vec3f(1.0) + color), vec3f(0.0), vec3f(1.0));\n}\nfn cineonToneMapping(inputColor: vec3f) -> vec3f {\n let color = max(vec3f(0.0), inputColor - 0.004);\n return pow((color * (6.2 * color + 0.5)) /\n (color * (6.2 * color + 1.7) + 0.06), vec3f(2.2));\n}\nfn rrtAndOdtFit(value: vec3f) -> vec3f {\n let numerator = value * (value + 0.0245786) - 0.000090537;\n let denominator = value * (0.983729 * value + 0.4329510) + 0.238081;\n return numerator / denominator;\n}\nfn acesToneMapping(inputColor: vec3f) -> vec3f {\n let inputMatrix = mat3x3f(\n vec3f(0.59719, 0.07600, 0.02840),\n vec3f(0.35458, 0.90834, 0.13383),\n vec3f(0.04823, 0.01566, 0.83777)\n );\n let outputMatrix = mat3x3f(\n vec3f(1.60475, -0.10208, -0.00327),\n vec3f(-0.53108, 1.10813, -0.07276),\n vec3f(-0.07367, -0.00605, 1.07602)\n );\n let color = inputMatrix * (inputColor / 0.6);\n return clamp(outputMatrix * rrtAndOdtFit(color), vec3f(0.0), vec3f(1.0));\n}\nfn agxDefaultContrastApprox(value: vec3f) -> vec3f {\n let value2 = value * value;\n let value4 = value2 * value2;\n return 15.5 * value4 * value2 - 40.14 * value4 * value\n + 31.96 * value4 - 6.868 * value2 * value\n + 0.4298 * value2 + 0.1191 * value - 0.00232;\n}\nfn agxToneMapping(inputColor: vec3f) -> vec3f {\n let linearRec2020ToLinearSrgb = mat3x3f(\n vec3f(1.6605, -0.1246, -0.0182),\n vec3f(-0.5876, 1.1329, -0.1006),\n vec3f(-0.0728, -0.0083, 1.1187)\n );\n let linearSrgbToLinearRec2020 = mat3x3f(\n vec3f(0.6274, 0.0691, 0.0164),\n vec3f(0.3293, 0.9195, 0.0880),\n vec3f(0.0433, 0.0113, 0.8956)\n );\n let insetMatrix = mat3x3f(\n vec3f(0.856627153315983, 0.137318972929847, 0.11189821299995),\n vec3f(0.0951212405381588, 0.761241990602591, 0.0767994186031903),\n vec3f(0.0482516061458583, 0.101439036467562, 0.811302368396859)\n );\n let outsetMatrix = mat3x3f(\n vec3f(1.1271005818144368, -0.1413297634984383, -0.14132976349843826),\n vec3f(-0.11060664309660323, 1.157823702216272, -0.11060664309660294),\n vec3f(-0.016493938717834573, -0.016493938717834257, 1.2519364065950405)\n );\n var color = insetMatrix * (linearSrgbToLinearRec2020 * inputColor);\n color = clamp((log2(max(color, vec3f(1e-10))) + 12.47393) / 16.5, vec3f(0.0), vec3f(1.0));\n color = outsetMatrix * agxDefaultContrastApprox(color);\n color = pow(max(color, vec3f(0.0)), vec3f(2.2));\n return clamp(linearRec2020ToLinearSrgb * color, vec3f(0.0), vec3f(1.0));\n}\nfn applyToneMapping(color: vec3f) -> vec3f {\n let toneMappingMode = i32(toneMappingParams.x);\n if (toneMappingMode == 1) { return acesToneMapping(color); }\n if (toneMappingMode == 2) { return cineonToneMapping(color); }\n if (toneMappingMode == 3) { return reinhardToneMapping(color); }\n if (toneMappingMode == 4) { return linearToneMapping(color); }\n return agxToneMapping(color);\n}\n\nfn linearToSrgb(color: vec3f) -> vec3f {\n let linear = max(color, vec3f(0.0));\n let low = linear * 12.92;\n let high = 1.055 * pow(linear, vec3f(1.0 / 2.4)) - 0.055;\n return select(high, low, linear <= vec3f(0.0031308));\n}\n\nfn gradeColor(inputColor: vec3f) -> vec3f {\n let contrast = colorGradingParams.x;\n let saturation = colorGradingParams.y;\n let temperature = colorGradingParams.z;\n let tint = colorGradingParams.w;\n let balance = vec3f(\n 1.0 + temperature * 0.16 + tint * 0.04,\n 1.0 - tint * 0.12,\n 1.0 - temperature * 0.16 + tint * 0.04\n );\n var color = max(inputColor * balance, vec3f(0.0));\n color = max((color - 0.18) * contrast + 0.18, vec3f(0.0));\n let luminance = dot(color, vec3f(0.2126, 0.7152, 0.0722));\n return max(mix(vec3f(luminance), color, saturation), vec3f(0.0));\n}\n";
3
5
  export declare function createComposeMain(sdrEncoding?: 'gamma22' | 'srgb'): string;
@@ -1,3 +1,5 @@
1
+ /** Mode indices understood by applyToneMapping. */
2
+ export const TONE_MAPPING_MODES = { agx: 0, aces: 1, cineon: 2, reinhard: 3, linear: 4 };
1
3
  export const linearToSrgbDefine = /* wgsl */ `
2
4
  fn linearToSrgb(color: vec3f) -> vec3f {
3
5
  let linear = max(color, vec3f(0.0));
@@ -8,24 +10,24 @@ return select(high, low, linear <= vec3f(0.0031308));
8
10
  `;
9
11
  export const composeDefine = /* wgsl */ `
10
12
 
11
- fn kb(color: vec3f) -> vec3f {
13
+ fn kH(color: vec3f) -> vec3f {
12
14
  return clamp(color, vec3f(0.0), vec3f(1.0));
13
15
  }
14
- fn iN(color: vec3f) -> vec3f {
16
+ fn jp(color: vec3f) -> vec3f {
15
17
  return clamp(color / (vec3f(1.0) + color), vec3f(0.0), vec3f(1.0));
16
18
  }
17
- fn jP(jz: vec3f) -> vec3f {
18
- let color = max(vec3f(0.0), jz - 0.004);
19
+ fn kw(kb: vec3f) -> vec3f {
20
+ let color = max(vec3f(0.0), kb - 0.004);
19
21
  return pow((color * (6.2 * color + 0.5)) /
20
22
  (color * (6.2 * color + 1.7) + 0.06), vec3f(2.2));
21
23
  }
22
- fn pm(value: vec3f) -> vec3f {
23
- let iF = value * (value + 0.0245786) - 0.000090537;
24
+ fn qw(value: vec3f) -> vec3f {
25
+ let je = value * (value + 0.0245786) - 0.000090537;
24
26
  let ah = value * (0.983729 * value + 0.4329510) + 0.238081;
25
- return iF / ah;
27
+ return je / ah;
26
28
  }
27
- fn lO(jz: vec3f) -> vec3f {
28
- let qk = mat3x3f(
29
+ fn mH(kb: vec3f) -> vec3f {
30
+ let rt = mat3x3f(
29
31
  vec3f(0.59719, 0.07600, 0.02840),
30
32
  vec3f(0.35458, 0.90834, 0.13383),
31
33
  vec3f(0.04823, 0.01566, 0.83777)
@@ -35,63 +37,63 @@ vec3f(1.60475, -0.10208, -0.00327),
35
37
  vec3f(-0.53108, 1.10813, -0.07276),
36
38
  vec3f(-0.07367, -0.00605, 1.07602)
37
39
  );
38
- let color = qk * (jz / 0.6);
39
- return clamp(outputMatrix * pm(color), vec3f(0.0), vec3f(1.0));
40
+ let color = rt * (kb / 0.6);
41
+ return clamp(outputMatrix * qw(color), vec3f(0.0), vec3f(1.0));
40
42
  }
41
- fn fT(value: vec3f) -> vec3f {
42
- let nB = value * value;
43
- let rO = nB * nB;
44
- return 15.5 * rO * nB - 40.14 * rO * value
45
- + 31.96 * rO - 6.868 * nB * value
46
- + 0.4298 * nB + 0.1191 * value - 0.00232;
43
+ fn gj(value: vec3f) -> vec3f {
44
+ let ox = value * value;
45
+ let tf = ox * ox;
46
+ return 15.5 * tf * ox - 40.14 * tf * value
47
+ + 31.96 * tf - 6.868 * ox * value
48
+ + 0.4298 * ox + 0.1191 * value - 0.00232;
47
49
  }
48
- fn my(jz: vec3f) -> vec3f {
49
- let nE = mat3x3f(
50
+ fn nC(kb: vec3f) -> vec3f {
51
+ let oB = mat3x3f(
50
52
  vec3f(1.6605, -0.1246, -0.0182),
51
53
  vec3f(-0.5876, 1.1329, -0.1006),
52
54
  vec3f(-0.0728, -0.0083, 1.1187)
53
55
  );
54
- let nF = mat3x3f(
56
+ let oC = mat3x3f(
55
57
  vec3f(0.6274, 0.0691, 0.0164),
56
58
  vec3f(0.3293, 0.9195, 0.0880),
57
59
  vec3f(0.0433, 0.0113, 0.8956)
58
60
  );
59
- let qm = mat3x3f(
61
+ let rv = mat3x3f(
60
62
  vec3f(0.856627153315983, 0.137318972929847, 0.11189821299995),
61
63
  vec3f(0.0951212405381588, 0.761241990602591, 0.0767994186031903),
62
64
  vec3f(0.0482516061458583, 0.101439036467562, 0.811302368396859)
63
65
  );
64
- let ph = mat3x3f(
66
+ let qr = mat3x3f(
65
67
  vec3f(1.1271005818144368, -0.1413297634984383, -0.14132976349843826),
66
68
  vec3f(-0.11060664309660323, 1.157823702216272, -0.11060664309660294),
67
69
  vec3f(-0.016493938717834573, -0.016493938717834257, 1.2519364065950405)
68
70
  );
69
- var color = qm * (nF * jz);
71
+ var color = rv * (oC * kb);
70
72
  color = clamp((log2(max(color, vec3f(1e-10))) + 12.47393) / 16.5, vec3f(0.0), vec3f(1.0));
71
- color = ph * fT(color);
73
+ color = qr * gj(color);
72
74
  color = pow(max(color, vec3f(0.0)), vec3f(2.2));
73
- return clamp(nE * color, vec3f(0.0), vec3f(1.0));
75
+ return clamp(oB * color, vec3f(0.0), vec3f(1.0));
74
76
  }
75
- fn bZ(color: vec3f) -> vec3f {
77
+ fn bH(color: vec3f) -> vec3f {
76
78
  let toneMappingMode = i32(toneMappingParams.x);
77
- if (toneMappingMode == 1) { return lO(color); }
78
- if (toneMappingMode == 2) { return jP(color); }
79
- if (toneMappingMode == 3) { return iN(color); }
80
- if (toneMappingMode == 4) { return kb(color); }
81
- return my(color);
79
+ if (toneMappingMode == 1) { return mH(color); }
80
+ if (toneMappingMode == 2) { return kw(color); }
81
+ if (toneMappingMode == 3) { return jp(color); }
82
+ if (toneMappingMode == 4) { return kH(color); }
83
+ return nC(color);
82
84
  }
83
85
  ${linearToSrgbDefine}
84
- fn ga(jz: vec3f) -> vec3f {
86
+ fn fm(kb: vec3f) -> vec3f {
85
87
  let contrast = colorGradingParams.x;
86
88
  let saturation = colorGradingParams.y;
87
89
  let temperature = colorGradingParams.z;
88
90
  let tint = colorGradingParams.w;
89
- let uL = vec3f(
91
+ let wu = vec3f(
90
92
  1.0 + temperature * 0.16 + tint * 0.04,
91
93
  1.0 - tint * 0.12,
92
94
  1.0 - temperature * 0.16 + tint * 0.04
93
95
  );
94
- var color = max(jz * uL, vec3f(0.0));
96
+ var color = max(kb * wu, vec3f(0.0));
95
97
  color = max((color - 0.18) * contrast + 0.18, vec3f(0.0));
96
98
  let luminance = dot(color, vec3f(0.2126, 0.7152, 0.0722));
97
99
  return max(mix(vec3f(luminance), color, saturation), vec3f(0.0));
@@ -101,54 +103,54 @@ export function createComposeMain(sdrEncoding = 'srgb') {
101
103
  return /* wgsl */ `
102
104
 
103
105
  var finalColor = load_colorTex(uv, 0);
104
- var jp = vec4(0.0);
106
+ var jU = vec4(0.0);
105
107
  if (bloomIntensity > 0.0) {
106
- jp = load_bloomTex(uv, 0) * bloomIntensity;
107
- finalColor = vec4f(finalColor.rgb + jp.rgb, finalColor.a);
108
+ jU = load_bloomTex(uv, 0) * bloomIntensity;
109
+ finalColor = vec4f(finalColor.rgb + jU.rgb, finalColor.a);
108
110
  }
109
111
 
110
- var gradedColor = ga(finalColor.rgb * exposure);
111
- let iJ = smoothstep(0.2, 0.72, distance(vec2f(uv) / vec2f(colorTexRegion()), vec2f(0.5)));
112
- gradedColor *= 1.0 - toneMappingParams.y * iJ;
113
- let gy = hdrOutputEnabled > 0.5;
114
- if (!gy) {
115
- gradedColor = bZ(gradedColor);
112
+ var gradedColor = fm(finalColor.rgb * exposure);
113
+ let ji = smoothstep(0.2, 0.72, distance(vec2f(uv) / vec2f(colorTexRegion()), vec2f(0.5)));
114
+ gradedColor *= 1.0 - toneMappingParams.y * ji;
115
+ let gS = hdrOutputEnabled > 0.5;
116
+ if (!gS) {
117
+ gradedColor = bH(gradedColor);
116
118
  }
117
- let mN = select(
119
+ let nP = select(
118
120
  ${sdrEncoding === 'srgb' ? 'linearToSrgb(gradedColor)' : 'pow(max(gradedColor, vec3f(0.0)), vec3f(1.0 / 2.2))'},
119
121
  linearToSrgb(gradedColor),
120
- gy
122
+ gS
121
123
  );
122
- var oL = mN;
124
+ var pT = nP;
123
125
  if (flatBackgroundColor.a > 0.5) {
124
- let jj = clamp(
126
+ let jN = clamp(
125
127
  load_flatBackgroundMaskTex(uv, 0).a,
126
128
  0.0,
127
129
  1.0
128
130
  );
129
- let pR = linearToSrgb(max(flatBackgroundColor.rgb, vec3f(0.0)));
130
- oL = mix(pR, mN, jj);
131
+ let qV = linearToSrgb(max(flatBackgroundColor.rgb, vec3f(0.0)));
132
+ pT = mix(qV, nP, jN);
131
133
  if (bloomIntensity > 0.0) {
132
- var unbloomedColor = ga(
133
- max(finalColor.rgb - jp.rgb, vec3f(0.0))
134
+ var unbloomedColor = fm(
135
+ max(finalColor.rgb - jU.rgb, vec3f(0.0))
134
136
  * exposure
135
137
  );
136
- unbloomedColor *= 1.0 - toneMappingParams.y * iJ;
137
- if (!gy) {
138
- unbloomedColor = bZ(unbloomedColor);
138
+ unbloomedColor *= 1.0 - toneMappingParams.y * ji;
139
+ if (!gS) {
140
+ unbloomedColor = bH(unbloomedColor);
139
141
  }
140
- let sC = select(
142
+ let ub = select(
141
143
  ${sdrEncoding === 'srgb' ? 'linearToSrgb(unbloomedColor)' : 'pow(max(unbloomedColor, vec3f(0.0)), vec3f(1.0 / 2.2))'},
142
144
  linearToSrgb(unbloomedColor),
143
- gy
145
+ gS
144
146
  );
145
- oL += max(mN - sC, vec3f(0.0))
146
- * (1.0 - jj);
147
+ pT += max(nP - ub, vec3f(0.0))
148
+ * (1.0 - jN);
147
149
  }
148
150
  }
149
- finalColor = vec4f(oL, finalColor.a);
151
+ finalColor = vec4f(pT, finalColor.a);
150
152
  if (bloomIntensity > 0.0) {
151
- finalColor.a = max(finalColor.a, min(dot(jp.rgb, vec3f(0.2125, 0.7154, 0.0721)), 1.0));
153
+ finalColor.a = max(finalColor.a, min(dot(jU.rgb, vec3f(0.2125, 0.7154, 0.0721)), 1.0));
152
154
  }
153
155
 
154
156
  if (shadowCatcherEnabled > 0.5) {
@@ -162,36 +164,36 @@ let background = load_catcherBackgroundTex(uv, 0);
162
164
 
163
165
 
164
166
 
165
- let kU = select(0.0, clamp(background.a - coverage, 0.0, 1.0 - coverage), flatBackgroundColor.a > 0.5);
166
- var foregroundColor = ga((foreground.rgb + jp.rgb) * exposure);
167
- var backgroundColor = ga((background.rgb / max(background.a, 0.000001) + jp.rgb) * exposure);
168
- foregroundColor *= 1.0 - toneMappingParams.y * iJ;
169
- backgroundColor *= 1.0 - toneMappingParams.y * iJ;
170
- if (!gy) {
171
- foregroundColor = bZ(foregroundColor);
172
- backgroundColor = bZ(backgroundColor);
167
+ let lN = select(0.0, clamp(background.a - coverage, 0.0, 1.0 - coverage), flatBackgroundColor.a > 0.5);
168
+ var foregroundColor = fm((foreground.rgb + jU.rgb) * exposure);
169
+ var backgroundColor = fm((background.rgb / max(background.a, 0.000001) + jU.rgb) * exposure);
170
+ foregroundColor *= 1.0 - toneMappingParams.y * ji;
171
+ backgroundColor *= 1.0 - toneMappingParams.y * ji;
172
+ if (!gS) {
173
+ foregroundColor = bH(foregroundColor);
174
+ backgroundColor = bH(backgroundColor);
173
175
  }
174
- foregroundColor = select(${sdrEncoding === 'srgb' ? 'linearToSrgb(foregroundColor)' : 'pow(max(foregroundColor, vec3f(0.0)), vec3f(1.0 / 2.2))'}, linearToSrgb(foregroundColor), gy);
175
- backgroundColor = select(${sdrEncoding === 'srgb' ? 'linearToSrgb(backgroundColor)' : 'pow(max(backgroundColor, vec3f(0.0)), vec3f(1.0 / 2.2))'}, linearToSrgb(backgroundColor), gy);
176
+ foregroundColor = select(${sdrEncoding === 'srgb' ? 'linearToSrgb(foregroundColor)' : 'pow(max(foregroundColor, vec3f(0.0)), vec3f(1.0 / 2.2))'}, linearToSrgb(foregroundColor), gS);
177
+ backgroundColor = select(${sdrEncoding === 'srgb' ? 'linearToSrgb(backgroundColor)' : 'pow(max(backgroundColor, vec3f(0.0)), vec3f(1.0 / 2.2))'}, linearToSrgb(backgroundColor), gS);
176
178
  if (flatBackgroundColor.a > 0.5) {
177
- var unbloomedBackground = ga(background.rgb / max(background.a, 0.000001) * exposure);
178
- unbloomedBackground *= 1.0 - toneMappingParams.y * iJ;
179
- if (!gy) { unbloomedBackground = bZ(unbloomedBackground); }
180
- let mO = select(${sdrEncoding === 'srgb' ? 'linearToSrgb(unbloomedBackground)' : 'pow(max(unbloomedBackground, vec3f(0.0)), vec3f(1.0 / 2.2))'}, linearToSrgb(unbloomedBackground), gy);
181
- let vY = select(vec3f(0.0), max(backgroundColor - mO, vec3f(0.0)), bloomIntensity > 0.0);
182
- backgroundColor = linearToSrgb(max(flatBackgroundColor.rgb, vec3f(0.0))) + vY;
179
+ var unbloomedBackground = fm(background.rgb / max(background.a, 0.000001) * exposure);
180
+ unbloomedBackground *= 1.0 - toneMappingParams.y * ji;
181
+ if (!gS) { unbloomedBackground = bH(unbloomedBackground); }
182
+ let nQ = select(${sdrEncoding === 'srgb' ? 'linearToSrgb(unbloomedBackground)' : 'pow(max(unbloomedBackground, vec3f(0.0)), vec3f(1.0 / 2.2))'}, linearToSrgb(unbloomedBackground), gS);
183
+ let xU = select(vec3f(0.0), max(backgroundColor - nQ, vec3f(0.0)), bloomIntensity > 0.0);
184
+ backgroundColor = linearToSrgb(max(flatBackgroundColor.rgb, vec3f(0.0))) + xU;
183
185
  }
184
186
 
185
187
 
186
- let fR = coverage * opacity;
187
- let mD = clamp(dot(jp.rgb, vec3f(0.2125, 0.7154, 0.0721)), 0.0, 1.0);
188
- let hq = max(foreground.a, mD * (1.0 - coverage - kU));
189
- let jf = max(background.a, mD * coverage);
190
- let kD = (jf - kU) * (1.0 - opacity) + kU;
191
- let alpha = hq + kD + fR;
192
- let premultiplied = foregroundColor * hq
193
- + backgroundColor * kD
194
- + shadowCatcherColor * fR;
188
+ let gd = coverage * opacity;
189
+ let nF = clamp(dot(jU.rgb, vec3f(0.2125, 0.7154, 0.0721)), 0.0, 1.0);
190
+ let hK = max(foreground.a, nF * (1.0 - coverage - lN));
191
+ let jJ = max(background.a, nF * coverage);
192
+ let ln = (jJ - lN) * (1.0 - opacity) + lN;
193
+ let alpha = hK + ln + gd;
194
+ let premultiplied = foregroundColor * hK
195
+ + backgroundColor * ln
196
+ + shadowCatcherColor * gd;
195
197
  finalColor = vec4f(premultiplied / max(alpha, 0.000001), alpha);
196
198
  }
197
199
  }
@@ -208,8 +210,8 @@ export function createCompositeDenoiseColorMain(output = 'output.denoiseColor',
208
210
  const srgbDecode = 'select(pow((encoded + 0.055) / 1.055, vec3f(2.4)), encoded / 12.92, encoded <= vec3f(0.04045))';
209
211
  return /* wgsl */ `
210
212
  let encoded = max(${input}.rgb, vec3f(0.0));
211
- let uq = ${sdrEncoding === 'srgb' ? srgbDecode : `select(pow(encoded, vec3f(2.2)), ${srgbDecode}, gy)`};
212
- ${output} = vec4f(uq, ${input}.a);
213
+ let wa = ${sdrEncoding === 'srgb' ? srgbDecode : `select(pow(encoded, vec3f(2.2)), ${srgbDecode}, gS)`};
214
+ ${output} = vec4f(wa, ${input}.a);
213
215
 
214
216
  `;
215
217
  }
@@ -219,22 +221,22 @@ export function createCompositeDenoiseAlbedoMain(output = 'output.denoiseAlbedo'
219
221
 
220
222
 
221
223
  let rawAlbedo = load_flatBackgroundMaskTex(uv, 0);
222
- var pJ = rawAlbedo.rgb;
224
+ var qM = rawAlbedo.rgb;
223
225
  if (shadowCatcherEnabled > 0.5 && flatBackgroundColor.a < 0.5) {
224
226
  let coverage = clamp(load_shadowCatcherTex(uv, 0).r, 0.0, 1.0);
225
227
  let background = load_catcherBackgroundTex(uv, 0);
226
228
  if (coverage > 0.0 && background.a > 0.0) {
227
- var iv = ga(background.rgb / background.a * exposure);
228
- iv *= 1.0 - toneMappingParams.y * iJ;
229
- if (!gy) { iv = bZ(iv); }
229
+ var iW = fm(background.rgb / background.a * exposure);
230
+ iW *= 1.0 - toneMappingParams.y * ji;
231
+ if (!gS) { iW = bH(iW); }
230
232
 
231
233
 
232
234
 
233
- let sr = clamp(background.a, 0.0, coverage);
234
- pJ += sr * (clamp(iv, vec3f(0.0), vec3f(1.0)) - vec3f(1.0));
235
+ let tS = clamp(background.a, 0.0, coverage);
236
+ qM += tS * (clamp(iW, vec3f(0.0), vec3f(1.0)) - vec3f(1.0));
235
237
  }
236
238
  }
237
- ${output} = vec4f(clamp(pJ, vec3f(0.0), vec3f(1.0)), rawAlbedo.a);
239
+ ${output} = vec4f(clamp(qM, vec3f(0.0), vec3f(1.0)), rawAlbedo.a);
238
240
  `;
239
241
  }
240
242
  export const compositeDenoiseOutputMain = createCompositeDenoiseColorMain() + createCompositeDenoiseAlbedoMain();
@@ -253,15 +255,15 @@ output.color = vec4f(select(vec3f(0.0), encoded, alpha > 0.0), alpha);
253
255
  export const compositeDenoiseDisplayMain = createCompositeDenoiseDisplayMain();
254
256
  // Shared hit normalization; CPU readback retains its f32 reference path.
255
257
  export const hdrResolveWGSL = /* wgsl */ `
256
- fn fo(color: f32, count: f32, hit: f32, uw: f32, rgb: bool) -> f32 {
258
+ fn fF(color: f32, count: f32, hit: f32, wf: f32, rgb: bool) -> f32 {
257
259
  if (count <= 0.0) {
258
260
  return 0.0;
259
261
  }
260
- let total = max(count, uw);
262
+ let total = max(count, wf);
261
263
  let divisor = select(total, hit, (rgb && (hit > 0.0)));
262
264
  return (color / divisor);
263
265
  }
264
- fn jx(color: f32, coverage: f32, flat: bool, rgb: bool) -> f32 {
266
+ fn ka(color: f32, coverage: f32, flat: bool, rgb: bool) -> f32 {
265
267
  if ((flat && rgb) && (coverage > 0.0)) {
266
268
  return (color * coverage);
267
269
  }
@@ -1 +1 @@
1
- {"version":3,"file":"compose.frag.wgsl.js","sourceRoot":"","sources":["../../../src/renderer/wgsl/compose.frag.wgsl.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAG,UAAU,CAAC;;;;;;;CAO5C,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0EtC,kBAAkB;;;;;;;;;;;;;;;;CAgBnB,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,cAAkC,MAAM;IACxE,OAAO,UAAU,CAAC;;;;;;;;;;;;;;;;;EAiBhB,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,qDAAqD;;;;;;;;;;;;;;;;;;;;;;;EAuBxG,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,wDAAwD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAiC3F,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,yDAAyD;2BACpH,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,yDAAyD;;;;;kBAKnG,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,mCAAmC,CAAC,CAAC,CAAC,6DAA6D;;;;;;;;;;;;;;;;;;;;;;CAsB3K,CAAC;AACF,CAAC;AACD,MAAM,CAAC,MAAM,WAAW,GAAG,iBAAiB,EAAE,CAAC;AAE/C,6EAA6E;AAC7E,8EAA8E;AAC9E,MAAM,UAAU,+BAA+B,CAAC,MAAM,GAAG,qBAAqB,EAAE,KAAK,GAAG,YAAY,EAAE,cAAkC,MAAM;IAC5I,MAAM,UAAU,GAAG,gGAAgG,CAAC;IACpH,OAAO,UAAU,CAAC;oBACA,KAAK;WACH,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,oCAAoC,UAAU,OAAc;EACtH,MAAM,gBAA2B,KAAK;;CAEvC,CAAC;AACF,CAAC;AACD,MAAM,UAAU,gCAAgC,CAAC,MAAM,GAAG,sBAAsB;IAC9E,OAAO,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;EAoBlB,MAAM;CACP,CAAC;AACF,CAAC;AACD,MAAM,CAAC,MAAM,0BAA0B,GAAG,+BAA+B,EAAE,GAAG,gCAAgC,EAAE,CAAC;AAEjH,MAAM,UAAU,iCAAiC,CAAC,cAAkC,MAAM;IACxF,OAAO,UAAU,CAAC;;;;;;;gBAOJ,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,qFAAqF;;CAEtJ,CAAC;AACF,CAAC;AAED,MAAM,CAAC,MAAM,2BAA2B,GAAG,iCAAiC,EAAE,CAAC;AAE/E,yEAAyE;AACzE,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;CAexC,CAAC","sourcesContent":["export const linearToSrgbDefine = /* wgsl */ `\nfn linearToSrgb(color: vec3f) -> vec3f {\n let linear = max(color, vec3f(0.0));\n let low = linear * 12.92;\n let high = 1.055 * pow(linear, vec3f(1.0 / 2.4)) - 0.055;\n return select(high, low, linear <= vec3f(0.0031308));\n}\n`;\n\nexport const composeDefine = /* wgsl */ `\n\nfn linearToneMapping(color: vec3f) -> vec3f {\n return clamp(color, vec3f(0.0), vec3f(1.0));\n}\nfn reinhardToneMapping(color: vec3f) -> vec3f {\n return clamp(color / (vec3f(1.0) + color), vec3f(0.0), vec3f(1.0));\n}\nfn cineonToneMapping(inputColor: vec3f) -> vec3f {\n let color = max(vec3f(0.0), inputColor - 0.004);\n return pow((color * (6.2 * color + 0.5)) /\n (color * (6.2 * color + 1.7) + 0.06), vec3f(2.2));\n}\nfn rrtAndOdtFit(value: vec3f) -> vec3f {\n let numerator = value * (value + 0.0245786) - 0.000090537;\n let denominator = value * (0.983729 * value + 0.4329510) + 0.238081;\n return numerator / denominator;\n}\nfn acesToneMapping(inputColor: vec3f) -> vec3f {\n let inputMatrix = mat3x3f(\n vec3f(0.59719, 0.07600, 0.02840),\n vec3f(0.35458, 0.90834, 0.13383),\n vec3f(0.04823, 0.01566, 0.83777)\n );\n let outputMatrix = mat3x3f(\n vec3f(1.60475, -0.10208, -0.00327),\n vec3f(-0.53108, 1.10813, -0.07276),\n vec3f(-0.07367, -0.00605, 1.07602)\n );\n let color = inputMatrix * (inputColor / 0.6);\n return clamp(outputMatrix * rrtAndOdtFit(color), vec3f(0.0), vec3f(1.0));\n}\nfn agxDefaultContrastApprox(value: vec3f) -> vec3f {\n let value2 = value * value;\n let value4 = value2 * value2;\n return 15.5 * value4 * value2 - 40.14 * value4 * value\n + 31.96 * value4 - 6.868 * value2 * value\n + 0.4298 * value2 + 0.1191 * value - 0.00232;\n}\nfn agxToneMapping(inputColor: vec3f) -> vec3f {\n let linearRec2020ToLinearSrgb = mat3x3f(\n vec3f(1.6605, -0.1246, -0.0182),\n vec3f(-0.5876, 1.1329, -0.1006),\n vec3f(-0.0728, -0.0083, 1.1187)\n );\n let linearSrgbToLinearRec2020 = mat3x3f(\n vec3f(0.6274, 0.0691, 0.0164),\n vec3f(0.3293, 0.9195, 0.0880),\n vec3f(0.0433, 0.0113, 0.8956)\n );\n let insetMatrix = mat3x3f(\n vec3f(0.856627153315983, 0.137318972929847, 0.11189821299995),\n vec3f(0.0951212405381588, 0.761241990602591, 0.0767994186031903),\n vec3f(0.0482516061458583, 0.101439036467562, 0.811302368396859)\n );\n let outsetMatrix = mat3x3f(\n vec3f(1.1271005818144368, -0.1413297634984383, -0.14132976349843826),\n vec3f(-0.11060664309660323, 1.157823702216272, -0.11060664309660294),\n vec3f(-0.016493938717834573, -0.016493938717834257, 1.2519364065950405)\n );\n var color = insetMatrix * (linearSrgbToLinearRec2020 * inputColor);\n color = clamp((log2(max(color, vec3f(1e-10))) + 12.47393) / 16.5, vec3f(0.0), vec3f(1.0));\n color = outsetMatrix * agxDefaultContrastApprox(color);\n color = pow(max(color, vec3f(0.0)), vec3f(2.2));\n return clamp(linearRec2020ToLinearSrgb * color, vec3f(0.0), vec3f(1.0));\n}\nfn applyToneMapping(color: vec3f) -> vec3f {\n let toneMappingMode = i32(toneMappingParams.x);\n if (toneMappingMode == 1) { return acesToneMapping(color); }\n if (toneMappingMode == 2) { return cineonToneMapping(color); }\n if (toneMappingMode == 3) { return reinhardToneMapping(color); }\n if (toneMappingMode == 4) { return linearToneMapping(color); }\n return agxToneMapping(color);\n}\n${linearToSrgbDefine}\nfn gradeColor(inputColor: vec3f) -> vec3f {\n let contrast = colorGradingParams.x;\n let saturation = colorGradingParams.y;\n let temperature = colorGradingParams.z;\n let tint = colorGradingParams.w;\n let balance = vec3f(\n 1.0 + temperature * 0.16 + tint * 0.04,\n 1.0 - tint * 0.12,\n 1.0 - temperature * 0.16 + tint * 0.04\n );\n var color = max(inputColor * balance, vec3f(0.0));\n color = max((color - 0.18) * contrast + 0.18, vec3f(0.0));\n let luminance = dot(color, vec3f(0.2126, 0.7152, 0.0722));\n return max(mix(vec3f(luminance), color, saturation), vec3f(0.0));\n}\n`;\n\nexport function createComposeMain(sdrEncoding: 'gamma22' | 'srgb' = 'srgb'): string {\n return /* wgsl */ `\n\nvar finalColor = load_colorTex(uv, 0);\nvar bloomTexel = vec4(0.0);\nif (bloomIntensity > 0.0) {\n bloomTexel = load_bloomTex(uv, 0) * bloomIntensity;\n finalColor = vec4f(finalColor.rgb + bloomTexel.rgb, finalColor.a);\n}\n\nvar gradedColor = gradeColor(finalColor.rgb * exposure);\nlet vignetteEdge = smoothstep(0.2, 0.72, distance(vec2f(uv) / vec2f(colorTexRegion()), vec2f(0.5)));\ngradedColor *= 1.0 - toneMappingParams.y * vignetteEdge;\nlet hdrOutput = hdrOutputEnabled > 0.5;\nif (!hdrOutput) {\n gradedColor = applyToneMapping(gradedColor);\n}\nlet encodedDisplay = select(\n ${sdrEncoding === 'srgb' ? 'linearToSrgb(gradedColor)' : 'pow(max(gradedColor, vec3f(0.0)), vec3f(1.0 / 2.2))'},\n linearToSrgb(gradedColor),\n hdrOutput\n);\nvar displayColor = encodedDisplay;\nif (flatBackgroundColor.a > 0.5) {\n let surfaceCoverage = clamp(\n load_flatBackgroundMaskTex(uv, 0).a,\n 0.0,\n 1.0\n );\n let flatBackgroundDisplay = linearToSrgb(max(flatBackgroundColor.rgb, vec3f(0.0)));\n displayColor = mix(flatBackgroundDisplay, encodedDisplay, surfaceCoverage);\n if (bloomIntensity > 0.0) {\n var unbloomedColor = gradeColor(\n max(finalColor.rgb - bloomTexel.rgb, vec3f(0.0))\n * exposure\n );\n unbloomedColor *= 1.0 - toneMappingParams.y * vignetteEdge;\n if (!hdrOutput) {\n unbloomedColor = applyToneMapping(unbloomedColor);\n }\n let encodedUnbloomed = select(\n ${sdrEncoding === 'srgb' ? 'linearToSrgb(unbloomedColor)' : 'pow(max(unbloomedColor, vec3f(0.0)), vec3f(1.0 / 2.2))'},\n linearToSrgb(unbloomedColor),\n hdrOutput\n );\n displayColor += max(encodedDisplay - encodedUnbloomed, vec3f(0.0))\n * (1.0 - surfaceCoverage);\n }\n}\nfinalColor = vec4f(displayColor, finalColor.a);\nif (bloomIntensity > 0.0) {\n finalColor.a = max(finalColor.a, min(dot(bloomTexel.rgb, vec3f(0.2125, 0.7154, 0.0721)), 1.0));\n}\n\nif (shadowCatcherEnabled > 0.5) {\n let shadowCatcher = load_shadowCatcherTex(uv, 0);\n let coverage = clamp(shadowCatcher.r, 0.0, 1.0);\n let opacity = max(clamp(shadowCatcher.a / max(coverage, 0.000001), 0.0, 1.0) - (1.0 - shadowCatcherAlpha), 0.0);\n if (coverage > 0.0 || flatBackgroundColor.a > 0.5) {\n let foreground = load_foregroundTex(uv, 0);\n let background = load_catcherBackgroundTex(uv, 0);\n // An opaque flat backdrop also owns primary misses outside the receiver.\n // Its alpha contains catcher coverage plus miss coverage; only the catcher\n // fraction receives shadow. These weights come from the accumulation,\n // independently of the quantized denoising/albedo guide.\n let flatMissCoverage = select(0.0, clamp(background.a - coverage, 0.0, 1.0 - coverage), flatBackgroundColor.a > 0.5);\n var foregroundColor = gradeColor((foreground.rgb + bloomTexel.rgb) * exposure);\n var backgroundColor = gradeColor((background.rgb / max(background.a, 0.000001) + bloomTexel.rgb) * exposure);\n foregroundColor *= 1.0 - toneMappingParams.y * vignetteEdge;\n backgroundColor *= 1.0 - toneMappingParams.y * vignetteEdge;\n if (!hdrOutput) {\n foregroundColor = applyToneMapping(foregroundColor);\n backgroundColor = applyToneMapping(backgroundColor);\n }\n foregroundColor = select(${sdrEncoding === 'srgb' ? 'linearToSrgb(foregroundColor)' : 'pow(max(foregroundColor, vec3f(0.0)), vec3f(1.0 / 2.2))'}, linearToSrgb(foregroundColor), hdrOutput);\n backgroundColor = select(${sdrEncoding === 'srgb' ? 'linearToSrgb(backgroundColor)' : 'pow(max(backgroundColor, vec3f(0.0)), vec3f(1.0 / 2.2))'}, linearToSrgb(backgroundColor), hdrOutput);\n if (flatBackgroundColor.a > 0.5) {\n var unbloomedBackground = gradeColor(background.rgb / max(background.a, 0.000001) * exposure);\n unbloomedBackground *= 1.0 - toneMappingParams.y * vignetteEdge;\n if (!hdrOutput) { unbloomedBackground = applyToneMapping(unbloomedBackground); }\n let encodedUnbloomedBackground = select(${sdrEncoding === 'srgb' ? 'linearToSrgb(unbloomedBackground)' : 'pow(max(unbloomedBackground, vec3f(0.0)), vec3f(1.0 / 2.2))'}, linearToSrgb(unbloomedBackground), hdrOutput);\n let bloomSpill = select(vec3f(0.0), max(backgroundColor - encodedUnbloomedBackground, vec3f(0.0)), bloomIntensity > 0.0);\n backgroundColor = linearToSrgb(max(flatBackgroundColor.rgb, vec3f(0.0))) + bloomSpill;\n }\n // Foreground and catcher are disjoint primary samples, not overlapping\n // alpha layers. Shadow only the catcher background before averaging.\n let shadowAlpha = coverage * opacity;\n let bloomAlpha = clamp(dot(bloomTexel.rgb, vec3f(0.2125, 0.7154, 0.0721)), 0.0, 1.0);\n let foregroundAlpha = max(foreground.a, bloomAlpha * (1.0 - coverage - flatMissCoverage));\n let backgroundAlpha = max(background.a, bloomAlpha * coverage);\n let visibleBackgroundAlpha = (backgroundAlpha - flatMissCoverage) * (1.0 - opacity) + flatMissCoverage;\n let alpha = foregroundAlpha + visibleBackgroundAlpha + shadowAlpha;\n let premultiplied = foregroundColor * foregroundAlpha\n + backgroundColor * visibleBackgroundAlpha\n + shadowCatcherColor * shadowAlpha;\n finalColor = vec4f(premultiplied / max(alpha, 0.000001), alpha);\n }\n}\n\noutput.color = finalColor;\n\n// output.color = load_bloomTex(uv, 0) * bloomIntensity;\n`;\n}\nexport const composeMain = createComposeMain();\n\n// Preserve the existing display composition, but give OIDN a floating-point,\n// linear-light image. Alpha is deliberately not used as a second color layer.\nexport function createCompositeDenoiseColorMain(output = 'output.denoiseColor', input = 'finalColor', sdrEncoding: 'gamma22' | 'srgb' = 'srgb'): string {\n const srgbDecode = 'select(pow((encoded + 0.055) / 1.055, vec3f(2.4)), encoded / 12.92, encoded <= vec3f(0.04045))';\n return /* wgsl */ `\nlet encoded = max(${input}.rgb, vec3f(0.0));\nlet displayLinear = ${sdrEncoding === 'srgb' ? srgbDecode : `select(pow(encoded, vec3f(2.2)), ${srgbDecode}, hdrOutput)`};\n${output} = vec4f(displayLinear, ${input}.a);\n\n`;\n}\nexport function createCompositeDenoiseAlbedoMain(output = 'output.denoiseAlbedo'): string {\n return /* wgsl */ `// The receiver is invisible: its visible texture is the displayed background,\n// not the neutral reflectance used for its lighting estimate. Match the beauty\n// reconstruction filter, including mixed foreground/receiver primary samples.\n// Exclude the stochastic shadow and bloom so neither is preserved as texture.\nlet rawAlbedo = load_flatBackgroundMaskTex(uv, 0);\nvar compositeAlbedo = rawAlbedo.rgb;\nif (shadowCatcherEnabled > 0.5 && flatBackgroundColor.a < 0.5) {\n let coverage = clamp(load_shadowCatcherTex(uv, 0).r, 0.0, 1.0);\n let background = load_catcherBackgroundTex(uv, 0);\n if (coverage > 0.0 && background.a > 0.0) {\n var backgroundAlbedo = gradeColor(background.rgb / background.a * exposure);\n backgroundAlbedo *= 1.0 - toneMappingParams.y * vignetteEdge;\n if (!hdrOutput) { backgroundAlbedo = applyToneMapping(backgroundAlbedo); }\n // Background alpha already includes primary catcher coverage. Retain the\n // neutral receiver for its transparent part, without counting coverage twice\n // or adding the stochastic shadow opacity to the texture guide.\n let backgroundWeight = clamp(background.a, 0.0, coverage);\n compositeAlbedo += backgroundWeight * (clamp(backgroundAlbedo, vec3f(0.0), vec3f(1.0)) - vec3f(1.0));\n }\n}\n${output} = vec4f(clamp(compositeAlbedo, vec3f(0.0), vec3f(1.0)), rawAlbedo.a);\n`;\n}\nexport const compositeDenoiseOutputMain = createCompositeDenoiseColorMain() + createCompositeDenoiseAlbedoMain();\n\nexport function createCompositeDenoiseDisplayMain(sdrEncoding: 'gamma22' | 'srgb' = 'srgb'): string {\n return /* wgsl */ `\nlet denoised = load_colorTex(uv, 0);\n// Keep the original primary coverage, including transparency. OIDN only\n// filters RGB; filtering coverage separately reintroduces silhouette seams.\n// The built-in filter weights color and coverage together and may replace it.\nlet alpha = select(load_composedTex(uv, 0).a, clamp(denoised.a, 0.0, 1.0), denoisedAlpha > 0.5);\nlet linear = max(denoised.rgb, vec3f(0.0));\nlet encoded = ${sdrEncoding === 'srgb' ? 'linearToSrgb(linear)' : 'select(pow(linear, vec3f(1.0 / 2.2)), linearToSrgb(linear), hdrOutputEnabled > 0.5)'};\noutput.color = vec4f(select(vec3f(0.0), encoded, alpha > 0.0), alpha);\n`;\n}\n\nexport const compositeDenoiseDisplayMain = createCompositeDenoiseDisplayMain();\n\n// Shared hit normalization; CPU readback retains its f32 reference path.\nexport const hdrResolveWGSL = /* wgsl */ `\nfn hdr_resolve_component(color: f32, count: f32, hit: f32, minimum_count: f32, rgb: bool) -> f32 {\nif (count <= 0.0) {\nreturn 0.0;\n}\nlet total = max(count, minimum_count);\nlet divisor = select(total, hit, (rgb && (hit > 0.0)));\nreturn (color / divisor);\n}\nfn hdr_flat_component(color: f32, coverage: f32, flat: bool, rgb: bool) -> f32 {\nif ((flat && rgb) && (coverage > 0.0)) {\nreturn (color * coverage);\n}\nreturn color;\n}\n`;\n"]}
1
+ {"version":3,"file":"compose.frag.wgsl.js","sourceRoot":"","sources":["../../../src/renderer/wgsl/compose.frag.wgsl.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,MAAM,CAAC,MAAM,kBAAkB,GAAqC,EAAC,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAC,CAAC;AAEzH,MAAM,CAAC,MAAM,kBAAkB,GAAG,UAAU,CAAC;;;;;;;CAO5C,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0EtC,kBAAkB;;;;;;;;;;;;;;;;CAgBnB,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,cAAkC,MAAM;IACxE,OAAO,UAAU,CAAC;;;;;;;;;;;;;;;;;EAiBhB,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,qDAAqD;;;;;;;;;;;;;;;;;;;;;;;EAuBxG,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,wDAAwD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAiC3F,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,yDAAyD;2BACpH,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,yDAAyD;;;;;kBAKnG,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,mCAAmC,CAAC,CAAC,CAAC,6DAA6D;;;;;;;;;;;;;;;;;;;;;;CAsB3K,CAAC;AACF,CAAC;AACD,MAAM,CAAC,MAAM,WAAW,GAAG,iBAAiB,EAAE,CAAC;AAE/C,6EAA6E;AAC7E,8EAA8E;AAC9E,MAAM,UAAU,+BAA+B,CAAC,MAAM,GAAG,qBAAqB,EAAE,KAAK,GAAG,YAAY,EAAE,cAAkC,MAAM;IAC5I,MAAM,UAAU,GAAG,gGAAgG,CAAC;IACpH,OAAO,UAAU,CAAC;oBACA,KAAK;WACH,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,oCAAoC,UAAU,OAAc;EACtH,MAAM,gBAA2B,KAAK;;CAEvC,CAAC;AACF,CAAC;AACD,MAAM,UAAU,gCAAgC,CAAC,MAAM,GAAG,sBAAsB;IAC9E,OAAO,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;EAoBlB,MAAM;CACP,CAAC;AACF,CAAC;AACD,MAAM,CAAC,MAAM,0BAA0B,GAAG,+BAA+B,EAAE,GAAG,gCAAgC,EAAE,CAAC;AAEjH,MAAM,UAAU,iCAAiC,CAAC,cAAkC,MAAM;IACxF,OAAO,UAAU,CAAC;;;;;;;gBAOJ,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,qFAAqF;;CAEtJ,CAAC;AACF,CAAC;AAED,MAAM,CAAC,MAAM,2BAA2B,GAAG,iCAAiC,EAAE,CAAC;AAE/E,yEAAyE;AACzE,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;CAexC,CAAC","sourcesContent":["/** Mode indices understood by applyToneMapping. */\nexport const TONE_MAPPING_MODES: Readonly<Record<string, number>> = {agx: 0, aces: 1, cineon: 2, reinhard: 3, linear: 4};\n\nexport const linearToSrgbDefine = /* wgsl */ `\nfn linearToSrgb(color: vec3f) -> vec3f {\n let linear = max(color, vec3f(0.0));\n let low = linear * 12.92;\n let high = 1.055 * pow(linear, vec3f(1.0 / 2.4)) - 0.055;\n return select(high, low, linear <= vec3f(0.0031308));\n}\n`;\n\nexport const composeDefine = /* wgsl */ `\n\nfn linearToneMapping(color: vec3f) -> vec3f {\n return clamp(color, vec3f(0.0), vec3f(1.0));\n}\nfn reinhardToneMapping(color: vec3f) -> vec3f {\n return clamp(color / (vec3f(1.0) + color), vec3f(0.0), vec3f(1.0));\n}\nfn cineonToneMapping(inputColor: vec3f) -> vec3f {\n let color = max(vec3f(0.0), inputColor - 0.004);\n return pow((color * (6.2 * color + 0.5)) /\n (color * (6.2 * color + 1.7) + 0.06), vec3f(2.2));\n}\nfn rrtAndOdtFit(value: vec3f) -> vec3f {\n let numerator = value * (value + 0.0245786) - 0.000090537;\n let denominator = value * (0.983729 * value + 0.4329510) + 0.238081;\n return numerator / denominator;\n}\nfn acesToneMapping(inputColor: vec3f) -> vec3f {\n let inputMatrix = mat3x3f(\n vec3f(0.59719, 0.07600, 0.02840),\n vec3f(0.35458, 0.90834, 0.13383),\n vec3f(0.04823, 0.01566, 0.83777)\n );\n let outputMatrix = mat3x3f(\n vec3f(1.60475, -0.10208, -0.00327),\n vec3f(-0.53108, 1.10813, -0.07276),\n vec3f(-0.07367, -0.00605, 1.07602)\n );\n let color = inputMatrix * (inputColor / 0.6);\n return clamp(outputMatrix * rrtAndOdtFit(color), vec3f(0.0), vec3f(1.0));\n}\nfn agxDefaultContrastApprox(value: vec3f) -> vec3f {\n let value2 = value * value;\n let value4 = value2 * value2;\n return 15.5 * value4 * value2 - 40.14 * value4 * value\n + 31.96 * value4 - 6.868 * value2 * value\n + 0.4298 * value2 + 0.1191 * value - 0.00232;\n}\nfn agxToneMapping(inputColor: vec3f) -> vec3f {\n let linearRec2020ToLinearSrgb = mat3x3f(\n vec3f(1.6605, -0.1246, -0.0182),\n vec3f(-0.5876, 1.1329, -0.1006),\n vec3f(-0.0728, -0.0083, 1.1187)\n );\n let linearSrgbToLinearRec2020 = mat3x3f(\n vec3f(0.6274, 0.0691, 0.0164),\n vec3f(0.3293, 0.9195, 0.0880),\n vec3f(0.0433, 0.0113, 0.8956)\n );\n let insetMatrix = mat3x3f(\n vec3f(0.856627153315983, 0.137318972929847, 0.11189821299995),\n vec3f(0.0951212405381588, 0.761241990602591, 0.0767994186031903),\n vec3f(0.0482516061458583, 0.101439036467562, 0.811302368396859)\n );\n let outsetMatrix = mat3x3f(\n vec3f(1.1271005818144368, -0.1413297634984383, -0.14132976349843826),\n vec3f(-0.11060664309660323, 1.157823702216272, -0.11060664309660294),\n vec3f(-0.016493938717834573, -0.016493938717834257, 1.2519364065950405)\n );\n var color = insetMatrix * (linearSrgbToLinearRec2020 * inputColor);\n color = clamp((log2(max(color, vec3f(1e-10))) + 12.47393) / 16.5, vec3f(0.0), vec3f(1.0));\n color = outsetMatrix * agxDefaultContrastApprox(color);\n color = pow(max(color, vec3f(0.0)), vec3f(2.2));\n return clamp(linearRec2020ToLinearSrgb * color, vec3f(0.0), vec3f(1.0));\n}\nfn applyToneMapping(color: vec3f) -> vec3f {\n let toneMappingMode = i32(toneMappingParams.x);\n if (toneMappingMode == 1) { return acesToneMapping(color); }\n if (toneMappingMode == 2) { return cineonToneMapping(color); }\n if (toneMappingMode == 3) { return reinhardToneMapping(color); }\n if (toneMappingMode == 4) { return linearToneMapping(color); }\n return agxToneMapping(color);\n}\n${linearToSrgbDefine}\nfn gradeColor(inputColor: vec3f) -> vec3f {\n let contrast = colorGradingParams.x;\n let saturation = colorGradingParams.y;\n let temperature = colorGradingParams.z;\n let tint = colorGradingParams.w;\n let balance = vec3f(\n 1.0 + temperature * 0.16 + tint * 0.04,\n 1.0 - tint * 0.12,\n 1.0 - temperature * 0.16 + tint * 0.04\n );\n var color = max(inputColor * balance, vec3f(0.0));\n color = max((color - 0.18) * contrast + 0.18, vec3f(0.0));\n let luminance = dot(color, vec3f(0.2126, 0.7152, 0.0722));\n return max(mix(vec3f(luminance), color, saturation), vec3f(0.0));\n}\n`;\n\nexport function createComposeMain(sdrEncoding: 'gamma22' | 'srgb' = 'srgb'): string {\n return /* wgsl */ `\n\nvar finalColor = load_colorTex(uv, 0);\nvar bloomTexel = vec4(0.0);\nif (bloomIntensity > 0.0) {\n bloomTexel = load_bloomTex(uv, 0) * bloomIntensity;\n finalColor = vec4f(finalColor.rgb + bloomTexel.rgb, finalColor.a);\n}\n\nvar gradedColor = gradeColor(finalColor.rgb * exposure);\nlet vignetteEdge = smoothstep(0.2, 0.72, distance(vec2f(uv) / vec2f(colorTexRegion()), vec2f(0.5)));\ngradedColor *= 1.0 - toneMappingParams.y * vignetteEdge;\nlet hdrOutput = hdrOutputEnabled > 0.5;\nif (!hdrOutput) {\n gradedColor = applyToneMapping(gradedColor);\n}\nlet encodedDisplay = select(\n ${sdrEncoding === 'srgb' ? 'linearToSrgb(gradedColor)' : 'pow(max(gradedColor, vec3f(0.0)), vec3f(1.0 / 2.2))'},\n linearToSrgb(gradedColor),\n hdrOutput\n);\nvar displayColor = encodedDisplay;\nif (flatBackgroundColor.a > 0.5) {\n let surfaceCoverage = clamp(\n load_flatBackgroundMaskTex(uv, 0).a,\n 0.0,\n 1.0\n );\n let flatBackgroundDisplay = linearToSrgb(max(flatBackgroundColor.rgb, vec3f(0.0)));\n displayColor = mix(flatBackgroundDisplay, encodedDisplay, surfaceCoverage);\n if (bloomIntensity > 0.0) {\n var unbloomedColor = gradeColor(\n max(finalColor.rgb - bloomTexel.rgb, vec3f(0.0))\n * exposure\n );\n unbloomedColor *= 1.0 - toneMappingParams.y * vignetteEdge;\n if (!hdrOutput) {\n unbloomedColor = applyToneMapping(unbloomedColor);\n }\n let encodedUnbloomed = select(\n ${sdrEncoding === 'srgb' ? 'linearToSrgb(unbloomedColor)' : 'pow(max(unbloomedColor, vec3f(0.0)), vec3f(1.0 / 2.2))'},\n linearToSrgb(unbloomedColor),\n hdrOutput\n );\n displayColor += max(encodedDisplay - encodedUnbloomed, vec3f(0.0))\n * (1.0 - surfaceCoverage);\n }\n}\nfinalColor = vec4f(displayColor, finalColor.a);\nif (bloomIntensity > 0.0) {\n finalColor.a = max(finalColor.a, min(dot(bloomTexel.rgb, vec3f(0.2125, 0.7154, 0.0721)), 1.0));\n}\n\nif (shadowCatcherEnabled > 0.5) {\n let shadowCatcher = load_shadowCatcherTex(uv, 0);\n let coverage = clamp(shadowCatcher.r, 0.0, 1.0);\n let opacity = max(clamp(shadowCatcher.a / max(coverage, 0.000001), 0.0, 1.0) - (1.0 - shadowCatcherAlpha), 0.0);\n if (coverage > 0.0 || flatBackgroundColor.a > 0.5) {\n let foreground = load_foregroundTex(uv, 0);\n let background = load_catcherBackgroundTex(uv, 0);\n // An opaque flat backdrop also owns primary misses outside the receiver.\n // Its alpha contains catcher coverage plus miss coverage; only the catcher\n // fraction receives shadow. These weights come from the accumulation,\n // independently of the quantized denoising/albedo guide.\n let flatMissCoverage = select(0.0, clamp(background.a - coverage, 0.0, 1.0 - coverage), flatBackgroundColor.a > 0.5);\n var foregroundColor = gradeColor((foreground.rgb + bloomTexel.rgb) * exposure);\n var backgroundColor = gradeColor((background.rgb / max(background.a, 0.000001) + bloomTexel.rgb) * exposure);\n foregroundColor *= 1.0 - toneMappingParams.y * vignetteEdge;\n backgroundColor *= 1.0 - toneMappingParams.y * vignetteEdge;\n if (!hdrOutput) {\n foregroundColor = applyToneMapping(foregroundColor);\n backgroundColor = applyToneMapping(backgroundColor);\n }\n foregroundColor = select(${sdrEncoding === 'srgb' ? 'linearToSrgb(foregroundColor)' : 'pow(max(foregroundColor, vec3f(0.0)), vec3f(1.0 / 2.2))'}, linearToSrgb(foregroundColor), hdrOutput);\n backgroundColor = select(${sdrEncoding === 'srgb' ? 'linearToSrgb(backgroundColor)' : 'pow(max(backgroundColor, vec3f(0.0)), vec3f(1.0 / 2.2))'}, linearToSrgb(backgroundColor), hdrOutput);\n if (flatBackgroundColor.a > 0.5) {\n var unbloomedBackground = gradeColor(background.rgb / max(background.a, 0.000001) * exposure);\n unbloomedBackground *= 1.0 - toneMappingParams.y * vignetteEdge;\n if (!hdrOutput) { unbloomedBackground = applyToneMapping(unbloomedBackground); }\n let encodedUnbloomedBackground = select(${sdrEncoding === 'srgb' ? 'linearToSrgb(unbloomedBackground)' : 'pow(max(unbloomedBackground, vec3f(0.0)), vec3f(1.0 / 2.2))'}, linearToSrgb(unbloomedBackground), hdrOutput);\n let bloomSpill = select(vec3f(0.0), max(backgroundColor - encodedUnbloomedBackground, vec3f(0.0)), bloomIntensity > 0.0);\n backgroundColor = linearToSrgb(max(flatBackgroundColor.rgb, vec3f(0.0))) + bloomSpill;\n }\n // Foreground and catcher are disjoint primary samples, not overlapping\n // alpha layers. Shadow only the catcher background before averaging.\n let shadowAlpha = coverage * opacity;\n let bloomAlpha = clamp(dot(bloomTexel.rgb, vec3f(0.2125, 0.7154, 0.0721)), 0.0, 1.0);\n let foregroundAlpha = max(foreground.a, bloomAlpha * (1.0 - coverage - flatMissCoverage));\n let backgroundAlpha = max(background.a, bloomAlpha * coverage);\n let visibleBackgroundAlpha = (backgroundAlpha - flatMissCoverage) * (1.0 - opacity) + flatMissCoverage;\n let alpha = foregroundAlpha + visibleBackgroundAlpha + shadowAlpha;\n let premultiplied = foregroundColor * foregroundAlpha\n + backgroundColor * visibleBackgroundAlpha\n + shadowCatcherColor * shadowAlpha;\n finalColor = vec4f(premultiplied / max(alpha, 0.000001), alpha);\n }\n}\n\noutput.color = finalColor;\n\n// output.color = load_bloomTex(uv, 0) * bloomIntensity;\n`;\n}\nexport const composeMain = createComposeMain();\n\n// Preserve the existing display composition, but give OIDN a floating-point,\n// linear-light image. Alpha is deliberately not used as a second color layer.\nexport function createCompositeDenoiseColorMain(output = 'output.denoiseColor', input = 'finalColor', sdrEncoding: 'gamma22' | 'srgb' = 'srgb'): string {\n const srgbDecode = 'select(pow((encoded + 0.055) / 1.055, vec3f(2.4)), encoded / 12.92, encoded <= vec3f(0.04045))';\n return /* wgsl */ `\nlet encoded = max(${input}.rgb, vec3f(0.0));\nlet displayLinear = ${sdrEncoding === 'srgb' ? srgbDecode : `select(pow(encoded, vec3f(2.2)), ${srgbDecode}, hdrOutput)`};\n${output} = vec4f(displayLinear, ${input}.a);\n\n`;\n}\nexport function createCompositeDenoiseAlbedoMain(output = 'output.denoiseAlbedo'): string {\n return /* wgsl */ `// The receiver is invisible: its visible texture is the displayed background,\n// not the neutral reflectance used for its lighting estimate. Match the beauty\n// reconstruction filter, including mixed foreground/receiver primary samples.\n// Exclude the stochastic shadow and bloom so neither is preserved as texture.\nlet rawAlbedo = load_flatBackgroundMaskTex(uv, 0);\nvar compositeAlbedo = rawAlbedo.rgb;\nif (shadowCatcherEnabled > 0.5 && flatBackgroundColor.a < 0.5) {\n let coverage = clamp(load_shadowCatcherTex(uv, 0).r, 0.0, 1.0);\n let background = load_catcherBackgroundTex(uv, 0);\n if (coverage > 0.0 && background.a > 0.0) {\n var backgroundAlbedo = gradeColor(background.rgb / background.a * exposure);\n backgroundAlbedo *= 1.0 - toneMappingParams.y * vignetteEdge;\n if (!hdrOutput) { backgroundAlbedo = applyToneMapping(backgroundAlbedo); }\n // Background alpha already includes primary catcher coverage. Retain the\n // neutral receiver for its transparent part, without counting coverage twice\n // or adding the stochastic shadow opacity to the texture guide.\n let backgroundWeight = clamp(background.a, 0.0, coverage);\n compositeAlbedo += backgroundWeight * (clamp(backgroundAlbedo, vec3f(0.0), vec3f(1.0)) - vec3f(1.0));\n }\n}\n${output} = vec4f(clamp(compositeAlbedo, vec3f(0.0), vec3f(1.0)), rawAlbedo.a);\n`;\n}\nexport const compositeDenoiseOutputMain = createCompositeDenoiseColorMain() + createCompositeDenoiseAlbedoMain();\n\nexport function createCompositeDenoiseDisplayMain(sdrEncoding: 'gamma22' | 'srgb' = 'srgb'): string {\n return /* wgsl */ `\nlet denoised = load_colorTex(uv, 0);\n// Keep the original primary coverage, including transparency. OIDN only\n// filters RGB; filtering coverage separately reintroduces silhouette seams.\n// The built-in filter weights color and coverage together and may replace it.\nlet alpha = select(load_composedTex(uv, 0).a, clamp(denoised.a, 0.0, 1.0), denoisedAlpha > 0.5);\nlet linear = max(denoised.rgb, vec3f(0.0));\nlet encoded = ${sdrEncoding === 'srgb' ? 'linearToSrgb(linear)' : 'select(pow(linear, vec3f(1.0 / 2.2)), linearToSrgb(linear), hdrOutputEnabled > 0.5)'};\noutput.color = vec4f(select(vec3f(0.0), encoded, alpha > 0.0), alpha);\n`;\n}\n\nexport const compositeDenoiseDisplayMain = createCompositeDenoiseDisplayMain();\n\n// Shared hit normalization; CPU readback retains its f32 reference path.\nexport const hdrResolveWGSL = /* wgsl */ `\nfn hdr_resolve_component(color: f32, count: f32, hit: f32, minimum_count: f32, rgb: bool) -> f32 {\nif (count <= 0.0) {\nreturn 0.0;\n}\nlet total = max(count, minimum_count);\nlet divisor = select(total, hit, (rgb && (hit > 0.0)));\nreturn (color / divisor);\n}\nfn hdr_flat_component(color: f32, coverage: f32, flat: bool, rgb: bool) -> f32 {\nif ((flat && rgb) && (coverage > 0.0)) {\nreturn (color * coverage);\n}\nreturn color;\n}\n`;\n"]}