@meimu/mutracer 0.2.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 (372) 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/README.md +3 -0
  5. package/THIRD_PARTY_NOTICES.md +18 -4
  6. package/dist/assets/bvh.worker.js +1 -1
  7. package/dist/mutracer.umd.js +9328 -7614
  8. package/docs/api.md +83 -35
  9. package/docs/caustics.md +80 -0
  10. package/docs/materials.md +9 -6
  11. package/docs/performance.md +7 -0
  12. package/docs/post-processing.md +62 -9
  13. package/docs/progressive-rendering.md +53 -9
  14. package/docs/sampling.md +4 -0
  15. package/docs/technical/acceleration.md +52 -0
  16. package/docs/technical/aovs.md +79 -0
  17. package/docs/technical/caustics.md +109 -0
  18. package/docs/technical/continuous-spectrum.md +122 -0
  19. package/docs/technical/display-upscale.md +82 -0
  20. package/docs/technical/openpbr.md +99 -0
  21. package/docs/technical/pbrt-import.md +168 -0
  22. package/docs/technical/tiling.md +74 -0
  23. package/docs/technical/webgl.md +53 -0
  24. package/docs/updates.md +3 -1
  25. package/docs/viewer-checklist.md +65 -0
  26. package/docs/viewer.md +18 -6
  27. package/lib/Display.d.ts +19 -5
  28. package/lib/Display.js +10 -7
  29. package/lib/Display.js.map +1 -1
  30. package/lib/Engine.d.ts +4 -1
  31. package/lib/Engine.js +77 -14
  32. package/lib/Engine.js.map +1 -1
  33. package/lib/Render.d.ts +81 -24
  34. package/lib/Render.js +201 -26
  35. package/lib/Render.js.map +1 -1
  36. package/lib/RenderLoop.d.ts +7 -3
  37. package/lib/RenderLoop.js +68 -44
  38. package/lib/RenderLoop.js.map +1 -1
  39. package/lib/main.d.ts +4 -2
  40. package/lib/main.js +1 -0
  41. package/lib/main.js.map +1 -1
  42. package/lib/oidn.d.ts +1 -1
  43. package/lib/renderer/AovPrimitiveCache.js +39 -8
  44. package/lib/renderer/AovPrimitiveCache.js.map +1 -1
  45. package/lib/renderer/DisplayPostProcess.d.ts +8 -3
  46. package/lib/renderer/DisplayPostProcess.js +51 -18
  47. package/lib/renderer/DisplayPostProcess.js.map +1 -1
  48. package/lib/renderer/GPUTraceQueue.d.ts +2 -1
  49. package/lib/renderer/GPUTraceQueue.js +3 -1
  50. package/lib/renderer/GPUTraceQueue.js.map +1 -1
  51. package/lib/renderer/MaterialData.js +7 -2
  52. package/lib/renderer/MaterialData.js.map +1 -1
  53. package/lib/renderer/RenderingPipeline.d.ts +11 -1
  54. package/lib/renderer/RenderingPipeline.js.map +1 -1
  55. package/lib/renderer/TileRender.d.ts +2 -2
  56. package/lib/renderer/TileRender.js +128 -7
  57. package/lib/renderer/TileRender.js.map +1 -1
  58. package/lib/renderer/WGPUAov.d.ts +6 -1
  59. package/lib/renderer/WGPUAov.js +108 -14
  60. package/lib/renderer/WGPUAov.js.map +1 -1
  61. package/lib/renderer/WGPUCanvasSurface.js +12 -1
  62. package/lib/renderer/WGPUCanvasSurface.js.map +1 -1
  63. package/lib/renderer/WGPUCausticLightPass.d.ts +48 -0
  64. package/lib/renderer/WGPUCausticLightPass.js +217 -0
  65. package/lib/renderer/WGPUCausticLightPass.js.map +1 -0
  66. package/lib/renderer/WGPUEnvMapDistribution.js +19 -19
  67. package/lib/renderer/WGPUFullQuadPass.js +3 -3
  68. package/lib/renderer/WGPUPhotonMap.d.ts +37 -0
  69. package/lib/renderer/WGPUPhotonMap.js +191 -0
  70. package/lib/renderer/WGPUPhotonMap.js.map +1 -0
  71. package/lib/renderer/WGPURayTraceOutput.d.ts +13 -1
  72. package/lib/renderer/WGPURayTraceOutput.js +122 -28
  73. package/lib/renderer/WGPURayTraceOutput.js.map +1 -1
  74. package/lib/renderer/WGPURayTracePass.d.ts +65 -21
  75. package/lib/renderer/WGPURayTracePass.js +730 -409
  76. package/lib/renderer/WGPURayTracePass.js.map +1 -1
  77. package/lib/renderer/WGPURenderingPipeline.js +110 -68
  78. package/lib/renderer/WGPURenderingPipeline.js.map +1 -1
  79. package/lib/renderer/WebGLAov.js +3 -3
  80. package/lib/renderer/WebGLAov.js.map +1 -1
  81. package/lib/renderer/WebGLFullQuadPass.d.ts +2 -1
  82. package/lib/renderer/WebGLFullQuadPass.js +10 -0
  83. package/lib/renderer/WebGLFullQuadPass.js.map +1 -1
  84. package/lib/renderer/WebGLJNLMDenoiser.js +66 -66
  85. package/lib/renderer/WebGLJNLMDenoiser.js.map +1 -1
  86. package/lib/renderer/WebGLRayTraceOutputPass.js +4 -4
  87. package/lib/renderer/WebGLRayTracePass.d.ts +20 -11
  88. package/lib/renderer/WebGLRayTracePass.js +157 -116
  89. package/lib/renderer/WebGLRayTracePass.js.map +1 -1
  90. package/lib/renderer/WebGLRenderingPipeline.js +17 -14
  91. package/lib/renderer/WebGLRenderingPipeline.js.map +1 -1
  92. package/lib/renderer/WebGLSkyBaker.js +60 -60
  93. package/lib/renderer/accumulationTarget.d.ts +2 -1
  94. package/lib/renderer/accumulationTarget.js.map +1 -1
  95. package/lib/renderer/aov.d.ts +13 -1
  96. package/lib/renderer/aov.js +21 -2
  97. package/lib/renderer/aov.js.map +1 -1
  98. package/lib/renderer/aovDisplay.js +2 -2
  99. package/lib/renderer/aovDisplay.js.map +1 -1
  100. package/lib/renderer/binnedSahBvh.d.ts +2 -1
  101. package/lib/renderer/binnedSahBvh.js +24 -17
  102. package/lib/renderer/binnedSahBvh.js.map +1 -1
  103. package/lib/renderer/bvhAccel.d.ts +3 -1
  104. package/lib/renderer/bvhAccel.js +36 -6
  105. package/lib/renderer/bvhAccel.js.map +1 -1
  106. package/lib/renderer/cameraUniform.d.ts +1 -1
  107. package/lib/renderer/cameraUniform.js +6 -2
  108. package/lib/renderer/cameraUniform.js.map +1 -1
  109. package/lib/renderer/causticDiagnostics.d.ts +31 -0
  110. package/lib/renderer/causticDiagnostics.js +5 -0
  111. package/lib/renderer/causticDiagnostics.js.map +1 -0
  112. package/lib/renderer/causticEmission.d.ts +10 -0
  113. package/lib/renderer/causticEmission.js +40 -0
  114. package/lib/renderer/causticEmission.js.map +1 -0
  115. package/lib/renderer/causticUniform.d.ts +12 -0
  116. package/lib/renderer/causticUniform.js +22 -0
  117. package/lib/renderer/causticUniform.js.map +1 -0
  118. package/lib/renderer/caustics.d.ts +16 -0
  119. package/lib/renderer/caustics.js +93 -0
  120. package/lib/renderer/caustics.js.map +1 -0
  121. package/lib/renderer/compactVertices.d.ts +14 -0
  122. package/lib/renderer/compactVertices.js +124 -0
  123. package/lib/renderer/compactVertices.js.map +1 -0
  124. package/lib/renderer/easu.d.ts +11 -0
  125. package/lib/renderer/easu.js +156 -0
  126. package/lib/renderer/easu.js.map +1 -0
  127. package/lib/renderer/geometryUpdateState.d.ts +1 -0
  128. package/lib/renderer/geometryUpdateState.js.map +1 -1
  129. package/lib/renderer/geometryUpdates.js +3 -2
  130. package/lib/renderer/geometryUpdates.js.map +1 -1
  131. package/lib/renderer/glsl/aovDisplay.frag.js +5 -5
  132. package/lib/renderer/glsl/aovReflectance.glsl.js +53 -53
  133. package/lib/renderer/glsl/aovReflectanceSamples.glsl.js +1 -1
  134. package/lib/renderer/glsl/aovTrace.frag.js +45 -37
  135. package/lib/renderer/glsl/aovTrace.frag.js.map +1 -1
  136. package/lib/renderer/glsl/chunks/cameraProjection.glsl.d.ts +2 -0
  137. package/lib/renderer/glsl/chunks/cameraProjection.glsl.js +16 -0
  138. package/lib/renderer/glsl/chunks/cameraProjection.glsl.js.map +1 -0
  139. package/lib/renderer/glsl/chunks/cameraRay.glsl.d.ts +1 -1
  140. package/lib/renderer/glsl/chunks/cameraRay.glsl.js +9 -16
  141. package/lib/renderer/glsl/chunks/cameraRay.glsl.js.map +1 -1
  142. package/lib/renderer/glsl/chunks/emissiveLight.glsl.d.ts +2 -0
  143. package/lib/renderer/glsl/chunks/emissiveLight.glsl.js +35 -0
  144. package/lib/renderer/glsl/chunks/emissiveLight.glsl.js.map +1 -0
  145. package/lib/renderer/glsl/chunks/envMap.glsl.js +73 -73
  146. package/lib/renderer/glsl/chunks/intersect.glsl.js +478 -465
  147. package/lib/renderer/glsl/chunks/intersect.glsl.js.map +1 -1
  148. package/lib/renderer/glsl/chunks/materialBuffer.glsl.d.ts +1 -0
  149. package/lib/renderer/glsl/chunks/materialBuffer.glsl.js +156 -153
  150. package/lib/renderer/glsl/chunks/materialBuffer.glsl.js.map +1 -1
  151. package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js +771 -771
  152. package/lib/renderer/glsl/chunks/rand.glsl.js +3 -3
  153. package/lib/renderer/glsl/chunks/random.glsl.js +6 -6
  154. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.d.ts +1 -0
  155. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js +70 -63
  156. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js.map +1 -1
  157. package/lib/renderer/glsl/chunks/sampleLight.glsl.js +89 -75
  158. package/lib/renderer/glsl/chunks/sampleLight.glsl.js.map +1 -1
  159. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.d.ts +1 -0
  160. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js +160 -118
  161. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js.map +1 -1
  162. package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js +14 -14
  163. package/lib/renderer/glsl/chunks/sampling.glsl.js +88 -91
  164. package/lib/renderer/glsl/chunks/sampling.glsl.js.map +1 -1
  165. package/lib/renderer/glsl/chunks/sobol.glsl.js +79 -79
  166. package/lib/renderer/glsl/chunks/spectralPrefix.glsl.d.ts +6 -0
  167. package/lib/renderer/glsl/chunks/spectralPrefix.glsl.js +47 -0
  168. package/lib/renderer/glsl/chunks/spectralPrefix.glsl.js.map +1 -0
  169. package/lib/renderer/glsl/chunks/textureLinear.glsl.js +5 -5
  170. package/lib/renderer/glsl/chunks/uvProjection.glsl.js +11 -11
  171. package/lib/renderer/glsl/depthQuery.frag.js +13 -7
  172. package/lib/renderer/glsl/depthQuery.frag.js.map +1 -1
  173. package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js +10 -10
  174. package/lib/renderer/glsl/rayTrace.frag.d.ts +1 -1
  175. package/lib/renderer/glsl/rayTrace.frag.js +338 -252
  176. package/lib/renderer/glsl/rayTrace.frag.js.map +1 -1
  177. package/lib/renderer/glsl/shadowCatcher.frag.js +27 -26
  178. package/lib/renderer/glsl/shadowCatcher.frag.js.map +1 -1
  179. package/lib/renderer/glsl/webglPipeline.frag.js +59 -59
  180. package/lib/renderer/gpuMemory.js +1 -1
  181. package/lib/renderer/gpuMemory.js.map +1 -1
  182. package/lib/renderer/lightSampling.d.ts +3 -2
  183. package/lib/renderer/lightSampling.js +14 -8
  184. package/lib/renderer/lightSampling.js.map +1 -1
  185. package/lib/renderer/openPbrEnergyLut.d.ts +2 -1
  186. package/lib/renderer/openPbrEnergyLut.js +18 -1
  187. package/lib/renderer/openPbrEnergyLut.js.map +1 -1
  188. package/lib/renderer/pathLimits.d.ts +5 -4
  189. package/lib/renderer/pathLimits.js +6 -5
  190. package/lib/renderer/pathLimits.js.map +1 -1
  191. package/lib/renderer/prepareMeshBVH.d.ts +2 -0
  192. package/lib/renderer/prepareMeshBVH.js +5 -3
  193. package/lib/renderer/prepareMeshBVH.js.map +1 -1
  194. package/lib/renderer/progressiveScheduler.js +5 -4
  195. package/lib/renderer/progressiveScheduler.js.map +1 -1
  196. package/lib/renderer/renderPipeline.d.ts +5 -0
  197. package/lib/renderer/renderPipeline.js +1 -0
  198. package/lib/renderer/renderPipeline.js.map +1 -1
  199. package/lib/renderer/researchTransport.d.ts +31 -0
  200. package/lib/renderer/researchTransport.js +5 -0
  201. package/lib/renderer/researchTransport.js.map +1 -0
  202. package/lib/renderer/sceneAssembly.d.ts +1 -1
  203. package/lib/renderer/sceneAssembly.js +4 -3
  204. package/lib/renderer/sceneAssembly.js.map +1 -1
  205. package/lib/renderer/sceneChangeDetector.d.ts +1 -1
  206. package/lib/renderer/sceneChangeDetector.js +3 -1
  207. package/lib/renderer/sceneChangeDetector.js.map +1 -1
  208. package/lib/renderer/sceneLayoutSchema.d.ts +2 -0
  209. package/lib/renderer/sceneLayoutSchema.js +3 -3
  210. package/lib/renderer/sceneLayoutSchema.js.map +1 -1
  211. package/lib/renderer/scenePreparation.d.ts +3 -2
  212. package/lib/renderer/scenePreparation.js +18 -2
  213. package/lib/renderer/scenePreparation.js.map +1 -1
  214. package/lib/renderer/scratchSampling.js +6 -6
  215. package/lib/renderer/spectrum.d.ts +21 -0
  216. package/lib/renderer/spectrum.js +154 -0
  217. package/lib/renderer/spectrum.js.map +1 -0
  218. package/lib/renderer/staticBvhPreparation.d.ts +9 -0
  219. package/lib/renderer/staticBvhPreparation.js +8 -2
  220. package/lib/renderer/staticBvhPreparation.js.map +1 -1
  221. package/lib/renderer/surfaceHit.d.ts +10 -0
  222. package/lib/renderer/surfaceHit.js +22 -0
  223. package/lib/renderer/surfaceHit.js.map +1 -0
  224. package/lib/renderer/tangentRequirements.d.ts +2 -0
  225. package/lib/renderer/tangentRequirements.js +7 -0
  226. package/lib/renderer/tangentRequirements.js.map +1 -0
  227. package/lib/renderer/textureAtlas.d.ts +4 -0
  228. package/lib/renderer/textureAtlas.js +48 -2
  229. package/lib/renderer/textureAtlas.js.map +1 -1
  230. package/lib/renderer/webgl.js +4 -0
  231. package/lib/renderer/webgl.js.map +1 -1
  232. package/lib/renderer/webglLightSampling.d.ts +39 -0
  233. package/lib/renderer/webglLightSampling.js +15 -0
  234. package/lib/renderer/webglLightSampling.js.map +1 -0
  235. package/lib/renderer/webglVertexAttributes.d.ts +17 -0
  236. package/lib/renderer/webglVertexAttributes.js +44 -0
  237. package/lib/renderer/webglVertexAttributes.js.map +1 -0
  238. package/lib/renderer/wgpuBindlessSource.js +3 -3
  239. package/lib/renderer/wgpuMaterialConstants.js +4 -3
  240. package/lib/renderer/wgpuMaterialConstants.js.map +1 -1
  241. package/lib/renderer/wgpuSceneUniform.js +2 -2
  242. package/lib/renderer/wgpuSceneUniform.js.map +1 -1
  243. package/lib/renderer/wgpuShaderSource.d.ts +22 -0
  244. package/lib/renderer/wgpuShaderSource.js +3 -1
  245. package/lib/renderer/wgpuShaderSource.js.map +1 -1
  246. package/lib/renderer/wgsl/aovCompact.wgsl.d.ts +4 -0
  247. package/lib/renderer/wgsl/aovCompact.wgsl.js +26 -0
  248. package/lib/renderer/wgsl/aovCompact.wgsl.js.map +1 -0
  249. package/lib/renderer/wgsl/aovDisplay.wgsl.js +9 -9
  250. package/lib/renderer/wgsl/aovReflectance.wgsl.js +55 -55
  251. package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.js +1 -1
  252. package/lib/renderer/wgsl/aovResolve.wgsl.d.ts +4 -0
  253. package/lib/renderer/wgsl/aovResolve.wgsl.js +21 -2
  254. package/lib/renderer/wgsl/aovResolve.wgsl.js.map +1 -1
  255. package/lib/renderer/wgsl/aovSnapshot.wgsl.js +2 -2
  256. package/lib/renderer/wgsl/aovSnapshot.wgsl.js.map +1 -1
  257. package/lib/renderer/wgsl/aovTrace.wgsl.js +33 -33
  258. package/lib/renderer/wgsl/aovTraceDisplay.wgsl.d.ts +2 -0
  259. package/lib/renderer/wgsl/aovTraceDisplay.wgsl.js +56 -0
  260. package/lib/renderer/wgsl/aovTraceDisplay.wgsl.js.map +1 -0
  261. package/lib/renderer/wgsl/bloom.wgsl.js +18 -18
  262. package/lib/renderer/wgsl/causticLight.compute.d.ts +6 -0
  263. package/lib/renderer/wgsl/causticLight.compute.js +539 -0
  264. package/lib/renderer/wgsl/causticLight.compute.js.map +1 -0
  265. package/lib/renderer/wgsl/chunks/background.wgsl.d.ts +2 -0
  266. package/lib/renderer/wgsl/chunks/background.wgsl.js +102 -0
  267. package/lib/renderer/wgsl/chunks/background.wgsl.js.map +1 -0
  268. package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.d.ts +2 -0
  269. package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js +12 -0
  270. package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js.map +1 -0
  271. package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.d.ts +2 -0
  272. package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js +16 -0
  273. package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js.map +1 -0
  274. package/lib/renderer/wgsl/chunks/caustics.wgsl.d.ts +1 -0
  275. package/lib/renderer/wgsl/chunks/caustics.wgsl.js +62 -0
  276. package/lib/renderer/wgsl/chunks/caustics.wgsl.js.map +1 -0
  277. package/lib/renderer/wgsl/chunks/common.wgsl.js +4 -4
  278. package/lib/renderer/wgsl/chunks/envMap.wgsl.js +37 -37
  279. package/lib/renderer/wgsl/chunks/intersect.wgsl.d.ts +6 -2
  280. package/lib/renderer/wgsl/chunks/intersect.wgsl.js +634 -620
  281. package/lib/renderer/wgsl/chunks/intersect.wgsl.js.map +1 -1
  282. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.d.ts +1 -1
  283. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js +23 -21
  284. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js.map +1 -1
  285. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.d.ts +3 -1
  286. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js +77 -74
  287. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js.map +1 -1
  288. package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js +795 -795
  289. package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js +139 -139
  290. package/lib/renderer/wgsl/chunks/rand.wgsl.js +3 -3
  291. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.d.ts +5 -1
  292. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js +45 -29
  293. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js.map +1 -1
  294. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.d.ts +1 -1
  295. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js +142 -138
  296. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js.map +1 -1
  297. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.d.ts +1 -1
  298. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js +228 -189
  299. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js.map +1 -1
  300. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.d.ts +1 -1
  301. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js +11 -11
  302. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js.map +1 -1
  303. package/lib/renderer/wgsl/chunks/sampling.wgsl.d.ts +1 -1
  304. package/lib/renderer/wgsl/chunks/sampling.wgsl.js +88 -92
  305. package/lib/renderer/wgsl/chunks/sampling.wgsl.js.map +1 -1
  306. package/lib/renderer/wgsl/chunks/sobol.wgsl.js +83 -83
  307. package/lib/renderer/wgsl/chunks/spectralPrefix.wgsl.d.ts +6 -0
  308. package/lib/renderer/wgsl/chunks/spectralPrefix.wgsl.js +66 -0
  309. package/lib/renderer/wgsl/chunks/spectralPrefix.wgsl.js.map +1 -0
  310. package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js +11 -11
  311. package/lib/renderer/wgsl/chunks/vertexAttributes.wgsl.d.ts +2 -0
  312. package/lib/renderer/wgsl/chunks/vertexAttributes.wgsl.js +61 -0
  313. package/lib/renderer/wgsl/chunks/vertexAttributes.wgsl.js.map +1 -0
  314. package/lib/renderer/wgsl/compose.frag.wgsl.d.ts +2 -0
  315. package/lib/renderer/wgsl/compose.frag.wgsl.js +100 -98
  316. package/lib/renderer/wgsl/compose.frag.wgsl.js.map +1 -1
  317. package/lib/renderer/wgsl/customDenoise.wgsl.js +10 -10
  318. package/lib/renderer/wgsl/depthQuery.wgsl.d.ts +1 -1
  319. package/lib/renderer/wgsl/depthQuery.wgsl.js +12 -3
  320. package/lib/renderer/wgsl/depthQuery.wgsl.js.map +1 -1
  321. package/lib/renderer/wgsl/easu.wgsl.d.ts +2 -0
  322. package/lib/renderer/wgsl/easu.wgsl.js +80 -0
  323. package/lib/renderer/wgsl/easu.wgsl.js.map +1 -0
  324. package/lib/renderer/wgsl/easuDetail.wgsl.d.ts +21 -0
  325. package/lib/renderer/wgsl/easuDetail.wgsl.js +230 -0
  326. package/lib/renderer/wgsl/easuDetail.wgsl.js.map +1 -0
  327. package/lib/renderer/wgsl/jnlm.compute.js +74 -74
  328. package/lib/renderer/wgsl/jnlm.compute.js.map +1 -1
  329. package/lib/renderer/wgsl/offlineAdaptive.compute.js +26 -26
  330. package/lib/renderer/wgsl/oidnAuxiliary.wgsl.js +3 -3
  331. package/lib/renderer/wgsl/photonMap.compute.d.ts +29 -0
  332. package/lib/renderer/wgsl/photonMap.compute.js +352 -0
  333. package/lib/renderer/wgsl/photonMap.compute.js.map +1 -0
  334. package/lib/renderer/wgsl/proceduralSky.compute.js +64 -64
  335. package/lib/renderer/wgsl/rayTrace.compute.d.ts +23 -1
  336. package/lib/renderer/wgsl/rayTrace.compute.js +531 -543
  337. package/lib/renderer/wgsl/rayTrace.compute.js.map +1 -1
  338. package/lib/scene/MaterialState.d.ts +2 -2
  339. package/lib/scene/MaterialState.js +2 -2
  340. package/lib/scene/MaterialState.js.map +1 -1
  341. package/lib/scene/Scene.js.map +1 -1
  342. package/lib/settings/render.d.ts +22 -0
  343. package/lib/settings/render.js +2 -0
  344. package/lib/settings/render.js.map +1 -1
  345. package/lib/util/fromTHREE.js +23 -16
  346. package/lib/util/fromTHREE.js.map +1 -1
  347. package/lib/version.d.ts +1 -1
  348. package/lib/version.js +1 -1
  349. package/lib/version.js.map +1 -1
  350. package/llms.txt +2 -1
  351. package/package.json +7 -4
  352. package/lib/oidnBundledWeights.cdn.d.ts +0 -2
  353. package/lib/oidnBundledWeights.cdn.js +0 -5
  354. package/lib/oidnBundledWeights.cdn.js.map +0 -1
  355. package/lib/renderer/bvh.worker.d.ts +0 -1
  356. package/lib/renderer/bvh.worker.js +0 -16
  357. package/lib/renderer/bvh.worker.js.map +0 -1
  358. package/lib/renderer/bvhWorkerBuild.d.ts +0 -13
  359. package/lib/renderer/bvhWorkerBuild.js +0 -17
  360. package/lib/renderer/bvhWorkerBuild.js.map +0 -1
  361. package/lib/renderer/lightCore.d.ts +0 -12
  362. package/lib/renderer/lightCore.js +0 -13
  363. package/lib/renderer/lightCore.js.map +0 -1
  364. package/lib/renderer/materialCore.d.ts +0 -8
  365. package/lib/renderer/materialCore.js +0 -9
  366. package/lib/renderer/materialCore.js.map +0 -1
  367. package/lib/scene/PixelTexture.d.ts +0 -6
  368. package/lib/scene/PixelTexture.js +0 -10
  369. package/lib/scene/PixelTexture.js.map +0 -1
  370. package/lib/util/studioLighting.d.ts +0 -18
  371. package/lib/util/studioLighting.js +0 -36
  372. package/lib/util/studioLighting.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"sampleLight.glsl.js","sourceRoot":"","sources":["../../../../src/renderer/glsl/chunks/sampleLight.glsl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,eAAe,IAAI,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2PlB,CAAC","sourcesContent":["import { glsl } from '../../shader.js';\n\nexport default glsl`\n#ifdef NUM_LIGHTS\nvoid light_sample_sphere(\n in Light light,\n in vec3 shadingPoint,\n in vec2 samplePoint,\n inout LightSampleRec result\n) {\n vec3 toCenter = light.position - shadingPoint;\n float centerDistance = length(toCenter);\n if (light.radius <= 0.0) {\n if (centerDistance <= 1e-6) {\n result.direction = vec3(0.0, 0.0, 1.0);\n result.normal = vec3(0.0, 0.0, -1.0);\n result.dist = 0.0;\n result.pdf = 1.0;\n result.emission = vec3(0.0);\n result.isDelta = true;\n return;\n }\n result.direction = toCenter / centerDistance;\n result.normal = -result.direction;\n result.dist = centerDistance;\n result.pdf = 1.0;\n result.emission = light.emission / max(centerDistance * centerDistance, 1e-8);\n result.isDelta = true;\n return;\n }\n float radius = max(light.radius, 1e-6);\n result.isDelta = false;\n vec3 direction;\n\n if (centerDistance <= radius) {\n float z = 1.0 - 2.0 * samplePoint.x;\n float radial = sqrt(max(0.0, 1.0 - z * z));\n float azimuth = TWOPI * samplePoint.y;\n direction = vec3(radial * cos(azimuth), radial * sin(azimuth), z);\n result.pdf = INV4PI;\n }\n else {\n vec3 axis = toCenter / centerDistance;\n float sineLimitSquared = min(\n 1.0,\n radius * radius / (centerDistance * centerDistance)\n );\n float cosineLimit = sqrt(max(0.0, 1.0 - sineLimitSquared));\n float cosine = mix(1.0, cosineLimit, samplePoint.x);\n float sine = sqrt(max(0.0, 1.0 - cosine * cosine));\n float azimuth = TWOPI * samplePoint.y;\n vec3 tangent;\n vec3 bitangent;\n sampling_orthonormal_basis(axis, tangent, bitangent);\n direction = axis * cosine\n + tangent * (sine * cos(azimuth))\n + bitangent * (sine * sin(azimuth));\n result.pdf = 1.0 / max(TWOPI * (1.0 - cosineLimit), 1e-8);\n }\n\n float projectedCenter = dot(direction, toCenter);\n float discriminant = projectedCenter * projectedCenter\n - dot(toCenter, toCenter) + radius * radius;\n float root = sqrt(max(0.0, discriminant));\n float nearDistance = projectedCenter - root;\n float farDistance = projectedCenter + root;\n result.dist = nearDistance > 1e-6 ? nearDistance : farDistance;\n result.direction = direction;\n vec3 surfacePoint = shadingPoint + direction * result.dist;\n result.normal = normalize(surfacePoint - light.position);\n result.emission = light.emission;\n}\n\nvoid light_apply_rect_texture(\n in Light light,\n in vec3 surfacePoint,\n in vec3 lowerLeft,\n inout LightSampleRec result\n) {\n#ifdef NUM_MAPS\n if (light.textureIndex >= 0) {\n float width = length(light.u);\n float height = length(light.v);\n vec3 relative = surfacePoint - lowerLeft;\n vec2 uv = vec2(\n dot(relative, light.u / width) / width,\n dot(relative, light.v / height) / height\n );\n result.emission *= sampleMap(light.textureIndex, uv).rgb;\n }\n#endif\n}\n\nvoid light_sample_rect(\n in Light light,\n in vec3 shadingPoint,\n in vec2 samplePoint,\n inout LightSampleRec result\n) {\n vec3 normal = normalize(cross(light.u, light.v));\n vec3 lowerLeft = light.position - 0.5 * (light.u + light.v);\n float spread = clamp(light.spread, 0.0, 1.0);\n\n if (spread <= 0.001) {\n float planeDistance = dot(normal, shadingPoint - light.position);\n vec3 surfacePoint = shadingPoint - normal * planeDistance;\n vec3 relative = surfacePoint - lowerLeft;\n float width = length(light.u);\n float height = length(light.v);\n vec2 uv = vec2(\n dot(relative, light.u / width) / width,\n dot(relative, light.v / height) / height\n );\n if (planeDistance <= 0.0 || any(lessThan(uv, vec2(0.0)))\n || any(greaterThan(uv, vec2(1.0)))) {\n result.emission = vec3(0.0);\n result.pdf = 0.0;\n return;\n }\n result.direction = -normal;\n result.dist = planeDistance;\n result.normal = normal;\n result.emission = light.emission;\n result.pdf = 1.0;\n result.isDelta = true;\n light_apply_rect_texture(light, surfacePoint, lowerLeft, result);\n return;\n }\n\n vec3 surfacePoint = lowerLeft\n + light.u * samplePoint.x\n + light.v * samplePoint.y;\n vec3 offset = surfacePoint - shadingPoint;\n float distanceSquared = dot(offset, offset);\n result.dist = sqrt(distanceSquared);\n result.direction = offset / result.dist;\n result.normal = normal;\n float emitterCosine = dot(-result.direction, normal);\n float spreadCosine = cos(0.5 * PI * spread);\n if (emitterCosine <= 0.0 || emitterCosine < spreadCosine) {\n result.emission = vec3(0.0);\n result.pdf = 0.0;\n return;\n }\n result.emission = light.emission;\n result.pdf = distanceSquared / max(light.area * emitterCosine, 1e-8);\n light_apply_rect_texture(light, surfacePoint, lowerLeft, result);\n}\n\nvoid light_sample_directional(\n in Light light,\n in vec3 shadingPoint,\n inout LightSampleRec result\n) {\n result.direction = normalize(-light.u);\n result.normal = -result.direction;\n result.emission = light.emission;\n result.dist = INF;\n result.pdf = 1.0;\n result.isDelta = true;\n}\n\nvoid light_sample_spot(\n in Light light,\n in vec3 shadingPoint,\n in vec2 samplePoint,\n inout LightSampleRec result\n) {\n light_sample_sphere(light, shadingPoint, samplePoint, result);\n vec3 surfacePoint = shadingPoint + result.direction * result.dist;\n result.emission *= evaluateSpotEmissionMultiplier(\n light,\n normalize(shadingPoint - surfacePoint)\n );\n}\n\nvoid sampleAnalyticLight(\n in Light light,\n in vec3 shadingPoint,\n in vec2 samplePoint,\n inout LightSampleRec result\n) {\n int lightType = int(light.type);\n#ifdef HAS_RECT_LIGHTS\n if (lightType == RECT_LIGHT) {\n light_sample_rect(light, shadingPoint, samplePoint, result);\n return;\n }\n#endif\n#ifdef HAS_SPHERE_LIGHTS\n if (lightType == SPHERE_LIGHT) {\n light_sample_sphere(light, shadingPoint, samplePoint, result);\n return;\n }\n#endif\n#ifdef HAS_SPOT_LIGHTS\n if (lightType == SPOT_LIGHT) {\n light_sample_spot(light, shadingPoint, samplePoint, result);\n return;\n }\n#endif\n#ifdef HAS_DIRECTIONAL_LIGHTS\n if (lightType == DIRECTIONAL_LIGHT) {\n light_sample_directional(light, shadingPoint, result);\n }\n#endif\n}\n#endif\n\nvoid sampleEnvLight(in vec2 samplePoint, inout LightSampleRec result) {\n vec2 uv;\n result.direction = sampleEnvmap(samplePoint, uv, result.pdf);\n result.emission = textureLinear(envMap, uv).rgb;\n result.dist = INF;\n}\n\nvoid sampleLight(\n in vec3 shadingPoint,\n in vec3 randomSampleValue,\n inout LightSampleRec result,\n bool distByIntensity\n) {\n result.isDelta = false;\n float selector = randomSampleValue.z;\n bool choseEnvironment = false;\n#ifdef USE_ENVMAP\n choseEnvironment = selector < envLightSelectionPmf;\n if (choseEnvironment) {\n sampleEnvLight(randomSampleValue.xy, result);\n result.pdf *= envLightSelectionPmf;\n }\n#endif\n\n#ifdef NUM_LIGHTS\n if (!choseEnvironment) {\n int selectedIndex = NUM_LIGHTS - 1;\n for (int index = 0; index < NUM_LIGHTS; index++) {\n if (selector < fetchLight(index).selectionCdf) {\n selectedIndex = index;\n break;\n }\n }\n Light selectedLight = fetchLight(selectedIndex);\n sampleAnalyticLight(\n selectedLight,\n shadingPoint,\n randomSampleValue.xy,\n result\n );\n result.pdf *= selectedLight.selectionPmf;\n }\n#endif\n}\n`;\n"]}
1
+ {"version":3,"file":"sampleLight.glsl.js","sourceRoot":"","sources":["../../../../src/renderer/glsl/chunks/sampleLight.glsl.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,yBAAyB,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,eAAe,IAAI,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2NjB,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6CT,CAAC","sourcesContent":["import emissive from './emissiveLight.glsl.js';\nimport { glsl } from '../../shader.js';\n\nexport default glsl`\n#ifdef NUM_LIGHTS\nvoid light_sample_sphere(\n in Light light,\n in vec3 shadingPoint,\n in vec2 samplePoint,\n inout LightSampleRec result\n) {\n vec3 toCenter = light.position - shadingPoint;\n float centerDistance = length(toCenter);\n if (light.radius <= 0.0) {\n if (centerDistance <= 1e-6) {\n result.direction = vec3(0.0, 0.0, 1.0);\n result.normal = vec3(0.0, 0.0, -1.0);\n result.dist = 0.0;\n result.pdf = 1.0;\n result.emission = vec3(0.0);\n result.isDelta = true;\n return;\n }\n result.direction = toCenter / centerDistance;\n result.normal = -result.direction;\n result.dist = centerDistance;\n result.pdf = 1.0;\n result.emission = light.emission / max(centerDistance * centerDistance, 1e-8);\n result.isDelta = true;\n return;\n }\n float radius = max(light.radius, 1e-6);\n result.isDelta = false;\n vec3 direction;\n\n if (centerDistance <= radius) {\n float z = 1.0 - 2.0 * samplePoint.x;\n float radial = sqrt(max(0.0, 1.0 - z * z));\n float azimuth = TWOPI * samplePoint.y;\n direction = vec3(radial * cos(azimuth), radial * sin(azimuth), z);\n result.pdf = INV4PI;\n }\n else {\n vec3 axis = toCenter / centerDistance;\n float sineLimitSquared = min(\n 1.0,\n radius * radius / (centerDistance * centerDistance)\n );\n float cosineLimit = sqrt(max(0.0, 1.0 - sineLimitSquared));\n // Keep the small solid angle and sampled sine without subtracting\n // nearly equal floats; otherwise small emitters produce irradiance bands.\n float oneMinusCosineLimit = sineLimitSquared / (1.0 + cosineLimit);\n float oneMinusCosine = samplePoint.x * oneMinusCosineLimit;\n float cosine = 1.0 - oneMinusCosine;\n float sine = sqrt(max(0.0, oneMinusCosine * (2.0 - oneMinusCosine)));\n float azimuth = TWOPI * samplePoint.y;\n vec3 tangent;\n vec3 bitangent;\n sampling_orthonormal_basis(axis, tangent, bitangent);\n direction = axis * cosine\n + tangent * (sine * cos(azimuth))\n + bitangent * (sine * sin(azimuth));\n result.pdf = 1.0 / max(TWOPI * oneMinusCosineLimit, 1e-8);\n }\n\n float projectedCenter = dot(direction, toCenter);\n float discriminant = projectedCenter * projectedCenter\n - dot(toCenter, toCenter) + radius * radius;\n float root = sqrt(max(0.0, discriminant));\n float nearDistance = projectedCenter - root;\n float farDistance = projectedCenter + root;\n result.dist = nearDistance > 1e-6 ? nearDistance : farDistance;\n result.direction = direction;\n vec3 surfacePoint = shadingPoint + direction * result.dist;\n result.normal = normalize(surfacePoint - light.position);\n result.emission = light.emission;\n}\n\nvoid light_apply_rect_texture(\n in Light light,\n in vec3 surfacePoint,\n in vec3 lowerLeft,\n inout LightSampleRec result\n) {\n#ifdef NUM_MAPS\n if (light.textureIndex >= 0) {\n float width = length(light.u);\n float height = length(light.v);\n vec3 relative = surfacePoint - lowerLeft;\n vec2 uv = vec2(\n dot(relative, light.u / width) / width,\n dot(relative, light.v / height) / height\n );\n result.emission *= sampleMap(light.textureIndex, uv).rgb;\n }\n#endif\n}\n\nvoid light_sample_rect(\n in Light light,\n in vec3 shadingPoint,\n in vec2 samplePoint,\n inout LightSampleRec result\n) {\n vec3 normal = normalize(cross(light.u, light.v));\n vec3 lowerLeft = light.position - 0.5 * (light.u + light.v);\n float spread = clamp(light.spread, 0.0, 1.0);\n\n if (spread <= 0.001) {\n float planeDistance = dot(normal, shadingPoint - light.position);\n vec3 surfacePoint = shadingPoint - normal * planeDistance;\n vec3 relative = surfacePoint - lowerLeft;\n float width = length(light.u);\n float height = length(light.v);\n vec2 uv = vec2(\n dot(relative, light.u / width) / width,\n dot(relative, light.v / height) / height\n );\n if (planeDistance <= 0.0 || any(lessThan(uv, vec2(0.0)))\n || any(greaterThan(uv, vec2(1.0)))) {\n result.emission = vec3(0.0);\n result.pdf = 0.0;\n return;\n }\n result.direction = -normal;\n result.dist = planeDistance;\n result.normal = normal;\n result.emission = light.emission;\n result.pdf = 1.0;\n result.isDelta = true;\n light_apply_rect_texture(light, surfacePoint, lowerLeft, result);\n return;\n }\n\n vec3 surfacePoint = lowerLeft\n + light.u * samplePoint.x\n + light.v * samplePoint.y;\n vec3 offset = surfacePoint - shadingPoint;\n float distanceSquared = dot(offset, offset);\n result.dist = sqrt(distanceSquared);\n result.direction = offset / result.dist;\n result.normal = normal;\n float emitterCosine = dot(-result.direction, normal);\n float spreadCosine = cos(0.5 * PI * spread);\n if (emitterCosine <= 0.0 || emitterCosine < spreadCosine) {\n result.emission = vec3(0.0);\n result.pdf = 0.0;\n return;\n }\n result.emission = light.emission;\n result.pdf = distanceSquared / max(light.area * emitterCosine, 1e-8);\n light_apply_rect_texture(light, surfacePoint, lowerLeft, result);\n}\n\nvoid light_sample_directional(\n in Light light,\n in vec3 shadingPoint,\n inout LightSampleRec result\n) {\n result.direction = normalize(-light.u);\n result.normal = -result.direction;\n result.emission = light.emission;\n result.dist = INF;\n result.pdf = 1.0;\n result.isDelta = true;\n}\n\nvoid light_sample_spot(\n in Light light,\n in vec3 shadingPoint,\n in vec2 samplePoint,\n inout LightSampleRec result\n) {\n light_sample_sphere(light, shadingPoint, samplePoint, result);\n vec3 surfacePoint = shadingPoint + result.direction * result.dist;\n result.emission *= evaluateSpotEmissionMultiplier(\n light,\n normalize(shadingPoint - surfacePoint)\n );\n}\n\nvoid sampleAnalyticLight(\n in Light light,\n in vec3 shadingPoint,\n in vec2 samplePoint,\n inout LightSampleRec result\n) {\n int lightType = int(light.type);\n#ifdef HAS_RECT_LIGHTS\n if (lightType == RECT_LIGHT) {\n light_sample_rect(light, shadingPoint, samplePoint, result);\n return;\n }\n#endif\n#ifdef HAS_SPHERE_LIGHTS\n if (lightType == SPHERE_LIGHT) {\n light_sample_sphere(light, shadingPoint, samplePoint, result);\n return;\n }\n#endif\n#ifdef HAS_SPOT_LIGHTS\n if (lightType == SPOT_LIGHT) {\n light_sample_spot(light, shadingPoint, samplePoint, result);\n return;\n }\n#endif\n#ifdef HAS_DIRECTIONAL_LIGHTS\n if (lightType == DIRECTIONAL_LIGHT) {\n light_sample_directional(light, shadingPoint, result);\n }\n#endif\n}\n#endif\n\nvoid sampleEnvLight(in vec2 samplePoint, inout LightSampleRec result) {\n vec2 uv;\n result.direction = sampleEnvmap(samplePoint, uv, result.pdf);\n result.emission = textureLinear(envMap, uv).rgb;\n result.dist = INF;\n}\n\n#ifdef HAS_EMISSIVE_LIGHTS\n${emissive}\n#endif\n\nvoid sampleLight(\n in vec3 shadingPoint,\n in vec3 randomSampleValue,\n inout LightSampleRec result,\n bool distByIntensity\n) {\n#ifdef HAS_EMISSIVE_LIGHTS\n sampleEmissiveSceneLight(shadingPoint,randomSampleValue,result);return;\n#endif\n result.sourceType=0;result.sourceIndex=-1;\n result.isDelta = false;\n float selector = randomSampleValue.z;\n bool choseEnvironment = false;\n#ifdef USE_ENVMAP\n choseEnvironment = selector < envLightSelectionPmf;\n if (choseEnvironment) {\n sampleEnvLight(randomSampleValue.xy, result);\n result.pdf *= envLightSelectionPmf;\n }\n#endif\n\n#ifdef NUM_LIGHTS\n if (!choseEnvironment) {\n int selectedIndex = NUM_LIGHTS - 1;\n for (int index = 0; index < NUM_LIGHTS; index++) {\n if (selector < fetchLight(index).selectionCdf) {\n selectedIndex = index;\n break;\n }\n }\n result.sourceType=2;result.sourceIndex=selectedIndex;\n Light selectedLight = fetchLight(selectedIndex);\n sampleAnalyticLight(\n selectedLight,\n shadingPoint,\n randomSampleValue.xy,\n result\n );\n result.pdf *= selectedLight.selectionPmf;\n }\n#endif\n}\n`;\n"]}
@@ -1,2 +1,3 @@
1
+ export declare function createSampleMaterialGlsl(fragments?: Readonly<Record<string, string>>, channelIndependentLight?: boolean): string;
1
2
  declare const _default: string;
2
3
  export default _default;
@@ -1,42 +1,64 @@
1
1
  // Estimate the direct lighting integral using multiple importance sampling
2
2
  // http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Direct_Lighting.html#EstimatingtheDirectLightingIntegral
3
3
  import { glsl } from '../../shader.js';
4
- export default glsl `
5
- vec3 ta(SurfaceInteraction si, OpenPbrResolvedMaterial mat, ag prepared, inout Path aa, vec3 ffnormal, bool eM) {
6
- float lY = 1.0;
7
- vec3 lV = vec3(dZ(cE(LIGHT_POSITION)), dp(cE(LIGHT_SELECT)));
4
+ export function createSampleMaterialGlsl(fragments = {}, channelIndependentLight = false) {
5
+ return glsl `
6
+ float emissiveHitMisWeight(SurfaceInteraction si,Path path) {
7
+
8
+ float Ar=dot(si.faceNormal,-path.ray.d);
9
+ if(Ar<=0.0&&fetchMatData(si.materialIndex*MAT_DATA_SIZE+MAT_ROW_ALPHA).z<0.5)return 0.0;
10
+ #ifdef HAS_EMISSIVE_LIGHTS
11
+ if(!path.fromEye && emissiveWeightTotal>0.0) {
12
+ vec3 emission=fetchMatData(si.materialIndex*MAT_DATA_SIZE+MAT_ROW_EMISSION).rgb;
13
+ float value=dot(emission,vec3(.2126,.7152,.0722)),cosine=dot(si.faceNormal,-path.ray.d);
14
+ if(value>0.0&&cosine>0.0){float d=distance(si.position,path.ray.o);return aG(path.scatteringPdf,value/emissiveWeightTotal*d*d/cosine);}
15
+ }
16
+ #endif
17
+ return 1.0;
18
+ }
19
+
20
+ vec3 qY(SurfaceInteraction si, OpenPbrResolvedMaterial mat, OpenPbrPreparedBsdf prepared, inout Path path, vec3 ffnormal, bool isSurface) {
21
+ float mz = 1.0;
22
+ vec3 ob = vec3(sample2D(aX(LIGHT_POSITION)), sample1D(aX(LIGHT_SELECT)));
8
23
 
9
24
  LightSampleRec lightSample;
10
- sampleLight(si.position, lV, lightSample, false);
11
- lightSample.emission = aj(lightSample.emission, bp);
25
+ sampleLight(si.position, ob, lightSample, false);${fragments['sample0'] ?? ''}
26
+ ${channelIndependentLight ? /* glsl */ ` if (dispersionWavelengths == 1) {
27
+ lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathChannel);
28
+ }` : /* glsl */ ` lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathChannel);`}
12
29
 
13
30
  vec3 lightDir = lightSample.direction;
14
- vec3 qY = -aa.ray.d;
15
- float fA = lightSample.pdf;
31
+ vec3 sg = -path.ray.d;
32
+ float lightPdf = lightSample.pdf;
16
33
 
17
34
 
18
35
 
19
36
 
20
37
  float cosThetaL = dot(ffnormal, lightDir);
21
38
  #ifdef USE_COAT_NORMAL_FRAMES
22
- if (eM && mat.coatNormalEnabled) { cosThetaL = dot(mat.geometricNormal, lightDir); }
39
+ if (isSurface && mat.coatNormalEnabled) { cosThetaL = dot(mat.geometricNormal, lightDir); }
23
40
  #endif
24
41
 
25
- if (fA <= 0.0 || max(max(lightSample.emission.x, lightSample.emission.y), lightSample.emission.z) <= 0.0) {
42
+ if (lightPdf <= 0.0 || max(max(lightSample.emission.x, lightSample.emission.y), lightSample.emission.z) <= 0.0) {
26
43
  return vec3(0.0);
27
44
  }
28
45
 
29
- float scatteringPdf = 0.0;
46
+ ${channelIndependentLight ? /* glsl */ `
47
+
48
+ if (dispersionWavelengths != 1) {
49
+ lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathChannel);
50
+ }
51
+ ` : ''} float scatteringPdf = 0.0;
30
52
  vec3 f = vec3(0.0);
31
- if (eM) {
53
+ if (isSurface) {
32
54
  if (cosThetaL <= 0.0 && mat.transmissionWeight <= 0.0 && mat.subsurfaceWeight <= 0.0) {
33
55
  return vec3(0.0);
34
56
  }
35
- f = bO(prepared, lightDir, scatteringPdf);
57
+ f = openpbr_eval_prepared(prepared, lightDir, scatteringPdf);
36
58
  }
37
59
  else {
38
- scatteringPdf = bL(
39
- dot(qY, lightDir),
60
+ scatteringPdf = ba(
61
+ dot(sg, lightDir),
40
62
  si.mediumAnisotropy
41
63
  );
42
64
  f = vec3(scatteringPdf);
@@ -46,83 +68,89 @@ if (scatteringPdf <= 0.0 || max(max(f.x, f.y), f.z) <= 0.0) {
46
68
  return vec3(0.0);
47
69
  }
48
70
 
49
- Ray ns;
50
- vec3 hw = si.position + EPS * lightDir;
51
- if (eM) {
52
- const float ch = 0.1;
53
- float dL = dot(si.normal, lightDir);
71
+ Ray oa;
72
+ vec3 eY = si.position + EPS * lightDir;
73
+ if (isSurface) {
74
+ const float shadowTerminatorCutoff = 0.1;
75
+ float dl = dot(si.normal, lightDir);
54
76
  #ifdef USE_COAT_NORMAL_FRAMES
55
- if (mat.coatNormalEnabled) { dL = dot(si.faceNormal, lightDir); }
77
+ if (mat.coatNormalEnabled) { dl = dot(si.faceNormal, lightDir); }
56
78
  #endif
57
- vec3 geometricNormal = dL < 0.0 ? -si.faceNormal : si.faceNormal;
58
- dL = abs(dL);
59
- float iq = dot(geometricNormal, lightDir);
60
- float pq = dL < ch
79
+ vec3 geometricNormal = dl < 0.0 ? -si.faceNormal : si.faceNormal;
80
+ dl = abs(dl);
81
+ float iw = dot(geometricNormal, lightDir);
82
+ float qo = dl < shadowTerminatorCutoff
61
83
  ? clamp(
62
- 2.0 - (iq + dL) / ch,
84
+ 2.0 - (iw + dl) / shadowTerminatorCutoff,
63
85
  0.0,
64
86
  1.0
65
87
  )
66
- : clamp(1.0 - iq / ch, 0.0, 1.0);
67
- hw += si.shadowOffset * pq;
88
+ : clamp(1.0 - iw / shadowTerminatorCutoff, 0.0, 1.0);
89
+ eY += si.shadowOffset * qo;
90
+ }
91
+ float rM=lightSample.dist-EPS;
92
+ vec3 qS=lightDir;
93
+ if(lightSample.sourceType==1){
94
+ vec3 endpoint=si.position+lightDir*lightSample.dist+EPS*lightSample.normal;
95
+ qS=normalize(endpoint-eY);rM=distance(endpoint,eY);
68
96
  }
69
- gC(ns, hw, lightDir);
70
- if (intersectSceneShadow(ns, lightSample.dist - EPS, si.triangleIndex)) {
97
+ initRay(oa, eY, qS);
98
+ if (intersectSceneShadow(oa, rM, si.triangleIndex)) {
71
99
  return vec3(0.0);
72
100
  }
73
101
 
74
102
  #ifdef USE_ENVMAP
75
103
 
76
104
 
77
- if (eM && cosThetaL < 0.0 && lV.z < envLightSelectionPmf) {
78
- vec4 background = cG(ns.o, lightDir);
79
- lightSample.emission = aj(background.rgb * background.a, bp);
105
+ if (isSurface && cosThetaL < 0.0 && lightSample.sourceType == 0) {
106
+ vec4 background = cq(oa.o, lightDir);
107
+ lightSample.emission = sampling_spectral_rgb_filter(background.rgb * background.a, pathChannel);
80
108
  }
81
109
  #endif
82
110
 
83
111
 
84
112
 
85
- float fl = lightSample.isDelta
113
+ float misWeight = lightSample.isDelta
86
114
  ? 1.0
87
- : aK(fA, scatteringPdf);
88
- return fl > 0.0
89
- ? fl * lightSample.emission * f / fA
115
+ : aG(lightPdf, scatteringPdf);
116
+ ${fragments['sample1'] ?? ''} return misWeight > 0.0
117
+ ? misWeight * lightSample.emission * f / lightPdf
90
118
  : vec3(0.0);
91
119
  }
92
120
 
93
121
  #ifdef USE_COAT_NORMAL_FRAMES
94
- vec3 fT(vec3 qt, vec3 face, vec3 view) {
122
+ vec3 fQ(vec3 ru, vec3 face, vec3 view) {
95
123
  bool front = dot(face, view) >= 0.0;
96
- vec3 vP = front ? face : -face;
97
- vec3 sc = front ? qt : -qt;
98
- if (dot(qt, face) <= 0.0 || dot(sc, view) <= 1e-6) { return vP; }
99
- return sc;
124
+ vec3 yc = front ? face : -face;
125
+ vec3 tv = front ? ru : -ru;
126
+ if (dot(ru, face) <= 0.0 || dot(tv, view) <= 1e-6) { return yc; }
127
+ return tv;
100
128
  }
101
129
  #endif
102
- void mL(inout SurfaceInteraction si, OpenPbrResolvedMaterial mat, inout Path aa) {
103
- vec3 vR = vec3(dZ(cE(BSDF_DIRECTION)), dp(cE(BSDF_LOBE)));
130
+ void nB(inout SurfaceInteraction si, OpenPbrResolvedMaterial mat, inout Path path) {
131
+ vec3 yh = vec3(sample2D(aX(BSDF_DIRECTION)), sample1D(aX(BSDF_LOBE)));
104
132
  #ifdef USE_COAT_NORMAL_FRAMES
105
- vec3 bK = si.faceNormal;
106
- vec3 nB = si.normal;
133
+ vec3 bC = si.faceNormal;
134
+ vec3 oh = si.normal;
107
135
  #endif
108
- float sO = -dot(si.faceNormal, aa.ray.d);
109
- float tV = -dot(si.normal, aa.ray.d);
136
+ float uk = -dot(si.faceNormal, path.ray.d);
137
+ float vH = -dot(si.normal, path.ray.d);
110
138
  if ((mat.transmissionWeight > 0.0 || mat.subsurfaceWeight > 0.0) && mat.thinWalled) {
111
139
 
112
- if (sO < 0.0) {
140
+ if (uk < 0.0) {
113
141
  si.faceNormal = -si.faceNormal;
114
- sO = -sO;
142
+ uk = -uk;
115
143
  }
116
- if (tV < 0.0) {
144
+ if (vH < 0.0) {
117
145
  si.normal = -si.normal;
118
- tV = -tV;
146
+ vH = -vH;
119
147
  }
120
148
  }
121
149
 
122
150
 
123
- bool qM = sO >= 0.0 && tV < 0.0;
124
- float ndv = qM ? sO : tV;
125
- vec3 normal = qM ? si.faceNormal : si.normal;
151
+ bool rS = uk >= 0.0 && vH < 0.0;
152
+ float ndv = rS ? uk : vH;
153
+ vec3 normal = rS ? si.faceNormal : si.normal;
126
154
 
127
155
  mat.inside = ndv <= 0.0 && !mat.thinWalled;
128
156
 
@@ -130,140 +158,152 @@ mat.relativeIor = ndv > 0.0 ? (1.0 / mat.specularIor) : mat.specularIor;
130
158
  vec3 ffnormal = ndv >= 0.0 ? normal : -normal;
131
159
  #ifdef USE_COAT_NORMAL_FRAMES
132
160
  if (mat.coatNormalEnabled) {
133
- vec3 view = -aa.ray.d;
134
- float gp = dot(bK, view);
135
- mat.geometricNormal = gp >= 0.0 ? bK : -bK;
136
- ffnormal = fT(nB, bK, view);
137
- mat.coatNormal = fT(si.coatNormal, bK, view);
138
- mat.inside = gp <= 0.0 && !mat.thinWalled;
139
- mat.relativeIor = (gp > 0.0 || mat.thinWalled) ? 1.0 / mat.specularIor : mat.specularIor;
161
+ vec3 view = -path.ray.d;
162
+ float gr = dot(bC, view);
163
+ mat.geometricNormal = gr >= 0.0 ? bC : -bC;
164
+ ffnormal = fQ(oh, bC, view);
165
+ mat.coatNormal = fQ(si.coatNormal, bC, view);
166
+ mat.inside = gr <= 0.0 && !mat.thinWalled;
167
+ mat.relativeIor = (gr > 0.0 || mat.thinWalled) ? 1.0 / mat.specularIor : mat.specularIor;
140
168
  }
141
169
  #endif
142
170
 
143
171
 
144
172
  float scatteringPdf;
145
- vec3 dH;
146
- aa.scatteringIsDelta = false;
147
- bool bs = false;
148
- bool hC = false;
149
- ag prepared;
173
+ vec3 di;
174
+ path.scatteringIsDelta = false;
175
+ bool mediumSampled = false;
176
+ bool hE = false;
177
+ OpenPbrPreparedBsdf prepared;
150
178
 
151
179
  #ifdef HAS_MEDIUM
152
180
  int mediumType = si.mediumType;
153
- float d = distance(si.position, aa.ray.o);
154
- vec3 os = aa.ray.o;
181
+ float d = distance(si.position, path.ray.o);
182
+ vec3 pd = path.ray.o;
155
183
  vec3 extinction = si.mediumExtinction;
156
184
  vec3 scattering = min(si.mediumScattering, extinction);
157
- float tR = max(max(extinction.x, extinction.y), extinction.z);
158
- if (mediumType > 0 && tR > 0.0) {
185
+ float vD = max(max(extinction.x, extinction.y), extinction.z);
186
+ if (mediumType > 0 && vD > 0.0) {
159
187
 
160
188
 
161
189
 
162
190
 
163
- int oi = min(int(dp(cE(MEDIUM_CHANNEL)) * 3.0), 2);
164
- float fS = extinction[oi];
165
- float iH = fS > 0.0
166
- ? min(-log(max(dp(cE(MEDIUM_DISTANCE)), 1e-7)) / fS, d)
191
+ int oW = min(int(sample1D(aX(MEDIUM_CHANNEL)) * 3.0), 2);
192
+ float fP = extinction[oW];
193
+ float iO = fP > 0.0
194
+ ? min(-log(max(sample1D(aX(MEDIUM_DISTANCE)), 1e-7)) / fP, d)
167
195
  : d;
168
- bs = iH < d;
169
- vec3 transmittance = exp(-extinction * iH);
170
- vec3 oU = bs
196
+ mediumSampled = iO < d;
197
+ vec3 transmittance = exp(-extinction * iO);
198
+ vec3 density = mediumSampled
171
199
  ? extinction * transmittance
172
200
  : transmittance;
173
- float oE = max(
174
- (oU.x + oU.y + oU.z) / 3.0,
201
+ float mediumPdf = max(
202
+ (density.x + density.y + density.z) / 3.0,
175
203
  1e-8
176
204
  );
177
- if (bs) {
178
- aa.beta *= transmittance * scattering / oE;
205
+ if (mediumSampled) {
206
+ path.beta *= transmittance * scattering / mediumPdf;
179
207
 
180
- aa.ray.o = os + iH * aa.ray.d;
181
- si.position = aa.ray.o;
182
- aa.li += ta(si, mat, prepared, aa, ffnormal, false) * aa.beta;
208
+ if (all(equal(path.beta, vec3(0.0)))) { path.abort = true; return; }
183
209
 
210
+ path.ray.o = pd + iO * path.ray.d;
211
+ si.position = path.ray.o;
184
212
 
185
- dH = fH(
186
- -aa.ray.d,
213
+ si.triangleIndex = -1;
214
+ si.instanceIndex = -1;
215
+ path.li += qY(si, mat, prepared, path, ffnormal, false) * path.beta;
216
+
217
+
218
+ di = dQ(
219
+ -path.ray.d,
187
220
  si.mediumAnisotropy,
188
- dZ(cE(PHASE_DIRECTION))
221
+ sample2D(aX(PHASE_DIRECTION))
189
222
  );
190
- scatteringPdf = bL(
191
- dot(dH, -aa.ray.d),
223
+ scatteringPdf = ba(
224
+ dot(di, -path.ray.d),
192
225
  si.mediumAnisotropy
193
226
  );
194
227
  }
195
228
  else {
196
- aa.beta *= transmittance / oE;
229
+ path.beta *= transmittance / mediumPdf;
230
+
231
+ if (all(equal(path.beta, vec3(0.0)))) { path.abort = true; return; }
197
232
  }
198
233
  }
199
234
  #endif
200
235
 
201
236
 
202
- if (!bs) {
203
- aa.li += mat.emission * aa.beta;
237
+ if (!mediumSampled) {
238
+
239
+ vec3 surfaceEmission = sampling_spectral_rgb_filter(mat.emission, pathChannel);
240
+ ${fragments['sample2'] ?? ''}path.li += emissiveHitMisWeight(si,path) * surfaceEmission * path.beta;${fragments['sample3'] ?? ''}
204
241
  if (mat.materialType == UNLIT) {
205
- aa.abort = true;
242
+ path.abort = true;
206
243
  return;
207
244
  }
208
- vec3 qJ = vec3(0.0);
245
+ vec3 rP = vec3(0.0);
209
246
  #ifdef USE_TANGENT
210
- qJ = si.tangent;
247
+ rP = si.tangent;
211
248
  #endif
212
249
  mat.directionTangent = si.directionTangent;
213
250
  mat.directionBitangent = si.directionBitangent;
214
251
  mat.geometryTangent = si.geometryTangent;
215
252
  mat.geometryBitangent = si.geometryBitangent;
216
- prepared = ds(qJ, mat, -aa.ray.d, ffnormal);
217
- aa.li += ta(si, mat, prepared, aa, ffnormal, true) * aa.beta;
218
-
253
+ prepared = bX(rP, mat, -path.ray.d, ffnormal);
254
+ path.li += qY(si, mat, prepared, path, ffnormal, true) * path.beta;
255
+ ${fragments['sample4'] ?? ''}
219
256
  bool isNextRefraction;
220
- vec3 f = eN(
257
+ vec3 f = dr(
221
258
  prepared,
222
- vR,
223
- dH,
259
+ yh,
260
+ di,
224
261
  scatteringPdf,
225
262
  isNextRefraction
226
263
  );
227
264
 
228
- aa.scatteringIsDelta = !prepared.material.thinWalled &&
265
+ path.scatteringIsDelta = !prepared.material.thinWalled &&
229
266
  abs(prepared.material.relativeIor - 1.0) <= 1e-6 &&
230
267
  prepared.probabilities[OPENPBR_LOBE_TRANSMISSION] >= 1.0 - 1e-6;
231
268
 
232
269
 
233
270
 
234
271
  if (!(scatteringPdf > 0.0) || any(isnan(f)) || any(isinf(f)) ||
235
- dot(dH, dH) < 0.5) {
236
- aa.scatteringPdf = 0.0;
237
- aa.abort = true;
272
+ dot(di, di) < 0.5) {
273
+ path.scatteringPdf = 0.0;
274
+ path.abort = true;
238
275
  return;
239
276
  }
240
- aa.beta *= f / scatteringPdf;
241
- hC = !mat.thinWalled &&
277
+ ${fragments['sample5'] ?? ''} path.beta *= f / scatteringPdf;
278
+
279
+ if (all(equal(path.beta, vec3(0.0)))) { path.abort = true; return; }
280
+ hE = !mat.thinWalled &&
242
281
  isNextRefraction;
243
- aa.isNextRefraction = isNextRefraction;
282
+ path.isNextRefraction = isNextRefraction;
244
283
 
245
284
 
246
- aa.ray.o = si.position + EPS * dH;
285
+ path.ray.o = si.position + EPS * di;
247
286
  #ifdef USE_COAT_NORMAL_FRAMES
248
- if (mat.coatNormalEnabled) { aa.ray.o = si.position + EPS * (dot(bK, dH) >= 0.0 ? bK : -bK); }
287
+ if (mat.coatNormalEnabled) { path.ray.o = si.position + EPS * (dot(bC, di) >= 0.0 ? bC : -bC); }
249
288
  #endif
250
289
  }
251
290
 
252
- aa.scatteringPdf = scatteringPdf;
253
- gC(aa.ray, aa.ray.o, dH);
254
- if (bs) {
255
- aa.isNextRefraction = false;
291
+ path.scatteringPdf = scatteringPdf;
292
+ initRay(path.ray, path.ray.o, di);
293
+ if (mediumSampled) {${fragments['sample6'] ?? ''}
294
+ path.isNextRefraction = false;
256
295
  }
257
- aa.fromEye = false;
296
+ path.fromEye = false;
258
297
 
259
298
  #ifdef HAS_MEDIUM
260
299
 
261
300
 
262
- if (!bs && hC && mat.mediumType > 0) {
263
- if (sO >= 0.0) {
301
+ if (!mediumSampled && hE && mat.mediumType > 0) {
302
+ if (uk >= 0.0) {
264
303
  si.mediumType = mat.mediumType;
265
304
  si.mediumExtinction = mat.mediumExtinction;
266
305
  si.mediumScattering = mat.mediumScattering;
306
+ path.scatteringMediumEntered = path.scatteringMediumEntered || any(greaterThan(mat.mediumScattering, vec3(0.0)));
267
307
  si.mediumAnisotropy = mat.mediumAnisotropy;
268
308
  }
269
309
  else {
@@ -276,4 +316,6 @@ si.mediumAnisotropy = 0.0;
276
316
  #endif
277
317
  }
278
318
  `;
319
+ }
320
+ export default createSampleMaterialGlsl();
279
321
  //# sourceMappingURL=sampleMaterial.glsl.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sampleMaterial.glsl.js","sourceRoot":"","sources":["../../../../src/renderer/glsl/chunks/sampleMaterial.glsl.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,iIAAiI;AAEjI,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,eAAe,IAAI,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkRlB,CAAC","sourcesContent":["// Estimate the direct lighting integral using multiple importance sampling\n// http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Direct_Lighting.html#EstimatingtheDirectLightingIntegral\n\nimport { glsl } from '../../shader.js';\nexport default glsl`\nvec3 DirectLight(SurfaceInteraction si, OpenPbrResolvedMaterial mat, OpenPbrPreparedBsdf prepared, inout Path path, vec3 ffnormal, bool isSurface) {\n float occluded = 1.0;\n vec3 lightRnd = vec3(sample2D(bounceDim(LIGHT_POSITION)), sample1D(bounceDim(LIGHT_SELECT)));\n\n LightSampleRec lightSample;\n sampleLight(si.position, lightRnd, lightSample, false);\n lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathWavelength);\n\n vec3 lightDir = lightSample.direction;\n vec3 viewDir = -path.ray.d;\n float lightPdf = lightSample.pdf;\n // Opaque surfaces are rendered two-sided by the core renderer. Use the\n // face-forward shading normal here as well, otherwise the early-out rejects\n // every direct-light sample seen from the back of a triangle (for example\n // the inside of an imported room wall).\n float cosThetaL = dot(ffnormal, lightDir);\n#ifdef USE_COAT_NORMAL_FRAMES\n if (isSurface && mat.coatNormalEnabled) { cosThetaL = dot(mat.geometricNormal, lightDir); }\n#endif\n\n if (lightPdf <= 0.0 || max(max(lightSample.emission.x, lightSample.emission.y), lightSample.emission.z) <= 0.0) {\n return vec3(0.0);\n }\n\n float scatteringPdf = 0.0;\n vec3 f = vec3(0.0);\n if (isSurface) {\n if (cosThetaL <= 0.0 && mat.transmissionWeight <= 0.0 && mat.subsurfaceWeight <= 0.0) {\n return vec3(0.0);\n }\n f = openpbr_eval_prepared(prepared, lightDir, scatteringPdf);\n }\n else {\n scatteringPdf = sampling_henyey_greenstein_phase(\n dot(viewDir, lightDir),\n si.mediumAnisotropy\n );\n f = vec3(scatteringPdf);\n }\n\n if (scatteringPdf <= 0.0 || max(max(f.x, f.y), f.z) <= 0.0) {\n return vec3(0.0);\n }\n\n Ray lightRay;\n vec3 shadowOrigin = si.position + EPS * lightDir;\n if (isSurface) {\n const float shadowTerminatorCutoff = 0.1;\n float normalLight = dot(si.normal, lightDir);\n#ifdef USE_COAT_NORMAL_FRAMES\n if (mat.coatNormalEnabled) { normalLight = dot(si.faceNormal, lightDir); }\n#endif\n vec3 geometricNormal = normalLight < 0.0 ? -si.faceNormal : si.faceNormal;\n normalLight = abs(normalLight);\n float geometricLight = dot(geometricNormal, lightDir);\n float offsetAmount = normalLight < shadowTerminatorCutoff\n ? clamp(\n 2.0 - (geometricLight + normalLight) / shadowTerminatorCutoff,\n 0.0,\n 1.0\n )\n : clamp(1.0 - geometricLight / shadowTerminatorCutoff, 0.0, 1.0);\n shadowOrigin += si.shadowOffset * offsetAmount;\n }\n initRay(lightRay, shadowOrigin, lightDir);\n if (intersectSceneShadow(lightRay, lightSample.dist - EPS, si.triangleIndex)) {\n return vec3(0.0);\n }\n\n#ifdef USE_ENVMAP\n // Match the endpoint used by a BSDF-sampled surface transmission, including\n // a separately displayed or grounded background and its coverage.\n if (isSurface && cosThetaL < 0.0 && lightRnd.z < envLightSelectionPmf) {\n vec4 background = sampleBackgroundFromRay(lightRay.o, lightDir);\n lightSample.emission = sampling_spectral_rgb_filter(background.rgb * background.a, pathWavelength);\n }\n#endif\n\n // Delta lights cannot be sampled by the BSDF strategy, so their MIS weight\n // is exactly one even when their light-selection PMF is small.\n float misWeight = lightSample.isDelta\n ? 1.0\n : sampling_power_heuristic(lightPdf, scatteringPdf);\n return misWeight > 0.0\n ? misWeight * lightSample.emission * f / lightPdf\n : vec3(0.0);\n}\n\n#ifdef USE_COAT_NORMAL_FRAMES\nvec3 coat_frame_normal(vec3 inputNormal, vec3 face, vec3 view) {\n bool front = dot(face, view) >= 0.0;\n vec3 ffFace = front ? face : -face;\n vec3 ffInput = front ? inputNormal : -inputNormal;\n if (dot(inputNormal, face) <= 0.0 || dot(ffInput, view) <= 1e-6) { return ffFace; }\n return ffInput;\n}\n#endif\nvoid SampleMaterial(inout SurfaceInteraction si, OpenPbrResolvedMaterial mat, inout Path path) {\n vec3 matRnd = vec3(sample2D(bounceDim(BSDF_DIRECTION)), sample1D(bounceDim(BSDF_LOBE)));\n#ifdef USE_COAT_NORMAL_FRAMES\n vec3 originalFace = si.faceNormal;\n vec3 originalNormal = si.normal;\n#endif\n float ndv1 = -dot(si.faceNormal, path.ray.d);\n float ndv2 = -dot(si.normal, path.ray.d);\n if ((mat.transmissionWeight > 0.0 || mat.subsurfaceWeight > 0.0) && mat.thinWalled) {\n // Always treat thin material as entering medium\n if (ndv1 < 0.0) {\n si.faceNormal = -si.faceNormal;\n ndv1 = -ndv1;\n }\n if (ndv2 < 0.0) {\n si.normal = -si.normal;\n ndv2 = -ndv2;\n }\n }\n // In same edge cases normal is not torwards the camera while we can still see the face.\n // We need to choose faceNormal in this case.\n bool useFaceN = ndv1 >= 0.0 && ndv2 < 0.0;\n float ndv = useFaceN ? ndv1 : ndv2;\n vec3 normal = useFaceN ? si.faceNormal : si.normal;\n\n mat.inside = ndv <= 0.0 && !mat.thinWalled;\n // In or out\n mat.relativeIor = ndv > 0.0 ? (1.0 / mat.specularIor) : mat.specularIor;\n vec3 ffnormal = ndv >= 0.0 ? normal : -normal;\n#ifdef USE_COAT_NORMAL_FRAMES\n if (mat.coatNormalEnabled) {\n vec3 view = -path.ray.d;\n float geometricView = dot(originalFace, view);\n mat.geometricNormal = geometricView >= 0.0 ? originalFace : -originalFace;\n ffnormal = coat_frame_normal(originalNormal, originalFace, view);\n mat.coatNormal = coat_frame_normal(si.coatNormal, originalFace, view);\n mat.inside = geometricView <= 0.0 && !mat.thinWalled;\n mat.relativeIor = (geometricView > 0.0 || mat.thinWalled) ? 1.0 / mat.specularIor : mat.specularIor;\n }\n#endif\n\n\n float scatteringPdf;\n vec3 scatterDir;\n path.scatteringIsDelta = false;\n bool mediumSampled = false;\n bool crossedBoundary = false;\n OpenPbrPreparedBsdf prepared;\n\n#ifdef HAS_MEDIUM\n int mediumType = si.mediumType;\n float d = distance(si.position, path.ray.o);\n vec3 segmentOrigin = path.ray.o;\n vec3 extinction = si.mediumExtinction;\n vec3 scattering = min(si.mediumScattering, extinction);\n float majorant = max(max(extinction.x, extinction.y), extinction.z);\n if (mediumType > 0 && majorant > 0.0) {\n // Sample one RGB extinction channel and divide by the mixture PDF. This\n // is the homogeneous-medium estimator used by PBRT and avoids the very\n // large exp((majorant - extinction) * distance) weights produced by\n // majorant tracking when OpenPBR SSS radii differ strongly by channel.\n int mediumChannel = min(int(sample1D(bounceDim(MEDIUM_CHANNEL)) * 3.0), 2);\n float channelExtinction = extinction[mediumChannel];\n float scatterDist = channelExtinction > 0.0\n ? min(-log(max(sample1D(bounceDim(MEDIUM_DISTANCE)), 1e-7)) / channelExtinction, d)\n : d;\n mediumSampled = scatterDist < d;\n vec3 transmittance = exp(-extinction * scatterDist);\n vec3 density = mediumSampled\n ? extinction * transmittance\n : transmittance;\n float mediumPdf = max(\n (density.x + density.y + density.z) / 3.0,\n 1e-8\n );\n if (mediumSampled) {\n path.beta *= transmittance * scattering / mediumPdf;\n // Move from the start of the segment, not from its end surface.\n path.ray.o = segmentOrigin + scatterDist * path.ray.d;\n si.position = path.ray.o;\n path.li += DirectLight(si, mat, prepared, path, ffnormal, false) * path.beta;\n\n // Pick a new direction based on the phase function\n scatterDir = sampling_henyey_greenstein(\n -path.ray.d,\n si.mediumAnisotropy,\n sample2D(bounceDim(PHASE_DIRECTION))\n );\n scatteringPdf = sampling_henyey_greenstein_phase(\n dot(scatterDir, -path.ray.d),\n si.mediumAnisotropy\n );\n }\n else {\n path.beta *= transmittance / mediumPdf;\n }\n }\n#endif\n\n // Direct lighting\n if (!mediumSampled) {\n path.li += mat.emission * path.beta;\n if (mat.materialType == UNLIT) {\n path.abort = true;\n return;\n }\n vec3 surfaceTangent = vec3(0.0);\n#ifdef USE_TANGENT\n surfaceTangent = si.tangent;\n#endif\n mat.directionTangent = si.directionTangent;\n mat.directionBitangent = si.directionBitangent;\n mat.geometryTangent = si.geometryTangent;\n mat.geometryBitangent = si.geometryBitangent;\n prepared = openpbr_prepare(surfaceTangent, mat, -path.ray.d, ffnormal);\n path.li += DirectLight(si, mat, prepared, path, ffnormal, true) * path.beta;\n // Sample BSDF for color and outgoing direction\n bool isNextRefraction;\n vec3 f = openpbr_sample_prepared(\n prepared,\n matRnd,\n scatterDir,\n scatteringPdf,\n isNextRefraction\n );\n // Null-boundary transmission is discrete and has no NEE competitor.\n path.scatteringIsDelta = !prepared.material.thinWalled &&\n abs(prepared.material.relativeIor - 1.0) <= 1e-6 &&\n prepared.probabilities[OPENPBR_LOBE_TRANSMISSION] >= 1.0 - 1e-6;\n // Match WebGPU: rejected VNDF/refraction proposals have no continuation.\n // Tracing their fallback direction with the incoming throughput invents\n // light paths, especially after total internal reflection inside glass.\n if (!(scatteringPdf > 0.0) || any(isnan(f)) || any(isinf(f)) ||\n dot(scatterDir, scatterDir) < 0.5) {\n path.scatteringPdf = 0.0;\n path.abort = true;\n return;\n }\n path.beta *= f / scatteringPdf;\n crossedBoundary = !mat.thinWalled &&\n isNextRefraction;\n path.isNextRefraction = isNextRefraction;\n // TODO prefer the opaque surface when transmission surface and opaque surface are overlapped.\n // Or the ray go out from transmission material will miss the opque surface.\n path.ray.o = si.position + EPS * scatterDir;\n#ifdef USE_COAT_NORMAL_FRAMES\n if (mat.coatNormalEnabled) { path.ray.o = si.position + EPS * (dot(originalFace, scatterDir) >= 0.0 ? originalFace : -originalFace); }\n#endif\n }\n\n path.scatteringPdf = scatteringPdf;\n initRay(path.ray, path.ray.o, scatterDir);\n if (mediumSampled) {\n path.isNextRefraction = false;\n }\n path.fromEye = false;\n\n#ifdef HAS_MEDIUM\n // A reflected ray stays in its current medium. Only a sampled transmission\n // event crosses the boundary of a medium-bearing closed mesh.\n if (!mediumSampled && crossedBoundary && mat.mediumType > 0) {\n if (ndv1 >= 0.0) {\n si.mediumType = mat.mediumType;\n si.mediumExtinction = mat.mediumExtinction;\n si.mediumScattering = mat.mediumScattering;\n si.mediumAnisotropy = mat.mediumAnisotropy;\n }\n else {\n si.mediumType = 0;\n si.mediumExtinction = vec3(0.0);\n si.mediumScattering = vec3(0.0);\n si.mediumAnisotropy = 0.0;\n }\n }\n#endif\n}\n`;\n"]}
1
+ {"version":3,"file":"sampleMaterial.glsl.js","sourceRoot":"","sources":["../../../../src/renderer/glsl/chunks/sampleMaterial.glsl.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,iIAAiI;AAEjI,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,MAAM,UAAU,wBAAwB,CAAC,YAA8C,EAAE,EAAE,uBAAuB,GAAG,KAAK;IAAI,OAAO,IAAI,CAAA;;;;;;;;;;;;;;;;;;;;mDAoB9E,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE;EACnF,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC;;EAEnC,CAAC,CAAC,CAAC,UAAU,CAAC,2FAA2F;;;;;;;;;;;;;;;;;;EAkB3G,uBAAuB,CAAC,CAAC,CAAC,UAAU,CAAC;;;;;CAKtC,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiEJ,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4HtB,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE,0EAA0E,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE;;;;;;;;;;;;;;;EAelI,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;EAsB1B,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE;;;;;;;;;;;;;;;;sBAgBJ,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;CAyBjD,CAAC;AACF,CAAC;AACD,eAAe,wBAAwB,EAAE,CAAC","sourcesContent":["// Estimate the direct lighting integral using multiple importance sampling\n// http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Direct_Lighting.html#EstimatingtheDirectLightingIntegral\n\nimport { glsl } from '../../shader.js';\nexport function createSampleMaterialGlsl(fragments: Readonly<Record<string, string>> = {}, channelIndependentLight = false) { return glsl`\nfloat emissiveHitMisWeight(SurfaceInteraction si,Path path) {\n // Secondary intersections remain two-sided, but one-sided emission does not.\n float facing=dot(si.faceNormal,-path.ray.d);\n if(facing<=0.0&&fetchMatData(si.materialIndex*MAT_DATA_SIZE+MAT_ROW_ALPHA).z<0.5)return 0.0;\n#ifdef HAS_EMISSIVE_LIGHTS\n if(!path.fromEye && emissiveWeightTotal>0.0) {\n vec3 emission=fetchMatData(si.materialIndex*MAT_DATA_SIZE+MAT_ROW_EMISSION).rgb;\n float value=dot(emission,vec3(.2126,.7152,.0722)),cosine=dot(si.faceNormal,-path.ray.d);\n if(value>0.0&&cosine>0.0){float d=distance(si.position,path.ray.o);return sampling_power_heuristic(path.scatteringPdf,value/emissiveWeightTotal*d*d/cosine);}\n }\n#endif\n return 1.0;\n}\n\nvec3 DirectLight(SurfaceInteraction si, OpenPbrResolvedMaterial mat, OpenPbrPreparedBsdf prepared, inout Path path, vec3 ffnormal, bool isSurface) {\n float occluded = 1.0;\n vec3 lightRnd = vec3(sample2D(bounceDim(LIGHT_POSITION)), sample1D(bounceDim(LIGHT_SELECT)));\n\n LightSampleRec lightSample;\n sampleLight(si.position, lightRnd, lightSample, false);${fragments['sample0'] ?? ''}\n${channelIndependentLight ? /* glsl */ ` if (dispersionWavelengths == 1) {\n lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathChannel);\n }` : /* glsl */ ` lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathChannel);`}\n\n vec3 lightDir = lightSample.direction;\n vec3 viewDir = -path.ray.d;\n float lightPdf = lightSample.pdf;\n // Opaque surfaces are rendered two-sided by the core renderer. Use the\n // face-forward shading normal here as well, otherwise the early-out rejects\n // every direct-light sample seen from the back of a triangle (for example\n // the inside of an imported room wall).\n float cosThetaL = dot(ffnormal, lightDir);\n#ifdef USE_COAT_NORMAL_FRAMES\n if (isSurface && mat.coatNormalEnabled) { cosThetaL = dot(mat.geometricNormal, lightDir); }\n#endif\n\n if (lightPdf <= 0.0 || max(max(lightSample.emission.x, lightSample.emission.y), lightSample.emission.z) <= 0.0) {\n return vec3(0.0);\n }\n\n${channelIndependentLight ? /* glsl */ ` // Test the full emission before filtering, so black spectral components\n // still consume the same visibility walk and random stream.\n if (dispersionWavelengths != 1) {\n lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, pathChannel);\n }\n` : ''} float scatteringPdf = 0.0;\n vec3 f = vec3(0.0);\n if (isSurface) {\n if (cosThetaL <= 0.0 && mat.transmissionWeight <= 0.0 && mat.subsurfaceWeight <= 0.0) {\n return vec3(0.0);\n }\n f = openpbr_eval_prepared(prepared, lightDir, scatteringPdf);\n }\n else {\n scatteringPdf = sampling_henyey_greenstein_phase(\n dot(viewDir, lightDir),\n si.mediumAnisotropy\n );\n f = vec3(scatteringPdf);\n }\n\n if (scatteringPdf <= 0.0 || max(max(f.x, f.y), f.z) <= 0.0) {\n return vec3(0.0);\n }\n\n Ray lightRay;\n vec3 shadowOrigin = si.position + EPS * lightDir;\n if (isSurface) {\n const float shadowTerminatorCutoff = 0.1;\n float normalLight = dot(si.normal, lightDir);\n#ifdef USE_COAT_NORMAL_FRAMES\n if (mat.coatNormalEnabled) { normalLight = dot(si.faceNormal, lightDir); }\n#endif\n vec3 geometricNormal = normalLight < 0.0 ? -si.faceNormal : si.faceNormal;\n normalLight = abs(normalLight);\n float geometricLight = dot(geometricNormal, lightDir);\n float offsetAmount = normalLight < shadowTerminatorCutoff\n ? clamp(\n 2.0 - (geometricLight + normalLight) / shadowTerminatorCutoff,\n 0.0,\n 1.0\n )\n : clamp(1.0 - geometricLight / shadowTerminatorCutoff, 0.0, 1.0);\n shadowOrigin += si.shadowOffset * offsetAmount;\n }\n float shadowDistance=lightSample.dist-EPS;\n vec3 shadowDirection=lightDir;\n if(lightSample.sourceType==1){\n vec3 endpoint=si.position+lightDir*lightSample.dist+EPS*lightSample.normal;\n shadowDirection=normalize(endpoint-shadowOrigin);shadowDistance=distance(endpoint,shadowOrigin);\n }\n initRay(lightRay, shadowOrigin, shadowDirection);\n if (intersectSceneShadow(lightRay, shadowDistance, si.triangleIndex)) {\n return vec3(0.0);\n }\n\n#ifdef USE_ENVMAP\n // Match the endpoint used by a BSDF-sampled surface transmission, including\n // a separately displayed or grounded background and its coverage.\n if (isSurface && cosThetaL < 0.0 && lightSample.sourceType == 0) {\n vec4 background = sampleBackgroundFromRay(lightRay.o, lightDir);\n lightSample.emission = sampling_spectral_rgb_filter(background.rgb * background.a, pathChannel);\n }\n#endif\n\n // Delta lights cannot be sampled by the BSDF strategy, so their MIS weight\n // is exactly one even when their light-selection PMF is small.\n float misWeight = lightSample.isDelta\n ? 1.0\n : sampling_power_heuristic(lightPdf, scatteringPdf);\n${fragments['sample1'] ?? ''} return misWeight > 0.0\n ? misWeight * lightSample.emission * f / lightPdf\n : vec3(0.0);\n}\n\n#ifdef USE_COAT_NORMAL_FRAMES\nvec3 coat_frame_normal(vec3 inputNormal, vec3 face, vec3 view) {\n bool front = dot(face, view) >= 0.0;\n vec3 ffFace = front ? face : -face;\n vec3 ffInput = front ? inputNormal : -inputNormal;\n if (dot(inputNormal, face) <= 0.0 || dot(ffInput, view) <= 1e-6) { return ffFace; }\n return ffInput;\n}\n#endif\nvoid SampleMaterial(inout SurfaceInteraction si, OpenPbrResolvedMaterial mat, inout Path path) {\n vec3 matRnd = vec3(sample2D(bounceDim(BSDF_DIRECTION)), sample1D(bounceDim(BSDF_LOBE)));\n#ifdef USE_COAT_NORMAL_FRAMES\n vec3 originalFace = si.faceNormal;\n vec3 originalNormal = si.normal;\n#endif\n float ndv1 = -dot(si.faceNormal, path.ray.d);\n float ndv2 = -dot(si.normal, path.ray.d);\n if ((mat.transmissionWeight > 0.0 || mat.subsurfaceWeight > 0.0) && mat.thinWalled) {\n // Always treat thin material as entering medium\n if (ndv1 < 0.0) {\n si.faceNormal = -si.faceNormal;\n ndv1 = -ndv1;\n }\n if (ndv2 < 0.0) {\n si.normal = -si.normal;\n ndv2 = -ndv2;\n }\n }\n // In same edge cases normal is not torwards the camera while we can still see the face.\n // We need to choose faceNormal in this case.\n bool useFaceN = ndv1 >= 0.0 && ndv2 < 0.0;\n float ndv = useFaceN ? ndv1 : ndv2;\n vec3 normal = useFaceN ? si.faceNormal : si.normal;\n\n mat.inside = ndv <= 0.0 && !mat.thinWalled;\n // In or out\n mat.relativeIor = ndv > 0.0 ? (1.0 / mat.specularIor) : mat.specularIor;\n vec3 ffnormal = ndv >= 0.0 ? normal : -normal;\n#ifdef USE_COAT_NORMAL_FRAMES\n if (mat.coatNormalEnabled) {\n vec3 view = -path.ray.d;\n float geometricView = dot(originalFace, view);\n mat.geometricNormal = geometricView >= 0.0 ? originalFace : -originalFace;\n ffnormal = coat_frame_normal(originalNormal, originalFace, view);\n mat.coatNormal = coat_frame_normal(si.coatNormal, originalFace, view);\n mat.inside = geometricView <= 0.0 && !mat.thinWalled;\n mat.relativeIor = (geometricView > 0.0 || mat.thinWalled) ? 1.0 / mat.specularIor : mat.specularIor;\n }\n#endif\n\n\n float scatteringPdf;\n vec3 scatterDir;\n path.scatteringIsDelta = false;\n bool mediumSampled = false;\n bool crossedBoundary = false;\n OpenPbrPreparedBsdf prepared;\n\n#ifdef HAS_MEDIUM\n int mediumType = si.mediumType;\n float d = distance(si.position, path.ray.o);\n vec3 segmentOrigin = path.ray.o;\n vec3 extinction = si.mediumExtinction;\n vec3 scattering = min(si.mediumScattering, extinction);\n float majorant = max(max(extinction.x, extinction.y), extinction.z);\n if (mediumType > 0 && majorant > 0.0) {\n // Sample one RGB extinction channel and divide by the mixture PDF. This\n // is the homogeneous-medium estimator used by PBRT and avoids the very\n // large exp((majorant - extinction) * distance) weights produced by\n // majorant tracking when OpenPBR SSS radii differ strongly by channel.\n int mediumChannel = min(int(sample1D(bounceDim(MEDIUM_CHANNEL)) * 3.0), 2);\n float channelExtinction = extinction[mediumChannel];\n float scatterDist = channelExtinction > 0.0\n ? min(-log(max(sample1D(bounceDim(MEDIUM_DISTANCE)), 1e-7)) / channelExtinction, d)\n : d;\n mediumSampled = scatterDist < d;\n vec3 transmittance = exp(-extinction * scatterDist);\n vec3 density = mediumSampled\n ? extinction * transmittance\n : transmittance;\n float mediumPdf = max(\n (density.x + density.y + density.z) / 3.0,\n 1e-8\n );\n if (mediumSampled) {\n path.beta *= transmittance * scattering / mediumPdf;\n // Zero throughput cannot contribute at subsequent vertices or light connections.\n if (all(equal(path.beta, vec3(0.0)))) { path.abort = true; return; }\n // Move from the start of the segment, not from its end surface.\n path.ray.o = segmentOrigin + scatterDist * path.ray.d;\n si.position = path.ray.o;\n // A volume vertex has no originating surface to skip on continuation or shadow rays.\n si.triangleIndex = -1;\n si.instanceIndex = -1;\n path.li += DirectLight(si, mat, prepared, path, ffnormal, false) * path.beta;\n\n // Pick a new direction based on the phase function\n scatterDir = sampling_henyey_greenstein(\n -path.ray.d,\n si.mediumAnisotropy,\n sample2D(bounceDim(PHASE_DIRECTION))\n );\n scatteringPdf = sampling_henyey_greenstein_phase(\n dot(scatterDir, -path.ray.d),\n si.mediumAnisotropy\n );\n }\n else {\n path.beta *= transmittance / mediumPdf;\n // Zero throughput cannot contribute at subsequent vertices or light connections.\n if (all(equal(path.beta, vec3(0.0)))) { path.abort = true; return; }\n }\n }\n#endif\n\n // Direct lighting\n if (!mediumSampled) {\n // Match NEE and background radiance when RGB wavelength passes are added.\n vec3 surfaceEmission = sampling_spectral_rgb_filter(mat.emission, pathChannel);\n ${fragments['sample2'] ?? ''}path.li += emissiveHitMisWeight(si,path) * surfaceEmission * path.beta;${fragments['sample3'] ?? ''}\n if (mat.materialType == UNLIT) {\n path.abort = true;\n return;\n }\n vec3 surfaceTangent = vec3(0.0);\n#ifdef USE_TANGENT\n surfaceTangent = si.tangent;\n#endif\n mat.directionTangent = si.directionTangent;\n mat.directionBitangent = si.directionBitangent;\n mat.geometryTangent = si.geometryTangent;\n mat.geometryBitangent = si.geometryBitangent;\n prepared = openpbr_prepare(surfaceTangent, mat, -path.ray.d, ffnormal);\n path.li += DirectLight(si, mat, prepared, path, ffnormal, true) * path.beta;\n${fragments['sample4'] ?? ''} // Sample BSDF for color and outgoing direction\n bool isNextRefraction;\n vec3 f = openpbr_sample_prepared(\n prepared,\n matRnd,\n scatterDir,\n scatteringPdf,\n isNextRefraction\n );\n // Null-boundary transmission is discrete and has no NEE competitor.\n path.scatteringIsDelta = !prepared.material.thinWalled &&\n abs(prepared.material.relativeIor - 1.0) <= 1e-6 &&\n prepared.probabilities[OPENPBR_LOBE_TRANSMISSION] >= 1.0 - 1e-6;\n // Match WebGPU: rejected VNDF/refraction proposals have no continuation.\n // Tracing their fallback direction with the incoming throughput invents\n // light paths, especially after total internal reflection inside glass.\n if (!(scatteringPdf > 0.0) || any(isnan(f)) || any(isinf(f)) ||\n dot(scatterDir, scatterDir) < 0.5) {\n path.scatteringPdf = 0.0;\n path.abort = true;\n return;\n }\n${fragments['sample5'] ?? ''} path.beta *= f / scatteringPdf;\n // Zero throughput cannot contribute at subsequent vertices or light connections.\n if (all(equal(path.beta, vec3(0.0)))) { path.abort = true; return; }\n crossedBoundary = !mat.thinWalled &&\n isNextRefraction;\n path.isNextRefraction = isNextRefraction;\n // TODO prefer the opaque surface when transmission surface and opaque surface are overlapped.\n // Or the ray go out from transmission material will miss the opque surface.\n path.ray.o = si.position + EPS * scatterDir;\n#ifdef USE_COAT_NORMAL_FRAMES\n if (mat.coatNormalEnabled) { path.ray.o = si.position + EPS * (dot(originalFace, scatterDir) >= 0.0 ? originalFace : -originalFace); }\n#endif\n }\n\n path.scatteringPdf = scatteringPdf;\n initRay(path.ray, path.ray.o, scatterDir);\n if (mediumSampled) {${fragments['sample6'] ?? ''}\n path.isNextRefraction = false;\n }\n path.fromEye = false;\n\n#ifdef HAS_MEDIUM\n // A reflected ray stays in its current medium. Only a sampled transmission\n // event crosses the boundary of a medium-bearing closed mesh.\n if (!mediumSampled && crossedBoundary && mat.mediumType > 0) {\n if (ndv1 >= 0.0) {\n si.mediumType = mat.mediumType;\n si.mediumExtinction = mat.mediumExtinction;\n si.mediumScattering = mat.mediumScattering;\n path.scatteringMediumEntered = path.scatteringMediumEntered || any(greaterThan(mat.mediumScattering, vec3(0.0)));\n si.mediumAnisotropy = mat.mediumAnisotropy;\n }\n else {\n si.mediumType = 0;\n si.mediumExtinction = vec3(0.0);\n si.mediumScattering = vec3(0.0);\n si.mediumAnisotropy = 0.0;\n }\n }\n#endif\n}\n`;\n}\nexport default createSampleMaterialGlsl();\n"]}
@@ -12,39 +12,39 @@ export default glsl `
12
12
 
13
13
  const uint SHADOW_CATCHER_LIGHT_SAMPLES = 4u;
14
14
 
15
- uint lc(uint candidate, uint slot) {
16
- return candidate == 0u ? cE(slot) : cE(9u + (candidate - 1u) * 3u + slot);
15
+ uint lA(uint candidate, uint slot) {
16
+ return candidate == 0u ? aX(slot) : aX(9u + (candidate - 1u) * 3u + slot);
17
17
  }
18
18
 
19
19
 
20
20
 
21
- vec2 sampleShadowCatcher(SurfaceInteraction si, int bounce, inout Path aa) {
22
- vec3 qY = -aa.ray.d;
21
+ vec2 sampleShadowCatcher(SurfaceInteraction si, int bounce, inout Path path) {
22
+ vec3 sg = -path.ray.d;
23
23
  vec2 counts = vec2(0.0);
24
24
 
25
25
  #if defined(NUM_LIGHTS) || defined(USE_ENVMAP)
26
26
  for (uint candidate = 0u; candidate < SHADOW_CATCHER_LIGHT_SAMPLES; candidate++) {
27
27
  LightSampleRec lightSample;
28
- vec3 lV = vec3(
29
- dZ(lc(candidate, LIGHT_POSITION)),
30
- dp(lc(candidate, LIGHT_SELECT))
28
+ vec3 ob = vec3(
29
+ sample2D(lA(candidate, LIGHT_POSITION)),
30
+ sample1D(lA(candidate, LIGHT_SELECT))
31
31
  );
32
- sampleLight(si.position, lV, lightSample, false);
32
+ sampleLight(si.position, ob, lightSample, false);
33
33
 
34
34
  vec3 lightDir = lightSample.direction;
35
35
  float cosThetaL = dot(si.normal, lightDir);
36
- float qB = dot(si.normal, qY) * cosThetaL;
37
- if (lightSample.pdf > 0.0 && qB >= 0.0) {
36
+ float rG = dot(si.normal, sg) * cosThetaL;
37
+ if (lightSample.pdf > 0.0 && rG >= 0.0) {
38
38
  if (dot(lightSample.emission, luminance) * abs(cosThetaL) > 0.0) {
39
39
  Ray ray;
40
- gC(ray, si.position + EPS * lightDir, lightDir);
41
- bool lY = intersectSceneShadow(ray, lightSample.dist - EPS, si.triangleIndex);
42
- counts += vec2(lY ? 1.0 : 0.0, 1.0);
40
+ initRay(ray, si.position + EPS * lightDir, lightDir);
41
+ bool mz = intersectSceneShadow(ray, lightSample.dist - EPS, si.triangleIndex);
42
+ counts += vec2(mz ? 1.0 : 0.0, 1.0);
43
43
  }
44
44
  }
45
45
  }
46
46
  #endif
47
- aa.fromEye = false;
47
+ path.fromEye = false;
48
48
  return counts;
49
49
  }
50
50
  `;