@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,11 +1,13 @@
1
+ import { spectralPrefixWgsl, prefixCheckpoint, prefixSave, prefixRestore, prefixRandomBindings } from './chunks/spectralPrefix.wgsl.js';
1
2
  import { photonQuerySource } from './photonMap.compute.js';
2
3
  import backgroundWgsl from './chunks/background.wgsl.js';
3
4
  import { researchTransport } from '../researchTransport.js';
4
5
  import { causticPartitionWGSL } from './chunks/caustics.wgsl.js';
5
- import { MAX_PATH_EVENTS } from '../pathLimits.js';
6
+ import { MAX_PATH_EVENTS_WEBGL } from '../pathLimits.js';
6
7
  import shadowCatcherAccumulationWGSL from './chunks/shadowCatcherAccumulation.wgsl.js';
7
8
  import reflectanceWGSL from './aovReflectance.wgsl.js';
8
9
  import aovTraceWGSL from './aovTrace.wgsl.js';
10
+ import aovTraceDisplayWGSL from './aovTraceDisplay.wgsl.js';
9
11
  import depthQueryWGSL from './depthQuery.wgsl.js';
10
12
  // Portions adapted from ray-tracing-renderer@0.10.15
11
13
  // (https://github.com/hoverinc/ray-tracing-renderer).
@@ -29,14 +31,28 @@ import uvProjectionWgsl from './chunks/uvProjection.wgsl.js';
29
31
  export const WORKGROUP_SIZE = 8;
30
32
  /** Generates the WebGPU megakernel path tracing compute shader. */
31
33
  export default function rayTraceCompute(options, sceneIntersections = '', pathDiagnostic = false, inputHooks) {
34
+ const maxPathEvents = options.maxPathEvents ?? MAX_PATH_EVENTS_WEBGL;
32
35
  const research = researchTransport()?.compute(options);
33
36
  const enabled = research?.enabled ?? false;
34
37
  const partitionDepth = research?.maxDepth ?? 20;
35
38
  const debugGroup = research?.debugGroup ?? options.debugGroup ?? -1;
36
- let { hasDisplacement, workgroupSize = WORKGROUP_SIZE, lightTracing = false, photonMapping = false, photonMaxDepth = 20, hasAnisotropyDirections = false, hasCoatNormals = false, hasAlpha = true, hasSceneAlpha = true, blasLayoutMask = 1, spectral, sceneCapabilities, dynamicEnvironment = false, materialCapabilities = ALL_MATERIAL_SHADER_CAPABILITIES, lightCapabilities } = options;
39
+ let { compactVertices = false, hasDisplacement, workgroupSize = WORKGROUP_SIZE, lightTracing = false, photonMapping = false, photonMaxDepth = 20, hasAnisotropyDirections = false, hasCoatNormals = false, hasAlpha = true, hasSceneAlpha = true, blasLayoutMask = 1, spectral, sceneCapabilities, dynamicEnvironment = false, materialCapabilities = ALL_MATERIAL_SHADER_CAPABILITIES, lightCapabilities } = options;
37
40
  hasAnisotropyDirections ||= hasCoatNormals;
38
41
  const deterministicPrimaryAlpha = hasAlpha;
39
42
  const hasShadowCatcher = sceneCapabilities === undefined || (sceneCapabilities & WGPU_SCENE_FEATURE_BITS.HAS_SHADOW_CATCHER) !== 0;
43
+ // MNEE can refract a wavelength-dependent connection at an ordinary receiver,
44
+ // before the camera path reaches any Cauchy boundary. Preserve its independent
45
+ // wavelength paths until a connection-solver checkpoint is available.
46
+ const sharePrefix = options.shareSpectralPrefix ?? false;
47
+ const surfacePrefix = {
48
+ path: ['Path', 'path'], si: ['SurfaceInteraction', '*si'], ma: ['OpenPbrResolvedMaterial', '*ma'],
49
+ aux: ['RayTraceAuxiliary', '*outAux'], depth: ['i32', 'depth'], event: ['i32', 'event'],
50
+ ignored: ['bool', 'sampleIgnored'], opaque: ['bool', 'isNotTransparent'], ...prefixRandomBindings
51
+ };
52
+ const flatPrefix = {
53
+ ...surfacePrefix, si: ['SurfaceInteraction', 'si'], ma: ['OpenPbrResolvedMaterial', 'ma'],
54
+ aux: ['RayTraceAuxiliary', 'wavelengthAux']
55
+ };
40
56
  const primaryVariables = /* wgsl */ `
41
57
  var si: SurfaceInteraction;
42
58
  var ma: OpenPbrResolvedMaterial;
@@ -65,7 +81,7 @@ return vec4f(1.0);
65
81
  else {
66
82
  if (HAS_BEVEL && rtUniform.bevel != 0) {
67
83
  if (ma.bevel > 0.0) {
68
- si.normal = mT(si, ma.bevel);
84
+ si.normal = kB(si, ma.bevel);
69
85
  }
70
86
  }
71
87
 
@@ -93,16 +109,16 @@ si.albedoSampled = ma.transmissionWeight > 0.5;
93
109
 
94
110
  ${commonWgsl}
95
111
 
96
- ${rayTraceCoreWgsl({ hasSceneAlpha, hasAnisotropyDirections, hasCoatNormals, lightCapabilities, caustics: enabled || lightTracing || photonMapping })}
112
+ ${rayTraceCoreWgsl({ independentTextures: options.independentTextures, compactVertices, cameraProjectionInverse: options.cameraProjectionInverse, hasSceneAlpha, hasAnisotropyDirections, hasCoatNormals, lightCapabilities, caustics: enabled || lightTracing || photonMapping })}
97
113
 
98
114
  ${uvProjectionWgsl}
99
115
 
100
- ${createMaterialBufferWgsl({ hasSceneAlpha, hasAnisotropyDirections, hasCoatNormals,
116
+ ${createMaterialBufferWgsl({ independentTextures: options.independentTextures, hasSceneAlpha, hasAnisotropyDirections, hasCoatNormals,
101
117
  caustics: enabled || lightTracing || photonMapping,
102
118
  hasTransmission: (materialCapabilities & MATERIAL_SHADER_CAPABILITIES.transmission) !== 0,
103
119
  hasMetalness: (materialCapabilities & MATERIAL_SHADER_CAPABILITIES.metal) !== 0 })}
104
120
 
105
- ${createIntersectionWgsl({ hasDisplacement, blasLayoutMask, hasAnisotropyDirections, hasCoatNormals, sceneIntersections })}
121
+ ${createIntersectionWgsl({ compactVertices, perInstanceBounds: options.perInstanceBounds, hasDisplacement, blasLayoutMask, hasAnisotropyDirections, hasCoatNormals, sceneIntersections })}
106
122
  ${randWgsl}
107
123
  ${randomWgsl}
108
124
  ${envMapWgsl}
@@ -113,35 +129,35 @@ ${createOpenPbrBsdfWgsl(hasAnisotropyDirections, hasCoatNormals)}
113
129
  ${sampleLightWgsl}${inputHooks?.declarations ?? ''}
114
130
 
115
131
 
116
- var<private> vp: u32 = 0u;
132
+ var<private> bounceIndex: u32 = 0u;
117
133
 
118
134
 
119
135
 
120
- fn ke() -> u32 {
136
+ fn kL() -> u32 {
121
137
  return u32(max(rtUniform.directLightCandidates, 1));
122
138
  }
123
139
 
124
140
 
125
141
 
126
142
 
127
- fn qp(yQ: u32) -> f32 {
143
+ fn rA(AT: u32) -> f32 {
128
144
 
129
145
 
130
146
 
131
147
 
132
148
  if (SAMPLING_PATTERN == 2) { _ = rand(); }
133
- let kl = aI.x + aI.y * u32(rtUniform.outputSize.x);
134
- let key = ak(ak(kl, aC), rtUniform.sequenceSeed);
135
- let dimension = ak(samplingBounce, yQ) ^ 0xa511e9b3u;
136
- return f32(cB(key ^ dimension) >> 8u) * (1.0 / 16777216.0);
149
+ let kT = aJ.x + aJ.y * u32(rtUniform.outputSize.x);
150
+ let key = ak(ak(kT, aC), rtUniform.sequenceSeed);
151
+ let dimension = ak(samplingBounce, AT) ^ 0xa511e9b3u;
152
+ return f32(cD(key ^ dimension) >> 8u) * (1.0 / 16777216.0);
137
153
  }
138
154
 
139
155
 
140
156
 
141
- fn uY(lightPdf: f32, scatteringPdf: f32) -> f32 {
142
- let candidateCount = ke();
157
+ fn wM(lightPdf: f32, scatteringPdf: f32) -> f32 {
158
+ let candidateCount = kL();
143
159
  if (candidateCount <= 1u) {
144
- return aF(lightPdf, scatteringPdf);
160
+ return aG(lightPdf, scatteringPdf);
145
161
  }
146
162
  let weightedLightPdf = f32(candidateCount) * lightPdf;
147
163
  return weightedLightPdf /
@@ -149,10 +165,10 @@ max(weightedLightPdf + scatteringPdf, 1e-20);
149
165
  }
150
166
 
151
167
 
152
- fn fV(scatteringPdf: f32, lightPdf: f32) -> f32 {
153
- let candidateCount = ke();
168
+ fn gm(scatteringPdf: f32, lightPdf: f32) -> f32 {
169
+ let candidateCount = kL();
154
170
  if (candidateCount <= 1u) {
155
- return aF(scatteringPdf, lightPdf);
171
+ return aG(scatteringPdf, lightPdf);
156
172
  }
157
173
  let weightedLightPdf = f32(candidateCount) * lightPdf;
158
174
  return scatteringPdf /
@@ -163,7 +179,7 @@ ${enabled || lightTracing || photonMapping ? causticPartitionWGSL(enabled, light
163
179
  const CAUSTIC_MNEE=${enabled};
164
180
  const CAUSTIC_MNEE_MAX_DEPTH=${partitionDepth}u;
165
181
  const CAUSTIC_PHOTON_MAX_DEPTH=${photonMaxDepth}u;
166
- ` + photonQuerySource(debugGroup, !lightTracing && (options.photonDirectSubset ?? true)) : ''}${createSampleMaterialWgsl(hasAnisotropyDirections, hasCoatNormals, enabled || lightTracing || photonMapping, research?.contribution, photonMapping)}
182
+ ` + photonQuerySource(debugGroup, !lightTracing && (options.photonDirectSubset ?? true)) : ''}${createSampleMaterialWgsl(hasAnisotropyDirections, hasCoatNormals, enabled || lightTracing || photonMapping, research?.contribution, photonMapping, options.channelIndependentRis)}
167
183
  ${sampleShadowCatcherWgsl}
168
184
 
169
185
 
@@ -175,24 +191,24 @@ ${shadowCatcherAccumulationWGSL}
175
191
  @group(3) @binding(3) var<storage, read_write> outShadowCatcher: array<ShadowCatcherAccumulation>;
176
192
 
177
193
 
178
- fn hH(
179
- gf: u32,
194
+ fn ij(
195
+ gx: u32,
180
196
  radiance: vec3f,
181
197
  normal: vec3f
182
198
  ) {
183
199
  if (rtUniform.varianceMoments != 0) {
184
200
  let value = dot(radiance, luminance);
185
- outNormal[gf] += vec4f(value * value, 0.0, 0.0, 1.0);
201
+ outNormal[gx] += vec4f(value * value, 0.0, 0.0, 1.0);
186
202
  }
187
203
  else {
188
- outNormal[gf] += vec4f(normal, 1.0);
204
+ outNormal[gx] += vec4f(normal, 1.0);
189
205
  }
190
206
  }
191
207
 
192
208
 
193
209
 
194
- fn iP(gf: u32, value: f32) {
195
- outShadowCatcher[gf].moments += vec4f(value, value * value, 0.0, 0.0);
210
+ fn ju(gx: u32, value: f32) {
211
+ outShadowCatcher[gx].moments += vec4f(value, value * value, 0.0, 0.0);
196
212
  }
197
213
 
198
214
 
@@ -206,8 +222,8 @@ isBlank: bool,
206
222
  shadowCounts: vec2f,
207
223
  }
208
224
 
209
- ${backgroundWgsl}fn cP(ray: Ray, channel: i32) -> vec4f {
210
- let bg = ft(ray);
225
+ ${backgroundWgsl}fn cS(ray: Ray, channel: i32) -> vec4f {
226
+ let bg = fI(ray);
211
227
  if (SPECTRAL) {
212
228
  return vec4f(sampling_spectral_rgb_filter(bg.rgb, channel), bg.a);
213
229
  }
@@ -216,8 +232,8 @@ return bg;
216
232
 
217
233
 
218
234
 
219
- fn nO(uv: vec2f, path: ptr<function, Path>, depth: ptr<function, i32>, si: ptr<function, SurfaceInteraction>, ma: ptr<function, OpenPbrResolvedMaterial>, outAux: ptr<function, RayTraceAuxiliary>, eV: ptr<function, bool>) {
220
- *eV = false;
235
+ fn mD(uv: vec2f, path: ptr<function, Path>, depth: ptr<function, i32>, si: ptr<function, SurfaceInteraction>, ma: ptr<function, OpenPbrResolvedMaterial>, outAux: ptr<function, RayTraceAuxiliary>, fg: ptr<function, bool>) {
236
+ *fg = false;
221
237
  samplingBounce = u32(max(*depth, 0));
222
238
  let matType = (*ma).materialType;
223
239
  let isShadowCatcher = ${hasShadowCatcher ? /* wgsl */ `matType == SHADOW_CATCHER` : /* wgsl */ `false`};
@@ -233,28 +249,28 @@ if (USE_ENVMAP) {
233
249
  if ((*path).isNextRefraction) {
234
250
 
235
251
 
236
- let bg = cP(
252
+ let bg = cS(
237
253
  (*path).ray,
238
254
  (*si).spectralChannel
239
255
  );
240
- let cM = select(fV((*path).scatteringPdf,
241
- envMapPdf(cT((*path).ray.d)) * rtUniform.envLightPmf),
256
+ let cP = select(gm((*path).scatteringPdf,
257
+ envMapPdf(cU((*path).ray.d)) * rtUniform.envLightPmf),
242
258
  1.0, (*path).scatteringIsDelta);
243
- (*path).li += cM * (*path).beta * bg.rgb * bg.a;
259
+ (*path).li += cP * (*path).beta * bg.rgb * bg.a;
244
260
  (*path).alpha = max((*path).alpha, bg.a);
245
261
  }
246
262
  else {
247
- let vC = cT((*path).ray.d);
248
- var emission = textureLinear(envMap, vC).rgb;
263
+ let xp = cU((*path).ray.d);
264
+ var emission = textureLinear(envMap, xp).rgb;
249
265
  if (SPECTRAL) {
250
266
  emission = sampling_spectral_rgb_filter(emission, (*si).spectralChannel);
251
267
  }
252
268
  (*path).li += (*path).beta * emission *
253
- fV((*path).scatteringPdf, envMapPdf(vC));
269
+ gm((*path).scatteringPdf, envMapPdf(xp));
254
270
  }
255
271
  }
256
272
  else {
257
- let bg = cP(
273
+ let bg = cS(
258
274
  (*path).ray,
259
275
  (*si).spectralChannel
260
276
  );
@@ -268,7 +284,7 @@ if (!(*si).hit) {
268
284
 
269
285
 
270
286
 
271
- let bg = cP(
287
+ let bg = cS(
272
288
  (*path).ray,
273
289
  (*si).spectralChannel
274
290
  );
@@ -281,10 +297,10 @@ if ((*path).fromEye) {
281
297
  (USE_BACKGROUND && !USE_BACKGROUND_MAP);
282
298
  }
283
299
  else {
284
- let cam = eT(uv);
285
- let nt = dot(cam.d, (*path).ray.d) > 0.0;
300
+ let cam = cV(uv);
301
+ let ou = dot(cam.d, (*path).ray.d) > 0.0;
286
302
  if (rtUniform.transmissiveOutputAlphaMin < 1.0) {
287
- if (nt) {
303
+ if (ou) {
288
304
  (*path).alpha = max((*path).alpha, bg.a);
289
305
  } else {
290
306
  (*path).alpha = 1.0;
@@ -293,11 +309,11 @@ if (nt) {
293
309
  if (!USE_ENVMAP) {
294
310
 
295
311
 
296
- if (nt) {
312
+ if (ou) {
297
313
 
298
314
 
299
315
  (*path).li += (*path).beta *
300
- fV((*path).scatteringPdf, 1.0) * bg.rgb;
316
+ gm((*path).scatteringPdf, 1.0) * bg.rgb;
301
317
  }
302
318
  }
303
319
  }
@@ -312,19 +328,19 @@ let alpha = clamp((*ma).alpha, 0.0, 1.0);
312
328
  if (alpha < 1.0) {
313
329
 
314
330
 
315
- if (alpha <= 0.0 || ek(3u) > alpha) {
316
- (*eV) = true;
331
+ if (alpha <= 0.0 || cm(3u) > alpha) {
332
+ (*fg) = true;
317
333
  }
318
334
  }
319
- if (!(*eV) && rtUniform.transmissiveOutputAlphaMin < 1.0) {
335
+ if (!(*fg) && rtUniform.transmissiveOutputAlphaMin < 1.0) {
320
336
 
321
337
 
322
338
  let outputAlpha = max(1.0 - (*ma).transmissionWeight, 1.0 - pow(1.0 - rtUniform.transmissiveOutputAlphaMin, f32(*depth)));
323
339
  (*path).alpha = max(outputAlpha, (*path).alpha);
324
340
  }
325
- if (!(*eV)) {
326
- vp = u32(max(*depth, 0));
327
- mx(si, ma, path);
341
+ if (!(*fg)) {
342
+ bounceIndex = u32(max(*depth, 0));
343
+ nB(si, ma, path);
328
344
  }
329
345
  else {
330
346
 
@@ -333,7 +349,7 @@ else {
333
349
  }
334
350
  }
335
351
 
336
- if (!(*si).albedoSampled && !(*eV)) {
352
+ if (!(*si).albedoSampled && !(*fg)) {
337
353
 
338
354
  if ((matType == STANDARD || matType == UNLIT)) {
339
355
  if (!((*ma).transmissionWeight > 0.5 ||
@@ -358,12 +374,12 @@ if (*depth > 4) {
358
374
 
359
375
 
360
376
  if (USE_RR) {
361
- if (*depth >= RR_MAX && !(*eV)) {
362
- let pl = (*path).beta;
377
+ if (*depth >= select(2, RR_MAX, (*path).scatteringMediumEntered) && !(*fg)) {
378
+ let qv = (*path).beta;
363
379
 
364
- let pc = max(max(pl.x, pl.y), pl.z);
365
- let q: f32 = max(0.0, 1.0 - pc);
366
- if (sample1D(bE(RUSSIAN_ROULETTE)) < q) {
380
+ let ql = max(max(qv.x, qv.y), qv.z);
381
+ let q: f32 = max(0.0, 1.0 - ql);
382
+ if (sample1D(aX(RUSSIAN_ROULETTE)) < q) {
367
383
 
368
384
 
369
385
  (*path).alpha = 1.0;
@@ -381,7 +397,7 @@ return;
381
397
 
382
398
  }
383
399
 
384
- fn jQ(path: ptr<function, Path>, depth: ptr<function, i32>, si: ptr<function, SurfaceInteraction>, ma: ptr<function, OpenPbrResolvedMaterial>, aJ: bool) {
400
+ fn gN(path: ptr<function, Path>, depth: ptr<function, i32>, si: ptr<function, SurfaceInteraction>, ma: ptr<function, OpenPbrResolvedMaterial>, sampleIgnored: bool) {
385
401
  if (SPECTRAL) {
386
402
 
387
403
  if ((*ma).transmissionWeight > 0.001) {
@@ -394,21 +410,21 @@ if ((*ma).transmissionWeight > 0.001) {
394
410
  }
395
411
  }
396
412
 
397
- if (aJ) {
413
+ if (sampleIgnored) {
398
414
  return;
399
415
  }
400
416
 
401
417
 
402
418
  var lightSample: LightSampleRec;
403
- let ht = ek(3u) < (*ma).alpha;
419
+ let hN = cm(3u) < (*ma).alpha;
404
420
  for (var i = 0; i < rtUniform.lightsCount; i++) {
405
421
 
406
422
  let light: Light = analyticLights[i];
407
- let d = mX((*path).ray, light, &lightSample);
423
+ let d = iB((*path).ray, light, &lightSample);
408
424
  lightSample.pdf *= light.selectionPmf;
409
- let lH = (*si).hit && d > distance((*si).position, (*path).ray.o);
410
- if (d != INF && !(lH && ht)) {
411
- let misWeight = fV((*path).scatteringPdf, lightSample.pdf);
425
+ let mz = (*si).hit && d > distance((*si).position, (*path).ray.o);
426
+ if (d != INF && !(mz && hN)) {
427
+ let misWeight = gm((*path).scatteringPdf, lightSample.pdf);
412
428
  if (SPECTRAL) {
413
429
  lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, (*si).spectralChannel);
414
430
  }
@@ -419,27 +435,27 @@ ${enabled || lightTracing || photonMapping ? 'if (!causticHitOwned(*path, true,
419
435
  }
420
436
 
421
437
  if (USE_ENVMAP) {
422
- if (!((*si).hit && ht)) {${lightTracing || photonMapping ? /* wgsl */ `
438
+ if (!((*si).hit && hN)) {${lightTracing || photonMapping ? /* wgsl */ `
423
439
  if(causticHitOwned(*path,false,true)){(*path).abort=true;return;}` : ''}
424
440
  if ((*path).isNextRefraction) {
425
441
 
426
442
 
427
443
 
428
- let bg = cP(
444
+ let bg = cS(
429
445
  (*path).ray,
430
446
  (*si).spectralChannel
431
447
  );
432
- let cM = select(fV((*path).scatteringPdf,
433
- envMapPdf(cT((*path).ray.d)) * rtUniform.envLightPmf),
448
+ let cP = select(gm((*path).scatteringPdf,
449
+ envMapPdf(cU((*path).ray.d)) * rtUniform.envLightPmf),
434
450
  1.0, (*path).scatteringIsDelta);
435
- (*path).li += cM * (*path).beta * bg.rgb * bg.a;
451
+ (*path).li += cP * (*path).beta * bg.rgb * bg.a;
436
452
  (*path).alpha = max((*path).alpha, bg.a);
437
453
  (*path).abort = true;
438
454
  return;
439
455
  }
440
- let _uv = cT((*path).ray.d);
456
+ let _uv = cU((*path).ray.d);
441
457
  var emission = textureLinear(envMap, _uv).rgb;
442
- let misWeight = fV(
458
+ let misWeight = gm(
443
459
  (*path).scatteringPdf,
444
460
  envMapPdf(_uv) * rtUniform.envLightPmf
445
461
  );
@@ -458,40 +474,52 @@ if (!USE_BACKGROUND) {
458
474
  *depth = *depth + 1;
459
475
  }
460
476
 
461
- fn eT(coord: vec2f) -> Ray {
477
+ ${options.cameraProjectionInverse ? /* wgsl */ `
478
+ fn cV(coord: vec2f) -> Ray {
479
+
480
+
481
+ let origin = cameraUniform.projectionInv * vec4f(coord * 2.0 - 1.0, -1.0, 1.0);
482
+ let center = cameraUniform.projectionInv * vec4f(coord * 2.0 - 1.0, 1.0, 1.0);
483
+ let direction = center.xyz * origin.w - origin.xyz * center.w;
484
+ var cam: Ray;
485
+ initRay(&cam, (cameraUniform.viewInv * vec4f(origin.xyz / origin.w, 1.0)).xyz,
486
+ normalize((cameraUniform.viewInv * vec4f(direction, 0.0)).xyz));
487
+ return cam;
488
+ }
489
+ ` : /* wgsl */ `fn cV(coord: vec2f) -> Ray {
462
490
  let origin = cameraUniform.viewProjectionInv * vec4f(coord * 2.0 - 1.0, -1.0, 1.0);
463
491
  let center = cameraUniform.viewProjectionInv * vec4f(coord * 2.0 - 1.0, 1.0, 1.0);
464
492
  var cam: Ray;
465
493
  initRay(&cam, origin.xyz / origin.w, normalize(center.xyz * origin.w - origin.xyz * center.w));
466
494
 
467
495
  return cam;
468
- }
496
+ }`}
469
497
 
470
498
 
471
- fn kK(radius: f32, xi: f32) -> vec2f {
499
+ fn lD(radius: f32, xi: f32) -> vec2f {
472
500
  var x = 0.25;
473
501
  for (var iteration = 0; iteration < 10; iteration++) {
474
502
  let x2 = x * x;
475
503
  let x3 = x2 * x;
476
- let la = 1.0 - x;
504
+ let lU = 1.0 - x;
477
505
  let value = 10.0 * x2 - 20.0 * x3 + 15.0 * x2 * x2 -
478
506
  4.0 * x2 * x3 - xi;
479
- let mJ = 20.0 * x * la * la * la;
480
- if (abs(value) < 1e-6 || mJ == 0.0) { break; }
481
- x = clamp(x - value / mJ, 0.0, 1.0);
507
+ let nL = 20.0 * x * lU * lU * lU;
508
+ if (abs(value) < 1e-6 || nL == 0.0) { break; }
509
+ x = clamp(x - value / nL, 0.0, 1.0);
482
510
  }
483
- let jr = x * radius;
484
- return vec2f(jr, sqrt(max(radius * radius - jr * jr, 0.0)));
511
+ let jW = x * radius;
512
+ return vec2f(jW, sqrt(max(radius * radius - jW * jW, 0.0)));
485
513
  }
486
514
 
487
- fn bevelCubicPdf(radius: f32, gu: f32) -> f32 {
488
- if (gu >= radius) { return 0.0; }
489
- let falloff = radius - gu;
515
+ fn bevelCubicPdf(radius: f32, gO: f32) -> f32 {
516
+ if (gO >= radius) { return 0.0; }
517
+ let falloff = radius - gO;
490
518
  return falloff * falloff * falloff;
491
519
  }
492
520
 
493
521
 
494
- fn mT(source: SurfaceInteraction, radius: f32) -> vec3f {
522
+ fn kB(source: SurfaceInteraction, radius: f32) -> vec3f {
495
523
  var geometricNormal = source.faceNormal;
496
524
  if (dot(geometricNormal, source.vertexNormal) < 0.0) {
497
525
  geometricNormal = -geometricNormal;
@@ -499,78 +527,78 @@ geometricNormal = -geometricNormal;
499
527
  var tangent: vec3f;
500
528
  var bitangent: vec3f;
501
529
  sampling_orthonormal_basis(geometricNormal, &tangent, &bitangent);
502
- var iE = vec3f(0.0);
503
-
504
- for (var ih = 0; ih < BEVEL_SAMPLES; ih++) {
505
- let qa = sample2D(CAMERA_BEVEL_BASE + u32(ih));
506
- var cr = qa.x;
507
- let pj = qa.y;
508
- var cZ = geometricNormal;
509
- var fI = tangent;
510
- var eh = bitangent;
511
- var ge = 0.5;
512
- var hW = 0.25;
513
- var gC = 0.25;
514
- if (cr < 0.5) {
515
- cr *= 2.0;
516
- }
517
- else if (cr < 0.75) {
518
- let nr = cZ;
519
- cZ = fI;
520
- fI = nr;
521
- ge = 0.25;
522
- hW = 0.5;
523
- cr = (cr - 0.5) * 4.0;
530
+ var jd = vec3f(0.0);
531
+
532
+ for (var iN = 0; iN < BEVEL_SAMPLES; iN++) {
533
+ let rh = sample2D(CAMERA_BEVEL_BASE + u32(iN));
534
+ var cu = rh.x;
535
+ let qt = rh.y;
536
+ var dc = geometricNormal;
537
+ var fU = tangent;
538
+ var eo = bitangent;
539
+ var gw = 0.5;
540
+ var iH = 0.25;
541
+ var gV = 0.25;
542
+ if (cu < 0.5) {
543
+ cu *= 2.0;
544
+ }
545
+ else if (cu < 0.75) {
546
+ let os = dc;
547
+ dc = fU;
548
+ fU = os;
549
+ gw = 0.25;
550
+ iH = 0.5;
551
+ cu = (cu - 0.5) * 4.0;
524
552
  }
525
553
  else {
526
- let nr = cZ;
527
- cZ = eh;
528
- eh = nr;
529
- ge = 0.25;
530
- gC = 0.5;
531
- cr = (cr - 0.75) * 4.0;
532
- }
533
-
534
- let gQ = kK(radius, pj);
535
- let phi = TWOPI * cr;
536
- let rr = gQ.x *
537
- (cos(phi) * fI + sin(phi) * eh);
554
+ let os = dc;
555
+ dc = eo;
556
+ eo = os;
557
+ gw = 0.25;
558
+ gV = 0.5;
559
+ cu = (cu - 0.75) * 4.0;
560
+ }
561
+
562
+ let hm = lD(radius, qt);
563
+ let phi = TWOPI * cu;
564
+ let sI = hm.x *
565
+ (cos(phi) * fU + sin(phi) * eo);
538
566
  var ray: Ray;
539
567
  initRay(
540
568
  &ray,
541
- source.position + cZ * gQ.y + rr,
542
- -cZ
569
+ source.position + dc * hm.y + sI,
570
+ -dc
543
571
  );
544
572
  var hit: SurfaceInteraction;
545
573
  intersectSceneBevel(
546
574
  ray,
547
575
  &hit,
548
576
  source.instanceIndex,
549
- max(2.0 * gQ.y, EPS)
577
+ max(2.0 * hm.y, EPS)
550
578
  );
551
579
  if (!hit.hit) { continue; }
552
580
 
553
- let lc = ge * abs(dot(cZ, hit.faceNormal));
554
- let nj = hW * abs(dot(fI, hit.faceNormal));
555
- let kj = gC * abs(dot(eh, hit.faceNormal));
556
- var weight = lc / max(
557
- lc * lc + nj * nj +
558
- kj * kj,
581
+ let lV = gw * abs(dot(dc, hit.faceNormal));
582
+ let oi = iH * abs(dot(fU, hit.faceNormal));
583
+ let kR = gV * abs(dot(eo, hit.faceNormal));
584
+ var weight = lV / max(
585
+ lV * lV + oi * oi +
586
+ kR * kR,
559
587
  1e-8
560
588
  );
561
589
  weight *= bevelCubicPdf(radius, distance(hit.position, source.position)) /
562
- max(bevelCubicPdf(radius, gQ.x), 1e-8);
563
- iE += weight * hit.vertexNormal;
590
+ max(bevelCubicPdf(radius, hm.x), 1e-8);
591
+ jd += weight * hit.vertexNormal;
564
592
  }
565
593
 
566
- if (dot(iE, iE) <= 1e-12) { return source.normal; }
567
- let jM = normalize(iE);
568
- let result = source.normal + jM - source.vertexNormal;
594
+ if (dot(jd, jd) <= 1e-12) { return source.normal; }
595
+ let kt = normalize(jd);
596
+ let result = source.normal + kt - source.vertexNormal;
569
597
  if (dot(result, result) > 1e-12) { return normalize(result); }
570
598
  return source.normal;
571
599
  }
572
600
 
573
- fn cG(uv: vec2f, si: ptr<function, SurfaceInteraction>, ray: Ray, ma: ptr<function, OpenPbrResolvedMaterial>, outAux: ptr<function, RayTraceAuxiliary>, sc: bool) -> vec4f {
601
+ ${sharePrefix ? spectralPrefixWgsl(!enabled) + prefixCheckpoint('spSurface', surfacePrefix) + prefixCheckpoint('spFlat', flatPrefix) : ''}fn cJ(uv: vec2f, si: ptr<function, SurfaceInteraction>, ray: Ray, ma: ptr<function, OpenPbrResolvedMaterial>, outAux: ptr<function, RayTraceAuxiliary>, initialQuery: bool) -> vec4f {
574
602
  var path: Path;
575
603
  path.ray = ray;
576
604
  path.li = vec3f(0.0);
@@ -583,112 +611,124 @@ path.isNextRefraction = false;
583
611
  path.abort = false;
584
612
 
585
613
  let bounceLimit = max(rtUniform.bounces, 0);
586
- let eZ = min(bounceLimit * 3, ${MAX_PATH_EVENTS});
614
+ let fj = min(bounceLimit * 3, ${maxPathEvents});
587
615
  var depth = 0;
588
- var aJ = false;
589
- var bH = false;
590
-
616
+ var sampleIgnored = false;
617
+ var isNotTransparent = false;
618
+ ${sharePrefix ? /* wgsl */ ` let spSlot = qz; qz++;
619
+ if (spActive && spChannel > 1 && eB[spSlot].ready) { return rN(spSlot, outAux); }
620
+ var spEvent = 0; var spResume = false;
621
+ if (spActive && spChannel > 1 && fC == spSlot) {
622
+ var event = 0;
623
+ ${prefixRestore('spSurface', surfacePrefix)}
624
+ spEvent = event; spResume = true; qA(&path, si);
625
+ } else if (sd) { (*si).spectralChannel = select(spChannel, 0, spActive); (*si).wavelength = lg; }
626
+ ` : ''}
591
627
 
592
628
 
593
629
 
594
- for (var event = 0; event <= eZ; event++) {
595
- if ((event != 0) | sc) {
630
+ for (var event = ${sharePrefix ? 'spEvent' : '0'}; event <= fj; event++) {
631
+ if (${sharePrefix ? '!spResume && ((event != 0) | initialQuery)' : '(event != 0) | initialQuery'}) {
596
632
  intersectScene(path.ray, si, depth, event != 0, path.isNextRefraction);
597
633
  getMaterial(ma, (*si).materialIndex, (*si).uv, (*si).uv1, (*si).instanceIndex, (*si).vertexColor);
598
634
  }
599
635
  if (event == 0) {
600
- if (sc & (*si).hit & ((*ma).materialType == STANDARD)) {
636
+ if (initialQuery & (*si).hit & ((*ma).materialType == STANDARD)) {
601
637
  (*outAux).albedo = select((*ma).baseColor, vec3f(1.0), (*ma).transmissionWeight > 0.5);
602
638
  (*outAux).normal = select((*si).normal, -(*si).normal,
603
639
  dot((*si).normal, (*si).position - cameraUniform.viewInv[3].xyz) > 0.0);
604
640
  (*si).albedoSampled = (*ma).transmissionWeight > 0.5;
605
641
  }
606
- bH = ((*ma).transmissionWeight < 0.001) & ((*ma).subsurfaceWeight < 0.001) & ((*ma).alpha > 0.99);
607
- } else {
608
- jQ(&path, &depth, si, ma, aJ);
609
- }
610
- if (bH & (event > bounceLimit)) { path.abort = true; }
611
- if (path.abort | (event >= eZ)) { break; }
612
- nO(uv, &path, &depth, si, ma, outAux, &aJ);
642
+ isNotTransparent = ((*ma).transmissionWeight < 0.001) & ((*ma).subsurfaceWeight < 0.001) & ((*ma).alpha > 0.99);
643
+ } else {${sharePrefix ? /* wgsl */ `
644
+ if (spActive && (*ma).transmissionWeight > 0.001 && gf(*ma)) {
645
+ ${prefixSave('spSurface', surfacePrefix)}
646
+ fC = spSlot; qA(&path, si);
647
+ }` : ''}
648
+ gN(&path, &depth, si, ma, sampleIgnored);
649
+ }
650
+ ${sharePrefix ? ' spResume = false;\n' : ''} if (isNotTransparent & (event > bounceLimit)) { path.abort = true; }
651
+ if (path.abort | (event >= fj)) { break; }
652
+ mD(uv, &path, &depth, si, ma, outAux, &sampleIgnored);
613
653
  if (path.abort) { break; }
614
654
  }
615
655
 
616
- return vec4f(path.li, path.alpha);
656
+ return ${sharePrefix ? 'spFinish(spSlot, vec4f(path.li, path.alpha), *outAux)' : 'vec4f(path.li, path.alpha)'};
617
657
  }
618
658
 
619
- fn iC(uv: vec2f, si: ptr<function, SurfaceInteraction>, ray: Ray, ma: ptr<function, OpenPbrResolvedMaterial>, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
659
+ fn jb(uv: vec2f, si: ptr<function, SurfaceInteraction>, ray: Ray, ma: ptr<function, OpenPbrResolvedMaterial>, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
620
660
  ${deterministicPrimaryAlpha ? /* wgsl */ `let coverage = clamp((*ma).alpha, 0.0, 1.0);
621
661
 
622
662
 
623
663
 
624
664
 
625
665
  let split = (*si).hit & (((*ma).materialType == STANDARD) | ((*ma).materialType == UNLIT)) & (coverage < 1.0);
626
- var st = ray;
627
- var tr = *si;
628
- var tq = *ma;
629
- var iw = *outAux;
666
+ var tT = ray;
667
+ var uW = *si;
668
+ var uV = *ma;
669
+ var iX = *outAux;
630
670
  if (split) {
631
- st.o = (*si).position + ray.d * (EPS * 0.02);
632
- tr.albedoSampled = false;
671
+ tT.o = (*si).position + ray.d * (EPS * 0.02);
672
+ uW.albedoSampled = false;
633
673
  }
634
674
  var back: vec4f;
635
- var eg: RayTraceAuxiliary;
675
+ var backAux: RayTraceAuxiliary;
636
676
 
637
677
 
638
- let vq = select(1u, rtUniform.loopUnrollGuard >> 1u, split & (coverage > 0.0));
639
- for (var uM = 0u; uM < vq; uM++) {
640
- let result = cG(uv, &tr, st, &tq, &iw, split & (uM == 0u));
641
- if (!split | (coverage <= 0.0)) { *outAux = iw; return result; }
642
- if (uM == 0u) {
643
- back = result; eg = iw;
644
- tr = *si; tq = *ma; tq.alpha = 1.0;
645
- st = ray; iw = *outAux;
678
+ let xh = select(1u, rtUniform.loopUnrollGuard >> 1u, split & (coverage > 0.0));
679
+ for (var wv = 0u; wv < xh; wv++) {
680
+ let result = cJ(uv, &uW, tT, &uV, &iX, split & (wv == 0u));
681
+ if (!split | (coverage <= 0.0)) { *outAux = iX; return result; }
682
+ if (wv == 0u) {
683
+ back = result; backAux = iX;
684
+ uW = *si; uV = *ma; uV.alpha = 1.0;
685
+ tT = ray; iX = *outAux;
646
686
  } else {
647
- (*outAux).albedo = mix(eg.albedo, iw.albedo, coverage);
648
- let cS = mix(eg.normal, iw.normal, coverage);
649
- (*outAux).normal = select(vec3f(0.0), normalize(cS), dot(cS, cS) > 1e-12);
650
- (*outAux).isBlank = eg.isBlank & iw.isBlank;
651
- (*outAux).isShadowCatcher = eg.isShadowCatcher & iw.isShadowCatcher;
652
- (*outAux).shadowCounts = mix(eg.shadowCounts, iw.shadowCounts, coverage);
687
+ (*outAux).albedo = mix(backAux.albedo, iX.albedo, coverage);
688
+ let aS = mix(backAux.normal, iX.normal, coverage);
689
+ (*outAux).normal = select(vec3f(0.0), normalize(aS), dot(aS, aS) > 1e-12);
690
+ (*outAux).isBlank = backAux.isBlank & iX.isBlank;
691
+ (*outAux).isShadowCatcher = backAux.isShadowCatcher & iX.isShadowCatcher;
692
+ (*outAux).shadowCounts = mix(backAux.shadowCounts, iX.shadowCounts, coverage);
653
693
  return mix(back, result, coverage);
654
694
  }
655
695
  }
656
- return vec4f(0.0);` : /* wgsl */ `return cG(uv, si, ray, ma, outAux, false);`}
696
+ return vec4f(0.0);` : /* wgsl */ `return cJ(uv, si, ray, ma, outAux, false);`}
657
697
  }
658
698
 
659
699
 
660
700
 
661
- ${spectral === false && deterministicPrimaryAlpha ? /* wgsl */ `fn hR(uv: vec2f, ray: Ray, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
701
+ ${spectral === false && deterministicPrimaryAlpha ? /* wgsl */ `fn hq(uv: vec2f, ray: Ray, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
662
702
  ${primaryVariables}
663
- var oy: SurfaceInteraction;
664
- var ox: OpenPbrResolvedMaterial;
665
- var uh: RayTraceAuxiliary;
666
- var iH = false;
703
+ var primarySi: SurfaceInteraction;
704
+ var primaryMa: OpenPbrResolvedMaterial;
705
+ var vR: RayTraceAuxiliary;
706
+ var jg = false;
667
707
  var query = true;
668
708
  var split = false;
669
709
  var coverage = 1.0;
670
710
  var front = false;
671
711
  var back: vec4f;
672
- var eg: RayTraceAuxiliary;
712
+ var backAux: RayTraceAuxiliary;
673
713
  var path: Path; path.ray = ray;
674
714
  path.alpha = select(1.0, 0.0, rtUniform.transmissiveOutputAlphaMin < 1.0);
675
715
  path.beta = vec3f(1.0); path.fromEye = true;
676
716
  let bounceLimit = max(rtUniform.bounces, 0);
677
- let eZ = min(bounceLimit * 3, ${MAX_PATH_EVENTS});
678
- var event = 0; var depth = 0; var aJ = false;
679
- var bH = false;
717
+ let fj = min(bounceLimit * 3, ${maxPathEvents});
718
+ var event = 0; var depth = 0; var sampleIgnored = false;
719
+ var isNotTransparent = false;
680
720
 
681
721
 
682
- for (var step = 0; step < (${MAX_PATH_EVENTS} + 1) * 2 + 2; step++) {
722
+ for (var step = 0; step < (${maxPathEvents} + 1) * 2 + 2; step++) {
683
723
  if (query) {
684
724
  intersectScene(path.ray, &si, depth, event != 0, path.isNextRefraction);
685
725
  getMaterial(&ma, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);
686
726
  }
687
727
  query = true;
688
- if (!iH) {
728
+ if (!jg) {
689
729
  ${primaryGuides}
690
- oy = si; ox = ma; uh = *outAux;
691
- iH = true;
730
+ primarySi = si; primaryMa = ma; vR = *outAux;
731
+ jg = true;
692
732
  coverage = clamp(ma.alpha, 0.0, 1.0);
693
733
  split = si.hit & ((ma.materialType == STANDARD) | (ma.materialType == UNLIT)) & (coverage < 1.0);
694
734
  if (split) {
@@ -705,36 +745,36 @@ si.albedoSampled = ma.transmissionWeight > 0.5;
705
745
  }
706
746
  }
707
747
  if (event == 0) {
708
- bH = (ma.transmissionWeight < 0.001) & (ma.subsurfaceWeight < 0.001) & (ma.alpha > 0.99);
748
+ isNotTransparent = (ma.transmissionWeight < 0.001) & (ma.subsurfaceWeight < 0.001) & (ma.alpha > 0.99);
709
749
  } else {
710
- jQ(&path, &depth, &si, &ma, aJ);
750
+ gN(&path, &depth, &si, &ma, sampleIgnored);
711
751
  }
712
- if (bH & (event > bounceLimit)) { path.abort = true; }
713
- if (!path.abort & (event < eZ)) {
714
- nO(uv, &path, &depth, &si, &ma, outAux, &aJ);
752
+ if (isNotTransparent & (event > bounceLimit)) { path.abort = true; }
753
+ if (!path.abort & (event < fj)) {
754
+ mD(uv, &path, &depth, &si, &ma, outAux, &sampleIgnored);
715
755
  }
716
- if (path.abort | (event >= eZ)) {
756
+ if (path.abort | (event >= fj)) {
717
757
  let result = vec4f(path.li, path.alpha);
718
758
  if (!split | (coverage <= 0.0)) { return result; }
719
759
  if (front) {
720
- (*outAux).albedo = mix(eg.albedo, (*outAux).albedo, coverage);
721
- let cS = mix(eg.normal, (*outAux).normal, coverage);
722
- (*outAux).normal = select(vec3f(0.0), normalize(cS), dot(cS, cS) > 1e-12);
723
- (*outAux).isBlank = eg.isBlank & (*outAux).isBlank;
724
- (*outAux).isShadowCatcher = eg.isShadowCatcher & (*outAux).isShadowCatcher;
725
- (*outAux).shadowCounts = mix(eg.shadowCounts, (*outAux).shadowCounts, coverage);
760
+ (*outAux).albedo = mix(backAux.albedo, (*outAux).albedo, coverage);
761
+ let aS = mix(backAux.normal, (*outAux).normal, coverage);
762
+ (*outAux).normal = select(vec3f(0.0), normalize(aS), dot(aS, aS) > 1e-12);
763
+ (*outAux).isBlank = backAux.isBlank & (*outAux).isBlank;
764
+ (*outAux).isShadowCatcher = backAux.isShadowCatcher & (*outAux).isShadowCatcher;
765
+ (*outAux).shadowCounts = mix(backAux.shadowCounts, (*outAux).shadowCounts, coverage);
726
766
  return mix(back, result, coverage);
727
767
  }
728
- back = result; eg = *outAux;
729
- front = true; query = false; event = 0; depth = 0; aJ = false;
730
- si = oy; ma = ox; ma.alpha = 1.0; *outAux = uh;
768
+ back = result; backAux = *outAux;
769
+ front = true; query = false; event = 0; depth = 0; sampleIgnored = false;
770
+ si = primarySi; ma = primaryMa; ma.alpha = 1.0; *outAux = vR;
731
771
  path = Path(); path.ray = ray; path.beta = vec3f(1.0); path.fromEye = true;
732
772
  path.alpha = select(1.0, 0.0, rtUniform.transmissiveOutputAlphaMin < 1.0);
733
773
  } else { event++; }
734
774
  }
735
775
  return vec4f(0.0);
736
776
  }
737
- ` : spectral === false && !deterministicPrimaryAlpha ? /* wgsl */ `fn hR(uv: vec2f, ray: Ray, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
777
+ ` : spectral === false && !deterministicPrimaryAlpha ? /* wgsl */ `fn hq(uv: vec2f, ray: Ray, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
738
778
  ${primaryVariables}
739
779
  var path: Path;
740
780
  path.ray = ray;
@@ -742,113 +782,133 @@ path.alpha = select(1.0, 0.0, rtUniform.transmissiveOutputAlphaMin < 1.0);
742
782
  path.beta = vec3f(1.0);
743
783
  path.fromEye = true;
744
784
  let bounceLimit = max(rtUniform.bounces, 0);
745
- let eZ = min(bounceLimit * 3, ${MAX_PATH_EVENTS});
746
- var bH = false;
785
+ let fj = min(bounceLimit * 3, ${maxPathEvents});
786
+ var isNotTransparent = false;
747
787
  var depth = 0;
748
- var aJ = false;
788
+ var sampleIgnored = false;
749
789
 
750
790
 
751
791
 
752
- for (var event = 0; event <= eZ; event++) {
792
+ for (var event = 0; event <= fj; event++) {
753
793
  intersectScene(path.ray, &si, depth, event != 0, path.isNextRefraction);
754
794
  getMaterial(&ma, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);
755
795
  if (event == 0) {
756
796
  ${primaryGuides}
757
- bH = ma.transmissionWeight < 0.001 && ma.subsurfaceWeight < 0.001 && ma.alpha > 0.99;
797
+ isNotTransparent = ma.transmissionWeight < 0.001 && ma.subsurfaceWeight < 0.001 && ma.alpha > 0.99;
758
798
  } else {
759
- jQ(&path, &depth, &si, &ma, aJ);
799
+ gN(&path, &depth, &si, &ma, sampleIgnored);
760
800
  }
761
- if (bH && event > bounceLimit) { path.abort = true; }
762
- if (path.abort || event >= eZ) { break; }
763
- nO(uv, &path, &depth, &si, &ma, outAux, &aJ);
801
+ if (isNotTransparent && event > bounceLimit) { path.abort = true; }
802
+ if (path.abort || event >= fj) { break; }
803
+ mD(uv, &path, &depth, &si, &ma, outAux, &sampleIgnored);
764
804
  if (path.abort) { break; }
765
805
  }
766
806
  return vec4f(path.li, path.alpha);
767
807
  }
768
808
  ` : spectral === true && !deterministicPrimaryAlpha ? /* wgsl */ `
769
- fn hR(uv: vec2f, ray: Ray, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
809
+ fn hq(uv: vec2f, ray: Ray, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
770
810
  ${primaryVariables}
771
- var oy: SurfaceInteraction;
772
- var ox: OpenPbrResolvedMaterial;
773
- var iH = false;
811
+ var primarySi: SurfaceInteraction;
812
+ var primaryMa: OpenPbrResolvedMaterial;
813
+ var jg = false;
774
814
  var path: Path; path.ray = ray;
775
815
  let bounceLimit = max(rtUniform.bounces, 0);
776
- let eZ = min(bounceLimit * 3, ${MAX_PATH_EVENTS});
777
- var depth = 0; var event = 0; var aJ = false;
778
- var bH = false;
779
- var mc = 0;
780
- let bi = rtUniform.dispersionWavelengths == 1;
781
- var ew = false;
782
- var eG = 0;
783
- var aZ = 0.0;
784
- var he: vec4u;
785
- var ey = 0u;
786
- var aU: RayTraceAuxiliary;
816
+ let fj = min(bounceLimit * 3, ${maxPathEvents});
817
+ var depth = 0; var event = 0; var sampleIgnored = false;
818
+ var isNotTransparent = false;
819
+ var jR = 0;
820
+ let bj = rtUniform.dispersionWavelengths == 1;
821
+ var eG = false;
822
+ var eQ = 0;
823
+ var aE = 0.0;
824
+ var wavelengthRngState: vec4u;
825
+ var eH = 0u;
826
+ var wavelengthAux: RayTraceAuxiliary;
787
827
  var color = vec3f(0.0); var alpha = 0.0;
788
- var dw = vec3f(0.0);
789
- var dz = vec3f(0.0);
790
- var mz = true;
828
+ var dD = vec3f(0.0);
829
+ var dE = vec3f(0.0);
830
+ var ik = true;
791
831
 
792
832
 
793
833
 
794
- let xf = min((${MAX_PATH_EVENTS} + 1) * 3, i32(rtUniform.loopUnrollGuard * ${Math.ceil((MAX_PATH_EVENTS + 1) * 3 / 4)}u));
795
- for (var step = 0; step < xf; step++) {
796
- if (!iH | ((event != 0) & !path.abort)) {
834
+ let zh = min((${maxPathEvents} + 1) * 3, i32(rtUniform.loopUnrollGuard * ${Math.ceil((maxPathEvents + 1) * 3 / 4)}u));
835
+ for (var step = 0; step < zh; step++) {
836
+ if (!jg | ((event != 0) & !path.abort)) {
797
837
  intersectScene(path.ray, &si, depth, event != 0, path.isNextRefraction);
798
838
  getMaterial(&ma, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);
799
839
  }
800
840
  if (event == 0) {
801
- if (!iH) {
841
+ if (!jg) {
802
842
  ${primaryGuides}
803
- oy = si; ox = ma; iH = true;
804
- ew = si.hit & (ma.transmissionWeight > 0.001) & (ma.transmissionDispersionScale > 0.001);
805
- aZ = sample1D(CAMERA_WAVELENGTH);
806
- if (bi) {
807
- eG = min(i32(floor(aZ * 3.0)), 2);
808
- aZ = fract(aZ * 3.0);
843
+ primarySi = si; primaryMa = ma; jg = true;
844
+ eG = si.hit & (ma.transmissionWeight > 0.001) & (ma.transmissionDispersionScale > 0.001);
845
+ aE = sample1D(CAMERA_WAVELENGTH);
846
+ if (bj) {
847
+ eQ = min(i32(floor(aE * 3.0)), 2);
848
+ aE = fract(aE * 3.0);
809
849
  }
810
- he = s0; ey = ca;
850
+ wavelengthRngState = s0; eH = hashedCounter;
811
851
  }
812
- si = oy; ma = ox; aU = *outAux;
813
- if (!bi) {
814
- s0 = he; ca = ey; samplingBounce = 0u;
815
- aU.isBlank = false; aU.isShadowCatcher = false;
852
+ si = primarySi; ma = primaryMa; wavelengthAux = *outAux;
853
+ if (!bj) {
854
+ s0 = wavelengthRngState; hashedCounter = eH; samplingBounce = 0u;
855
+ wavelengthAux.isBlank = false; wavelengthAux.isShadowCatcher = false;
816
856
  }
817
857
  si.wavelength = 0.0; si.spectralChannel = 0;
818
- if (!bi | ew) {
819
- let channel = select(mc, eG, bi);
858
+ if (!bj | eG) {
859
+ let channel = select(jR, eQ, bj);
820
860
  si.spectralChannel = channel + 1;
821
- si.wavelength = cU(u32(channel), aZ);
822
- ma.specularIor = sampling_cauchy_ior(si.wavelength, ma.specularIor,
861
+ si.wavelength = ce(u32(channel), aE);
862
+ ${sharePrefix ? /* wgsl */ ` wY(channel + 1, si.wavelength, gf(ma));
863
+ if (spActive) { si.spectralChannel = 0; }
864
+ ` : ''} ma.specularIor = sampling_cauchy_ior(si.wavelength, ma.specularIor,
823
865
  ma.transmissionDispersionScale, ma.dispersionAbbeNumber);
824
866
  }
825
867
  path = Path(); path.ray = ray; path.beta = vec3f(1.0); path.fromEye = true;
826
868
  path.alpha = select(1.0, 0.0, rtUniform.transmissiveOutputAlphaMin < 1.0);
827
- depth = 0; aJ = false;
828
- bH = (ma.transmissionWeight < 0.001) & (ma.subsurfaceWeight < 0.001) & (ma.alpha > 0.99);
829
- } else if (!path.abort) {
830
- jQ(&path, &depth, &si, &ma, aJ);
831
- }
832
- if (bH & (event > bounceLimit)) { path.abort = true; }
833
- if (!path.abort & (event < eZ)) {
834
- nO(uv, &path, &depth, &si, &ma, &aU, &aJ);
835
- }
836
- if (path.abort | (event >= eZ)) {
869
+ depth = 0; sampleIgnored = false;
870
+ isNotTransparent = (ma.transmissionWeight < 0.001) & (ma.subsurfaceWeight < 0.001) & (ma.alpha > 0.99);
871
+ ${sharePrefix ? /* wgsl */ ` if (spActive && jR > 0 && fC == 0) {
872
+ ${prefixRestore('spFlat', flatPrefix)}
873
+ qA(&path, &si);
874
+ }
875
+ }
876
+ if (event > 0 && !path.abort) {
877
+ if (spActive && ma.transmissionWeight > 0.001 && gf(ma)) {
878
+ ${prefixSave('spFlat', flatPrefix)}
879
+ fC = 0; qA(&path, &si);
880
+ }
881
+ gN(&path, &depth, &si, &ma, sampleIgnored);
882
+ }` : /* wgsl */ ` } else if (!path.abort) {
883
+ gN(&path, &depth, &si, &ma, sampleIgnored);
884
+ }`}
885
+ if (isNotTransparent & (event > bounceLimit)) { path.abort = true; }
886
+ if (!path.abort & (event < fj)) {
887
+ mD(uv, &path, &depth, &si, &ma, &wavelengthAux, &sampleIgnored);
888
+ }
889
+ if (path.abort | (event >= fj)) {
837
890
  let result = vec4f(path.li, path.alpha);
838
- if (bi) {
839
- *outAux = aU;
840
- let scale = select(1.0, 3.0, ew);
891
+ if (bj) {
892
+ *outAux = wavelengthAux;
893
+ let scale = select(1.0, 3.0, eG);
841
894
  return vec4f(result.rgb * scale, result.a);
842
895
  }
843
- color += result.rgb; alpha = max(alpha, result.a);
844
- dw += aU.albedo;
845
- dz += aU.normal;
846
- mz = mz & aU.isBlank;
847
- mc++;
848
- if (mc >= 3) {
849
- (*outAux).albedo = dw / 3.0;
850
- (*outAux).normal = dz / 3.0;
851
- (*outAux).isBlank = mz;
896
+ ${sharePrefix ? /* wgsl */ ` if (spActive) {
897
+ (*outAux).isBlank = wavelengthAux.isBlank;
898
+
899
+ (*outAux).albedo = (wavelengthAux.albedo + wavelengthAux.albedo + wavelengthAux.albedo) / 3.0;
900
+ (*outAux).normal = (wavelengthAux.normal + wavelengthAux.normal + wavelengthAux.normal) / 3.0;
901
+ return result;
902
+ }
903
+ ` : ''} color += result.rgb; alpha = max(alpha, result.a);
904
+ dD += wavelengthAux.albedo;
905
+ dE += wavelengthAux.normal;
906
+ ik = ik & wavelengthAux.isBlank;
907
+ jR++;
908
+ if (jR >= 3) {
909
+ (*outAux).albedo = dD / 3.0;
910
+ (*outAux).normal = dE / 3.0;
911
+ (*outAux).isBlank = ik;
852
912
  return vec4f(color, alpha);
853
913
  }
854
914
  event = 0;
@@ -856,7 +916,7 @@ event = 0;
856
916
  }
857
917
  return vec4f(0.0);
858
918
  }
859
- ` : /* wgsl */ `fn hR(uv: vec2f, ray: Ray, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
919
+ ` : /* wgsl */ `fn hq(uv: vec2f, ray: Ray, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
860
920
  ${primaryVariables}
861
921
  intersectScene(ray, &si, 0, false, false);
862
922
  getMaterial(&ma, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);
@@ -866,85 +926,87 @@ if (SPECTRAL) {
866
926
 
867
927
 
868
928
 
869
- var vu = vec3f(0.0);
929
+ var xl = vec3f(0.0);
870
930
  var alpha = 0.0;
871
- var dw = vec3f(0.0);
872
- var dz = vec3f(0.0);
873
- var mz = true;
931
+ var dD = vec3f(0.0);
932
+ var dE = vec3f(0.0);
933
+ var ik = true;
874
934
  var si2 = si;
875
935
  var ma2 = ma;
876
- var aZ = sample1D(CAMERA_WAVELENGTH);
877
- let he = s0;
878
- let ey = ca;
879
- let bi = rtUniform.dispersionWavelengths == 1;
880
- let ew = si.hit &&
936
+ var aE = sample1D(CAMERA_WAVELENGTH);
937
+ let wavelengthRngState = s0;
938
+ let eH = hashedCounter;
939
+ let bj = rtUniform.dispersionWavelengths == 1;
940
+ let eG = si.hit &&
881
941
  ma.transmissionWeight > 0.001 &&
882
942
  ma.transmissionDispersionScale > 0.001;
883
- let tm = select(3, 1, bi);
884
- var eG = 0;
885
- if (bi) {
943
+ let uR = select(3, 1, bj);
944
+ var eQ = 0;
945
+ if (bj) {
886
946
 
887
947
 
888
- eG = min(i32(floor(aZ * 3.0)), 2);
889
- aZ = fract(aZ * 3.0);
948
+ eQ = min(i32(floor(aE * 3.0)), 2);
949
+ aE = fract(aE * 3.0);
890
950
  }
891
- for (var i = 0; i < tm; i++) {
951
+ for (var i = 0; i < uR; i++) {
892
952
 
893
953
 
894
954
 
895
- if (!bi) {
896
- s0 = he;
897
- ca = ey;
955
+ if (!bj) {
956
+ s0 = wavelengthRngState;
957
+ hashedCounter = eH;
898
958
  samplingBounce = 0u;
899
959
  }
900
960
  si.wavelength = 0.0;
901
961
  si.spectralChannel = 0;
902
- if (!bi || ew) {
903
- let channel = select(i, eG, bi);
962
+ if (!bj || eG) {
963
+ let channel = select(i, eQ, bj);
904
964
  si.spectralChannel = channel + 1;
905
- si.wavelength = cU(u32(channel), aZ);
906
- ma.specularIor = sampling_cauchy_ior(
965
+ si.wavelength = ce(u32(channel), aE);
966
+ ${sharePrefix ? /* wgsl */ ` wY(channel + 1, si.wavelength, gf(ma));
967
+ if (spActive) { si.spectralChannel = 0; }
968
+ ` : ''} ma.specularIor = sampling_cauchy_ior(
907
969
  si.wavelength,
908
970
  ma.specularIor,
909
971
  ma.transmissionDispersionScale,
910
972
  ma.dispersionAbbeNumber
911
973
  );
912
974
  }
913
- var aU: RayTraceAuxiliary;
914
- if (bi) {
915
- aU = *outAux;
975
+ var wavelengthAux: RayTraceAuxiliary;
976
+ if (bj) {
977
+ wavelengthAux = *outAux;
916
978
  } else {
917
- aU.albedo = (*outAux).albedo;
918
- aU.normal = (*outAux).normal;
919
- aU.isBlank = false;
920
- aU.isShadowCatcher = false;
921
- }
922
- let res = iC(uv, &si, ray, &ma, &aU);
923
- if (bi) {
924
- *outAux = aU;
925
- let scale = select(1.0, 3.0, ew);
979
+ wavelengthAux.albedo = (*outAux).albedo;
980
+ wavelengthAux.normal = (*outAux).normal;
981
+ wavelengthAux.isBlank = false;
982
+ wavelengthAux.isShadowCatcher = false;
983
+ }
984
+ let res = jb(uv, &si, ray, &ma, &wavelengthAux);
985
+ if (bj) {
986
+ *outAux = wavelengthAux;
987
+ let scale = select(1.0, 3.0, eG);
926
988
  return vec4f(res.rgb * scale, res.a);
927
989
  }
928
- vu += res.rgb;
990
+ xl += res.rgb;
929
991
  alpha = max(alpha, res.a);
930
- dw += aU.albedo;
931
- dz += aU.normal;
932
- mz = mz && aU.isBlank;
992
+ dD += wavelengthAux.albedo;
993
+ dE += wavelengthAux.normal;
994
+ ik = ik && wavelengthAux.isBlank;
933
995
  si = si2;
934
996
  ma = ma2;
935
997
  }
936
- (*outAux).albedo = dw / 3.0;
937
- (*outAux).normal = dz / 3.0;
938
- (*outAux).isBlank = mz;
939
- return vec4f(vu, alpha);
998
+ (*outAux).albedo = dD / 3.0;
999
+ (*outAux).normal = dE / 3.0;
1000
+ (*outAux).isBlank = ik;
1001
+ return vec4f(xl, alpha);
940
1002
  }
941
1003
  else {
942
- return iC(uv, &si, ray, &ma, outAux);
1004
+ return jb(uv, &si, ray, &ma, outAux);
943
1005
  }
944
1006
  }
945
1007
  `}
946
1008
 
947
- fn kq(ip: vec2f) -> vec2f {
1009
+ fn kX(ip: vec2f) -> vec2f {
948
1010
  let p = 2.0 * ip - 1.0;
949
1011
  let greater = abs(p.x) > abs(p.y);
950
1012
  let r = select(p.y, p.x, greater);
@@ -983,23 +1045,23 @@ return;
983
1045
 
984
1046
  let uv = (vec2<f32>(f32(coord.x), f32(coord.y)) + vec2f(0.5)) / outputSize;
985
1047
 
986
- aI = coord;
1048
+ aJ = coord;
987
1049
  aC = u32(outNormal[idx].a) + rtUniform.sampleSequenceOffset;
988
- samplingBounce = 0u; ca = 0u;
1050
+ samplingBounce = 0u; hashedCounter = 0u;
989
1051
  if (${inputHooks?.uniformJitter ? 'false' : 'SAMPLING_PATTERN == 0 || SAMPLING_PATTERN == 1'}) {
990
1052
  jitter = (sample2D(CAMERA_PIXEL) - 0.5) / outputSize;
991
1053
  }
992
- fi(coord, i32(aC ^ cB(rtUniform.sequenceSeed)));
993
- var cam = eT(uv + jitter);
1054
+ fA(coord, i32(aC ^ cD(rtUniform.sequenceSeed)));
1055
+ var cam = cV(uv + jitter);
994
1056
 
995
1057
  if (cameraUniform.apertureRadius > 0.0) {
996
1058
 
997
1059
  let eye = cameraUniform.viewInv[3].xyz;
998
1060
  let forward = -normalize(cameraUniform.viewInv[2].xyz);
999
- let ju = eye + cam.d * (cameraUniform.focusDistance / dot(cam.d, forward));
1000
- let sH = cameraUniform.apertureRadius * kq(sample2D(CAMERA_LENS));
1001
- let origin = (cameraUniform.viewInv * vec4f(sH, 0.0, 1.0)).xyz;
1002
- let dir = normalize(ju - origin);
1061
+ let jY = eye + cam.d * (cameraUniform.focusDistance / dot(cam.d, forward));
1062
+ let uh = cameraUniform.apertureRadius * kX(sample2D(CAMERA_LENS));
1063
+ let origin = (cameraUniform.viewInv * vec4f(uh, 0.0, 1.0)).xyz;
1064
+ let dir = normalize(jY - origin);
1003
1065
  initRay(&cam, origin, dir);
1004
1066
  }
1005
1067
 
@@ -1008,7 +1070,7 @@ outAux.albedo = vec3f(0.0);
1008
1070
  outAux.normal = vec3f(0.0);
1009
1071
  outAux.isBlank = false;
1010
1072
  outAux.isShadowCatcher = false;
1011
- ${pathDiagnostic ? ' mtPathBegin(coord);\n' : ''}${inputHooks?.begin ?? ''} var liAndAlpha = hR(uv + jitter, cam, &outAux);
1073
+ ${pathDiagnostic ? ' mtPathBegin(coord);\n' : ''}${inputHooks?.begin ?? ''} var liAndAlpha = hq(uv + jitter, cam, &outAux);
1012
1074
  ${inputHooks?.unclampedColor ?? ''}
1013
1075
  ${(enabled || lightTracing || photonMapping) && debugGroup >= 0 ? /* wgsl */ ` liAndAlpha=${debugGroup >= 50 ? `vec4f(photonQueryStats,1.0)` : debugGroup >= 30 ? `vec4f(causticHot[${debugGroup - 30}],1.0)` : research?.debugOutput ?? 'liAndAlpha'};
1014
1076
  ` : ''}
@@ -1024,23 +1086,23 @@ liAndAlpha = vec4f(0.0, 0.0, 0.0, 1.0);
1024
1086
  if (outAux.isShadowCatcher) {
1025
1087
 
1026
1088
 
1027
- let aW = ft(cam);
1028
- let qX = select(0.0, 1.0, aW.a >= 0.01);
1029
- let jC = vec4f(aW.rgb * aW.a, aW.a);
1089
+ let aW = fI(cam);
1090
+ let sn = select(0.0, 1.0, aW.a >= 0.01);
1091
+ let kg = vec4f(aW.rgb * aW.a, aW.a);
1030
1092
 
1031
1093
 
1032
1094
 
1033
- outShadowCatcher[idx].mask += vec4f(1.0, aW.a, qX, 0.0);
1095
+ outShadowCatcher[idx].mask += vec4f(1.0, aW.a, sn, 0.0);
1034
1096
  outShadowCatcher[idx].moments += vec4f(0.0, 0.0, outAux.shadowCounts);
1035
- outShadowCatcher[idx].background += jC;
1036
- outColor[idx] += jC;
1037
- outAlbedo[idx] += vec4f(outAux.albedo, qX);
1038
- hH(idx, aW.rgb, outAux.normal);
1097
+ outShadowCatcher[idx].background += kg;
1098
+ outColor[idx] += kg;
1099
+ outAlbedo[idx] += vec4f(outAux.albedo, sn);
1100
+ ij(idx, aW.rgb, outAux.normal);
1039
1101
 
1040
1102
 
1041
1103
  let counts = outAux.shadowCounts;
1042
1104
  let visibility = 1.0 - select(0.0, counts.x / counts.y, counts.y > 0.0);
1043
- iP(idx, visibility * select(
1105
+ ju(idx, visibility * select(
1044
1106
  1.0, dot(aW.rgb, luminance), aW.a >= 0.01
1045
1107
  ));
1046
1108
  }
@@ -1056,8 +1118,8 @@ outShadowCatcher[idx].mask.g += liAndAlpha.a;
1056
1118
  }
1057
1119
  outColor[idx] += liAndAlpha;
1058
1120
  outAlbedo[idx] += vec4f(outAux.albedo, select(1.0, 0.0, outAux.isBlank));
1059
- hH(idx, liAndAlpha.rgb, outAux.normal);
1060
- iP(idx, dot(liAndAlpha.rgb, luminance));
1121
+ ij(idx, liAndAlpha.rgb, outAux.normal);
1122
+ ju(idx, dot(liAndAlpha.rgb, luminance));
1061
1123
  }
1062
1124
  ${pathDiagnostic ? ' mtPathEnd(outAux.normal, outAux.albedo);\n' : ''}${inputHooks?.end ?? ''}}
1063
1125
  `;
@@ -1065,7 +1127,7 @@ ${pathDiagnostic ? ' mtPathEnd(outAux.normal, outAux.albedo);\n' : ''}${inputHo
1065
1127
  // It has no effect on the beauty entry point or its bindings.
1066
1128
  // Gate optional material layers on scene-level feature flags so drivers can
1067
1129
  // skip the unused BSDF lobes.
1068
- let specializedSource = source + depthQueryWGSL + reflectanceWGSL + aovTraceWGSL;
1130
+ let specializedSource = source + depthQueryWGSL + reflectanceWGSL + (options.displayAovStorage ? aovTraceDisplayWGSL : aovTraceWGSL);
1069
1131
  const backgroundBits = {
1070
1132
  USE_BACKGROUND: 1,
1071
1133
  USE_BACKGROUND_MAP: 2,