@meimu/mutracer 0.2.0 → 0.3.0

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 (211) hide show
  1. package/README.md +3 -0
  2. package/dist/assets/bvh.worker.js +1 -1
  3. package/dist/mutracer.umd.js +8949 -7915
  4. package/docs/api.md +42 -21
  5. package/docs/caustics.md +80 -0
  6. package/docs/materials.md +5 -4
  7. package/docs/progressive-rendering.md +50 -9
  8. package/docs/technical/continuous-spectrum.md +93 -0
  9. package/docs/updates.md +3 -1
  10. package/docs/viewer-checklist.md +65 -0
  11. package/docs/viewer.md +7 -5
  12. package/lib/Display.js +1 -1
  13. package/lib/Display.js.map +1 -1
  14. package/lib/Engine.d.ts +2 -0
  15. package/lib/Engine.js +47 -12
  16. package/lib/Engine.js.map +1 -1
  17. package/lib/Render.d.ts +61 -13
  18. package/lib/Render.js +169 -19
  19. package/lib/Render.js.map +1 -1
  20. package/lib/RenderLoop.d.ts +7 -3
  21. package/lib/RenderLoop.js +68 -44
  22. package/lib/RenderLoop.js.map +1 -1
  23. package/lib/main.d.ts +1 -1
  24. package/lib/main.js.map +1 -1
  25. package/lib/oidn.d.ts +1 -1
  26. package/lib/oidnBundledWeights.cdn.d.ts +2 -2
  27. package/lib/renderer/GPUTraceQueue.d.ts +2 -1
  28. package/lib/renderer/GPUTraceQueue.js +3 -1
  29. package/lib/renderer/GPUTraceQueue.js.map +1 -1
  30. package/lib/renderer/RenderingPipeline.d.ts +4 -0
  31. package/lib/renderer/RenderingPipeline.js.map +1 -1
  32. package/lib/renderer/WGPUCausticLightPass.d.ts +48 -0
  33. package/lib/renderer/WGPUCausticLightPass.js +217 -0
  34. package/lib/renderer/WGPUCausticLightPass.js.map +1 -0
  35. package/lib/renderer/WGPUEnvMapDistribution.js +18 -18
  36. package/lib/renderer/WGPUFullQuadPass.js +3 -3
  37. package/lib/renderer/WGPUPhotonMap.d.ts +37 -0
  38. package/lib/renderer/WGPUPhotonMap.js +191 -0
  39. package/lib/renderer/WGPUPhotonMap.js.map +1 -0
  40. package/lib/renderer/WGPURayTraceOutput.d.ts +13 -1
  41. package/lib/renderer/WGPURayTraceOutput.js +122 -28
  42. package/lib/renderer/WGPURayTraceOutput.js.map +1 -1
  43. package/lib/renderer/WGPURayTracePass.d.ts +48 -17
  44. package/lib/renderer/WGPURayTracePass.js +538 -340
  45. package/lib/renderer/WGPURayTracePass.js.map +1 -1
  46. package/lib/renderer/WGPURenderingPipeline.js +83 -47
  47. package/lib/renderer/WGPURenderingPipeline.js.map +1 -1
  48. package/lib/renderer/WebGLFullQuadPass.d.ts +2 -1
  49. package/lib/renderer/WebGLFullQuadPass.js +4 -0
  50. package/lib/renderer/WebGLFullQuadPass.js.map +1 -1
  51. package/lib/renderer/WebGLJNLMDenoiser.js +66 -66
  52. package/lib/renderer/WebGLRayTraceOutputPass.js +4 -4
  53. package/lib/renderer/WebGLRayTracePass.d.ts +6 -1
  54. package/lib/renderer/WebGLRayTracePass.js +43 -6
  55. package/lib/renderer/WebGLRayTracePass.js.map +1 -1
  56. package/lib/renderer/WebGLRenderingPipeline.js +10 -14
  57. package/lib/renderer/WebGLRenderingPipeline.js.map +1 -1
  58. package/lib/renderer/WebGLSkyBaker.js +60 -60
  59. package/lib/renderer/accumulationTarget.d.ts +2 -1
  60. package/lib/renderer/accumulationTarget.js.map +1 -1
  61. package/lib/renderer/causticDiagnostics.d.ts +31 -0
  62. package/lib/renderer/causticDiagnostics.js +5 -0
  63. package/lib/renderer/causticDiagnostics.js.map +1 -0
  64. package/lib/renderer/causticEmission.d.ts +10 -0
  65. package/lib/renderer/causticEmission.js +40 -0
  66. package/lib/renderer/causticEmission.js.map +1 -0
  67. package/lib/renderer/causticUniform.d.ts +12 -0
  68. package/lib/renderer/causticUniform.js +22 -0
  69. package/lib/renderer/causticUniform.js.map +1 -0
  70. package/lib/renderer/caustics.d.ts +16 -0
  71. package/lib/renderer/caustics.js +93 -0
  72. package/lib/renderer/caustics.js.map +1 -0
  73. package/lib/renderer/glsl/aovDisplay.frag.js +5 -5
  74. package/lib/renderer/glsl/aovReflectance.glsl.js +53 -53
  75. package/lib/renderer/glsl/aovReflectanceSamples.glsl.js +1 -1
  76. package/lib/renderer/glsl/aovTrace.frag.js +33 -33
  77. package/lib/renderer/glsl/chunks/cameraRay.glsl.js +9 -9
  78. package/lib/renderer/glsl/chunks/emissiveLight.glsl.d.ts +2 -0
  79. package/lib/renderer/glsl/chunks/emissiveLight.glsl.js +35 -0
  80. package/lib/renderer/glsl/chunks/emissiveLight.glsl.js.map +1 -0
  81. package/lib/renderer/glsl/chunks/envMap.glsl.js +73 -73
  82. package/lib/renderer/glsl/chunks/intersect.glsl.js +426 -428
  83. package/lib/renderer/glsl/chunks/intersect.glsl.js.map +1 -1
  84. package/lib/renderer/glsl/chunks/materialBuffer.glsl.d.ts +1 -0
  85. package/lib/renderer/glsl/chunks/materialBuffer.glsl.js +156 -153
  86. package/lib/renderer/glsl/chunks/materialBuffer.glsl.js.map +1 -1
  87. package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js +771 -771
  88. package/lib/renderer/glsl/chunks/rand.glsl.js +3 -3
  89. package/lib/renderer/glsl/chunks/random.glsl.js +6 -6
  90. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.d.ts +1 -0
  91. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js +68 -63
  92. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js.map +1 -1
  93. package/lib/renderer/glsl/chunks/sampleLight.glsl.js +94 -76
  94. package/lib/renderer/glsl/chunks/sampleLight.glsl.js.map +1 -1
  95. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.d.ts +1 -0
  96. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js +140 -117
  97. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js.map +1 -1
  98. package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js +14 -14
  99. package/lib/renderer/glsl/chunks/sampling.glsl.js +89 -92
  100. package/lib/renderer/glsl/chunks/sampling.glsl.js.map +1 -1
  101. package/lib/renderer/glsl/chunks/sobol.glsl.js +79 -79
  102. package/lib/renderer/glsl/chunks/textureLinear.glsl.js +5 -5
  103. package/lib/renderer/glsl/chunks/uvProjection.glsl.js +11 -11
  104. package/lib/renderer/glsl/depthQuery.frag.js +2 -2
  105. package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js +10 -10
  106. package/lib/renderer/glsl/rayTrace.frag.d.ts +1 -1
  107. package/lib/renderer/glsl/rayTrace.frag.js +260 -237
  108. package/lib/renderer/glsl/rayTrace.frag.js.map +1 -1
  109. package/lib/renderer/glsl/shadowCatcher.frag.js +26 -26
  110. package/lib/renderer/glsl/shadowCatcher.frag.js.map +1 -1
  111. package/lib/renderer/glsl/webglPipeline.frag.js +59 -59
  112. package/lib/renderer/lightSampling.d.ts +3 -2
  113. package/lib/renderer/lightSampling.js +14 -8
  114. package/lib/renderer/lightSampling.js.map +1 -1
  115. package/lib/renderer/progressiveScheduler.js +4 -3
  116. package/lib/renderer/progressiveScheduler.js.map +1 -1
  117. package/lib/renderer/renderPipeline.d.ts +1 -0
  118. package/lib/renderer/renderPipeline.js.map +1 -1
  119. package/lib/renderer/researchTransport.d.ts +31 -0
  120. package/lib/renderer/researchTransport.js +5 -0
  121. package/lib/renderer/researchTransport.js.map +1 -0
  122. package/lib/renderer/sceneLayoutSchema.d.ts +1 -0
  123. package/lib/renderer/sceneLayoutSchema.js +2 -2
  124. package/lib/renderer/sceneLayoutSchema.js.map +1 -1
  125. package/lib/renderer/scratchSampling.js +6 -6
  126. package/lib/renderer/spectrum.d.ts +21 -0
  127. package/lib/renderer/spectrum.js +154 -0
  128. package/lib/renderer/spectrum.js.map +1 -0
  129. package/lib/renderer/webglLightSampling.d.ts +39 -0
  130. package/lib/renderer/webglLightSampling.js +15 -0
  131. package/lib/renderer/webglLightSampling.js.map +1 -0
  132. package/lib/renderer/wgpuBindlessSource.js +3 -3
  133. package/lib/renderer/wgpuShaderSource.d.ts +7 -0
  134. package/lib/renderer/wgpuShaderSource.js +2 -0
  135. package/lib/renderer/wgpuShaderSource.js.map +1 -1
  136. package/lib/renderer/wgsl/aovDisplay.wgsl.js +9 -9
  137. package/lib/renderer/wgsl/aovReflectance.wgsl.js +55 -55
  138. package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.js +1 -1
  139. package/lib/renderer/wgsl/aovResolve.wgsl.js +2 -2
  140. package/lib/renderer/wgsl/aovSnapshot.wgsl.js +1 -1
  141. package/lib/renderer/wgsl/aovTrace.wgsl.js +33 -33
  142. package/lib/renderer/wgsl/bloom.wgsl.js +18 -18
  143. package/lib/renderer/wgsl/causticLight.compute.d.ts +6 -0
  144. package/lib/renderer/wgsl/causticLight.compute.js +537 -0
  145. package/lib/renderer/wgsl/causticLight.compute.js.map +1 -0
  146. package/lib/renderer/wgsl/chunks/background.wgsl.d.ts +2 -0
  147. package/lib/renderer/wgsl/chunks/background.wgsl.js +102 -0
  148. package/lib/renderer/wgsl/chunks/background.wgsl.js.map +1 -0
  149. package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.d.ts +2 -0
  150. package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js +12 -0
  151. package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js.map +1 -0
  152. package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.d.ts +2 -0
  153. package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js +16 -0
  154. package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js.map +1 -0
  155. package/lib/renderer/wgsl/chunks/caustics.wgsl.d.ts +1 -0
  156. package/lib/renderer/wgsl/chunks/caustics.wgsl.js +62 -0
  157. package/lib/renderer/wgsl/chunks/caustics.wgsl.js.map +1 -0
  158. package/lib/renderer/wgsl/chunks/common.wgsl.js +4 -4
  159. package/lib/renderer/wgsl/chunks/envMap.wgsl.js +37 -37
  160. package/lib/renderer/wgsl/chunks/intersect.wgsl.js +598 -592
  161. package/lib/renderer/wgsl/chunks/intersect.wgsl.js.map +1 -1
  162. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js +14 -14
  163. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.d.ts +2 -1
  164. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js +75 -73
  165. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js.map +1 -1
  166. package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js +794 -794
  167. package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js +139 -139
  168. package/lib/renderer/wgsl/chunks/rand.wgsl.js +3 -3
  169. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.d.ts +2 -1
  170. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js +35 -25
  171. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js.map +1 -1
  172. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.d.ts +1 -1
  173. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js +142 -138
  174. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js.map +1 -1
  175. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.d.ts +1 -1
  176. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js +204 -187
  177. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js.map +1 -1
  178. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.d.ts +1 -1
  179. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js +11 -11
  180. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js.map +1 -1
  181. package/lib/renderer/wgsl/chunks/sampling.wgsl.d.ts +1 -1
  182. package/lib/renderer/wgsl/chunks/sampling.wgsl.js +89 -93
  183. package/lib/renderer/wgsl/chunks/sampling.wgsl.js.map +1 -1
  184. package/lib/renderer/wgsl/chunks/sobol.wgsl.js +83 -83
  185. package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js +11 -11
  186. package/lib/renderer/wgsl/compose.frag.wgsl.js +98 -98
  187. package/lib/renderer/wgsl/customDenoise.wgsl.js +10 -10
  188. package/lib/renderer/wgsl/depthQuery.wgsl.js +2 -2
  189. package/lib/renderer/wgsl/jnlm.compute.js +74 -74
  190. package/lib/renderer/wgsl/offlineAdaptive.compute.js +25 -25
  191. package/lib/renderer/wgsl/oidnAuxiliary.wgsl.js +3 -3
  192. package/lib/renderer/wgsl/photonMap.compute.d.ts +29 -0
  193. package/lib/renderer/wgsl/photonMap.compute.js +352 -0
  194. package/lib/renderer/wgsl/photonMap.compute.js.map +1 -0
  195. package/lib/renderer/wgsl/proceduralSky.compute.js +64 -64
  196. package/lib/renderer/wgsl/rayTrace.compute.d.ts +9 -1
  197. package/lib/renderer/wgsl/rayTrace.compute.js +448 -522
  198. package/lib/renderer/wgsl/rayTrace.compute.js.map +1 -1
  199. package/lib/scene/MaterialState.d.ts +2 -2
  200. package/lib/scene/MaterialState.js +2 -2
  201. package/lib/scene/MaterialState.js.map +1 -1
  202. package/lib/settings/render.d.ts +11 -0
  203. package/lib/settings/render.js +1 -0
  204. package/lib/settings/render.js.map +1 -1
  205. package/lib/util/fromTHREE.js +2 -2
  206. package/lib/util/fromTHREE.js.map +1 -1
  207. package/lib/version.d.ts +1 -1
  208. package/lib/version.js +1 -1
  209. package/lib/version.js.map +1 -1
  210. package/llms.txt +2 -1
  211. package/package.json +3 -3
@@ -1,3 +1,7 @@
1
+ import { photonQuerySource } from './photonMap.compute.js';
2
+ import backgroundWgsl from './chunks/background.wgsl.js';
3
+ import { researchTransport } from '../researchTransport.js';
4
+ import { causticPartitionWGSL } from './chunks/caustics.wgsl.js';
1
5
  import { MAX_PATH_EVENTS } from '../pathLimits.js';
2
6
  import shadowCatcherAccumulationWGSL from './chunks/shadowCatcherAccumulation.wgsl.js';
3
7
  import reflectanceWGSL from './aovReflectance.wgsl.js';
@@ -18,12 +22,18 @@ import { createSampleMaterialWgsl } from './chunks/sampleMaterial.wgsl.js';
18
22
  import sampleLightWgsl from './chunks/sampleLight.wgsl.js';
19
23
  import { createOpenPbrBsdfWgsl } from './chunks/openPbrBsdf.wgsl.js';
20
24
  import samplingWgsl from './chunks/sampling.wgsl.js';
25
+ import { spectrumWgsl } from '../spectrum.js';
21
26
  import sampleShadowCatcherWgsl from './chunks/sampleShadowCatcher.wgsl.js';
22
27
  import envMapWgsl from './chunks/envMap.wgsl.js';
23
28
  import uvProjectionWgsl from './chunks/uvProjection.wgsl.js';
24
29
  export const WORKGROUP_SIZE = 8;
25
30
  /** Generates the WebGPU megakernel path tracing compute shader. */
26
- export default function rayTraceCompute({ hasDisplacement, hasAnisotropyDirections = false, hasCoatNormals = false, hasAlpha = true, hasSceneAlpha = true, blasLayoutMask = 1, spectral, sceneCapabilities, dynamicEnvironment = false, materialCapabilities = ALL_MATERIAL_SHADER_CAPABILITIES, lightCapabilities }, sceneIntersections = '', pathDiagnostic = false, inputHooks) {
31
+ export default function rayTraceCompute(options, sceneIntersections = '', pathDiagnostic = false, inputHooks) {
32
+ const research = researchTransport()?.compute(options);
33
+ const enabled = research?.enabled ?? false;
34
+ const partitionDepth = research?.maxDepth ?? 20;
35
+ const debugGroup = research?.debugGroup ?? options.debugGroup ?? -1;
36
+ let { hasDisplacement, workgroupSize = WORKGROUP_SIZE, lightTracing = false, photonMapping = false, photonMaxDepth = 20, hasAnisotropyDirections = false, hasCoatNormals = false, hasAlpha = true, hasSceneAlpha = true, blasLayoutMask = 1, spectral, sceneCapabilities, dynamicEnvironment = false, materialCapabilities = ALL_MATERIAL_SHADER_CAPABILITIES, lightCapabilities } = options;
27
37
  hasAnisotropyDirections ||= hasCoatNormals;
28
38
  const deterministicPrimaryAlpha = hasAlpha;
29
39
  const hasShadowCatcher = sceneCapabilities === undefined || (sceneCapabilities & WGPU_SCENE_FEATURE_BITS.HAS_SHADOW_CATCHER) !== 0;
@@ -44,10 +54,10 @@ si.barycentrics = vec2f(0.0);
44
54
 
45
55
  (*outAux).albedo = vec3f(1.0);
46
56
  (*outAux).normal = select(si.normal, -si.normal, dot(si.normal, ray.d) > 0.0);
47
- var aa: Path;
48
- aa.ray = ray;
49
- aa.fromEye = true;
50
- (*outAux).shadowCounts = sampleShadowCatcher(si, 0, &aa);
57
+ var path: Path;
58
+ path.ray = ray;
59
+ path.fromEye = true;
60
+ (*outAux).shadowCounts = sampleShadowCatcher(si, 0, &path);
51
61
 
52
62
 
53
63
  return vec4f(1.0);
@@ -55,7 +65,7 @@ return vec4f(1.0);
55
65
  else {
56
66
  if (HAS_BEVEL && rtUniform.bevel != 0) {
57
67
  if (ma.bevel > 0.0) {
58
- si.normal = nj(si, ma.bevel);
68
+ si.normal = mT(si, ma.bevel);
59
69
  }
60
70
  }
61
71
 
@@ -83,11 +93,12 @@ si.albedoSampled = ma.transmissionWeight > 0.5;
83
93
 
84
94
  ${commonWgsl}
85
95
 
86
- ${rayTraceCoreWgsl({ hasSceneAlpha, hasAnisotropyDirections, hasCoatNormals, lightCapabilities })}
96
+ ${rayTraceCoreWgsl({ hasSceneAlpha, hasAnisotropyDirections, hasCoatNormals, lightCapabilities, caustics: enabled || lightTracing || photonMapping })}
87
97
 
88
98
  ${uvProjectionWgsl}
89
99
 
90
100
  ${createMaterialBufferWgsl({ hasSceneAlpha, hasAnisotropyDirections, hasCoatNormals,
101
+ caustics: enabled || lightTracing || photonMapping,
91
102
  hasTransmission: (materialCapabilities & MATERIAL_SHADER_CAPABILITIES.transmission) !== 0,
92
103
  hasMetalness: (materialCapabilities & MATERIAL_SHADER_CAPABILITIES.metal) !== 0 })}
93
104
 
@@ -97,57 +108,62 @@ ${randomWgsl}
97
108
  ${envMapWgsl}
98
109
 
99
110
  ${samplingWgsl}
111
+ ${spectrumWgsl}
100
112
  ${createOpenPbrBsdfWgsl(hasAnisotropyDirections, hasCoatNormals)}
101
113
  ${sampleLightWgsl}${inputHooks?.declarations ?? ''}
102
114
 
103
115
 
104
- var<private> vg: u32 = 0u;
116
+ var<private> vp: u32 = 0u;
105
117
 
106
118
 
107
119
 
108
- fn kB() -> u32 {
120
+ fn ke() -> u32 {
109
121
  return u32(max(rtUniform.directLightCandidates, 1));
110
122
  }
111
123
 
112
124
 
113
125
 
114
126
 
115
- fn qx(ys: u32) -> f32 {
127
+ fn qp(yQ: u32) -> f32 {
116
128
 
117
129
 
118
130
 
119
131
 
120
132
  if (SAMPLING_PATTERN == 2) { _ = rand(); }
121
- let kI = aZ.x + aZ.y * u32(rtUniform.outputSize.x);
122
- let key = ar(ar(kI, aQ), rtUniform.sequenceSeed);
123
- let dimension = ar(bT, ys) ^ 0xa511e9b3u;
124
- return f32(dG(key ^ dimension) >> 8u) * (1.0 / 16777216.0);
133
+ let kl = aI.x + aI.y * u32(rtUniform.outputSize.x);
134
+ let key = ak(ak(kl, aC), rtUniform.sequenceSeed);
135
+ let dimension = ak(samplingBounce, yQ) ^ 0xa511e9b3u;
136
+ return f32(cB(key ^ dimension) >> 8u) * (1.0 / 16777216.0);
125
137
  }
126
138
 
127
139
 
128
140
 
129
- fn uS(fA: f32, scatteringPdf: f32) -> f32 {
130
- let candidateCount = kB();
141
+ fn uY(lightPdf: f32, scatteringPdf: f32) -> f32 {
142
+ let candidateCount = ke();
131
143
  if (candidateCount <= 1u) {
132
- return aK(fA, scatteringPdf);
144
+ return aF(lightPdf, scatteringPdf);
133
145
  }
134
- let jb = f32(candidateCount) * fA;
135
- return jb /
136
- max(jb + scatteringPdf, 1e-20);
146
+ let weightedLightPdf = f32(candidateCount) * lightPdf;
147
+ return weightedLightPdf /
148
+ max(weightedLightPdf + scatteringPdf, 1e-20);
137
149
  }
138
150
 
139
151
 
140
- fn gj(scatteringPdf: f32, fA: f32) -> f32 {
141
- let candidateCount = kB();
152
+ fn fV(scatteringPdf: f32, lightPdf: f32) -> f32 {
153
+ let candidateCount = ke();
142
154
  if (candidateCount <= 1u) {
143
- return aK(scatteringPdf, fA);
155
+ return aF(scatteringPdf, lightPdf);
144
156
  }
145
- let jb = f32(candidateCount) * fA;
157
+ let weightedLightPdf = f32(candidateCount) * lightPdf;
146
158
  return scatteringPdf /
147
- max(scatteringPdf + jb, 1e-20);
159
+ max(scatteringPdf + weightedLightPdf, 1e-20);
148
160
  }
149
161
 
150
- ${createSampleMaterialWgsl(hasAnisotropyDirections, hasCoatNormals)}
162
+ ${enabled || lightTracing || photonMapping ? causticPartitionWGSL(enabled, lightTracing, photonMapping, partitionDepth, debugGroup >= 30, photonMaxDepth) : ''}${research?.declarations ?? ''}${photonMapping ? `const CAUSTIC_LIGHT_TRACING=${lightTracing};
163
+ const CAUSTIC_MNEE=${enabled};
164
+ const CAUSTIC_MNEE_MAX_DEPTH=${partitionDepth}u;
165
+ const CAUSTIC_PHOTON_MAX_DEPTH=${photonMaxDepth}u;
166
+ ` + photonQuerySource(debugGroup, !lightTracing && (options.photonDirectSubset ?? true)) : ''}${createSampleMaterialWgsl(hasAnisotropyDirections, hasCoatNormals, enabled || lightTracing || photonMapping, research?.contribution, photonMapping)}
151
167
  ${sampleShadowCatcherWgsl}
152
168
 
153
169
 
@@ -159,24 +175,24 @@ ${shadowCatcherAccumulationWGSL}
159
175
  @group(3) @binding(3) var<storage, read_write> outShadowCatcher: array<ShadowCatcherAccumulation>;
160
176
 
161
177
 
162
- fn ie(
163
- gv: u32,
178
+ fn hH(
179
+ gf: u32,
164
180
  radiance: vec3f,
165
181
  normal: vec3f
166
182
  ) {
167
183
  if (rtUniform.varianceMoments != 0) {
168
184
  let value = dot(radiance, luminance);
169
- outNormal[gv] += vec4f(value * value, 0.0, 0.0, 1.0);
185
+ outNormal[gf] += vec4f(value * value, 0.0, 0.0, 1.0);
170
186
  }
171
187
  else {
172
- outNormal[gv] += vec4f(normal, 1.0);
188
+ outNormal[gf] += vec4f(normal, 1.0);
173
189
  }
174
190
  }
175
191
 
176
192
 
177
193
 
178
- fn ji(gv: u32, value: f32) {
179
- outShadowCatcher[gv].moments += vec4f(value, value * value, 0.0, 0.0);
194
+ fn iP(gf: u32, value: f32) {
195
+ outShadowCatcher[gf].moments += vec4f(value, value * value, 0.0, 0.0);
180
196
  }
181
197
 
182
198
 
@@ -190,123 +206,23 @@ isBlank: bool,
190
206
  shadowCounts: vec2f,
191
207
  }
192
208
 
193
- fn dK(point: vec3f, height: f32, radius: f32) -> f32 {
194
- let ge = length(point);
195
- if (ge < 0.00001) {
196
- return -radius;
197
- }
198
-
199
- let iX = radius * point.y / ge;
200
- let iL = -1.5 * height;
201
- var eH: f32;
202
- if (iX >= 0.0) {
203
- eH = radius;
204
- }
205
- else if (iX < iL) {
206
- eH = -height * ge / point.y;
207
- }
208
- else {
209
- let cL = 1.0
210
- - iX * iX / (3.0 * iL * iL);
211
- eH = radius * cL;
212
- }
213
- return ge - eH;
214
- }
215
-
216
- fn fd(origin: vec3f, direction: vec3f) -> vec3f {
217
- if (!USE_GROUNDED_BACKGROUND) {
218
- return direction;
219
- }
220
- let params = rtUniform.groundedBackgroundParams;
221
- let cf = normalize(direction);
222
- let center = vec3f(
223
- rtUniform.groundedBackgroundCenter.x,
224
- params.z + params.x,
225
- rtUniform.groundedBackgroundCenter.y
226
- );
227
- let bI = origin - center;
228
- let eT = dot(bI, cf);
229
- let br = eT * eT
230
- - dot(bI, bI) + params.y * params.y;
231
- if (
232
- br <= 0.0
233
- || dK(bI, params.x, params.y) > 0.0
234
- ) {
235
- return direction;
236
- }
237
-
238
- var cM = -eT + sqrt(br);
239
- if (cM <= 0.0) {
240
- return direction;
241
- }
242
-
243
- let oK = bI + cf * cM;
244
- if (oK.y >= 0.0) {
245
- return normalize(oK);
246
- }
247
-
248
- if (cf.y < -0.00001 && params.y > 1.5 * params.x) {
249
- let ir = (-params.x - bI.y) / cf.y;
250
- let oB = bI + cf * ir;
251
- let pe = (2.0 / 3.0)
252
- * sqrt(params.y * params.y - 2.25 * params.x * params.x);
253
- if (ir > 0.0 && length(oB.xz) <= pe) {
254
- return normalize(oB);
255
- }
256
- }
257
-
258
- var cV = 0.0;
259
- for (var i = 0; i < 14; i++) {
260
- let fB = (cV + cM) * 0.5;
261
- let qy = bI + cf * fB;
262
- if (dK(qy, params.x, params.y) > 0.0) {
263
- cM = fB;
264
- }
265
- else {
266
- cV = fB;
267
- }
268
- }
269
- let hit = bI + cf * ((cV + cM) * 0.5);
270
- return normalize(hit);
271
- }
272
-
273
- fn hX(ray: Ray) -> vec4f {
274
- var bg = vec4f(0.0);
275
- if (USE_BACKGROUND_MAP) {
276
- let d = fd(ray.o, ray.d);
277
- let t = rtUniform.backgroundMapTransform;
278
- let qZ = vec3f(t.x * d.x - t.y * d.z, d.y, t.y * d.x + t.x * d.z);
279
- let rotation = rtUniform.backgroundMapRotation;
280
- let hn = transpose(mat3x3f(rotation[0].xyz, rotation[1].xyz, rotation[2].xyz)) * qZ;
281
- let bc = textureLinear(backgroundMap, eV(hn));
282
- bg = vec4f(bc.rgb * t.z, bc.a);
283
- }
284
- else if (USE_BACKGROUND) {
285
- bg = rtUniform.backgroundColor;
286
- }
287
- else if (USE_ENVMAP) {
288
- bg = textureLinear(envMap, dm(ray.d));
289
- }
290
- return bg;
291
- }
292
-
293
- fn di(ray: Ray, wavelength: f32) -> vec4f {
294
- let bg = hX(ray);
209
+ ${backgroundWgsl}fn cP(ray: Ray, channel: i32) -> vec4f {
210
+ let bg = ft(ray);
295
211
  if (SPECTRAL) {
296
- return vec4f(aj(bg.rgb, wavelength), bg.a);
212
+ return vec4f(sampling_spectral_rgb_filter(bg.rgb, channel), bg.a);
297
213
  }
298
214
  return bg;
299
215
  }
300
216
 
301
217
 
302
218
 
303
- fn nY(uv: vec2f, aa: ptr<function, Path>, depth: ptr<function, i32>, si: ptr<function, SurfaceInteraction>, ma: ptr<function, OpenPbrResolvedMaterial>, outAux: ptr<function, RayTraceAuxiliary>, fm: ptr<function, bool>) {
304
- *fm = false;
305
- bT = u32(max(*depth, 0));
219
+ fn nO(uv: vec2f, path: ptr<function, Path>, depth: ptr<function, i32>, si: ptr<function, SurfaceInteraction>, ma: ptr<function, OpenPbrResolvedMaterial>, outAux: ptr<function, RayTraceAuxiliary>, eV: ptr<function, bool>) {
220
+ *eV = false;
221
+ samplingBounce = u32(max(*depth, 0));
306
222
  let matType = (*ma).materialType;
307
223
  let isShadowCatcher = ${hasShadowCatcher ? /* wgsl */ `matType == SHADOW_CATCHER` : /* wgsl */ `false`};
308
224
  if (isShadowCatcher) {
309
- if ((*aa).fromEye) {
225
+ if ((*path).fromEye) {
310
226
  (*si).hit = false;
311
227
  }
312
228
  else {
@@ -314,37 +230,37 @@ else {
314
230
 
315
231
 
316
232
  if (USE_ENVMAP) {
317
- if ((*aa).isNextRefraction) {
233
+ if ((*path).isNextRefraction) {
318
234
 
319
235
 
320
- let bg = di(
321
- (*aa).ray,
322
- (*si).wavelength
236
+ let bg = cP(
237
+ (*path).ray,
238
+ (*si).spectralChannel
323
239
  );
324
- let da = select(gj((*aa).scatteringPdf,
325
- iT(dm((*aa).ray.d)) * rtUniform.envLightPmf),
326
- 1.0, (*aa).scatteringIsDelta);
327
- (*aa).li += da * (*aa).beta * bg.rgb * bg.a;
328
- (*aa).alpha = max((*aa).alpha, bg.a);
240
+ let cM = select(fV((*path).scatteringPdf,
241
+ envMapPdf(cT((*path).ray.d)) * rtUniform.envLightPmf),
242
+ 1.0, (*path).scatteringIsDelta);
243
+ (*path).li += cM * (*path).beta * bg.rgb * bg.a;
244
+ (*path).alpha = max((*path).alpha, bg.a);
329
245
  }
330
246
  else {
331
- let vo = dm((*aa).ray.d);
332
- var emission = textureLinear(envMap, vo).rgb;
247
+ let vC = cT((*path).ray.d);
248
+ var emission = textureLinear(envMap, vC).rgb;
333
249
  if (SPECTRAL) {
334
- emission = aj(emission, (*si).wavelength);
250
+ emission = sampling_spectral_rgb_filter(emission, (*si).spectralChannel);
335
251
  }
336
- (*aa).li += (*aa).beta * emission *
337
- gj((*aa).scatteringPdf, iT(vo));
252
+ (*path).li += (*path).beta * emission *
253
+ fV((*path).scatteringPdf, envMapPdf(vC));
338
254
  }
339
255
  }
340
256
  else {
341
- let bg = di(
342
- (*aa).ray,
343
- (*si).wavelength
257
+ let bg = cP(
258
+ (*path).ray,
259
+ (*si).spectralChannel
344
260
  );
345
- (*aa).li += (*aa).beta * bg.rgb * bg.a;
261
+ (*path).li += (*path).beta * bg.rgb * bg.a;
346
262
  }
347
- (*aa).abort = true;
263
+ (*path).abort = true;
348
264
  return;
349
265
  }
350
266
  }
@@ -352,40 +268,40 @@ if (!(*si).hit) {
352
268
 
353
269
 
354
270
 
355
- let bg = di(
356
- (*aa).ray,
357
- (*si).wavelength
271
+ let bg = cP(
272
+ (*path).ray,
273
+ (*si).spectralChannel
358
274
  );
359
- if ((*aa).fromEye) {
275
+ if ((*path).fromEye) {
360
276
 
361
- (*aa).li = (*aa).beta * bg.rgb * bg.a;
362
- (*aa).alpha = bg.a;
277
+ (*path).li = (*path).beta * bg.rgb * bg.a;
278
+ (*path).alpha = bg.a;
363
279
 
364
280
  (*outAux).isBlank = bg.a < 0.001 ||
365
281
  (USE_BACKGROUND && !USE_BACKGROUND_MAP);
366
282
  }
367
283
  else {
368
- let cam = fj(uv);
369
- let nK = dot(cam.d, (*aa).ray.d) > 0.0;
284
+ let cam = eT(uv);
285
+ let nt = dot(cam.d, (*path).ray.d) > 0.0;
370
286
  if (rtUniform.transmissiveOutputAlphaMin < 1.0) {
371
- if (nK) {
372
- (*aa).alpha = max((*aa).alpha, bg.a);
287
+ if (nt) {
288
+ (*path).alpha = max((*path).alpha, bg.a);
373
289
  } else {
374
- (*aa).alpha = 1.0;
290
+ (*path).alpha = 1.0;
375
291
  }
376
292
  }
377
293
  if (!USE_ENVMAP) {
378
294
 
379
295
 
380
- if (nK) {
296
+ if (nt) {
381
297
 
382
298
 
383
- (*aa).li += (*aa).beta *
384
- gj((*aa).scatteringPdf, 1.0) * bg.rgb;
299
+ (*path).li += (*path).beta *
300
+ fV((*path).scatteringPdf, 1.0) * bg.rgb;
385
301
  }
386
302
  }
387
303
  }
388
- (*aa).abort = true;
304
+ (*path).abort = true;
389
305
  return;
390
306
  }
391
307
 
@@ -396,28 +312,28 @@ let alpha = clamp((*ma).alpha, 0.0, 1.0);
396
312
  if (alpha < 1.0) {
397
313
 
398
314
 
399
- if (alpha <= 0.0 || eC(3u) > alpha) {
400
- (*fm) = true;
315
+ if (alpha <= 0.0 || ek(3u) > alpha) {
316
+ (*eV) = true;
401
317
  }
402
318
  }
403
- if (!(*fm) && rtUniform.transmissiveOutputAlphaMin < 1.0) {
319
+ if (!(*eV) && rtUniform.transmissiveOutputAlphaMin < 1.0) {
404
320
 
405
321
 
406
322
  let outputAlpha = max(1.0 - (*ma).transmissionWeight, 1.0 - pow(1.0 - rtUniform.transmissiveOutputAlphaMin, f32(*depth)));
407
- (*aa).alpha = max(outputAlpha, (*aa).alpha);
323
+ (*path).alpha = max(outputAlpha, (*path).alpha);
408
324
  }
409
- if (!(*fm)) {
410
- vg = u32(max(*depth, 0));
411
- mL(si, ma, aa);
325
+ if (!(*eV)) {
326
+ vp = u32(max(*depth, 0));
327
+ mx(si, ma, path);
412
328
  }
413
329
  else {
414
330
 
415
331
 
416
- (*aa).ray.o = (*si).position + (*aa).ray.d * EPS;
332
+ (*path).ray.o = (*si).position + (*path).ray.d * EPS;
417
333
  }
418
334
  }
419
335
 
420
- if (!(*si).albedoSampled && !(*fm)) {
336
+ if (!(*si).albedoSampled && !(*eV)) {
421
337
 
422
338
  if ((matType == STANDARD || matType == UNLIT)) {
423
339
  if (!((*ma).transmissionWeight > 0.5 ||
@@ -442,34 +358,34 @@ if (*depth > 4) {
442
358
 
443
359
 
444
360
  if (USE_RR) {
445
- if (*depth >= RR_MAX && !(*fm)) {
446
- let pG = (*aa).beta;
361
+ if (*depth >= RR_MAX && !(*eV)) {
362
+ let pl = (*path).beta;
447
363
 
448
- let pn = max(max(pG.x, pG.y), pG.z);
449
- let q: f32 = max(0.0, 1.0 - pn);
450
- if (dp(cE(RUSSIAN_ROULETTE)) < q) {
364
+ let pc = max(max(pl.x, pl.y), pl.z);
365
+ let q: f32 = max(0.0, 1.0 - pc);
366
+ if (sample1D(bE(RUSSIAN_ROULETTE)) < q) {
451
367
 
452
368
 
453
- (*aa).alpha = 1.0;
454
- (*aa).abort = true;
369
+ (*path).alpha = 1.0;
370
+ (*path).abort = true;
455
371
  }
456
372
  else {
457
- (*aa).beta /= 1.0 - q;
373
+ (*path).beta /= 1.0 - q;
458
374
  }
459
375
  }
460
376
  }
461
- if ((*aa).abort) {
377
+ if ((*path).abort) {
462
378
  return;
463
379
  }
464
380
 
465
381
 
466
382
  }
467
383
 
468
- fn kl(aa: ptr<function, Path>, depth: ptr<function, i32>, si: ptr<function, SurfaceInteraction>, ma: ptr<function, OpenPbrResolvedMaterial>, aJ: bool) {
384
+ fn jQ(path: ptr<function, Path>, depth: ptr<function, i32>, si: ptr<function, SurfaceInteraction>, ma: ptr<function, OpenPbrResolvedMaterial>, aJ: bool) {
469
385
  if (SPECTRAL) {
470
386
 
471
387
  if ((*ma).transmissionWeight > 0.001) {
472
- (*ma).specularIor = ee(
388
+ (*ma).specularIor = sampling_cauchy_ior(
473
389
  (*si).wavelength,
474
390
  (*ma).specularIor,
475
391
  (*ma).transmissionDispersionScale,
@@ -484,298 +400,299 @@ return;
484
400
 
485
401
 
486
402
  var lightSample: LightSampleRec;
487
- let hM = eC(3u) < (*ma).alpha;
403
+ let ht = ek(3u) < (*ma).alpha;
488
404
  for (var i = 0; i < rtUniform.lightsCount; i++) {
489
405
 
490
406
  let light: Light = analyticLights[i];
491
- let d = nr((*aa).ray, light, &lightSample);
407
+ let d = mX((*path).ray, light, &lightSample);
492
408
  lightSample.pdf *= light.selectionPmf;
493
- let lY = (*si).hit && d > distance((*si).position, (*aa).ray.o);
494
- if (d != INF && !(lY && hM)) {
495
- let fl = gj((*aa).scatteringPdf, lightSample.pdf);
409
+ let lH = (*si).hit && d > distance((*si).position, (*path).ray.o);
410
+ if (d != INF && !(lH && ht)) {
411
+ let misWeight = fV((*path).scatteringPdf, lightSample.pdf);
496
412
  if (SPECTRAL) {
497
- lightSample.emission = aj(lightSample.emission, (*si).wavelength);
413
+ lightSample.emission = sampling_spectral_rgb_filter(lightSample.emission, (*si).spectralChannel);
498
414
  }
499
- (*aa).li += fl * (*aa).beta * lightSample.emission;
500
- (*aa).alpha = 1.0;
501
- (*aa).abort = true;
415
+ ${enabled || lightTracing || photonMapping ? 'if (!causticHitOwned(*path, true, true)) { causticHotRecord(*path,misWeight*lightSample.emission,2u); ' : ''}(*path).li += misWeight * (*path).beta * lightSample.emission;${enabled || lightTracing || photonMapping ? ' }' : ''}
416
+ (*path).alpha = 1.0;
417
+ (*path).abort = true;
502
418
  }
503
419
  }
504
420
 
505
421
  if (USE_ENVMAP) {
506
- if (!((*si).hit && hM)) {
507
- if ((*aa).isNextRefraction) {
422
+ if (!((*si).hit && ht)) {${lightTracing || photonMapping ? /* wgsl */ `
423
+ if(causticHitOwned(*path,false,true)){(*path).abort=true;return;}` : ''}
424
+ if ((*path).isNextRefraction) {
508
425
 
509
426
 
510
427
 
511
- let bg = di(
512
- (*aa).ray,
513
- (*si).wavelength
428
+ let bg = cP(
429
+ (*path).ray,
430
+ (*si).spectralChannel
514
431
  );
515
- let da = select(gj((*aa).scatteringPdf,
516
- iT(dm((*aa).ray.d)) * rtUniform.envLightPmf),
517
- 1.0, (*aa).scatteringIsDelta);
518
- (*aa).li += da * (*aa).beta * bg.rgb * bg.a;
519
- (*aa).alpha = max((*aa).alpha, bg.a);
520
- (*aa).abort = true;
432
+ let cM = select(fV((*path).scatteringPdf,
433
+ envMapPdf(cT((*path).ray.d)) * rtUniform.envLightPmf),
434
+ 1.0, (*path).scatteringIsDelta);
435
+ (*path).li += cM * (*path).beta * bg.rgb * bg.a;
436
+ (*path).alpha = max((*path).alpha, bg.a);
437
+ (*path).abort = true;
521
438
  return;
522
439
  }
523
- let _uv = dm((*aa).ray.d);
440
+ let _uv = cT((*path).ray.d);
524
441
  var emission = textureLinear(envMap, _uv).rgb;
525
- let fl = gj(
526
- (*aa).scatteringPdf,
527
- iT(_uv) * rtUniform.envLightPmf
442
+ let misWeight = fV(
443
+ (*path).scatteringPdf,
444
+ envMapPdf(_uv) * rtUniform.envLightPmf
528
445
  );
529
446
  if (SPECTRAL) {
530
- emission = aj(emission, (*si).wavelength);
447
+ emission = sampling_spectral_rgb_filter(emission, (*si).spectralChannel);
531
448
  }
532
449
 
533
450
  if (!USE_BACKGROUND) {
534
- (*aa).alpha = 1.0;
451
+ (*path).alpha = 1.0;
535
452
  }
536
- (*aa).li += (*aa).beta * emission * fl;
537
- (*aa).abort = true;
453
+ (*path).li += (*path).beta * emission * misWeight;
454
+ (*path).abort = true;
538
455
  }
539
456
  }
540
457
 
541
458
  *depth = *depth + 1;
542
459
  }
543
460
 
544
- fn fj(coord: vec2f) -> Ray {
461
+ fn eT(coord: vec2f) -> Ray {
545
462
  let origin = cameraUniform.viewProjectionInv * vec4f(coord * 2.0 - 1.0, -1.0, 1.0);
546
463
  let center = cameraUniform.viewProjectionInv * vec4f(coord * 2.0 - 1.0, 1.0, 1.0);
547
464
  var cam: Ray;
548
- gC(&cam, origin.xyz / origin.w, normalize(center.xyz * origin.w - origin.xyz * center.w));
465
+ initRay(&cam, origin.xyz / origin.w, normalize(center.xyz * origin.w - origin.xyz * center.w));
549
466
 
550
467
  return cam;
551
468
  }
552
469
 
553
470
 
554
- fn ld(radius: f32, xi: f32) -> vec2f {
471
+ fn kK(radius: f32, xi: f32) -> vec2f {
555
472
  var x = 0.25;
556
- for (var oD = 0; oD < 10; oD++) {
473
+ for (var iteration = 0; iteration < 10; iteration++) {
557
474
  let x2 = x * x;
558
475
  let x3 = x2 * x;
559
- let lw = 1.0 - x;
476
+ let la = 1.0 - x;
560
477
  let value = 10.0 * x2 - 20.0 * x3 + 15.0 * x2 * x2 -
561
478
  4.0 * x2 * x3 - xi;
562
- let mX = 20.0 * x * lw * lw * lw;
563
- if (abs(value) < 1e-6 || mX == 0.0) { break; }
564
- x = clamp(x - value / mX, 0.0, 1.0);
479
+ let mJ = 20.0 * x * la * la * la;
480
+ if (abs(value) < 1e-6 || mJ == 0.0) { break; }
481
+ x = clamp(x - value / mJ, 0.0, 1.0);
565
482
  }
566
- let jL = x * radius;
567
- return vec2f(jL, sqrt(max(radius * radius - jL * jL, 0.0)));
483
+ let jr = x * radius;
484
+ return vec2f(jr, sqrt(max(radius * radius - jr * jr, 0.0)));
568
485
  }
569
486
 
570
- fn jj(radius: f32, gM: f32) -> f32 {
571
- if (gM >= radius) { return 0.0; }
572
- let pa = radius - gM;
573
- return pa * pa * pa;
487
+ fn bevelCubicPdf(radius: f32, gu: f32) -> f32 {
488
+ if (gu >= radius) { return 0.0; }
489
+ let falloff = radius - gu;
490
+ return falloff * falloff * falloff;
574
491
  }
575
492
 
576
493
 
577
- fn nj(source: SurfaceInteraction, radius: f32) -> vec3f {
494
+ fn mT(source: SurfaceInteraction, radius: f32) -> vec3f {
578
495
  var geometricNormal = source.faceNormal;
579
496
  if (dot(geometricNormal, source.vertexNormal) < 0.0) {
580
497
  geometricNormal = -geometricNormal;
581
498
  }
582
499
  var tangent: vec3f;
583
500
  var bitangent: vec3f;
584
- aP(geometricNormal, &tangent, &bitangent);
585
- var iW = vec3f(0.0);
586
-
587
- for (var iG = 0; iG < BEVEL_SAMPLES; iG++) {
588
- let qf = dZ(CAMERA_BEVEL_BASE + u32(iG));
589
- var cJ = qf.x;
590
- let pv = qf.y;
591
- var dz = geometricNormal;
592
- var fW = tangent;
593
- var eA = bitangent;
594
- var gu = 0.5;
595
- var iB = 0.25;
596
- var gT = 0.25;
597
- if (cJ < 0.5) {
598
- cJ *= 2.0;
599
- }
600
- else if (cJ < 0.75) {
601
- let nI = dz;
602
- dz = fW;
603
- fW = nI;
604
- gu = 0.25;
605
- iB = 0.5;
606
- cJ = (cJ - 0.5) * 4.0;
501
+ sampling_orthonormal_basis(geometricNormal, &tangent, &bitangent);
502
+ var iE = vec3f(0.0);
503
+
504
+ for (var ih = 0; ih < BEVEL_SAMPLES; ih++) {
505
+ let qa = sample2D(CAMERA_BEVEL_BASE + u32(ih));
506
+ var cr = qa.x;
507
+ let pj = qa.y;
508
+ var cZ = geometricNormal;
509
+ var fI = tangent;
510
+ var eh = bitangent;
511
+ var ge = 0.5;
512
+ var hW = 0.25;
513
+ var gC = 0.25;
514
+ if (cr < 0.5) {
515
+ cr *= 2.0;
516
+ }
517
+ else if (cr < 0.75) {
518
+ let nr = cZ;
519
+ cZ = fI;
520
+ fI = nr;
521
+ ge = 0.25;
522
+ hW = 0.5;
523
+ cr = (cr - 0.5) * 4.0;
607
524
  }
608
525
  else {
609
- let nI = dz;
610
- dz = eA;
611
- eA = nI;
612
- gu = 0.25;
613
- gT = 0.5;
614
- cJ = (cJ - 0.75) * 4.0;
615
- }
616
-
617
- let hj = ld(radius, pv);
618
- let phi = TWOPI * cJ;
619
- let rw = hj.x *
620
- (cos(phi) * fW + sin(phi) * eA);
526
+ let nr = cZ;
527
+ cZ = eh;
528
+ eh = nr;
529
+ ge = 0.25;
530
+ gC = 0.5;
531
+ cr = (cr - 0.75) * 4.0;
532
+ }
533
+
534
+ let gQ = kK(radius, pj);
535
+ let phi = TWOPI * cr;
536
+ let rr = gQ.x *
537
+ (cos(phi) * fI + sin(phi) * eh);
621
538
  var ray: Ray;
622
- gC(
539
+ initRay(
623
540
  &ray,
624
- source.position + dz * hj.y + rw,
625
- -dz
541
+ source.position + cZ * gQ.y + rr,
542
+ -cZ
626
543
  );
627
544
  var hit: SurfaceInteraction;
628
545
  intersectSceneBevel(
629
546
  ray,
630
547
  &hit,
631
548
  source.instanceIndex,
632
- max(2.0 * hj.y, EPS)
549
+ max(2.0 * gQ.y, EPS)
633
550
  );
634
551
  if (!hit.hit) { continue; }
635
552
 
636
- let lA = gu * abs(dot(dz, hit.faceNormal));
637
- let nC = iB * abs(dot(fW, hit.faceNormal));
638
- let kG = gT * abs(dot(eA, hit.faceNormal));
639
- var weight = lA / max(
640
- lA * lA + nC * nC +
641
- kG * kG,
553
+ let lc = ge * abs(dot(cZ, hit.faceNormal));
554
+ let nj = hW * abs(dot(fI, hit.faceNormal));
555
+ let kj = gC * abs(dot(eh, hit.faceNormal));
556
+ var weight = lc / max(
557
+ lc * lc + nj * nj +
558
+ kj * kj,
642
559
  1e-8
643
560
  );
644
- weight *= jj(radius, distance(hit.position, source.position)) /
645
- max(jj(radius, hj.x), 1e-8);
646
- iW += weight * hit.vertexNormal;
561
+ weight *= bevelCubicPdf(radius, distance(hit.position, source.position)) /
562
+ max(bevelCubicPdf(radius, gQ.x), 1e-8);
563
+ iE += weight * hit.vertexNormal;
647
564
  }
648
565
 
649
- if (dot(iW, iW) <= 1e-12) { return source.normal; }
650
- let kg = normalize(iW);
651
- let result = source.normal + kg - source.vertexNormal;
566
+ if (dot(iE, iE) <= 1e-12) { return source.normal; }
567
+ let jM = normalize(iE);
568
+ let result = source.normal + jM - source.vertexNormal;
652
569
  if (dot(result, result) > 1e-12) { return normalize(result); }
653
570
  return source.normal;
654
571
  }
655
572
 
656
- fn cT(uv: vec2f, si: ptr<function, SurfaceInteraction>, ray: Ray, ma: ptr<function, OpenPbrResolvedMaterial>, outAux: ptr<function, RayTraceAuxiliary>, sh: bool) -> vec4f {
657
- var aa: Path;
658
- aa.ray = ray;
659
- aa.li = vec3f(0.0);
660
- aa.alpha = select(1.0, 0.0, rtUniform.transmissiveOutputAlphaMin < 1.0);
661
- aa.beta = vec3f(1.0);
662
- aa.fromEye = true;
663
- aa.scatteringPdf = 0.0;
664
- aa.scatteringIsDelta = false;
665
- aa.isNextRefraction = false;
666
- aa.abort = false;
573
+ fn cG(uv: vec2f, si: ptr<function, SurfaceInteraction>, ray: Ray, ma: ptr<function, OpenPbrResolvedMaterial>, outAux: ptr<function, RayTraceAuxiliary>, sc: bool) -> vec4f {
574
+ var path: Path;
575
+ path.ray = ray;
576
+ path.li = vec3f(0.0);
577
+ path.alpha = select(1.0, 0.0, rtUniform.transmissiveOutputAlphaMin < 1.0);
578
+ path.beta = vec3f(1.0);
579
+ path.fromEye = true;
580
+ path.scatteringPdf = 0.0;
581
+ path.scatteringIsDelta = false;
582
+ path.isNextRefraction = false;
583
+ path.abort = false;
667
584
 
668
585
  let bounceLimit = max(rtUniform.bounces, 0);
669
- let ft = min(bounceLimit * 3, ${MAX_PATH_EVENTS});
586
+ let eZ = min(bounceLimit * 3, ${MAX_PATH_EVENTS});
670
587
  var depth = 0;
671
588
  var aJ = false;
672
- var bQ = false;
589
+ var bH = false;
673
590
 
674
591
 
675
592
 
676
593
 
677
- for (var event = 0; event <= ft; event++) {
678
- if ((event != 0) | sh) {
679
- intersectScene(aa.ray, si, depth, event != 0, aa.isNextRefraction);
680
- dg(ma, (*si).materialIndex, (*si).uv, (*si).uv1, (*si).instanceIndex, (*si).vertexColor);
594
+ for (var event = 0; event <= eZ; event++) {
595
+ if ((event != 0) | sc) {
596
+ intersectScene(path.ray, si, depth, event != 0, path.isNextRefraction);
597
+ getMaterial(ma, (*si).materialIndex, (*si).uv, (*si).uv1, (*si).instanceIndex, (*si).vertexColor);
681
598
  }
682
599
  if (event == 0) {
683
- if (sh & (*si).hit & ((*ma).materialType == STANDARD)) {
600
+ if (sc & (*si).hit & ((*ma).materialType == STANDARD)) {
684
601
  (*outAux).albedo = select((*ma).baseColor, vec3f(1.0), (*ma).transmissionWeight > 0.5);
685
602
  (*outAux).normal = select((*si).normal, -(*si).normal,
686
603
  dot((*si).normal, (*si).position - cameraUniform.viewInv[3].xyz) > 0.0);
687
604
  (*si).albedoSampled = (*ma).transmissionWeight > 0.5;
688
605
  }
689
- bQ = ((*ma).transmissionWeight < 0.001) & ((*ma).subsurfaceWeight < 0.001) & ((*ma).alpha > 0.99);
606
+ bH = ((*ma).transmissionWeight < 0.001) & ((*ma).subsurfaceWeight < 0.001) & ((*ma).alpha > 0.99);
690
607
  } else {
691
- kl(&aa, &depth, si, ma, aJ);
608
+ jQ(&path, &depth, si, ma, aJ);
692
609
  }
693
- if (bQ & (event > bounceLimit)) { aa.abort = true; }
694
- if (aa.abort | (event >= ft)) { break; }
695
- nY(uv, &aa, &depth, si, ma, outAux, &aJ);
696
- if (aa.abort) { break; }
610
+ if (bH & (event > bounceLimit)) { path.abort = true; }
611
+ if (path.abort | (event >= eZ)) { break; }
612
+ nO(uv, &path, &depth, si, ma, outAux, &aJ);
613
+ if (path.abort) { break; }
697
614
  }
698
615
 
699
- return vec4f(aa.li, aa.alpha);
616
+ return vec4f(path.li, path.alpha);
700
617
  }
701
618
 
702
- fn iU(uv: vec2f, si: ptr<function, SurfaceInteraction>, ray: Ray, ma: ptr<function, OpenPbrResolvedMaterial>, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
619
+ fn iC(uv: vec2f, si: ptr<function, SurfaceInteraction>, ray: Ray, ma: ptr<function, OpenPbrResolvedMaterial>, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
703
620
  ${deterministicPrimaryAlpha ? /* wgsl */ `let coverage = clamp((*ma).alpha, 0.0, 1.0);
704
621
 
705
622
 
706
623
 
707
624
 
708
625
  let split = (*si).hit & (((*ma).materialType == STANDARD) | ((*ma).materialType == UNLIT)) & (coverage < 1.0);
709
- var sB = ray;
626
+ var st = ray;
710
627
  var tr = *si;
711
628
  var tq = *ma;
712
- var iP = *outAux;
629
+ var iw = *outAux;
713
630
  if (split) {
714
- sB.o = (*si).position + ray.d * (EPS * 0.02);
631
+ st.o = (*si).position + ray.d * (EPS * 0.02);
715
632
  tr.albedoSampled = false;
716
633
  }
717
634
  var back: vec4f;
718
- var ez: RayTraceAuxiliary;
635
+ var eg: RayTraceAuxiliary;
719
636
 
720
637
 
721
- let vh = select(1u, rtUniform.loopUnrollGuard >> 1u, split & (coverage > 0.0));
722
- for (var uI = 0u; uI < vh; uI++) {
723
- let result = cT(uv, &tr, sB, &tq, &iP, split & (uI == 0u));
724
- if (!split | (coverage <= 0.0)) { *outAux = iP; return result; }
725
- if (uI == 0u) {
726
- back = result; ez = iP;
638
+ let vq = select(1u, rtUniform.loopUnrollGuard >> 1u, split & (coverage > 0.0));
639
+ for (var uM = 0u; uM < vq; uM++) {
640
+ let result = cG(uv, &tr, st, &tq, &iw, split & (uM == 0u));
641
+ if (!split | (coverage <= 0.0)) { *outAux = iw; return result; }
642
+ if (uM == 0u) {
643
+ back = result; eg = iw;
727
644
  tr = *si; tq = *ma; tq.alpha = 1.0;
728
- sB = ray; iP = *outAux;
645
+ st = ray; iw = *outAux;
729
646
  } else {
730
- (*outAux).albedo = mix(ez.albedo, iP.albedo, coverage);
731
- let dl = mix(ez.normal, iP.normal, coverage);
732
- (*outAux).normal = select(vec3f(0.0), normalize(dl), dot(dl, dl) > 1e-12);
733
- (*outAux).isBlank = ez.isBlank & iP.isBlank;
734
- (*outAux).isShadowCatcher = ez.isShadowCatcher & iP.isShadowCatcher;
735
- (*outAux).shadowCounts = mix(ez.shadowCounts, iP.shadowCounts, coverage);
647
+ (*outAux).albedo = mix(eg.albedo, iw.albedo, coverage);
648
+ let cS = mix(eg.normal, iw.normal, coverage);
649
+ (*outAux).normal = select(vec3f(0.0), normalize(cS), dot(cS, cS) > 1e-12);
650
+ (*outAux).isBlank = eg.isBlank & iw.isBlank;
651
+ (*outAux).isShadowCatcher = eg.isShadowCatcher & iw.isShadowCatcher;
652
+ (*outAux).shadowCounts = mix(eg.shadowCounts, iw.shadowCounts, coverage);
736
653
  return mix(back, result, coverage);
737
654
  }
738
655
  }
739
- return vec4f(0.0);` : /* wgsl */ `return cT(uv, si, ray, ma, outAux, false);`}
656
+ return vec4f(0.0);` : /* wgsl */ `return cG(uv, si, ray, ma, outAux, false);`}
740
657
  }
741
658
 
742
659
 
743
660
 
744
- ${spectral === false && deterministicPrimaryAlpha ? /* wgsl */ `fn iu(uv: vec2f, ray: Ray, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
661
+ ${spectral === false && deterministicPrimaryAlpha ? /* wgsl */ `fn hR(uv: vec2f, ray: Ray, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
745
662
  ${primaryVariables}
746
- var oI: SurfaceInteraction;
747
- var oH: OpenPbrResolvedMaterial;
748
- var ue: RayTraceAuxiliary;
749
- var iY = false;
663
+ var oy: SurfaceInteraction;
664
+ var ox: OpenPbrResolvedMaterial;
665
+ var uh: RayTraceAuxiliary;
666
+ var iH = false;
750
667
  var query = true;
751
668
  var split = false;
752
669
  var coverage = 1.0;
753
670
  var front = false;
754
671
  var back: vec4f;
755
- var ez: RayTraceAuxiliary;
756
- var aa: Path; aa.ray = ray;
757
- aa.alpha = select(1.0, 0.0, rtUniform.transmissiveOutputAlphaMin < 1.0);
758
- aa.beta = vec3f(1.0); aa.fromEye = true;
672
+ var eg: RayTraceAuxiliary;
673
+ var path: Path; path.ray = ray;
674
+ path.alpha = select(1.0, 0.0, rtUniform.transmissiveOutputAlphaMin < 1.0);
675
+ path.beta = vec3f(1.0); path.fromEye = true;
759
676
  let bounceLimit = max(rtUniform.bounces, 0);
760
- let ft = min(bounceLimit * 3, ${MAX_PATH_EVENTS});
677
+ let eZ = min(bounceLimit * 3, ${MAX_PATH_EVENTS});
761
678
  var event = 0; var depth = 0; var aJ = false;
762
- var bQ = false;
679
+ var bH = false;
763
680
 
764
681
 
765
682
  for (var step = 0; step < (${MAX_PATH_EVENTS} + 1) * 2 + 2; step++) {
766
683
  if (query) {
767
- intersectScene(aa.ray, &si, depth, event != 0, aa.isNextRefraction);
768
- dg(&ma, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);
684
+ intersectScene(path.ray, &si, depth, event != 0, path.isNextRefraction);
685
+ getMaterial(&ma, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);
769
686
  }
770
687
  query = true;
771
- if (!iY) {
688
+ if (!iH) {
772
689
  ${primaryGuides}
773
- oI = si; oH = ma; ue = *outAux;
774
- iY = true;
690
+ oy = si; ox = ma; uh = *outAux;
691
+ iH = true;
775
692
  coverage = clamp(ma.alpha, 0.0, 1.0);
776
693
  split = si.hit & ((ma.materialType == STANDARD) | (ma.materialType == UNLIT)) & (coverage < 1.0);
777
694
  if (split) {
778
- aa.ray.o = si.position + ray.d * (EPS * 0.02);
695
+ path.ray.o = si.position + ray.d * (EPS * 0.02);
779
696
  si.albedoSampled = false;
780
697
  continue;
781
698
  }
@@ -788,146 +705,150 @@ si.albedoSampled = ma.transmissionWeight > 0.5;
788
705
  }
789
706
  }
790
707
  if (event == 0) {
791
- bQ = (ma.transmissionWeight < 0.001) & (ma.subsurfaceWeight < 0.001) & (ma.alpha > 0.99);
708
+ bH = (ma.transmissionWeight < 0.001) & (ma.subsurfaceWeight < 0.001) & (ma.alpha > 0.99);
792
709
  } else {
793
- kl(&aa, &depth, &si, &ma, aJ);
710
+ jQ(&path, &depth, &si, &ma, aJ);
794
711
  }
795
- if (bQ & (event > bounceLimit)) { aa.abort = true; }
796
- if (!aa.abort & (event < ft)) {
797
- nY(uv, &aa, &depth, &si, &ma, outAux, &aJ);
712
+ if (bH & (event > bounceLimit)) { path.abort = true; }
713
+ if (!path.abort & (event < eZ)) {
714
+ nO(uv, &path, &depth, &si, &ma, outAux, &aJ);
798
715
  }
799
- if (aa.abort | (event >= ft)) {
800
- let result = vec4f(aa.li, aa.alpha);
716
+ if (path.abort | (event >= eZ)) {
717
+ let result = vec4f(path.li, path.alpha);
801
718
  if (!split | (coverage <= 0.0)) { return result; }
802
719
  if (front) {
803
- (*outAux).albedo = mix(ez.albedo, (*outAux).albedo, coverage);
804
- let dl = mix(ez.normal, (*outAux).normal, coverage);
805
- (*outAux).normal = select(vec3f(0.0), normalize(dl), dot(dl, dl) > 1e-12);
806
- (*outAux).isBlank = ez.isBlank & (*outAux).isBlank;
807
- (*outAux).isShadowCatcher = ez.isShadowCatcher & (*outAux).isShadowCatcher;
808
- (*outAux).shadowCounts = mix(ez.shadowCounts, (*outAux).shadowCounts, coverage);
720
+ (*outAux).albedo = mix(eg.albedo, (*outAux).albedo, coverage);
721
+ let cS = mix(eg.normal, (*outAux).normal, coverage);
722
+ (*outAux).normal = select(vec3f(0.0), normalize(cS), dot(cS, cS) > 1e-12);
723
+ (*outAux).isBlank = eg.isBlank & (*outAux).isBlank;
724
+ (*outAux).isShadowCatcher = eg.isShadowCatcher & (*outAux).isShadowCatcher;
725
+ (*outAux).shadowCounts = mix(eg.shadowCounts, (*outAux).shadowCounts, coverage);
809
726
  return mix(back, result, coverage);
810
727
  }
811
- back = result; ez = *outAux;
728
+ back = result; eg = *outAux;
812
729
  front = true; query = false; event = 0; depth = 0; aJ = false;
813
- si = oI; ma = oH; ma.alpha = 1.0; *outAux = ue;
814
- aa = Path(); aa.ray = ray; aa.beta = vec3f(1.0); aa.fromEye = true;
815
- aa.alpha = select(1.0, 0.0, rtUniform.transmissiveOutputAlphaMin < 1.0);
730
+ si = oy; ma = ox; ma.alpha = 1.0; *outAux = uh;
731
+ path = Path(); path.ray = ray; path.beta = vec3f(1.0); path.fromEye = true;
732
+ path.alpha = select(1.0, 0.0, rtUniform.transmissiveOutputAlphaMin < 1.0);
816
733
  } else { event++; }
817
734
  }
818
735
  return vec4f(0.0);
819
736
  }
820
- ` : spectral === false && !deterministicPrimaryAlpha ? /* wgsl */ `fn iu(uv: vec2f, ray: Ray, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
737
+ ` : spectral === false && !deterministicPrimaryAlpha ? /* wgsl */ `fn hR(uv: vec2f, ray: Ray, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
821
738
  ${primaryVariables}
822
- var aa: Path;
823
- aa.ray = ray;
824
- aa.alpha = select(1.0, 0.0, rtUniform.transmissiveOutputAlphaMin < 1.0);
825
- aa.beta = vec3f(1.0);
826
- aa.fromEye = true;
739
+ var path: Path;
740
+ path.ray = ray;
741
+ path.alpha = select(1.0, 0.0, rtUniform.transmissiveOutputAlphaMin < 1.0);
742
+ path.beta = vec3f(1.0);
743
+ path.fromEye = true;
827
744
  let bounceLimit = max(rtUniform.bounces, 0);
828
- let ft = min(bounceLimit * 3, ${MAX_PATH_EVENTS});
829
- var bQ = false;
745
+ let eZ = min(bounceLimit * 3, ${MAX_PATH_EVENTS});
746
+ var bH = false;
830
747
  var depth = 0;
831
748
  var aJ = false;
832
749
 
833
750
 
834
751
 
835
- for (var event = 0; event <= ft; event++) {
836
- intersectScene(aa.ray, &si, depth, event != 0, aa.isNextRefraction);
837
- dg(&ma, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);
752
+ for (var event = 0; event <= eZ; event++) {
753
+ intersectScene(path.ray, &si, depth, event != 0, path.isNextRefraction);
754
+ getMaterial(&ma, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);
838
755
  if (event == 0) {
839
756
  ${primaryGuides}
840
- bQ = ma.transmissionWeight < 0.001 && ma.subsurfaceWeight < 0.001 && ma.alpha > 0.99;
757
+ bH = ma.transmissionWeight < 0.001 && ma.subsurfaceWeight < 0.001 && ma.alpha > 0.99;
841
758
  } else {
842
- kl(&aa, &depth, &si, &ma, aJ);
759
+ jQ(&path, &depth, &si, &ma, aJ);
843
760
  }
844
- if (bQ && event > bounceLimit) { aa.abort = true; }
845
- if (aa.abort || event >= ft) { break; }
846
- nY(uv, &aa, &depth, &si, &ma, outAux, &aJ);
847
- if (aa.abort) { break; }
761
+ if (bH && event > bounceLimit) { path.abort = true; }
762
+ if (path.abort || event >= eZ) { break; }
763
+ nO(uv, &path, &depth, &si, &ma, outAux, &aJ);
764
+ if (path.abort) { break; }
848
765
  }
849
- return vec4f(aa.li, aa.alpha);
766
+ return vec4f(path.li, path.alpha);
850
767
  }
851
768
  ` : spectral === true && !deterministicPrimaryAlpha ? /* wgsl */ `
852
- fn iu(uv: vec2f, ray: Ray, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
769
+ fn hR(uv: vec2f, ray: Ray, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
853
770
  ${primaryVariables}
854
- var oI: SurfaceInteraction;
855
- var oH: OpenPbrResolvedMaterial;
856
- var iY = false;
857
- var aa: Path; aa.ray = ray;
771
+ var oy: SurfaceInteraction;
772
+ var ox: OpenPbrResolvedMaterial;
773
+ var iH = false;
774
+ var path: Path; path.ray = ray;
858
775
  let bounceLimit = max(rtUniform.bounces, 0);
859
- let ft = min(bounceLimit * 3, ${MAX_PATH_EVENTS});
776
+ let eZ = min(bounceLimit * 3, ${MAX_PATH_EVENTS});
860
777
  var depth = 0; var event = 0; var aJ = false;
861
- var bQ = false;
862
- var mx = 0;
863
- let bo = rtUniform.dispersionWavelengths == 1;
864
- var df = false;
865
- var eX = 0;
866
- var hz: vec4u;
867
- var eO = 0u;
868
- var ba: RayTraceAuxiliary;
869
- let wavelengths = array<f32, 3>(650.0, 510.0, 475.0);
778
+ var bH = false;
779
+ var mc = 0;
780
+ let bi = rtUniform.dispersionWavelengths == 1;
781
+ var ew = false;
782
+ var eG = 0;
783
+ var aZ = 0.0;
784
+ var he: vec4u;
785
+ var ey = 0u;
786
+ var aU: RayTraceAuxiliary;
870
787
  var color = vec3f(0.0); var alpha = 0.0;
871
- var dO = vec3f(0.0);
872
- var dP = vec3f(0.0);
873
- var mN = true;
788
+ var dw = vec3f(0.0);
789
+ var dz = vec3f(0.0);
790
+ var mz = true;
874
791
 
875
792
 
876
793
 
877
- let wF = min((${MAX_PATH_EVENTS} + 1) * 3, i32(rtUniform.loopUnrollGuard * ${Math.ceil((MAX_PATH_EVENTS + 1) * 3 / 4)}u));
878
- for (var step = 0; step < wF; step++) {
879
- if (!iY | ((event != 0) & !aa.abort)) {
880
- intersectScene(aa.ray, &si, depth, event != 0, aa.isNextRefraction);
881
- dg(&ma, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);
794
+ let xf = min((${MAX_PATH_EVENTS} + 1) * 3, i32(rtUniform.loopUnrollGuard * ${Math.ceil((MAX_PATH_EVENTS + 1) * 3 / 4)}u));
795
+ for (var step = 0; step < xf; step++) {
796
+ if (!iH | ((event != 0) & !path.abort)) {
797
+ intersectScene(path.ray, &si, depth, event != 0, path.isNextRefraction);
798
+ getMaterial(&ma, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);
882
799
  }
883
800
  if (event == 0) {
884
- if (!iY) {
801
+ if (!iH) {
885
802
  ${primaryGuides}
886
- oI = si; oH = ma; iY = true;
887
- hz = s0; eO = cP;
888
- df = si.hit & (ma.transmissionWeight > 0.001) & (ma.transmissionDispersionScale > 0.001);
889
- if (bo & df) {
890
- eX = min(i32(floor(dp(CAMERA_WAVELENGTH) * 3.0)), 2);
891
- }
892
- }
893
- si = oI; ma = oH; ba = *outAux;
894
- if (!bo) {
895
- s0 = hz; cP = eO; bT = 0u;
896
- ba.isBlank = false; ba.isShadowCatcher = false;
897
- }
898
- si.wavelength = 0.0;
899
- if (!bo | df) {
900
- si.wavelength = wavelengths[select(mx, eX, bo)];
901
- ma.specularIor = ee(si.wavelength, ma.specularIor,
803
+ oy = si; ox = ma; iH = true;
804
+ ew = si.hit & (ma.transmissionWeight > 0.001) & (ma.transmissionDispersionScale > 0.001);
805
+ aZ = sample1D(CAMERA_WAVELENGTH);
806
+ if (bi) {
807
+ eG = min(i32(floor(aZ * 3.0)), 2);
808
+ aZ = fract(aZ * 3.0);
809
+ }
810
+ he = s0; ey = ca;
811
+ }
812
+ si = oy; ma = ox; aU = *outAux;
813
+ if (!bi) {
814
+ s0 = he; ca = ey; samplingBounce = 0u;
815
+ aU.isBlank = false; aU.isShadowCatcher = false;
816
+ }
817
+ si.wavelength = 0.0; si.spectralChannel = 0;
818
+ if (!bi | ew) {
819
+ let channel = select(mc, eG, bi);
820
+ si.spectralChannel = channel + 1;
821
+ si.wavelength = cU(u32(channel), aZ);
822
+ ma.specularIor = sampling_cauchy_ior(si.wavelength, ma.specularIor,
902
823
  ma.transmissionDispersionScale, ma.dispersionAbbeNumber);
903
824
  }
904
- aa = Path(); aa.ray = ray; aa.beta = vec3f(1.0); aa.fromEye = true;
905
- aa.alpha = select(1.0, 0.0, rtUniform.transmissiveOutputAlphaMin < 1.0);
825
+ path = Path(); path.ray = ray; path.beta = vec3f(1.0); path.fromEye = true;
826
+ path.alpha = select(1.0, 0.0, rtUniform.transmissiveOutputAlphaMin < 1.0);
906
827
  depth = 0; aJ = false;
907
- bQ = (ma.transmissionWeight < 0.001) & (ma.subsurfaceWeight < 0.001) & (ma.alpha > 0.99);
908
- } else if (!aa.abort) {
909
- kl(&aa, &depth, &si, &ma, aJ);
910
- }
911
- if (bQ & (event > bounceLimit)) { aa.abort = true; }
912
- if (!aa.abort & (event < ft)) {
913
- nY(uv, &aa, &depth, &si, &ma, &ba, &aJ);
914
- }
915
- if (aa.abort | (event >= ft)) {
916
- let result = vec4f(aa.li, aa.alpha);
917
- if (bo) {
918
- *outAux = ba;
919
- let scale = select(1.0, 3.0, df);
828
+ bH = (ma.transmissionWeight < 0.001) & (ma.subsurfaceWeight < 0.001) & (ma.alpha > 0.99);
829
+ } else if (!path.abort) {
830
+ jQ(&path, &depth, &si, &ma, aJ);
831
+ }
832
+ if (bH & (event > bounceLimit)) { path.abort = true; }
833
+ if (!path.abort & (event < eZ)) {
834
+ nO(uv, &path, &depth, &si, &ma, &aU, &aJ);
835
+ }
836
+ if (path.abort | (event >= eZ)) {
837
+ let result = vec4f(path.li, path.alpha);
838
+ if (bi) {
839
+ *outAux = aU;
840
+ let scale = select(1.0, 3.0, ew);
920
841
  return vec4f(result.rgb * scale, result.a);
921
842
  }
922
843
  color += result.rgb; alpha = max(alpha, result.a);
923
- dO += ba.albedo;
924
- dP += ba.normal;
925
- mN = mN & ba.isBlank;
926
- mx++;
927
- if (mx >= 3) {
928
- (*outAux).albedo = dO / 3.0;
929
- (*outAux).normal = dP / 3.0;
930
- (*outAux).isBlank = mN;
844
+ dw += aU.albedo;
845
+ dz += aU.normal;
846
+ mz = mz & aU.isBlank;
847
+ mc++;
848
+ if (mc >= 3) {
849
+ (*outAux).albedo = dw / 3.0;
850
+ (*outAux).normal = dz / 3.0;
851
+ (*outAux).isBlank = mz;
931
852
  return vec4f(color, alpha);
932
853
  }
933
854
  event = 0;
@@ -935,91 +856,95 @@ event = 0;
935
856
  }
936
857
  return vec4f(0.0);
937
858
  }
938
- ` : /* wgsl */ `fn iu(uv: vec2f, ray: Ray, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
859
+ ` : /* wgsl */ `fn hR(uv: vec2f, ray: Ray, outAux: ptr<function, RayTraceAuxiliary>) -> vec4f {
939
860
  ${primaryVariables}
940
861
  intersectScene(ray, &si, 0, false, false);
941
- dg(&ma, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);
862
+ getMaterial(&ma, si.materialIndex, si.uv, si.uv1, si.instanceIndex, si.vertexColor);
942
863
  ${primaryGuides}
943
864
  if (SPECTRAL) {
944
865
 
945
866
 
946
867
 
947
868
 
948
- let ug = array<f32, 3>(650.0, 510.0, 475.0);
949
- var vl = vec3f(0.0);
869
+ var vu = vec3f(0.0);
950
870
  var alpha = 0.0;
951
- var dO = vec3f(0.0);
952
- var dP = vec3f(0.0);
953
- var mN = true;
871
+ var dw = vec3f(0.0);
872
+ var dz = vec3f(0.0);
873
+ var mz = true;
954
874
  var si2 = si;
955
875
  var ma2 = ma;
956
- let hz = s0;
957
- let eO = cP;
958
- let bo = rtUniform.dispersionWavelengths == 1;
959
- let df = si.hit &&
876
+ var aZ = sample1D(CAMERA_WAVELENGTH);
877
+ let he = s0;
878
+ let ey = ca;
879
+ let bi = rtUniform.dispersionWavelengths == 1;
880
+ let ew = si.hit &&
960
881
  ma.transmissionWeight > 0.001 &&
961
882
  ma.transmissionDispersionScale > 0.001;
962
- let tm = select(3, 1, bo);
963
- var eX = 0;
964
- if (bo && df) {
883
+ let tm = select(3, 1, bi);
884
+ var eG = 0;
885
+ if (bi) {
965
886
 
966
887
 
967
- eX = min(i32(floor(dp(CAMERA_WAVELENGTH) * 3.0)), 2);
888
+ eG = min(i32(floor(aZ * 3.0)), 2);
889
+ aZ = fract(aZ * 3.0);
968
890
  }
969
891
  for (var i = 0; i < tm; i++) {
970
892
 
971
893
 
972
894
 
973
- if (!bo) {
974
- s0 = hz;
975
- cP = eO;
976
- bT = 0u;
895
+ if (!bi) {
896
+ s0 = he;
897
+ ca = ey;
898
+ samplingBounce = 0u;
977
899
  }
978
900
  si.wavelength = 0.0;
979
- if (!bo || df) {
980
- si.wavelength = ug[select(i, eX, bo)];
981
- ma.specularIor = ee(
901
+ si.spectralChannel = 0;
902
+ if (!bi || ew) {
903
+ let channel = select(i, eG, bi);
904
+ si.spectralChannel = channel + 1;
905
+ si.wavelength = cU(u32(channel), aZ);
906
+ ma.specularIor = sampling_cauchy_ior(
982
907
  si.wavelength,
983
908
  ma.specularIor,
984
909
  ma.transmissionDispersionScale,
985
910
  ma.dispersionAbbeNumber
986
911
  );
987
912
  }
988
- var ba: RayTraceAuxiliary;
989
- if (bo) {
990
- ba = *outAux;
913
+ var aU: RayTraceAuxiliary;
914
+ if (bi) {
915
+ aU = *outAux;
991
916
  } else {
992
- ba.albedo = (*outAux).albedo;
993
- ba.normal = (*outAux).normal;
994
- ba.isBlank = false;
995
- ba.isShadowCatcher = false;
996
- }
997
- let res = iU(uv, &si, ray, &ma, &ba);
998
- if (bo) {
999
- *outAux = ba;
1000
- let scale = select(1.0, 3.0, df);
917
+ aU.albedo = (*outAux).albedo;
918
+ aU.normal = (*outAux).normal;
919
+ aU.isBlank = false;
920
+ aU.isShadowCatcher = false;
921
+ }
922
+ let res = iC(uv, &si, ray, &ma, &aU);
923
+ if (bi) {
924
+ *outAux = aU;
925
+ let scale = select(1.0, 3.0, ew);
1001
926
  return vec4f(res.rgb * scale, res.a);
1002
927
  }
1003
- vl += res.rgb;
928
+ vu += res.rgb;
1004
929
  alpha = max(alpha, res.a);
1005
- dO += ba.albedo;
1006
- dP += ba.normal;
1007
- mN = mN && ba.isBlank;
930
+ dw += aU.albedo;
931
+ dz += aU.normal;
932
+ mz = mz && aU.isBlank;
1008
933
  si = si2;
1009
934
  ma = ma2;
1010
935
  }
1011
- (*outAux).albedo = dO / 3.0;
1012
- (*outAux).normal = dP / 3.0;
1013
- (*outAux).isBlank = mN;
1014
- return vec4f(vl, alpha);
936
+ (*outAux).albedo = dw / 3.0;
937
+ (*outAux).normal = dz / 3.0;
938
+ (*outAux).isBlank = mz;
939
+ return vec4f(vu, alpha);
1015
940
  }
1016
941
  else {
1017
- return iU(uv, &si, ray, &ma, outAux);
942
+ return iC(uv, &si, ray, &ma, outAux);
1018
943
  }
1019
944
  }
1020
945
  `}
1021
946
 
1022
- fn kN(ip: vec2f) -> vec2f {
947
+ fn kq(ip: vec2f) -> vec2f {
1023
948
  let p = 2.0 * ip - 1.0;
1024
949
  let greater = abs(p.x) > abs(p.y);
1025
950
  let r = select(p.y, p.x, greater);
@@ -1028,7 +953,7 @@ return r * vec2f(cos(theta), sin(theta));
1028
953
  }
1029
954
 
1030
955
 
1031
- @compute @workgroup_size(${WORKGROUP_SIZE}, ${WORKGROUP_SIZE}, 1)
956
+ @compute @workgroup_size(${workgroupSize}, ${workgroupSize}, 1)
1032
957
  fn main(@builtin(global_invocation_id) globalId: vec3u) {
1033
958
  let outputSize = rtUniform.outputSize;
1034
959
  let scaleOffset = rtUniform.scaleOffset;
@@ -1058,24 +983,24 @@ return;
1058
983
 
1059
984
  let uv = (vec2<f32>(f32(coord.x), f32(coord.y)) + vec2f(0.5)) / outputSize;
1060
985
 
1061
- aZ = coord;
1062
- aQ = u32(outNormal[idx].a) + rtUniform.sampleSequenceOffset;
1063
- bT = 0u; cP = 0u;
986
+ aI = coord;
987
+ aC = u32(outNormal[idx].a) + rtUniform.sampleSequenceOffset;
988
+ samplingBounce = 0u; ca = 0u;
1064
989
  if (${inputHooks?.uniformJitter ? 'false' : 'SAMPLING_PATTERN == 0 || SAMPLING_PATTERN == 1'}) {
1065
- jitter = (dZ(CAMERA_PIXEL) - 0.5) / outputSize;
990
+ jitter = (sample2D(CAMERA_PIXEL) - 0.5) / outputSize;
1066
991
  }
1067
- gW(coord, i32(aQ ^ dG(rtUniform.sequenceSeed)));
1068
- var cam = fj(uv + jitter);
992
+ fi(coord, i32(aC ^ cB(rtUniform.sequenceSeed)));
993
+ var cam = eT(uv + jitter);
1069
994
 
1070
995
  if (cameraUniform.apertureRadius > 0.0) {
1071
996
 
1072
997
  let eye = cameraUniform.viewInv[3].xyz;
1073
998
  let forward = -normalize(cameraUniform.viewInv[2].xyz);
1074
- let jN = eye + cam.d * (cameraUniform.focusDistance / dot(cam.d, forward));
1075
- let sK = cameraUniform.apertureRadius * kN(dZ(CAMERA_LENS));
1076
- let origin = (cameraUniform.viewInv * vec4f(sK, 0.0, 1.0)).xyz;
1077
- let dir = normalize(jN - origin);
1078
- gC(&cam, origin, dir);
999
+ let ju = eye + cam.d * (cameraUniform.focusDistance / dot(cam.d, forward));
1000
+ let sH = cameraUniform.apertureRadius * kq(sample2D(CAMERA_LENS));
1001
+ let origin = (cameraUniform.viewInv * vec4f(sH, 0.0, 1.0)).xyz;
1002
+ let dir = normalize(ju - origin);
1003
+ initRay(&cam, origin, dir);
1079
1004
  }
1080
1005
 
1081
1006
  var outAux: RayTraceAuxiliary;
@@ -1083,39 +1008,40 @@ outAux.albedo = vec3f(0.0);
1083
1008
  outAux.normal = vec3f(0.0);
1084
1009
  outAux.isBlank = false;
1085
1010
  outAux.isShadowCatcher = false;
1086
- ${pathDiagnostic ? ' mtPathBegin(coord);\n' : ''}${inputHooks?.begin ?? ''} var aW = iu(uv + jitter, cam, &outAux);
1011
+ ${pathDiagnostic ? ' mtPathBegin(coord);\n' : ''}${inputHooks?.begin ?? ''} var liAndAlpha = hR(uv + jitter, cam, &outAux);
1087
1012
  ${inputHooks?.unclampedColor ?? ''}
1088
-
1013
+ ${(enabled || lightTracing || photonMapping) && debugGroup >= 0 ? /* wgsl */ ` liAndAlpha=${debugGroup >= 50 ? `vec4f(photonQueryStats,1.0)` : debugGroup >= 30 ? `vec4f(causticHot[${debugGroup - 30}],1.0)` : research?.debugOutput ?? 'liAndAlpha'};
1014
+ ` : ''}
1089
1015
 
1090
1016
  if (rtUniform.clamping > 0.0) {
1091
1017
  let clamping = rtUniform.clamping;
1092
- aW = vec4(clamp(aW.rgb, -vec3f(clamping), vec3f(clamping)), aW.a);
1018
+ liAndAlpha = vec4(clamp(liAndAlpha.rgb, -vec3f(clamping), vec3f(clamping)), liAndAlpha.a);
1093
1019
  }
1094
- if (!(aW.x < INF && aW.x > -EPS)) {
1095
- aW = vec4f(0.0, 0.0, 0.0, 1.0);
1020
+ if (!(liAndAlpha.x < INF && liAndAlpha.x > -EPS)) {
1021
+ liAndAlpha = vec4f(0.0, 0.0, 0.0, 1.0);
1096
1022
  }
1097
1023
 
1098
1024
  if (outAux.isShadowCatcher) {
1099
1025
 
1100
1026
 
1101
- let bc = hX(cam);
1102
- let rh = select(0.0, 1.0, bc.a >= 0.01);
1103
- let jW = vec4f(bc.rgb * bc.a, bc.a);
1027
+ let aW = ft(cam);
1028
+ let qX = select(0.0, 1.0, aW.a >= 0.01);
1029
+ let jC = vec4f(aW.rgb * aW.a, aW.a);
1104
1030
 
1105
1031
 
1106
1032
 
1107
- outShadowCatcher[idx].mask += vec4f(1.0, bc.a, rh, 0.0);
1033
+ outShadowCatcher[idx].mask += vec4f(1.0, aW.a, qX, 0.0);
1108
1034
  outShadowCatcher[idx].moments += vec4f(0.0, 0.0, outAux.shadowCounts);
1109
- outShadowCatcher[idx].background += jW;
1110
- outColor[idx] += jW;
1111
- outAlbedo[idx] += vec4f(outAux.albedo, rh);
1112
- ie(idx, bc.rgb, outAux.normal);
1035
+ outShadowCatcher[idx].background += jC;
1036
+ outColor[idx] += jC;
1037
+ outAlbedo[idx] += vec4f(outAux.albedo, qX);
1038
+ hH(idx, aW.rgb, outAux.normal);
1113
1039
 
1114
1040
 
1115
1041
  let counts = outAux.shadowCounts;
1116
1042
  let visibility = 1.0 - select(0.0, counts.x / counts.y, counts.y > 0.0);
1117
- ji(idx, visibility * select(
1118
- 1.0, dot(bc.rgb, luminance), bc.a >= 0.01
1043
+ iP(idx, visibility * select(
1044
+ 1.0, dot(aW.rgb, luminance), aW.a >= 0.01
1119
1045
  ));
1120
1046
  }
1121
1047
  else {
@@ -1125,13 +1051,13 @@ if (HAS_SHADOW_CATCHER && outAux.isBlank && USE_BACKGROUND && !USE_BACKGROUND_MA
1125
1051
 
1126
1052
 
1127
1053
 
1128
- outShadowCatcher[idx].background += aW;
1129
- outShadowCatcher[idx].mask.g += aW.a;
1054
+ outShadowCatcher[idx].background += liAndAlpha;
1055
+ outShadowCatcher[idx].mask.g += liAndAlpha.a;
1130
1056
  }
1131
- outColor[idx] += aW;
1057
+ outColor[idx] += liAndAlpha;
1132
1058
  outAlbedo[idx] += vec4f(outAux.albedo, select(1.0, 0.0, outAux.isBlank));
1133
- ie(idx, aW.rgb, outAux.normal);
1134
- ji(idx, dot(aW.rgb, luminance));
1059
+ hH(idx, liAndAlpha.rgb, outAux.normal);
1060
+ iP(idx, dot(liAndAlpha.rgb, luminance));
1135
1061
  }
1136
1062
  ${pathDiagnostic ? ' mtPathEnd(outAux.normal, outAux.albedo);\n' : ''}${inputHooks?.end ?? ''}}
1137
1063
  `;