@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 +1 @@
1
- {"version":3,"file":"rayTrace.frag.js","sourceRoot":"","sources":["../../../src/renderer/glsl/rayTrace.frag.ts"],"names":[],"mappings":"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","sourcesContent":["import {researchTransport} from '../researchTransport.js';\nimport { MAX_PATH_EVENTS } from '../pathLimits.js';\nimport cameraRayGlsl from './chunks/cameraRay.glsl.js';\n// Portions adapted from ray-tracing-renderer@0.10.15\n// (https://github.com/hoverinc/ray-tracing-renderer).\n// Copyright (c) 2019 HOVER, MIT license; see LICENSES/RayTracingRenderer-MIT.txt.\n\nimport commonGlsl from './chunks/common.glsl.js';\nimport {createRayTraceCoreGlsl} from './chunks/rayTraceCore.glsl.js';\nimport textureLinear from './chunks/textureLinear.glsl.js';\nimport {createMaterialBufferGlsl} from './chunks/materialBuffer.glsl.js';\nimport intersect from './chunks/intersect.glsl.js';\nimport randGlsl from './chunks/rand.glsl.js';\nimport random from './chunks/random.glsl.js';\nimport envMap from './chunks/envMap.glsl.js';\nimport {createSampleMaterialGlsl} from './chunks/sampleMaterial.glsl.js';\nimport sampleLightGlsl from './chunks/sampleLight.glsl.js';\nimport { FragmentShader, glsl, Shader } from '../shader.js';\nimport openPbrBsdfGlsl from './chunks/openPbrBsdf.glsl.js';\nimport samplingGlsl from './chunks/sampling.glsl.js';\nimport {spectrumGlsl} from '../spectrum.js';\nimport { isIntelMac } from '../util.js';\nimport uvProjectionGlsl from './chunks/uvProjection.glsl.js';\n\nconst doubleTransmissionCheckCode = glsl`\n#if defined(HAS_TRANSMISSION) || defined(HAS_ALPHA)\n if (!si.isTransparency && BOUNCES < 16 && depth * 2 > BOUNCES) {\n path.abort = true;\n return;\n }\n#endif\n`;\n\n// bounce fix on intel mac\n// The intel mac only have one bounce if the loop is not unrolled\n// But windows will have extremely slow shader compilation if the loop is unrolled\n// So here the code are injected separately.\nconst bounceCodeOnIntelMac = glsl`\n// Mark loop can be unrolled\nfor(int _idx_ = 0; _idx_ < BOUNCES; _idx_++) {{\n if (path.abort) {\n return vec4(path.li, path.alpha);\n }\n bounce(path, depth, si, mat, outAux);\n}}\n`;\nconst bounceCodeOnOther = glsl`\nbool isOpaque = !si.isTransparency;\nint activeBounceLimit = min(BOUNCES, bounceLimit);\nfor(int idx = 0; idx < min(BOUNCES * 3, ${MAX_PATH_EVENTS}); idx++) {\n if (isOpaque && idx > activeBounceLimit) {\n path.abort = true;\n }\n if (path.abort) {\n return vec4(path.li, path.alpha);\n }\n bounce(path, depth, si, mat, outAux);\n}\n`;\n\nexport default function createRayTraceFragmentShader(...options: unknown[]) {\n const research = researchTransport()?.fragment(options);\n const enabled = research?.enabled ?? false;\n const fragments = research?.fragments;\n const materialBufferGlsl = createMaterialBufferGlsl(fragments);\n const rayTraceCore = createRayTraceCoreGlsl(fragments);\n const sampleMaterialGlsl = createSampleMaterialGlsl(fragments);\n const intelMac = isIntelMac();\n return new FragmentShader({\n name: 'rayTraceFrag',\n outputs: ['color', 'albedo', 'normal', 'moments'],\n defines: {\n BOUNCES: 2\n },\n uniforms: {\n emissiveLightData: Shader.uniform('sampler2D'), emissiveLightColumns: Shader.uniform('int'),\n emissiveChoiceOffset: Shader.uniform('int'), emissiveChoiceCount: Shader.uniform('int'), emissivePmfOffset: Shader.uniform('int'),\n emissiveWeightTotal: Shader.uniform('float',0),\n cameraApertureRadius: Shader.uniform('float', 0),\n cameraFocusDistance: Shader.uniform('float', 10),\n\n viewProjectionInv: Shader.uniform('mat4'),\n viewInv: Shader.uniform('mat4'),\n transmissiveOutputAlphaMin: Shader.uniform('float'),\n openPbrEnergyLut: Shader.uniform('sampler2D'),\n\n viewportSize: Shader.uniform('vec2'),\n\n spectralChannel: Shader.uniform('int', 0),\n bevelEnabled: Shader.uniform('bool', true),\n dispersionWavelengths: Shader.uniform('int', 3),\n bounceLimit: Shader.uniform('int', 8)\n },\n includes: [rayTraceCore, materialBufferGlsl, intersect, random, envMap, ...(research?.mixin ? [research.mixin] : [])],\n main: glsl`\n${commonGlsl}\n\n${randGlsl}\n${random.main}\n\n${textureLinear}\n\n${rayTraceCore.main}\n\n${uvProjectionGlsl}\n\n${materialBufferGlsl.main}\n${intersect.main}\n${envMap.main}\n\n${samplingGlsl}\n${spectrumGlsl}\n${openPbrBsdfGlsl}\n\nfloat heroWavelength;\nfloat pathWavelength;\nint heroChannel;\nint pathChannel;\n\n${sampleLightGlsl}\n${research?.declarations ?? ''}${sampleMaterialGlsl}\n\n${cameraRayGlsl}\nstruct RayTraceAuxiliary {\n // Denoising guides and auxiliary pixel classification.\n vec3 albedo;\n vec3 normal;\n bool isBlank;\n // The primary ray hit a shadow catcher, whose sample the catcher pass owns.\n bool isShadowCatcher;\n};\n\nvoid bounce(inout Path path, inout int depth, inout SurfaceInteraction si, inout OpenPbrResolvedMaterial mat, inout RayTraceAuxiliary outAux) {\n samplingBounce = uint(max(depth, 0));\n // The bounce will be doubled on the transmission material.\n // For other materials. We will quite early\n // TODO It is only used on Mac with AMD card. If I enabled it on windows.\n // It will cause shader compilation too slow.\n${intelMac ? doubleTransmissionCheckCode : ''}\n\n bool isShadowCatcher = mat.materialType == SHADOW_CATCHER;\n if (isShadowCatcher) {\n if (path.fromEye) {\n // Match the composed shadow with neutral receiver guides, while keeping\n // background coverage and radiance independent of the invisible ground.\n outAux.albedo = vec3(1.0);\n outAux.normal = dot(si.normal, path.ray.d) > 0.0 ? -si.normal : si.normal;\n si.hit = false;\n outAux.isShadowCatcher = true;\n }\n else {\n // The catcher belongs only to the shadow-mask pass. Keep its default\n // white material out of glossy and transmission reflections.\n#ifdef USE_ENVMAP\n if (path.isNextRefraction) {\n // The invisible catcher can sit between a transmitted camera ray and\n // the grounded skybox. Use the displayed background here instead of\n // terminating early with the raw lighting environment.\n vec4 bg = sampleBackgroundFromRay(path.ray.o, path.ray.d);\n bg.rgb = sampling_spectral_rgb_filter(bg.rgb, pathChannel);\n float backgroundMisWeight = path.scatteringIsDelta ? 1.0\n : sampling_power_heuristic(path.scatteringPdf,\n envMapPdf(environmentUv(path.ray.d)) * envLightSelectionPmf);\n path.li += backgroundMisWeight * path.beta * bg.rgb * bg.a;\n path.alpha = max(path.alpha, bg.a);\n }\n else {\n vec2 envUv = environmentUv(path.ray.d);\n vec3 emission = textureLinear(envMap, envUv).rgb;\n emission = sampling_spectral_rgb_filter(emission, pathChannel);\n path.li += path.beta * emission *\n sampling_power_heuristic(\n path.scatteringPdf,\n envMapPdf(envUv) * envLightSelectionPmf\n );\n }\n#else\n vec4 bg = sampleBackgroundFromRay(path.ray.o, path.ray.d);\n bg.rgb = sampling_spectral_rgb_filter(bg.rgb, pathChannel);\n path.li += path.beta * bg.rgb * bg.a;\n#endif\n path.abort = true;\n return;\n }\n }\n\n if (!si.hit) {\n // Sample from background if first ray not hit anything.\n vec4 bg = sampleBackgroundFromRay(path.ray.o, path.ray.d);\n // Dispersion renders one additive pass per RGB wavelength. Background\n // radiance has to be split in the same way as lights and emissive\n // surfaces, otherwise the full skybox is accumulated three times.\n bg.rgb = sampling_spectral_rgb_filter(bg.rgb, pathChannel);\n if (path.fromEye) {\n path.li = bg.rgb * bg.a;\n path.alpha = bg.a;\n // Only treat as blank pixels when the background is transparent\n outAux.isBlank = bg.a < 0.01;\n }\n else {\n Ray cam = initCameraRay(v_Texcoord + pixelJitter());\n bool towardsCam = dot(cam.d, path.ray.d) > 0.0;\n if (transmissiveOutputAlphaMin < 1.0) {\n if (towardsCam) {\n path.alpha = max(path.alpha, bg.a);\n } else {\n path.alpha = 1.0;\n }\n }\n#if !defined(USE_ENVMAP)\n // TODO treat background as a light source\n if (towardsCam) {\n path.li += path.beta * sampling_power_heuristic(path.scatteringPdf, 1.0) * bg.rgb;\n }\n#endif\n }\n path.abort = true;\n return;\n }\n\n bool sampleIgnored = false;\n if ((mat.materialType == STANDARD || mat.materialType == UNLIT)) {\n if (transmissiveOutputAlphaMin < 1.0) {\n // TODO increase the alpha when there are more bounces.\n float alpha = max(1.0 - mat.transmissionWeight, 1.0 - pow(1.0 - transmissiveOutputAlphaMin, float(depth)));\n path.alpha = max(alpha, path.alpha);\n }\n float alpha = mat.alpha;\n if (alpha < 1.0) {\n // Alpha is sampled as stochastic coverage. An accepted surface branch\n // must use full radiance weight; multiplying by alpha again is biased.\n path.alpha = max(path.alpha, alpha);\n if (hashedSample(3u) > alpha) {\n sampleIgnored = true;\n }\n }\n if (!sampleIgnored) {\n SampleMaterial(si, mat, path);\n }\n else {\n path.ray.o = si.position + path.ray.d * EPS;\n }\n }\n\n if (!si.albedoSampled && !sampleIgnored) {\n // Select denoising guides.\n if ((mat.materialType == STANDARD || mat.materialType == UNLIT) &&\n !(mat.transmissionWeight > 0.5 ||\n (mat.specularRoughness <= 0.02 && mat.baseMetalness > 0.98))) {\n // Alpha-blended decals can be skipped stochastically. In that case keep\n // looking for the first useful rough-surface guide behind the decal,\n // even though it is reached after depth zero.\n outAux.albedo = mat.baseColor;\n outAux.normal = dot(si.normal, si.position - vec3(viewInv[3])) > 0.0\n ? -si.normal\n : si.normal;\n si.albedoSampled = true;\n }\n if (depth > 4) {\n si.albedoSampled = true;\n }\n }\n\n\n // Russian Roulette sampling\n#ifdef USE_RR\n if (depth >= RR_MAX && !sampleIgnored) {\n // Max-component survival (pbrt-v4) avoids over-amplifying saturated paths.\n float maxComponent = max(max(path.beta.x, path.beta.y), path.beta.z);\n float q = max(0.0, 1.0 - maxComponent);\n if (sample1D(bounceDim(RUSSIAN_ROULETTE)) < q) {\n // TODO we force use alpha 1.0 here.\n // To avoid the glass pixels is transparent even if it's on an opaque object.\n path.alpha = 1.0;\n path.abort = true;\n }\n else {\n path.beta /= 1.0 - q;\n }\n }\n#endif\n\n if (path.abort) {\n return;\n }\n\n // Next ray hit\n intersectScene(path.ray, si, true);\n getMaterial(mat, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);\n si.isTransparency = mat.transmissionWeight > 0.001 || mat.subsurfaceWeight > 0.001 || mat.alpha < 0.999;\n\n // Dynamic preview only becomes spectral when the primary visible surface\n // actually disperses transmitted light. Direct background and ordinary\n // opaque materials stay full RGB and therefore remain noise-free.\n if (dispersionWavelengths == 1 && si.hit && mat.transmissionWeight > 0.001 && mat.transmissionDispersionScale > 0.001) {\n pathWavelength = heroWavelength;\n pathChannel = heroChannel;\n }\n if (mat.transmissionWeight > 0.001 && pathWavelength > 0.0) {\n mat.specularIor = sampling_cauchy_ior(\n pathWavelength,\n mat.specularIor,\n mat.transmissionDispersionScale,\n mat.dispersionAbbeNumber\n );\n }\n\n if (sampleIgnored) {\n return;\n }\n\n bool isAlphaOccluded = hashedSample(3u) < mat.alpha;\n#ifdef NUM_LIGHTS\n // Use light if hit the light\n LightSampleRec lightSample;\n for (int i = 0; i < NUM_LIGHTS; i++) {\n // Fetch light Data\n Light light = fetchLight(i);\n float d = intersectLight(path.ray, light, lightSample);\n bool occluded = si.hit && d > distance(si.position, path.ray.o);\n if (d != INF && !(occluded && isAlphaOccluded)) {\n lightSample.pdf *= light.selectionPmf;\n float misWeight = sampling_power_heuristic(path.scatteringPdf, lightSample.pdf);\n lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathChannel);\n ${enabled ? 'if (!causticHitOwned(path)) { ' : ''}path.li += misWeight * path.beta * lightSample.emission;${enabled ? ' }' : ''}\n // TODO set alpha to 1.0 will cause some sharp edges\n path.alpha = 1.0;\n path.abort = true;\n }\n }\n#endif\n\n#ifdef USE_ENVMAP\n if (!(si.hit && isAlphaOccluded)) {\n if (path.isNextRefraction) {\n // Camera-visible transmission must use the displayed background. The\n // raw environment remains the lighting source for non-transmission rays.\n vec4 bg = sampleBackgroundFromRay(path.ray.o, path.ray.d);\n bg.rgb = sampling_spectral_rgb_filter(bg.rgb, pathChannel);\n float backgroundMisWeight = path.scatteringIsDelta ? 1.0\n : sampling_power_heuristic(path.scatteringPdf,\n envMapPdf(environmentUv(path.ray.d)) * envLightSelectionPmf);\n path.li += backgroundMisWeight * path.beta * bg.rgb * bg.a;\n path.alpha = max(path.alpha, bg.a);\n path.abort = true;\n return;\n }\n vec2 uv = environmentUv(path.ray.d);\n vec3 emission = textureLinear(envMap, uv).rgb;\n float misWeight = sampling_power_heuristic(\n path.scatteringPdf,\n envMapPdf(uv) * envLightSelectionPmf\n );\n emission = sampling_spectral_rgb_filter(emission, pathChannel);\n path.li += path.beta * emission * misWeight;\n\n // TODO force the min alpha to be 1 when showing envmap as background\n #if !defined(USE_BACKGROUND)\n path.alpha = 1.0;\n #endif\n path.abort = true;\n return;\n }\n#endif\n\n depth++;\n}\n\n\nvec2 bevelCubicSample(float radius, float xi) {\n float x = 0.25;\n for (int iteration = 0; iteration < 10; iteration++) {\n float x2 = x * x;\n float x3 = x2 * x;\n float oneMinusX = 1.0 - x;\n float value = 10.0 * x2 - 20.0 * x3 + 15.0 * x2 * x2 -\n 4.0 * x2 * x3 - xi;\n float derivative = 20.0 * x * oneMinusX * oneMinusX * oneMinusX;\n if (abs(value) < 1e-6 || derivative == 0.0) break;\n x = clamp(x - value / derivative, 0.0, 1.0);\n }\n float diskRadius = x * radius;\n return vec2(\n diskRadius,\n sqrt(max(radius * radius - diskRadius * diskRadius, 0.0))\n );\n}\n\nfloat bevelCubicPdf(float radius, float distanceToSource) {\n if (distanceToSource >= radius) return 0.0;\n float falloff = radius - distanceToSource;\n return falloff * falloff * falloff;\n}\n\n// Shader bevel. Usage: docs/materials.md (Renderer extensions)\nvec3 getBevelNormal(SurfaceInteraction source, float radius) {\n vec3 geometricNormal = source.faceNormal;\n if (dot(geometricNormal, source.vertexNormal) < 0.0) geometricNormal = -geometricNormal;\n vec3 tangent;\n vec3 bitangent;\n sampling_orthonormal_basis(geometricNormal, tangent, bitangent);\n vec3 normalSum = vec3(0.0);\n\n for (int sampleIndex = 0; sampleIndex < BEVEL_SAMPLES; sampleIndex++) {\n vec2 bevelRnd = sample2D(CAMERA_BEVEL_BASE + uint(sampleIndex));\n float axisSample = bevelRnd.x;\n float radialSample = bevelRnd.y;\n vec3 diskNormal = geometricNormal;\n vec3 diskTangent = tangent;\n vec3 diskBitangent = bitangent;\n float pickPdfNormal = 0.5;\n float pickPdfTangent = 0.25;\n float pickPdfBitangent = 0.25;\n if (axisSample < 0.5) {\n axisSample *= 2.0;\n }\n else if (axisSample < 0.75) {\n vec3 swapAxis = diskNormal;\n diskNormal = diskTangent;\n diskTangent = swapAxis;\n pickPdfNormal = 0.25;\n pickPdfTangent = 0.5;\n axisSample = (axisSample - 0.5) * 4.0;\n }\n else {\n vec3 swapAxis = diskNormal;\n diskNormal = diskBitangent;\n diskBitangent = swapAxis;\n pickPdfNormal = 0.25;\n pickPdfBitangent = 0.5;\n axisSample = (axisSample - 0.75) * 4.0;\n }\n\n vec2 diskSample = bevelCubicSample(radius, radialSample);\n float phi = TWOPI * axisSample;\n vec3 diskOffset = diskSample.x *\n (cos(phi) * diskTangent + sin(phi) * diskBitangent);\n Ray ray;\n initRay(\n ray,\n source.position + diskNormal * diskSample.y + diskOffset,\n -diskNormal\n );\n SurfaceInteraction hit;\n intersectSceneBevel(\n ray,\n hit,\n source.instanceIndex,\n max(2.0 * diskSample.y, EPS)\n );\n if (!hit.hit) continue;\n\n float pdfNormal = pickPdfNormal * abs(dot(diskNormal, hit.faceNormal));\n float pdfTangent = pickPdfTangent * abs(dot(diskTangent, hit.faceNormal));\n float pdfBitangent = pickPdfBitangent * abs(dot(diskBitangent, hit.faceNormal));\n float weight = pdfNormal / max(\n pdfNormal * pdfNormal + pdfTangent * pdfTangent +\n pdfBitangent * pdfBitangent,\n 1e-8\n );\n weight *= bevelCubicPdf(radius, distance(hit.position, source.position)) /\n max(bevelCubicPdf(radius, diskSample.x), 1e-8);\n normalSum += weight * hit.vertexNormal;\n }\n\n if (dot(normalSum, normalSum) <= 1e-12) return source.normal;\n vec3 bevelVertexNormal = normalize(normalSum);\n vec3 result = source.normal + bevelVertexNormal - source.vertexNormal;\n return dot(result, result) > 1e-12 ? normalize(result) : source.normal;\n}\n\nvec4 integrateOnePathSample(SurfaceInteraction si, Ray ray, OpenPbrResolvedMaterial mat, inout RayTraceAuxiliary outAux) {\n Path path;\n path.ray = ray;\n path.li = vec3(0);\n path.alpha = transmissiveOutputAlphaMin < 1.0 ? 0.0 : 1.0;\n path.beta = vec3(1.0);\n path.fromEye = true;${enabled ? /* glsl */ `\n path.causticK = 0; path.causticSingleT = false;\n path.causticReceiverPrimary = false; path.causticHasReceiver = false; path.causticMneeReceiver=false;` : ''}\n path.scatteringPdf = 0.0;\n path.scatteringIsDelta = false;\n path.isNextRefraction = false;\n path.abort = false;\n int depth = 0;\n${intelMac ? bounceCodeOnIntelMac : bounceCodeOnOther}\n return vec4(path.li, path.alpha);\n}\n\nvec4 integrateOnePath(SurfaceInteraction si, Ray ray, OpenPbrResolvedMaterial mat, inout RayTraceAuxiliary outAux) {\n float coverage = clamp(mat.alpha, 0.0, 1.0);\n if (!si.hit || (mat.materialType != STANDARD && mat.materialType != UNLIT) || coverage >= 1.0) {\n return integrateOnePathSample(si, ray, mat, outAux);\n }\n\n // glTF BLEND is source-over opacity, not a physical glass boundary. Split\n // the primary ray so reflected radiance is attenuated by alpha every sample\n // while the complementary branch continues straight to the scene behind it.\n // Secondary alpha hits remain stochastic to avoid exponential path growth.\n Ray backRay = ray;\n backRay.o = si.position + ray.d * (EPS * 0.02);\n SurfaceInteraction backSi = si;\n backSi.albedoSampled = false;\n intersectScene(backRay, backSi, false);\n OpenPbrResolvedMaterial backMat;\n getMaterial(backMat, backSi.materialIndex, backSi.uv, backSi.uv1, backSi.instanceIndex, backSi.vertexColor);\n RayTraceAuxiliary backAux = outAux;\n if (backSi.hit && (backMat.materialType == STANDARD || backMat.materialType == UNLIT)) {\n backAux.albedo = backMat.transmissionWeight > 0.5\n ? vec3(1.0)\n : backMat.baseColor;\n backAux.normal = dot(\n backSi.normal,\n backSi.position - vec3(viewInv[3])\n ) > 0.0\n ? -backSi.normal\n : backSi.normal;\n backSi.albedoSampled = backMat.transmissionWeight > 0.5;\n }\n vec4 back = integrateOnePathSample(backSi, backRay, backMat, backAux);\n if (coverage <= 0.0) {\n outAux = backAux;\n return back;\n }\n\n SurfaceInteraction frontSi = si;\n OpenPbrResolvedMaterial frontMat = mat;\n frontMat.alpha = 1.0;\n RayTraceAuxiliary frontAux = outAux;\n vec4 front = integrateOnePathSample(frontSi, ray, frontMat, frontAux);\n outAux.albedo = mix(backAux.albedo, frontAux.albedo, coverage);\n vec3 blendedNormal = mix(backAux.normal, frontAux.normal, coverage);\n outAux.normal = dot(blendedNormal, blendedNormal) > 1e-12\n ? normalize(blendedNormal)\n : vec3(0.0);\n outAux.isBlank = backAux.isBlank && frontAux.isBlank;\n return mix(back, front, coverage);\n}\n\n// Path tracing integrator as described in\n// http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Path_Tracing.html#\nvec4 integrator(Ray ray, out RayTraceAuxiliary outAux) {\n\n SurfaceInteraction si;\n OpenPbrResolvedMaterial mat;\n\n si.albedoSampled = false;\n#ifdef HAS_MEDIUM\n si.mediumType = 0;\n si.mediumExtinction = vec3(0.0);\n si.mediumScattering = vec3(0.0);\n si.mediumAnisotropy = 0.0;\n#endif\n\n intersectScene(ray, si, false);\n getMaterial(mat, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);\n si.isTransparency = mat.transmissionWeight > 0.001 || mat.subsurfaceWeight > 0.001 || mat.alpha < 0.999;\n\n#ifdef HAS_BEVEL\n if (bevelEnabled && mat.bevel > 0.0) {\n si.normal = getBevelNormal(si, mat.bevel);\n }\n#endif\n\n // Keep a clean first-hit fallback for denoising. Glass retains this stable\n // guide; other delta paths may replace it at their first non-delta hit.\n if (si.hit && (mat.materialType == STANDARD || mat.materialType == UNLIT)) {\n outAux.albedo = mat.transmissionWeight > 0.5 ? vec3(1.0) : mat.baseColor;\n outAux.normal = dot(si.normal, si.position - vec3(viewInv[3])) > 0.0\n ? -si.normal\n : si.normal;\n // A refracted/reflected continuation is stochastic and therefore not a\n // clean OIDN feature. Keep the stable primary glass guide instead.\n si.albedoSampled = mat.transmissionWeight > 0.5;\n }\n\n if (mat.transmissionDispersionScale > 0.001) {\n mat.specularIor = sampling_cauchy_ior(\n pathWavelength,\n mat.specularIor,\n mat.transmissionDispersionScale,\n mat.dispersionAbbeNumber\n );\n }\n return integrateOnePath(si, ray, mat, outAux);\n}\n\nvoid main() {\n\n${fragments?.debugInit ?? ''} initRandom();\n rng_initialize(v_Texcoord * viewportSize, int(uint(sampleCount) ^ sampleHash(uint(sequenceSeed))));\n\n\n pathWavelength = 0.0;\n pathChannel = 0;\n if (spectralChannel > 0) {\n float wavelengthSample = sample1D(CAMERA_WAVELENGTH);\n if (dispersionWavelengths == 1) {\n heroChannel = min(int(wavelengthSample * 3.0), 2) + 1;\n heroWavelength = spectrumCameraWavelength(heroChannel - 1, fract(wavelengthSample * 3.0));\n } else {\n pathChannel = spectralChannel;\n pathWavelength = spectrumCameraWavelength(spectralChannel - 1, wavelengthSample);\n }\n }\n\n // Thin lens model with depth-of-field\n // http://www.pbr-book.org/3ed-2018/Camera_Models/Projective_Camera_Models.html#TheThinLensModelandDepthofField\n Ray cam = primaryCameraRay();\n\n RayTraceAuxiliary outAux;\n outAux.albedo = vec3(0.0);\n outAux.normal = vec3(0.0);\n outAux.isBlank = false;\n outAux.isShadowCatcher = false;\n\n vec4 liAndAlpha = integrator(cam, outAux);\n\n // Clamp at Integration Level to reduce fireflies.\n // TODO Path level configuration?\n#ifdef CLAMPING\n float clamping = float(CLAMPING);\n liAndAlpha.rgb = clamp(liAndAlpha.rgb, -clamping, clamping);\n#endif\n\n // Each sample will be accumulated three times.\n if (pathWavelength > 0.0) {\n // RGB will be normalized using accumated hit in out_albedo.a\n liAndAlpha.rgb *= 3.0;\n if (dispersionWavelengths != 1) {\n // Full spectral samples use three additive passes. Preview only submits\n // one hero wavelength, so its alpha must not be divided.\n liAndAlpha.a /= 3.0;\n }\n }\n if (!(liAndAlpha.x < INF && liAndAlpha.x > -EPS)) {\n liAndAlpha = vec4(0, 0, 0, 1);\n }\n\n out_color = ${research?.debugOutput || 'liAndAlpha'};\n out_albedo = vec4(outAux.albedo, outAux.isBlank ? 0.0 : 1.0);\n out_normal = vec4(outAux.normal, 1.0);\n // Moments and count of the built-in denoiser's guide value. The catcher\n // pass accumulates its own samples (see shadowCatcher.frag).\n float guideValue = dot(liAndAlpha.rgb, vec3(0.2126, 0.7152, 0.0722));\n out_moments = outAux.isShadowCatcher\n ? vec4(0.0)\n : vec4(guideValue, guideValue * guideValue, 1.0, 0.0);\n\n}`\n });\n}\n"]}
1
+ {"version":3,"file":"rayTrace.frag.js","sourceRoot":"","sources":["../../../src/renderer/glsl/rayTrace.frag.ts"],"names":[],"mappings":"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","sourcesContent":["import {spectralPrefixGlsl, prefixCheckpoint, prefixSave, prefixRestore, prefixRandomBindings, type PrefixBindings} from './chunks/spectralPrefix.glsl.js';\nimport {researchTransport} from '../researchTransport.js';\nimport { MAX_PATH_EVENTS_WEBGL } from '../pathLimits.js';\nimport cameraRayGlsl from './chunks/cameraRay.glsl.js';\n// Portions adapted from ray-tracing-renderer@0.10.15\n// (https://github.com/hoverinc/ray-tracing-renderer).\n// Copyright (c) 2019 HOVER, MIT license; see LICENSES/RayTracingRenderer-MIT.txt.\n\nimport commonGlsl from './chunks/common.glsl.js';\nimport {createRayTraceCoreGlsl} from './chunks/rayTraceCore.glsl.js';\nimport textureLinear from './chunks/textureLinear.glsl.js';\nimport {createMaterialBufferGlsl} from './chunks/materialBuffer.glsl.js';\nimport intersect from './chunks/intersect.glsl.js';\nimport randGlsl from './chunks/rand.glsl.js';\nimport random from './chunks/random.glsl.js';\nimport envMap from './chunks/envMap.glsl.js';\nimport {createSampleMaterialGlsl} from './chunks/sampleMaterial.glsl.js';\nimport sampleLightGlsl from './chunks/sampleLight.glsl.js';\nimport { FragmentShader, glsl, Shader } from '../shader.js';\nimport openPbrBsdfGlsl from './chunks/openPbrBsdf.glsl.js';\nimport samplingGlsl from './chunks/sampling.glsl.js';\nimport {spectrumGlsl} from '../spectrum.js';\nimport { isIntelMac } from '../util.js';\nimport uvProjectionGlsl from './chunks/uvProjection.glsl.js';\n\nconst doubleTransmissionCheckCode = glsl`\n#if defined(HAS_TRANSMISSION) || defined(HAS_ALPHA)\n if (!si.isTransparency && BOUNCES < 16 && depth * 2 > BOUNCES) {\n path.abort = true;\n return;\n }\n#endif\n`;\n\n// bounce fix on intel mac\n// The intel mac only have one bounce if the loop is not unrolled\n// But windows will have extremely slow shader compilation if the loop is unrolled\n// So here the code are injected separately.\nconst bounceCodeOnIntelMac = glsl`\n// Mark loop can be unrolled\nfor(int _idx_ = 0; _idx_ < BOUNCES; _idx_++) {{\n if (path.abort) {\n return vec4(path.li, path.alpha);\n }\n bounce(path, depth, si, mat, outAux);\n}}\n`;\nconst bounceCodeOnOther = glsl`\nbool isOpaque = !si.isTransparency;\nint activeBounceLimit = min(BOUNCES, bounceLimit);\nfor(int idx = 0; idx < min(BOUNCES * 3, ${MAX_PATH_EVENTS_WEBGL}); idx++) {\n if (isOpaque && idx > activeBounceLimit) {\n path.abort = true;\n }\n if (path.abort) {\n return vec4(path.li, path.alpha);\n }\n bounce(path, depth, si, mat, outAux);\n}\n`;\n\nexport default function createRayTraceFragmentShader(...options: unknown[]) {\n const channelIndependentLight = (options[0] as {channelIndependentLight?: boolean} | undefined)?.channelIndependentLight ?? false;\n const sharePrefix = (options[0] as {shareSpectralPrefix?: boolean} | undefined)?.shareSpectralPrefix ?? false;\n const surfacePrefix: PrefixBindings = {\n path: ['Path', 'path'], si: ['SurfaceInteraction', 'si'], mat: ['OpenPbrResolvedMaterial', 'mat'],\n aux: ['RayTraceAuxiliary', 'outAux'], depth: ['int', 'depth'], event: ['int', 'idx'],\n ignored: ['bool', 'sampleIgnored'], opaque: ['bool', 'isOpaque'], ...prefixRandomBindings\n };\n const research = researchTransport()?.fragment(typeof options[0] === 'object' ? [] : options);\n const enabled = research?.enabled ?? false;\n const fragments = research?.fragments;\n const materialBufferGlsl = createMaterialBufferGlsl(fragments);\n const rayTraceCore = createRayTraceCoreGlsl(fragments);\n const sampleMaterialGlsl = createSampleMaterialGlsl(fragments, channelIndependentLight);\n const intelMac = isIntelMac();\n return new FragmentShader({\n name: 'rayTraceFrag',\n outputs: ['color', 'albedo', 'normal', 'moments'],\n defines: {\n BOUNCES: 2\n },\n uniforms: {\n emissiveLightData: Shader.uniform('sampler2D'), emissiveLightColumns: Shader.uniform('int'),\n emissiveChoiceOffset: Shader.uniform('int'), emissiveChoiceCount: Shader.uniform('int'), emissivePmfOffset: Shader.uniform('int'),\n emissiveWeightTotal: Shader.uniform('float',0),\n cameraApertureRadius: Shader.uniform('float', 0),\n cameraFocusDistance: Shader.uniform('float', 10),\n\n viewProjectionInv: Shader.uniform('mat4'),\n projectionInv: Shader.uniform('mat4'),\n viewInv: Shader.uniform('mat4'),\n transmissiveOutputAlphaMin: Shader.uniform('float'),\n openPbrEnergyLut: Shader.uniform('sampler2D'),\n\n viewportSize: Shader.uniform('vec2'),\n\n spectralChannel: Shader.uniform('int', 0),\n bevelEnabled: Shader.uniform('bool', true),\n dispersionWavelengths: Shader.uniform('int', 3),\n bounceLimit: Shader.uniform('int', 8)\n },\n includes: [rayTraceCore, materialBufferGlsl, intersect, random, envMap, ...(research?.mixin ? [research.mixin] : [])],\n main: glsl`\n${commonGlsl}\n\n${randGlsl}\n${random.main}\n\n${textureLinear}\n\n${rayTraceCore.main}\n\n${uvProjectionGlsl}\n\n${materialBufferGlsl.main}\n${intersect.main}\n${envMap.main}\n\n${samplingGlsl}\n${spectrumGlsl}\n${openPbrBsdfGlsl}\n\nfloat heroWavelength;\nfloat pathWavelength;\nint heroChannel;\nint pathChannel;\n\n${sampleLightGlsl}\n${research?.declarations ?? ''}${sampleMaterialGlsl}\n\n${cameraRayGlsl}\nstruct RayTraceAuxiliary {\n // Denoising guides and auxiliary pixel classification.\n vec3 albedo;\n vec3 normal;\n bool isBlank;\n // The primary ray hit a shadow catcher, whose sample the catcher pass owns.\n bool isShadowCatcher;\n};\n\n${sharePrefix ? spectralPrefixGlsl + prefixCheckpoint('spSurface', surfacePrefix) : ''}void ${sharePrefix ? 'shadeSurfaceVertex' : 'bounce'}(inout Path path, inout int depth, inout SurfaceInteraction si, inout OpenPbrResolvedMaterial mat, inout RayTraceAuxiliary outAux${sharePrefix ? ', out bool sampleIgnored' : ''}) {${sharePrefix ? '\\n sampleIgnored = false;' : ''}\n samplingBounce = uint(max(depth, 0));\n // The bounce will be doubled on the transmission material.\n // For other materials. We will quite early\n // TODO It is only used on Mac with AMD card. If I enabled it on windows.\n // It will cause shader compilation too slow.\n${intelMac ? doubleTransmissionCheckCode : ''}\n\n bool isShadowCatcher = mat.materialType == SHADOW_CATCHER;\n if (isShadowCatcher) {\n if (path.fromEye) {\n // Match the composed shadow with neutral receiver guides, while keeping\n // background coverage and radiance independent of the invisible ground.\n outAux.albedo = vec3(1.0);\n outAux.normal = dot(si.normal, path.ray.d) > 0.0 ? -si.normal : si.normal;\n si.hit = false;\n outAux.isShadowCatcher = true;\n }\n else {\n // The catcher belongs only to the shadow-mask pass. Keep its default\n // white material out of glossy and transmission reflections.\n#ifdef USE_ENVMAP\n if (path.isNextRefraction) {\n // The invisible catcher can sit between a transmitted camera ray and\n // the grounded skybox. Use the displayed background here instead of\n // terminating early with the raw lighting environment.\n vec4 bg = sampleBackgroundFromRay(path.ray.o, path.ray.d);\n bg.rgb = sampling_spectral_rgb_filter(bg.rgb, pathChannel);\n float backgroundMisWeight = path.scatteringIsDelta ? 1.0\n : sampling_power_heuristic(path.scatteringPdf,\n envMapPdf(environmentUv(path.ray.d)) * envLightSelectionPmf);\n path.li += backgroundMisWeight * path.beta * bg.rgb * bg.a;\n path.alpha = max(path.alpha, bg.a);\n }\n else {\n vec2 envUv = environmentUv(path.ray.d);\n vec3 emission = textureLinear(envMap, envUv).rgb;\n emission = sampling_spectral_rgb_filter(emission, pathChannel);\n path.li += path.beta * emission *\n sampling_power_heuristic(\n path.scatteringPdf,\n envMapPdf(envUv) * envLightSelectionPmf\n );\n }\n#else\n vec4 bg = sampleBackgroundFromRay(path.ray.o, path.ray.d);\n bg.rgb = sampling_spectral_rgb_filter(bg.rgb, pathChannel);\n path.li += path.beta * bg.rgb * bg.a;\n#endif\n path.abort = true;\n return;\n }\n }\n\n if (!si.hit) {\n // Sample from background if first ray not hit anything.\n vec4 bg = sampleBackgroundFromRay(path.ray.o, path.ray.d);\n // Dispersion renders one additive pass per RGB wavelength. Background\n // radiance has to be split in the same way as lights and emissive\n // surfaces, otherwise the full skybox is accumulated three times.\n bg.rgb = sampling_spectral_rgb_filter(bg.rgb, pathChannel);\n if (path.fromEye) {\n path.li = bg.rgb * bg.a;\n path.alpha = bg.a;\n // Only treat as blank pixels when the background is transparent\n outAux.isBlank = bg.a < 0.01;\n }\n else {\n Ray cam = initCameraRay(v_Texcoord + pixelJitter());\n bool towardsCam = dot(cam.d, path.ray.d) > 0.0;\n if (transmissiveOutputAlphaMin < 1.0) {\n if (towardsCam) {\n path.alpha = max(path.alpha, bg.a);\n } else {\n path.alpha = 1.0;\n }\n }\n#if !defined(USE_ENVMAP)\n // TODO treat background as a light source\n if (towardsCam) {\n path.li += path.beta * sampling_power_heuristic(path.scatteringPdf, 1.0) * bg.rgb;\n }\n#endif\n }\n path.abort = true;\n return;\n }\n\n${sharePrefix ? ' sampleIgnored = false;' : ' bool sampleIgnored = false;'}\n if ((mat.materialType == STANDARD || mat.materialType == UNLIT)) {\n if (transmissiveOutputAlphaMin < 1.0) {\n // TODO increase the alpha when there are more bounces.\n float alpha = max(1.0 - mat.transmissionWeight, 1.0 - pow(1.0 - transmissiveOutputAlphaMin, float(depth)));\n path.alpha = max(alpha, path.alpha);\n }\n float alpha = mat.alpha;\n if (alpha < 1.0) {\n // Alpha is sampled as stochastic coverage. An accepted surface branch\n // must use full radiance weight; multiplying by alpha again is biased.\n path.alpha = max(path.alpha, alpha);\n if (hashedSample(3u) > alpha) {\n sampleIgnored = true;\n }\n }\n if (!sampleIgnored) {\n SampleMaterial(si, mat, path);\n }\n else {\n path.ray.o = si.position + path.ray.d * EPS;\n }\n }\n\n if (!si.albedoSampled && !sampleIgnored) {\n // Select denoising guides.\n if ((mat.materialType == STANDARD || mat.materialType == UNLIT) &&\n !(mat.transmissionWeight > 0.5 ||\n (mat.specularRoughness <= 0.02 && mat.baseMetalness > 0.98))) {\n // Alpha-blended decals can be skipped stochastically. In that case keep\n // looking for the first useful rough-surface guide behind the decal,\n // even though it is reached after depth zero.\n outAux.albedo = mat.baseColor;\n outAux.normal = dot(si.normal, si.position - vec3(viewInv[3])) > 0.0\n ? -si.normal\n : si.normal;\n si.albedoSampled = true;\n }\n if (depth > 4) {\n si.albedoSampled = true;\n }\n }\n\n\n // Russian Roulette sampling\n#ifdef USE_RR\n int rouletteStart = path.scatteringMediumEntered ? RR_MAX : 2;\n if (depth >= rouletteStart && !sampleIgnored) {\n // Max-component survival (pbrt-v4) avoids over-amplifying saturated paths.\n float maxComponent = max(max(path.beta.x, path.beta.y), path.beta.z);\n float q = max(0.0, 1.0 - maxComponent);\n if (sample1D(bounceDim(RUSSIAN_ROULETTE)) < q) {\n // TODO we force use alpha 1.0 here.\n // To avoid the glass pixels is transparent even if it's on an opaque object.\n path.alpha = 1.0;\n path.abort = true;\n }\n else {\n path.beta /= 1.0 - q;\n }\n }\n#endif\n\n if (path.abort) {\n return;\n }\n\n${sharePrefix ? /* glsl */ ` return;\n}\nvoid completeSurfaceVertex(inout Path path, inout int depth, inout SurfaceInteraction si, inout OpenPbrResolvedMaterial mat, bool sampleIgnored) {\n` : ''} // Next ray hit\n${sharePrefix ? '' : /* glsl */ ` intersectScene(path.ray, si, true);\n getMaterial(mat, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);\n si.isTransparency = mat.transmissionWeight > 0.001 || mat.subsurfaceWeight > 0.001 || mat.alpha < 0.999;\n`}\n // Dynamic preview only becomes spectral when the primary visible surface\n // actually disperses transmitted light. Direct background and ordinary\n // opaque materials stay full RGB and therefore remain noise-free.\n if (dispersionWavelengths == 1 && si.hit && mat.transmissionWeight > 0.001 && mat.transmissionDispersionScale > 0.001) {\n pathWavelength = heroWavelength;\n pathChannel = heroChannel;\n }\n if (mat.transmissionWeight > 0.001 && pathWavelength > 0.0) {\n mat.specularIor = sampling_cauchy_ior(\n pathWavelength,\n mat.specularIor,\n mat.transmissionDispersionScale,\n mat.dispersionAbbeNumber\n );\n }\n\n if (sampleIgnored) {\n return;\n }\n\n bool isAlphaOccluded = hashedSample(3u) < mat.alpha;\n#ifdef NUM_LIGHTS\n // Use light if hit the light\n LightSampleRec lightSample;\n for (int i = 0; i < NUM_LIGHTS; i++) {\n // Fetch light Data\n Light light = fetchLight(i);\n float d = intersectLight(path.ray, light, lightSample);\n bool occluded = si.hit && d > distance(si.position, path.ray.o);\n if (d != INF && !(occluded && isAlphaOccluded)) {\n lightSample.pdf *= light.selectionPmf;\n float misWeight = sampling_power_heuristic(path.scatteringPdf, lightSample.pdf);\n lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathChannel);\n ${enabled ? 'if (!causticHitOwned(path)) { ' : ''}path.li += misWeight * path.beta * lightSample.emission;${enabled ? ' }' : ''}\n // TODO set alpha to 1.0 will cause some sharp edges\n path.alpha = 1.0;\n path.abort = true;\n }\n }\n#endif\n\n#ifdef USE_ENVMAP\n if (!(si.hit && isAlphaOccluded)) {\n if (path.isNextRefraction) {\n // Camera-visible transmission must use the displayed background. The\n // raw environment remains the lighting source for non-transmission rays.\n vec4 bg = sampleBackgroundFromRay(path.ray.o, path.ray.d);\n bg.rgb = sampling_spectral_rgb_filter(bg.rgb, pathChannel);\n float backgroundMisWeight = path.scatteringIsDelta ? 1.0\n : sampling_power_heuristic(path.scatteringPdf,\n envMapPdf(environmentUv(path.ray.d)) * envLightSelectionPmf);\n path.li += backgroundMisWeight * path.beta * bg.rgb * bg.a;\n path.alpha = max(path.alpha, bg.a);\n path.abort = true;\n return;\n }\n vec2 uv = environmentUv(path.ray.d);\n vec3 emission = textureLinear(envMap, uv).rgb;\n float misWeight = sampling_power_heuristic(\n path.scatteringPdf,\n envMapPdf(uv) * envLightSelectionPmf\n );\n emission = sampling_spectral_rgb_filter(emission, pathChannel);\n path.li += path.beta * emission * misWeight;\n\n // TODO force the min alpha to be 1 when showing envmap as background\n #if !defined(USE_BACKGROUND)\n path.alpha = 1.0;\n #endif\n path.abort = true;\n return;\n }\n#endif\n\n depth++;\n}\n\n\nvec2 bevelCubicSample(float radius, float xi) {\n float x = 0.25;\n for (int iteration = 0; iteration < 10; iteration++) {\n float x2 = x * x;\n float x3 = x2 * x;\n float oneMinusX = 1.0 - x;\n float value = 10.0 * x2 - 20.0 * x3 + 15.0 * x2 * x2 -\n 4.0 * x2 * x3 - xi;\n float derivative = 20.0 * x * oneMinusX * oneMinusX * oneMinusX;\n if (abs(value) < 1e-6 || derivative == 0.0) break;\n x = clamp(x - value / derivative, 0.0, 1.0);\n }\n float diskRadius = x * radius;\n return vec2(\n diskRadius,\n sqrt(max(radius * radius - diskRadius * diskRadius, 0.0))\n );\n}\n\nfloat bevelCubicPdf(float radius, float distanceToSource) {\n if (distanceToSource >= radius) return 0.0;\n float falloff = radius - distanceToSource;\n return falloff * falloff * falloff;\n}\n\n// Shader bevel. Usage: docs/materials.md (Renderer extensions)\nvec3 getBevelNormal(SurfaceInteraction source, float radius) {\n vec3 geometricNormal = source.faceNormal;\n if (dot(geometricNormal, source.vertexNormal) < 0.0) geometricNormal = -geometricNormal;\n vec3 tangent;\n vec3 bitangent;\n sampling_orthonormal_basis(geometricNormal, tangent, bitangent);\n vec3 normalSum = vec3(0.0);\n\n for (int sampleIndex = 0; sampleIndex < BEVEL_SAMPLES; sampleIndex++) {\n vec2 bevelRnd = sample2D(CAMERA_BEVEL_BASE + uint(sampleIndex));\n float axisSample = bevelRnd.x;\n float radialSample = bevelRnd.y;\n vec3 diskNormal = geometricNormal;\n vec3 diskTangent = tangent;\n vec3 diskBitangent = bitangent;\n float pickPdfNormal = 0.5;\n float pickPdfTangent = 0.25;\n float pickPdfBitangent = 0.25;\n if (axisSample < 0.5) {\n axisSample *= 2.0;\n }\n else if (axisSample < 0.75) {\n vec3 swapAxis = diskNormal;\n diskNormal = diskTangent;\n diskTangent = swapAxis;\n pickPdfNormal = 0.25;\n pickPdfTangent = 0.5;\n axisSample = (axisSample - 0.5) * 4.0;\n }\n else {\n vec3 swapAxis = diskNormal;\n diskNormal = diskBitangent;\n diskBitangent = swapAxis;\n pickPdfNormal = 0.25;\n pickPdfBitangent = 0.5;\n axisSample = (axisSample - 0.75) * 4.0;\n }\n\n vec2 diskSample = bevelCubicSample(radius, radialSample);\n float phi = TWOPI * axisSample;\n vec3 diskOffset = diskSample.x *\n (cos(phi) * diskTangent + sin(phi) * diskBitangent);\n Ray ray;\n initRay(\n ray,\n source.position + diskNormal * diskSample.y + diskOffset,\n -diskNormal\n );\n SurfaceInteraction hit;\n intersectSceneBevel(\n ray,\n hit,\n source.instanceIndex,\n max(2.0 * diskSample.y, EPS)\n );\n if (!hit.hit) continue;\n\n float pdfNormal = pickPdfNormal * abs(dot(diskNormal, hit.faceNormal));\n float pdfTangent = pickPdfTangent * abs(dot(diskTangent, hit.faceNormal));\n float pdfBitangent = pickPdfBitangent * abs(dot(diskBitangent, hit.faceNormal));\n float weight = pdfNormal / max(\n pdfNormal * pdfNormal + pdfTangent * pdfTangent +\n pdfBitangent * pdfBitangent,\n 1e-8\n );\n weight *= bevelCubicPdf(radius, distance(hit.position, source.position)) /\n max(bevelCubicPdf(radius, diskSample.x), 1e-8);\n normalSum += weight * hit.vertexNormal;\n }\n\n if (dot(normalSum, normalSum) <= 1e-12) return source.normal;\n vec3 bevelVertexNormal = normalize(normalSum);\n vec3 result = source.normal + bevelVertexNormal - source.vertexNormal;\n return dot(result, result) > 1e-12 ? normalize(result) : source.normal;\n}\n\nvec4 integrateOnePathSample(SurfaceInteraction si, Ray ray, OpenPbrResolvedMaterial mat, inout RayTraceAuxiliary outAux) {\n Path path; path.scatteringMediumEntered = false;\n path.ray = ray;\n path.li = vec3(0);\n path.alpha = transmissiveOutputAlphaMin < 1.0 ? 0.0 : 1.0;\n path.beta = vec3(1.0);\n path.fromEye = true;${enabled ? /* glsl */ `\n path.causticK = 0; path.causticSingleT = false;\n path.causticReceiverPrimary = false; path.causticHasReceiver = false; path.causticMneeReceiver=false;` : ''}\n path.scatteringPdf = 0.0;\n path.scatteringIsDelta = false;\n path.isNextRefraction = false;\n path.abort = false;\n int depth = 0;\n${sharePrefix ? /* glsl */ ` int spSlot = spCall++;\n if (spActive && spChannel > 1 && spCompleted[spSlot].ready) return spReplay(spSlot, outAux);\n bool isOpaque = !si.isTransparency;\n bool sampleIgnored = false, spResume = false;\n int spEvent = 0;\n if (spActive && spChannel > 1 && spForkCall == spSlot) {\n int idx = 0;\n ${prefixRestore('spSurface', surfacePrefix)}\n spEvent = idx; spResume = true; spFork(path);\n }\n int activeBounceLimit = min(BOUNCES, bounceLimit);\n for (int idx = ${intelMac ? '0' : 'spEvent'}; idx < ${intelMac ? 'BOUNCES' : `min(BOUNCES * 3, ${MAX_PATH_EVENTS_WEBGL})`}; idx++) {\n${intelMac ? ' if (idx < spEvent) continue;' : ' if (isOpaque && idx > activeBounceLimit) path.abort = true;'}\n if (path.abort) break;\n if (!spResume) {\n shadeSurfaceVertex(path, depth, si, mat, outAux, sampleIgnored);\n if (!path.abort) {\n intersectScene(path.ray, si, true);\n getMaterial(mat, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);\n si.isTransparency = mat.transmissionWeight > 0.001 || mat.subsurfaceWeight > 0.001 || mat.alpha < 0.999;\n }\n }\n spResume = false;\n if (!path.abort) {\n if (spActive && mat.transmissionWeight > 0.001 && spDisperses(mat)) {\n ${prefixSave('spSurface', surfacePrefix)}\n spForkCall = spSlot; spFork(path);\n }\n completeSurfaceVertex(path, depth, si, mat, sampleIgnored);\n }\n }\n return spFinish(spSlot, vec4(path.li, path.alpha), outAux);` : /* glsl */ `${intelMac ? bounceCodeOnIntelMac : bounceCodeOnOther}\n return vec4(path.li, path.alpha);`}\n}\n\nvec4 integrateOnePath(SurfaceInteraction si, Ray ray, OpenPbrResolvedMaterial mat, inout RayTraceAuxiliary outAux) {\n float coverage = clamp(mat.alpha, 0.0, 1.0);\n if (!si.hit || (mat.materialType != STANDARD && mat.materialType != UNLIT) || coverage >= 1.0) {\n return integrateOnePathSample(si, ray, mat, outAux);\n }\n\n // glTF BLEND is source-over opacity, not a physical glass boundary. Split\n // the primary ray so reflected radiance is attenuated by alpha every sample\n // while the complementary branch continues straight to the scene behind it.\n // Secondary alpha hits remain stochastic to avoid exponential path growth.\n Ray backRay = ray;\n backRay.o = si.position + ray.d * (EPS * 0.02);\n SurfaceInteraction backSi = si;\n backSi.albedoSampled = false;\n intersectScene(backRay, backSi, false);\n OpenPbrResolvedMaterial backMat;\n getMaterial(backMat, backSi.materialIndex, backSi.uv, backSi.uv1, backSi.instanceIndex, backSi.vertexColor);\n RayTraceAuxiliary backAux = outAux;\n if (backSi.hit && (backMat.materialType == STANDARD || backMat.materialType == UNLIT)) {\n backAux.albedo = backMat.transmissionWeight > 0.5\n ? vec3(1.0)\n : backMat.baseColor;\n backAux.normal = dot(\n backSi.normal,\n backSi.position - vec3(viewInv[3])\n ) > 0.0\n ? -backSi.normal\n : backSi.normal;\n backSi.albedoSampled = backMat.transmissionWeight > 0.5;\n }\n vec4 back = integrateOnePathSample(backSi, backRay, backMat, backAux);\n if (coverage <= 0.0) {\n outAux = backAux;\n return back;\n }\n\n SurfaceInteraction frontSi = si;\n OpenPbrResolvedMaterial frontMat = mat;\n frontMat.alpha = 1.0;\n RayTraceAuxiliary frontAux = outAux;\n vec4 front = integrateOnePathSample(frontSi, ray, frontMat, frontAux);\n outAux.albedo = mix(backAux.albedo, frontAux.albedo, coverage);\n vec3 blendedNormal = mix(backAux.normal, frontAux.normal, coverage);\n outAux.normal = dot(blendedNormal, blendedNormal) > 1e-12\n ? normalize(blendedNormal)\n : vec3(0.0);\n outAux.isBlank = backAux.isBlank && frontAux.isBlank;\n return mix(back, front, coverage);\n}\n\n// Path tracing integrator as described in\n// http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Path_Tracing.html#\nvec4 integrator(Ray ray, out RayTraceAuxiliary outAux) {\n\n SurfaceInteraction si;\n OpenPbrResolvedMaterial mat;\n\n si.albedoSampled = false;\n#ifdef HAS_MEDIUM\n si.mediumType = 0;\n si.mediumExtinction = vec3(0.0);\n si.mediumScattering = vec3(0.0);\n si.mediumAnisotropy = 0.0;\n#endif\n\n${sharePrefix ? ' if (spChannel == 1) {\\n' : ''} intersectScene(ray, si, false);\n getMaterial(mat, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);\n si.isTransparency = mat.transmissionWeight > 0.001 || mat.subsurfaceWeight > 0.001 || mat.alpha < 0.999;\n\n#ifdef HAS_BEVEL\n if (bevelEnabled && mat.bevel > 0.0) {\n si.normal = getBevelNormal(si, mat.bevel);\n }\n#endif\n\n // Keep a clean first-hit fallback for denoising. Glass retains this stable\n // guide; other delta paths may replace it at their first non-delta hit.\n if (si.hit && (mat.materialType == STANDARD || mat.materialType == UNLIT)) {\n outAux.albedo = mat.transmissionWeight > 0.5 ? vec3(1.0) : mat.baseColor;\n outAux.normal = dot(si.normal, si.position - vec3(viewInv[3])) > 0.0\n ? -si.normal\n : si.normal;\n // A refracted/reflected continuation is stochastic and therefore not a\n // clean OIDN feature. Keep the stable primary glass guide instead.\n si.albedoSampled = mat.transmissionWeight > 0.5;\n }\n\n${sharePrefix ? /* glsl */ ` spPrimary = SpectralPrimary(si, mat, outAux, s0, hashedCounter, samplingBounce);\n } else {\n si = spPrimary.si; mat = spPrimary.mat; outAux = spPrimary.aux;\n s0 = spPrimary.rng; hashedCounter = spPrimary.counter; samplingBounce = spPrimary.bounce;\n }\n spActive = ${enabled ? 'false' : '!(mat.transmissionDispersionScale > 0.001 && mat.specularIor != 1.0)'};\n pathChannel = spActive ? 0 : spChannel;\n spCall = 0;\n` : ''} if (mat.transmissionDispersionScale > 0.001) {\n mat.specularIor = sampling_cauchy_ior(\n pathWavelength,\n mat.specularIor,\n mat.transmissionDispersionScale,\n mat.dispersionAbbeNumber\n );\n }\n return integrateOnePath(si, ray, mat, outAux);\n}\n\nvoid ${sharePrefix ? 'traceSpectralWavelength' : 'main'}(${sharePrefix ? 'int channel' : ''}) {\n\n${fragments?.debugInit ?? ''} initRandom();\n rng_initialize(v_Texcoord * viewportSize, int(uint(sampleCount) ^ sampleHash(uint(sequenceSeed))));\n\n\n${sharePrefix ? ' spChannel = channel;\\n' : ''} pathWavelength = 0.0;\n pathChannel = 0;\n if (spectralChannel > 0) {\n float wavelengthSample = sample1D(CAMERA_WAVELENGTH);\n if (dispersionWavelengths == 1) {\n heroChannel = min(int(wavelengthSample * 3.0), 2) + 1;\n heroWavelength = spectrumCameraWavelength(heroChannel - 1, fract(wavelengthSample * 3.0));\n } else {\n pathChannel = ${sharePrefix ? 'spChannel' : 'spectralChannel'};\n pathWavelength = spectrumCameraWavelength(${sharePrefix ? 'spChannel' : 'spectralChannel'} - 1, wavelengthSample);\n }\n }\n\n // Thin lens model with depth-of-field\n // http://www.pbr-book.org/3ed-2018/Camera_Models/Projective_Camera_Models.html#TheThinLensModelandDepthofField\n Ray cam = primaryCameraRay();\n\n RayTraceAuxiliary outAux;\n outAux.albedo = vec3(0.0);\n outAux.normal = vec3(0.0);\n outAux.isBlank = false;\n outAux.isShadowCatcher = false;\n\n vec4 liAndAlpha = integrator(cam, outAux);\n\n // Clamp at Integration Level to reduce fireflies.\n // TODO Path level configuration?\n#ifdef CLAMPING\n float clamping = float(CLAMPING);\n liAndAlpha.rgb = clamp(liAndAlpha.rgb, -clamping, clamping);\n#endif\n\n // Each sample will be accumulated three times.\n if (pathWavelength > 0.0) {\n // RGB will be normalized using accumated hit in out_albedo.a\n liAndAlpha.rgb *= 3.0;\n if (dispersionWavelengths != 1) {\n // Full spectral samples use three additive passes. Preview only submits\n // one hero wavelength, so its alpha must not be divided.\n liAndAlpha.a /= 3.0;\n }\n }\n if (!(liAndAlpha.x < INF && liAndAlpha.x > -EPS)) {\n liAndAlpha = vec4(0, 0, 0, 1);\n }\n\n out_color = ${research?.debugOutput || 'liAndAlpha'};\n out_albedo = vec4(outAux.albedo, outAux.isBlank ? 0.0 : 1.0);\n out_normal = vec4(outAux.normal, 1.0);\n // Moments and count of the built-in denoiser's guide value. The catcher\n // pass accumulates its own samples (see shadowCatcher.frag).\n float guideValue = dot(liAndAlpha.rgb, vec3(0.2126, 0.7152, 0.0722));\n out_moments = outAux.isShadowCatcher\n ? vec4(0.0)\n : vec4(guideValue, guideValue * guideValue, 1.0, 0.0);\n\n}${sharePrefix ? /* glsl */ `\nvoid main() {\n spCompleted[0].ready = false; spCompleted[1].ready = false;\n vec4 color = vec4(0.0), albedo = vec4(0.0), normal = vec4(0.0), moments = vec4(0.0);\n // A uniform bound keeps the driver from cloning the complete optical graph.\n for (int channel = 1; channel <= dispersionWavelengths; channel++) {\n traceSpectralWavelength(channel);\n color += out_color; albedo += out_albedo; normal += out_normal; moments += out_moments;\n }\n out_color = color; out_albedo = albedo; out_normal = normal; out_moments = moments;\n}\n` : ''}`\n });\n}\n"]}
@@ -26,6 +26,7 @@ export default new FragmentShader({
26
26
  spectralChannel: Shader.uniform('int', 0),
27
27
  viewportSize: Shader.uniform('vec2'),
28
28
  viewProjectionInv: Shader.uniform('mat4'),
29
+ projectionInv: Shader.uniform('mat4'),
29
30
  viewInv: Shader.uniform('mat4'),
30
31
  cameraApertureRadius: Shader.uniform('float', 0),
31
32
  cameraFocusDistance: Shader.uniform('float', 10)
@@ -52,10 +53,10 @@ ${cameraRayGlsl}
52
53
 
53
54
 
54
55
 
55
- vec4 hR(inout Ray ray, out vec4 background, out vec2 shadowCounts) {
56
+ vec4 hq(inout Ray ray, out vec4 background, out vec2 shadowCounts) {
56
57
  background = vec4(0.0);
57
58
  shadowCounts = vec2(0.0);
58
- Path path;
59
+ Path path; path.scatteringMediumEntered = false;
59
60
  path.ray = ray;
60
61
  path.li = vec3(0);
61
62
  path.alpha = 1.0;
@@ -82,7 +83,7 @@ if (mat.materialType != SHADOW_CATCHER) {
82
83
  return vec4(0.0, 0.0, 0.0, 1.0);
83
84
  }
84
85
 
85
- vec4 bg = cn(ray.o, ray.d);
86
+ vec4 bg = cq(ray.o, ray.d);
86
87
  background = vec4(bg.rgb * bg.a, bg.a);
87
88
  if (!path.abort) {
88
89
  shadowCounts = sampleShadowCatcher(si, 0, path);
@@ -91,14 +92,14 @@ return vec4(1.0, bg.a, bg.a >= 0.01 ? 1.0 : 0.0, 0.0);
91
92
  }
92
93
 
93
94
  void main() {
94
- rA();
95
- fi(v_Texcoord * viewportSize, int(uint(sampleCount) ^ cB(uint(sequenceSeed))));
95
+ sP();
96
+ fA(v_Texcoord * viewportSize, int(uint(sampleCount) ^ cD(uint(sequenceSeed))));
96
97
 
97
98
  if (spectralChannel > 0) { sample1D(CAMERA_WAVELENGTH); }
98
- Ray cam = ow();
99
+ Ray cam = pq();
99
100
  vec4 background;
100
101
  vec2 shadowCounts;
101
- vec4 liAndAlpha = hR(cam, background, shadowCounts);
102
+ vec4 liAndAlpha = hq(cam, background, shadowCounts);
102
103
 
103
104
  if (!(liAndAlpha.x < INF && liAndAlpha.x > -EPS)) {
104
105
  liAndAlpha = vec4(0.0);
@@ -112,11 +113,11 @@ out_catcherBackground = background;
112
113
 
113
114
 
114
115
  float visibility = 1.0 - (shadowCounts.y > 0.0 ? shadowCounts.x / shadowCounts.y : 0.0);
115
- float jw = visibility * (background.a >= 0.01
116
+ float jZ = visibility * (background.a >= 0.01
116
117
  ? dot(background.rgb / background.a, vec3(0.2126, 0.7152, 0.0722))
117
118
  : 1.0);
118
119
  out_catcherMoments = liAndAlpha.r > 0.0
119
- ? vec4(jw, jw * jw, 1.0, shadowCounts.y)
120
+ ? vec4(jZ, jZ * jZ, 1.0, shadowCounts.y)
120
121
  : vec4(0.0);
121
122
 
122
123
  }`
@@ -1 +1 @@
1
- {"version":3,"file":"shadowCatcher.frag.js","sourceRoot":"","sources":["../../../src/renderer/glsl/shadowCatcher.frag.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,sDAAsD;AACtD,kFAAkF;AAElF,OAAO,aAAa,MAAM,4BAA4B,CAAC;AACvD,OAAO,MAAM,MAAM,yBAAyB,CAAC;AAC7C,OAAO,YAAY,MAAM,+BAA+B,CAAC;AACzD,OAAO,aAAa,MAAM,gCAAgC,CAAC;AAC3D,OAAO,kBAAkB,MAAM,iCAAiC,CAAC;AACjE,OAAO,SAAS,MAAM,4BAA4B,CAAC;AACnD,OAAO,QAAQ,MAAM,uBAAuB,CAAC;AAC7C,OAAO,MAAM,MAAM,yBAAyB,CAAC;AAC7C,OAAO,MAAM,MAAM,yBAAyB,CAAC;AAC7C,OAAO,mBAAmB,MAAM,sCAAsC,CAAC;AACvE,OAAO,WAAW,MAAM,8BAA8B,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,YAAY,MAAM,2BAA2B,CAAC;AACrD,OAAO,gBAAgB,MAAM,+BAA+B,CAAC;AAE7D,eAAe,IAAI,cAAc,CAAC;IAChC,IAAI,EAAE,eAAe;IACrB,OAAO,EAAE,CAAC,eAAe,EAAE,mBAAmB,EAAE,gBAAgB,CAAC;IACjE,OAAO,EAAE;QACP,OAAO,EAAE,CAAC;KACX;IACD,QAAQ,EAAE;QACR,qBAAqB,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QAC/C,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACzC,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QACpC,iBAAiB,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QACzC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QAC/B,oBAAoB,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAChD,mBAAmB,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;KACjD;IACD,QAAQ,EAAE,CAAC,YAAY,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC;IACvE,IAAI,EAAE,IAAI,CAAA;EACV,MAAM;EACN,QAAQ;EACR,MAAM,CAAC,IAAI;;EAEX,aAAa;;EAEb,YAAY,CAAC,IAAI;EACjB,gBAAgB;;EAEhB,kBAAkB,CAAC,IAAI;EACvB,SAAS,CAAC,IAAI;EACd,MAAM,CAAC,IAAI;;EAEX,YAAY;EACZ,WAAW;EACX,mBAAmB;EACnB,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuEb;CACD,CAAC,CAAC","sourcesContent":["// Portions adapted from ray-tracing-renderer@0.10.15\n// (https://github.com/hoverinc/ray-tracing-renderer).\n// Copyright (c) 2019 HOVER, MIT license; see LICENSES/RayTracingRenderer-MIT.txt.\n\nimport cameraRayGlsl from './chunks/cameraRay.glsl.js';\nimport common from './chunks/common.glsl.js';\nimport rayTraceCore from './chunks/rayTraceCore.glsl.js';\nimport textureLinear from './chunks/textureLinear.glsl.js';\nimport materialBufferGlsl from './chunks/materialBuffer.glsl.js';\nimport intersect from './chunks/intersect.glsl.js';\nimport randGlsl from './chunks/rand.glsl.js';\nimport random from './chunks/random.glsl.js';\nimport envMap from './chunks/envMap.glsl.js';\nimport sampleShadowCatcher from './chunks/sampleShadowCatcher.glsl.js';\nimport sampleLight from './chunks/sampleLight.glsl.js';\nimport { FragmentShader, glsl, Shader } from '../shader.js';\nimport samplingGlsl from './chunks/sampling.glsl.js';\nimport uvProjectionGlsl from './chunks/uvProjection.glsl.js';\n\nexport default new FragmentShader({\n name: 'shadowCatcher',\n outputs: ['shadowCatcher', 'catcherBackground', 'catcherMoments'],\n defines: {\n BOUNCES: 2\n },\n uniforms: {\n dispersionWavelengths: Shader.uniform('int', 3),\n spectralChannel: Shader.uniform('int', 0),\n viewportSize: Shader.uniform('vec2'),\n viewProjectionInv: Shader.uniform('mat4'),\n viewInv: Shader.uniform('mat4'),\n cameraApertureRadius: Shader.uniform('float', 0),\n cameraFocusDistance: Shader.uniform('float', 10)\n },\n includes: [rayTraceCore, materialBufferGlsl, intersect, random, envMap],\n main: glsl`\n${common}\n${randGlsl}\n${random.main}\n\n${textureLinear}\n\n${rayTraceCore.main}\n${uvProjectionGlsl}\n\n${materialBufferGlsl.main}\n${intersect.main}\n${envMap.main}\n\n${samplingGlsl}\n${sampleLight}\n${sampleShadowCatcher}\n${cameraRayGlsl}\n\n// Path tracing integrator as described in\n// http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Path_Tracing.html#\nvec4 integrator(inout Ray ray, out vec4 background, out vec2 shadowCounts) {\n background = vec4(0.0);\n shadowCounts = vec2(0.0);\n Path path;\n path.ray = ray;\n path.li = vec3(0);\n path.alpha = 1.0;\n path.beta = vec3(1.0);\n path.fromEye = true;\n path.scatteringPdf = 0.0;\n path.abort = false;\n\n SurfaceInteraction si;\n\n intersectScene(path.ray, si, false);\n if (!si.hit) {\n // Red stores catcher coverage. Keep it zero for pixels where the primary\n // ray did not hit the catcher so denoised shadows cannot bleed onto the\n // model silhouette during composition.\n return vec4(0.0, 0.0, 0.0, 1.0);\n }\n\n OpenPbrResolvedMaterial mat;\n getMaterial(mat, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);\n if (mat.materialType != SHADOW_CATCHER) {\n // The main path tracer already renders regular geometry. Only evaluate\n // shadow opacity when the primary ray actually hits the catcher.\n return vec4(0.0, 0.0, 0.0, 1.0);\n }\n\n vec4 bg = sampleBackgroundFromRay(ray.o, ray.d);\n background = vec4(bg.rgb * bg.a, bg.a);\n if (!path.abort) {\n shadowCounts = sampleShadowCatcher(si, 0, path);\n }\n return vec4(1.0, bg.a, bg.a >= 0.01 ? 1.0 : 0.0, 0.0);\n}\n\nvoid main() {\n initRandom();\n rng_initialize(v_Texcoord * viewportSize, int(uint(sampleCount) ^ sampleHash(uint(sequenceSeed))));\n // Match the beauty pass's random stream in spectral renders.\n if (spectralChannel > 0) { sample1D(CAMERA_WAVELENGTH); }\n Ray cam = primaryCameraRay();\n vec4 background;\n vec2 shadowCounts;\n vec4 liAndAlpha = integrator(cam, background, shadowCounts);\n\n if (!(liAndAlpha.x < INF && liAndAlpha.x > -EPS)) {\n liAndAlpha = vec4(0.0);\n shadowCounts = vec2(0.0);\n }\n\n // Alpha and the moments' w sum the occluded and total light sample counts;\n // the output pass resolves their ratio into shadow visibility.\n out_shadowCatcher = vec4(liAndAlpha.rgb, shadowCounts.x);\n out_catcherBackground = background;\n // The composed catcher is the background darkened by the shadow. Over a\n // transparent background the shadow is only its opacity.\n float visibility = 1.0 - (shadowCounts.y > 0.0 ? shadowCounts.x / shadowCounts.y : 0.0);\n float guideValue = visibility * (background.a >= 0.01\n ? dot(background.rgb / background.a, vec3(0.2126, 0.7152, 0.0722))\n : 1.0);\n out_catcherMoments = liAndAlpha.r > 0.0\n ? vec4(guideValue, guideValue * guideValue, 1.0, shadowCounts.y)\n : vec4(0.0);\n\n}`\n});\n"]}
1
+ {"version":3,"file":"shadowCatcher.frag.js","sourceRoot":"","sources":["../../../src/renderer/glsl/shadowCatcher.frag.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,sDAAsD;AACtD,kFAAkF;AAElF,OAAO,aAAa,MAAM,4BAA4B,CAAC;AACvD,OAAO,MAAM,MAAM,yBAAyB,CAAC;AAC7C,OAAO,YAAY,MAAM,+BAA+B,CAAC;AACzD,OAAO,aAAa,MAAM,gCAAgC,CAAC;AAC3D,OAAO,kBAAkB,MAAM,iCAAiC,CAAC;AACjE,OAAO,SAAS,MAAM,4BAA4B,CAAC;AACnD,OAAO,QAAQ,MAAM,uBAAuB,CAAC;AAC7C,OAAO,MAAM,MAAM,yBAAyB,CAAC;AAC7C,OAAO,MAAM,MAAM,yBAAyB,CAAC;AAC7C,OAAO,mBAAmB,MAAM,sCAAsC,CAAC;AACvE,OAAO,WAAW,MAAM,8BAA8B,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,YAAY,MAAM,2BAA2B,CAAC;AACrD,OAAO,gBAAgB,MAAM,+BAA+B,CAAC;AAE7D,eAAe,IAAI,cAAc,CAAC;IAChC,IAAI,EAAE,eAAe;IACrB,OAAO,EAAE,CAAC,eAAe,EAAE,mBAAmB,EAAE,gBAAgB,CAAC;IACjE,OAAO,EAAE;QACP,OAAO,EAAE,CAAC;KACX;IACD,QAAQ,EAAE;QACR,qBAAqB,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QAC/C,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACzC,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QACpC,iBAAiB,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QACzC,aAAa,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QACrC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QAC/B,oBAAoB,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAChD,mBAAmB,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;KACjD;IACD,QAAQ,EAAE,CAAC,YAAY,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC;IACvE,IAAI,EAAE,IAAI,CAAA;EACV,MAAM;EACN,QAAQ;EACR,MAAM,CAAC,IAAI;;EAEX,aAAa;;EAEb,YAAY,CAAC,IAAI;EACjB,gBAAgB;;EAEhB,kBAAkB,CAAC,IAAI;EACvB,SAAS,CAAC,IAAI;EACd,MAAM,CAAC,IAAI;;EAEX,YAAY;EACZ,WAAW;EACX,mBAAmB;EACnB,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuEb;CACD,CAAC,CAAC","sourcesContent":["// Portions adapted from ray-tracing-renderer@0.10.15\n// (https://github.com/hoverinc/ray-tracing-renderer).\n// Copyright (c) 2019 HOVER, MIT license; see LICENSES/RayTracingRenderer-MIT.txt.\n\nimport cameraRayGlsl from './chunks/cameraRay.glsl.js';\nimport common from './chunks/common.glsl.js';\nimport rayTraceCore from './chunks/rayTraceCore.glsl.js';\nimport textureLinear from './chunks/textureLinear.glsl.js';\nimport materialBufferGlsl from './chunks/materialBuffer.glsl.js';\nimport intersect from './chunks/intersect.glsl.js';\nimport randGlsl from './chunks/rand.glsl.js';\nimport random from './chunks/random.glsl.js';\nimport envMap from './chunks/envMap.glsl.js';\nimport sampleShadowCatcher from './chunks/sampleShadowCatcher.glsl.js';\nimport sampleLight from './chunks/sampleLight.glsl.js';\nimport { FragmentShader, glsl, Shader } from '../shader.js';\nimport samplingGlsl from './chunks/sampling.glsl.js';\nimport uvProjectionGlsl from './chunks/uvProjection.glsl.js';\n\nexport default new FragmentShader({\n name: 'shadowCatcher',\n outputs: ['shadowCatcher', 'catcherBackground', 'catcherMoments'],\n defines: {\n BOUNCES: 2\n },\n uniforms: {\n dispersionWavelengths: Shader.uniform('int', 3),\n spectralChannel: Shader.uniform('int', 0),\n viewportSize: Shader.uniform('vec2'),\n viewProjectionInv: Shader.uniform('mat4'),\n projectionInv: Shader.uniform('mat4'),\n viewInv: Shader.uniform('mat4'),\n cameraApertureRadius: Shader.uniform('float', 0),\n cameraFocusDistance: Shader.uniform('float', 10)\n },\n includes: [rayTraceCore, materialBufferGlsl, intersect, random, envMap],\n main: glsl`\n${common}\n${randGlsl}\n${random.main}\n\n${textureLinear}\n\n${rayTraceCore.main}\n${uvProjectionGlsl}\n\n${materialBufferGlsl.main}\n${intersect.main}\n${envMap.main}\n\n${samplingGlsl}\n${sampleLight}\n${sampleShadowCatcher}\n${cameraRayGlsl}\n\n// Path tracing integrator as described in\n// http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Path_Tracing.html#\nvec4 integrator(inout Ray ray, out vec4 background, out vec2 shadowCounts) {\n background = vec4(0.0);\n shadowCounts = vec2(0.0);\n Path path; path.scatteringMediumEntered = false;\n path.ray = ray;\n path.li = vec3(0);\n path.alpha = 1.0;\n path.beta = vec3(1.0);\n path.fromEye = true;\n path.scatteringPdf = 0.0;\n path.abort = false;\n\n SurfaceInteraction si;\n\n intersectScene(path.ray, si, false);\n if (!si.hit) {\n // Red stores catcher coverage. Keep it zero for pixels where the primary\n // ray did not hit the catcher so denoised shadows cannot bleed onto the\n // model silhouette during composition.\n return vec4(0.0, 0.0, 0.0, 1.0);\n }\n\n OpenPbrResolvedMaterial mat;\n getMaterial(mat, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);\n if (mat.materialType != SHADOW_CATCHER) {\n // The main path tracer already renders regular geometry. Only evaluate\n // shadow opacity when the primary ray actually hits the catcher.\n return vec4(0.0, 0.0, 0.0, 1.0);\n }\n\n vec4 bg = sampleBackgroundFromRay(ray.o, ray.d);\n background = vec4(bg.rgb * bg.a, bg.a);\n if (!path.abort) {\n shadowCounts = sampleShadowCatcher(si, 0, path);\n }\n return vec4(1.0, bg.a, bg.a >= 0.01 ? 1.0 : 0.0, 0.0);\n}\n\nvoid main() {\n initRandom();\n rng_initialize(v_Texcoord * viewportSize, int(uint(sampleCount) ^ sampleHash(uint(sequenceSeed))));\n // Match the beauty pass's random stream in spectral renders.\n if (spectralChannel > 0) { sample1D(CAMERA_WAVELENGTH); }\n Ray cam = primaryCameraRay();\n vec4 background;\n vec2 shadowCounts;\n vec4 liAndAlpha = integrator(cam, background, shadowCounts);\n\n if (!(liAndAlpha.x < INF && liAndAlpha.x > -EPS)) {\n liAndAlpha = vec4(0.0);\n shadowCounts = vec2(0.0);\n }\n\n // Alpha and the moments' w sum the occluded and total light sample counts;\n // the output pass resolves their ratio into shadow visibility.\n out_shadowCatcher = vec4(liAndAlpha.rgb, shadowCounts.x);\n out_catcherBackground = background;\n // The composed catcher is the background darkened by the shadow. Over a\n // transparent background the shadow is only its opacity.\n float visibility = 1.0 - (shadowCounts.y > 0.0 ? shadowCounts.x / shadowCounts.y : 0.0);\n float guideValue = visibility * (background.a >= 0.01\n ? dot(background.rgb / background.a, vec3(0.2126, 0.7152, 0.0722))\n : 1.0);\n out_catcherMoments = liAndAlpha.r > 0.0\n ? vec4(guideValue, guideValue * guideValue, 1.0, shadowCounts.y)\n : vec4(0.0);\n\n}`\n});\n"]}
@@ -7,22 +7,22 @@ export const brightFragment = new FragmentShader({
7
7
  scale: Shader.uniform('float', 1)
8
8
  },
9
9
  main: glsl `
10
- const vec3 xc = vec3(0.2125, 0.7154, 0.0721);
11
- vec4 tV(vec4 a, vec4 b, vec4 c) {
10
+ const vec3 ze = vec3(0.2125, 0.7154, 0.0721);
11
+ vec4 vE(vec4 a, vec4 b, vec4 c) {
12
12
  return a + b + c - min(min(a, b), c) - max(max(a, b), c);
13
13
  }
14
14
  void main() {
15
15
  vec2 d = 1.0 / vec2(colorTexRegion());
16
- vec4 cR = sample_colorTex(v_Texcoord);
16
+ vec4 texel = sample_colorTex(v_Texcoord);
17
17
  vec4 s1 = sample_colorTex(v_Texcoord - vec2(d.x, 0.0));
18
18
  vec4 s2 = sample_colorTex(v_Texcoord + vec2(d.x, 0.0));
19
19
  vec4 s3 = sample_colorTex(v_Texcoord - vec2(0.0, d.y));
20
20
  vec4 s4 = sample_colorTex(v_Texcoord + vec2(0.0, d.y));
21
- cR = tV(tV(cR, s1, s2), s3, s4);
22
- float lum = dot(cR.rgb, xc);
23
- out_color = lum > threshold && cR.a > 0.0
24
- ? vec4(cR.rgb * scale, cR.a)
25
- : vec4(0.0, 0.0, 0.0, cR.a);
21
+ texel = vE(vE(texel, s1, s2), s3, s4);
22
+ float lum = dot(texel.rgb, ze);
23
+ out_color = lum > threshold && texel.a > 0.0
24
+ ? vec4(texel.rgb * scale, texel.a)
25
+ : vec4(0.0, 0.0, 0.0, texel.a);
26
26
  }`
27
27
  });
28
28
  export const composeFragment = new FragmentShader({
@@ -48,29 +48,29 @@ export const composeFragment = new FragmentShader({
48
48
  sRGBOutput: Shader.uniform('bool', 1)
49
49
  },
50
50
  main: glsl `
51
- vec3 nT(vec3 color) {
51
+ vec3 oS(vec3 color) {
52
52
  color = max(color, 0.0);
53
53
  return mix(1.055 * pow(color, vec3(1.0 / 2.4)) - 0.055,
54
54
  color * 12.92, lessThanEqual(color, vec3(0.0031308)));
55
55
  }
56
- vec3 kb(vec3 color) {
56
+ vec3 kH(vec3 color) {
57
57
  return clamp(color, 0.0, 1.0);
58
58
  }
59
- vec3 iN(vec3 color) {
59
+ vec3 jp(vec3 color) {
60
60
  return clamp(color / (vec3(1.0) + color), 0.0, 1.0);
61
61
  }
62
- vec3 jP(vec3 color) {
62
+ vec3 kw(vec3 color) {
63
63
  color = max(vec3(0.0), color - 0.004);
64
64
  return pow((color * (6.2 * color + 0.5)) /
65
65
  (color * (6.2 * color + 1.7) + 0.06), vec3(2.2));
66
66
  }
67
- vec3 pm(vec3 value) {
68
- vec3 iF = value * (value + 0.0245786) - 0.000090537;
67
+ vec3 qw(vec3 value) {
68
+ vec3 je = value * (value + 0.0245786) - 0.000090537;
69
69
  vec3 ah = value * (0.983729 * value + 0.4329510) + 0.238081;
70
- return iF / ah;
70
+ return je / ah;
71
71
  }
72
- vec3 lO(vec3 color) {
73
- const mat3 qk = mat3(
72
+ vec3 mH(vec3 color) {
73
+ const mat3 rt = mat3(
74
74
  vec3(0.59719, 0.07600, 0.02840),
75
75
  vec3(0.35458, 0.90834, 0.13383),
76
76
  vec3(0.04823, 0.01566, 0.83777)
@@ -80,8 +80,8 @@ vec3(1.60475, -0.10208, -0.00327),
80
80
  vec3(-0.53108, 1.10813, -0.07276),
81
81
  vec3(-0.07367, -0.00605, 1.07602)
82
82
  );
83
- color = qk * (color / 0.6);
84
- return clamp(outputMatrix * pm(color), 0.0, 1.0);
83
+ color = rt * (color / 0.6);
84
+ return clamp(outputMatrix * qw(color), 0.0, 1.0);
85
85
  }
86
86
  const mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3(
87
87
  vec3(1.6605, -0.1246, -0.0182),
@@ -93,44 +93,44 @@ vec3(0.6274, 0.0691, 0.0164),
93
93
  vec3(0.3293, 0.9195, 0.0880),
94
94
  vec3(0.0433, 0.0113, 0.8956)
95
95
  );
96
- vec3 fT(vec3 value) {
97
- vec3 nB = value * value;
98
- vec3 rO = nB * nB;
99
- return 15.5 * rO * nB - 40.14 * rO * value
100
- + 31.96 * rO - 6.868 * nB * value
101
- + 0.4298 * nB + 0.1191 * value - 0.00232;
102
- }
103
- vec3 my(vec3 color) {
104
- const mat3 qm = mat3(
96
+ vec3 gj(vec3 value) {
97
+ vec3 ox = value * value;
98
+ vec3 tf = ox * ox;
99
+ return 15.5 * tf * ox - 40.14 * tf * value
100
+ + 31.96 * tf - 6.868 * ox * value
101
+ + 0.4298 * ox + 0.1191 * value - 0.00232;
102
+ }
103
+ vec3 nC(vec3 color) {
104
+ const mat3 rv = mat3(
105
105
  vec3(0.856627153315983, 0.137318972929847, 0.11189821299995),
106
106
  vec3(0.0951212405381588, 0.761241990602591, 0.0767994186031903),
107
107
  vec3(0.0482516061458583, 0.101439036467562, 0.811302368396859)
108
108
  );
109
- const mat3 ph = mat3(
109
+ const mat3 qr = mat3(
110
110
  vec3(1.1271005818144368, -0.1413297634984383, -0.14132976349843826),
111
111
  vec3(-0.11060664309660323, 1.157823702216272, -0.11060664309660294),
112
112
  vec3(-0.016493938717834573, -0.016493938717834257, 1.2519364065950405)
113
113
  );
114
- color = qm * (LINEAR_SRGB_TO_LINEAR_REC2020 * color);
114
+ color = rv * (LINEAR_SRGB_TO_LINEAR_REC2020 * color);
115
115
  color = clamp((log2(max(color, 1e-10)) + 12.47393) / 16.5, 0.0, 1.0);
116
- color = ph * fT(color);
116
+ color = qr * gj(color);
117
117
  color = pow(max(color, 0.0), vec3(2.2));
118
118
  return clamp(LINEAR_REC2020_TO_LINEAR_SRGB * color, 0.0, 1.0);
119
119
  }
120
- vec3 bZ(vec3 color) {
121
- if (toneMappingMode == 1) return lO(color);
122
- if (toneMappingMode == 2) return jP(color);
123
- if (toneMappingMode == 3) return iN(color);
124
- if (toneMappingMode == 4) return kb(color);
125
- return my(color);
120
+ vec3 bH(vec3 color) {
121
+ if (toneMappingMode == 1) return mH(color);
122
+ if (toneMappingMode == 2) return kw(color);
123
+ if (toneMappingMode == 3) return jp(color);
124
+ if (toneMappingMode == 4) return kH(color);
125
+ return nC(color);
126
126
  }
127
- vec3 ga(vec3 color) {
128
- vec3 uL = vec3(
127
+ vec3 fm(vec3 color) {
128
+ vec3 wu = vec3(
129
129
  1.0 + temperature * 0.16 + tint * 0.04,
130
130
  1.0 - tint * 0.12,
131
131
  1.0 - temperature * 0.16 + tint * 0.04
132
132
  );
133
- color = max(color * uL, 0.0);
133
+ color = max(color * wu, 0.0);
134
134
  color = max((color - 0.18) * contrast + 0.18, 0.0);
135
135
  float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));
136
136
  return max(mix(vec3(luminance), color, saturation), 0.0);
@@ -146,12 +146,12 @@ return;
146
146
  vec4 color = sample_colorTex(uv);
147
147
  vec4 bloom = sample_bloomTex(uv) * bloomIntensity;
148
148
  color.rgb += bloom.rgb;
149
- color.rgb = ga(color.rgb * exposure);
149
+ color.rgb = fm(color.rgb * exposure);
150
150
  if (sRGBOutput) {
151
151
  float edge = smoothstep(0.2, 0.72, distance(uv, vec2(0.5)));
152
152
  color.rgb *= 1.0 - vignette * edge;
153
- color.rgb = bZ(color.rgb);
154
- color.rgb = nT(color.rgb);
153
+ color.rgb = bH(color.rgb);
154
+ color.rgb = oS(color.rgb);
155
155
  }
156
156
  color.a = max(color.a, min(dot(bloom.rgb, vec3(0.2125, 0.7154, 0.0721)), 1.0));
157
157
 
@@ -159,32 +159,32 @@ if (shadowCatcherEnabled > 0.5) {
159
159
  float coverage = clamp(shadow.r, 0.0, 1.0);
160
160
 
161
161
 
162
- float fR = clamp(
162
+ float gd = clamp(
163
163
  (1.0 - shadow.a) / max(coverage, 0.000001), 0.0, 1.0
164
164
  );
165
- fR = max(fR - (1.0 - shadowCatcherAlpha), 0.0);
165
+ gd = max(gd - (1.0 - shadowCatcherAlpha), 0.0);
166
166
  if (coverage > 0.0) {
167
167
  vec4 foreground = sample_foregroundTex(uv);
168
168
  vec4 background = sample_catcherBackgroundTex(uv);
169
- vec3 foregroundColor = ga((foreground.rgb + bloom.rgb) * exposure);
170
- vec3 backgroundColor = ga((background.rgb / max(background.a, 0.000001) + bloom.rgb) * exposure);
169
+ vec3 foregroundColor = fm((foreground.rgb + bloom.rgb) * exposure);
170
+ vec3 backgroundColor = fm((background.rgb / max(background.a, 0.000001) + bloom.rgb) * exposure);
171
171
  if (sRGBOutput) {
172
172
  float edge = smoothstep(0.2, 0.72, distance(uv, vec2(0.5)));
173
173
  foregroundColor *= 1.0 - vignette * edge;
174
174
  backgroundColor *= 1.0 - vignette * edge;
175
- foregroundColor = nT(bZ(foregroundColor));
176
- backgroundColor = nT(bZ(backgroundColor));
175
+ foregroundColor = oS(bH(foregroundColor));
176
+ backgroundColor = oS(bH(backgroundColor));
177
177
  }
178
178
 
179
- float opacity = fR;
180
- fR *= coverage;
181
- float mD = clamp(dot(bloom.rgb, vec3(0.2125, 0.7154, 0.0721)), 0.0, 1.0);
182
- float hq = max(foreground.a, mD * (1.0 - coverage));
183
- float jf = max(background.a, mD * coverage);
184
- float alpha = hq + jf * (1.0 - opacity) + fR;
185
- vec3 premultiplied = foregroundColor * hq
186
- + backgroundColor * jf * (1.0 - opacity)
187
- + shadowCatcherColor * fR;
179
+ float opacity = gd;
180
+ gd *= coverage;
181
+ float nF = clamp(dot(bloom.rgb, vec3(0.2125, 0.7154, 0.0721)), 0.0, 1.0);
182
+ float hK = max(foreground.a, nF * (1.0 - coverage));
183
+ float jJ = max(background.a, nF * coverage);
184
+ float alpha = hK + jJ * (1.0 - opacity) + gd;
185
+ vec3 premultiplied = foregroundColor * hK
186
+ + backgroundColor * jJ * (1.0 - opacity)
187
+ + shadowCatcherColor * gd;
188
188
  color = vec4(premultiplied / max(alpha, 0.000001), alpha);
189
189
  }
190
190
  }
@@ -3,7 +3,7 @@ export function textureBytes(texture) {
3
3
  if (!texture)
4
4
  return 0;
5
5
  const bytes = texture.format === 'rgba32float' ? 16 :
6
- texture.format === 'rgba16float' ? 8 :
6
+ texture.format === 'rgba16float' || texture.format === 'rg32float' ? 8 :
7
7
  texture.format === 'r32float' ? 4 : 4;
8
8
  return texture.width * texture.height * texture.depthOrArrayLayers * bytes;
9
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"gpuMemory.js","sourceRoot":"","sources":["../../src/renderer/gpuMemory.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,MAAM,UAAU,YAAY,CAAC,OAA+B;IAC1D,IAAI,CAAC,OAAO;QAAE,OAAO,CAAC,CAAC;IACvB,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACnD,OAAO,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACtC,OAAO,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,OAAO,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,KAAK,CAAC;AAC7E,CAAC","sourcesContent":["/** Payload bytes of the uncompressed render-target formats used by MuTracer. */\nexport function textureBytes(texture: GPUTexture | undefined): number {\n if (!texture) return 0;\n const bytes = texture.format === 'rgba32float' ? 16 :\n texture.format === 'rgba16float' ? 8 :\n texture.format === 'r32float' ? 4 : 4;\n return texture.width * texture.height * texture.depthOrArrayLayers * bytes;\n}\n"]}
1
+ {"version":3,"file":"gpuMemory.js","sourceRoot":"","sources":["../../src/renderer/gpuMemory.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,MAAM,UAAU,YAAY,CAAC,OAA+B;IAC1D,IAAI,CAAC,OAAO;QAAE,OAAO,CAAC,CAAC;IACvB,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACnD,OAAO,CAAC,MAAM,KAAK,aAAa,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACxE,OAAO,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,OAAO,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,KAAK,CAAC;AAC7E,CAAC","sourcesContent":["/** Payload bytes of the uncompressed render-target formats used by MuTracer. */\nexport function textureBytes(texture: GPUTexture | undefined): number {\n if (!texture) return 0;\n const bytes = texture.format === 'rgba32float' ? 16 :\n texture.format === 'rgba16float' || texture.format === 'rg32float' ? 8 :\n texture.format === 'r32float' ? 4 : 4;\n return texture.width * texture.height * texture.depthOrArrayLayers * bytes;\n}\n"]}
@@ -8,7 +8,8 @@
8
8
  * This repository re-quantized the Adobe data to 8-bit row-normalized values.
9
9
  * Directional rows store Uint16 min/max followed by 32 Uint8 samples.
10
10
  * Metal and ideal-dielectric averages store exact little-endian Uint16 values.
11
- * They decode directly to Float32 without row quantization or repeated texels.
11
+ * Dielectric averages decode directly to Float32. Metal averages are normalized
12
+ * to the decoded piecewise-linear directional rows (see below).
12
13
  * Storage uses differences from the previous row: little-endian min/max
13
14
  * modulo 65536 and samples modulo 256. The first row is relative to zero;
14
15
  * differences continue across all concatenated energy tables.
@@ -8,7 +8,8 @@
8
8
  * This repository re-quantized the Adobe data to 8-bit row-normalized values.
9
9
  * Directional rows store Uint16 min/max followed by 32 Uint8 samples.
10
10
  * Metal and ideal-dielectric averages store exact little-endian Uint16 values.
11
- * They decode directly to Float32 without row quantization or repeated texels.
11
+ * Dielectric averages decode directly to Float32. Metal averages are normalized
12
+ * to the decoded piecewise-linear directional rows (see below).
12
13
  * Storage uses differences from the previous row: little-endian min/max
13
14
  * modulo 65536 and samples modulo 256. The first row is relative to zero;
14
15
  * differences continue across all concatenated energy tables.
@@ -963,6 +964,22 @@ export function getOpenPbrEnergyLutData() {
963
964
  : OPENPBR_DIELECTRIC_ENERGY_LUT_AVERAGE_ROW * 32 + index - 32;
964
965
  data[offset] = value;
965
966
  }
967
+ // Integrating before interpolation in roughness commutes with that linear
968
+ // interpolation. Use the exact integral of 2*mu times each linear segment,
969
+ // rather than the separately tabulated u16 average: low-roughness rows have
970
+ // narrow grazing features that the 32 cosine samples cannot resolve exactly.
971
+ // This makes the compensation lobe integrate to its directional loss for any
972
+ // roughness without changing the directional table or the Fresnel model.
973
+ for (let row = 0; row < OPENPBR_ENERGY_LUT_SIZE; row++) {
974
+ const offset = (OPENPBR_METAL_ENERGY_LUT_ROW + row) * OPENPBR_ENERGY_LUT_WIDTH;
975
+ const h = 1 / (OPENPBR_ENERGY_LUT_SIZE - 1);
976
+ let average = 0;
977
+ for (let i = 0; i < OPENPBR_ENERGY_LUT_SIZE - 1; i++) {
978
+ const a = data[offset + i], b = data[offset + i + 1];
979
+ average += h * (i * h * (a + b) + h * (a + 2 * b) / 3);
980
+ }
981
+ data[OPENPBR_METAL_ENERGY_LUT_AVERAGE_ROW * OPENPBR_ENERGY_LUT_WIDTH + row] = average;
982
+ }
966
983
  cachedData = data;
967
984
  return data;
968
985
  }