@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,10 +1,10 @@
1
1
  // Next-event estimation with resampled importance sampling over the light
2
2
  // candidates, followed by BSDF (or phase function) sampling, as described in
3
3
  // http://www.pbr-book.org/3ed-2018/Light_Transport_I_Surface_Reflection/Direct_Lighting.html#EstimatingtheDirectLightingIntegral
4
- export function createSampleMaterialWgsl(hasAnisotropyDirections = true, hasCoatNormals = false) {
4
+ export function createSampleMaterialWgsl(hasAnisotropyDirections = true, hasCoatNormals = false, caustics = false, researchContribution = '', photonMapping = false) {
5
5
  return /* wgsl */ `
6
6
 
7
- struct ob {
7
+ struct nR {
8
8
  ray: Ray,
9
9
  maxDistance: f32,
10
10
  triangleIndex: i32,
@@ -16,32 +16,37 @@ lightSelectionPmf: f32,
16
16
  valid: bool,
17
17
  }
18
18
 
19
- fn sd(
19
+ fn rZ(
20
20
  si: ptr<function, SurfaceInteraction>,
21
21
  ma: OpenPbrResolvedMaterial,
22
- aa: ptr<function, Path>,
22
+ path: ptr<function, Path>,
23
23
  ffnormal: vec3f,
24
- eM: bool,
24
+ isSurface: bool,
25
25
  lightSample: LightSampleRec,
26
26
  f: vec3f,
27
27
  scatteringPdf: f32,
28
- gz: ptr<function, ob>
28
+ gj: ptr<function, nR>
29
29
  ) -> bool {
30
- (*gz).valid = false;
31
- (*gz).lightSelectionPmf = 0.0;
32
- (*gz).risTarget = 0.0;
30
+ (*gj).valid = false;
31
+ (*gj).lightSelectionPmf = 0.0;
32
+ (*gj).risTarget = 0.0;
33
33
  var Li = lightSample.emission;
34
34
 
35
- let lightDir = lightSample.direction;
36
- let qY = -(*aa).ray.d;
37
- let fA = lightSample.pdf;
35
+ let lightDir = lightSample.direction;${caustics ? /* wgsl */ `
36
+ if(isSurface&&isCausticSpecular(ma)){
37
+ var connection=*path;
38
+ causticAdvance(&connection,ma,dot(ffnormal,lightDir)<0.0,true);
39
+ if(causticHitOwned(connection,lightSample.sourceType!=0u,true)){return false;}
40
+ }` : ''}
41
+ let qR = -(*path).ray.d;
42
+ let lightPdf = lightSample.pdf;
38
43
  let lightSelectionPmf = lightSample.selectionPmf;
39
44
 
40
45
 
41
46
  ${hasCoatNormals ? /* wgsl */ `var cosThetaL = dot(ffnormal, lightDir);
42
- if (eM && ma.coatNormalEnabled) { cosThetaL = dot(ma.geometricNormal, lightDir); }` : 'let cosThetaL = dot(ffnormal, lightDir);'}
47
+ if (isSurface && ma.coatNormalEnabled) { cosThetaL = dot(ma.geometricNormal, lightDir); }` : 'let cosThetaL = dot(ffnormal, lightDir);'}
43
48
 
44
- if ((fA <= 0.0) | (lightSelectionPmf <= 0.0) |
49
+ if ((lightPdf <= 0.0) | (lightSelectionPmf <= 0.0) |
45
50
  (max(max(Li.x, Li.y), Li.z) <= 0.0)) {
46
51
  return false;
47
52
  }
@@ -50,201 +55,209 @@ if ((scatteringPdf <= 0.0) | (max(max(f.x, f.y), f.z) <= 0.0)) {
50
55
  return false;
51
56
  }
52
57
 
53
- var ns: Ray;
54
- var hw = (*si).position + EPS * lightDir;
55
- if (eM) {
56
- hw = sR((*si).position, (*si).faceNormal, lightDir);
57
- let ch = 0.1;
58
- var dL = dot((*si).normal, lightDir);
59
- ${hasCoatNormals ? /* wgsl */ ` if (ma.coatNormalEnabled) { dL = dot((*si).faceNormal, lightDir); }` : ''}
58
+ var mY: Ray;
59
+ var eO = (*si).position + EPS * lightDir;
60
+ if (isSurface) {
61
+ eO = sO((*si).position, (*si).faceNormal, lightDir);
62
+ let shadowTerminatorCutoff = 0.1;
63
+ var dj = dot((*si).normal, lightDir);
64
+ ${hasCoatNormals ? /* wgsl */ ` if (ma.coatNormalEnabled) { dj = dot((*si).faceNormal, lightDir); }` : ''}
60
65
  let geometricNormal = select(
61
66
  (*si).faceNormal,
62
67
  -(*si).faceNormal,
63
- dL < 0.0
68
+ dj < 0.0
64
69
  );
65
- dL = abs(dL);
66
- let iq = dot(geometricNormal, lightDir);
67
- let pq = select(
68
- clamp(1.0 - iq / ch, 0.0, 1.0),
70
+ dj = abs(dj);
71
+ let hO = dot(geometricNormal, lightDir);
72
+ let pf = select(
73
+ clamp(1.0 - hO / shadowTerminatorCutoff, 0.0, 1.0),
69
74
  clamp(
70
- 2.0 - (iq + dL) / ch,
75
+ 2.0 - (hO + dj) / shadowTerminatorCutoff,
71
76
  0.0,
72
77
  1.0
73
78
  ),
74
- dL < ch
79
+ dj < shadowTerminatorCutoff
75
80
  );
76
- hw += (*si).shadowOffset * pq;
81
+ eO += (*si).shadowOffset * pf;
77
82
  }
78
83
 
79
84
 
80
85
 
81
86
 
82
- var mA = lightDir;
83
- var nN = lightSample.dist - EPS;
87
+ var mh = lightDir;
88
+ var nC = lightSample.dist - EPS;
84
89
  if (lightSample.sourceType == 1u) {
85
- let uo =
90
+ let us =
86
91
  (*si).position + lightSample.direction * lightSample.dist;
87
- let rc = uo + EPS * lightSample.normal;
88
- let rr = rc - hw;
89
- nN = length(rr);
90
- mA = normalize(rr);
92
+ let qU = us + EPS * lightSample.normal;
93
+ let rk = qU - eO;
94
+ nC = length(rk);
95
+ mh = normalize(rk);
91
96
  }
92
- gC(&ns, hw, mA);
97
+ initRay(&mY, eO, mh);
93
98
 
94
99
 
95
100
 
96
101
 
97
- if (eM & (cosThetaL < 0.0) & (lightSample.sourceType == 0u)) {
98
- let background = hX(ns);
102
+ if (isSurface & (cosThetaL < 0.0) & (lightSample.sourceType == 0u)) {
103
+ let background = ft(mY);
99
104
  Li = background.rgb * background.a;
100
105
  }
101
106
  if (SPECTRAL) {
102
- Li = aj(Li, (*si).wavelength);
107
+ Li = sampling_spectral_rgb_filter(Li, (*si).spectralChannel);
103
108
  }
104
109
 
105
110
 
106
111
 
107
- let fl = select(
108
- uS(fA, scatteringPdf),
112
+ let misWeight = select(
113
+ uY(lightPdf, scatteringPdf),
109
114
  1.0,
110
115
  lightSample.isDelta
111
116
  );
112
- if (fl > 0.0) {
113
- let kV = Li * f / fA * (*aa).beta;
114
- (*gz).risTarget = max(
115
- dot(max(kV * lightSelectionPmf, vec3f(0.0)), luminance),
117
+ if (misWeight > 0.0) {
118
+ let kB = Li * f / lightPdf * (*path).beta;
119
+ (*gj).risTarget = max(
120
+ dot(max(kB * lightSelectionPmf, vec3f(0.0)), luminance),
116
121
  0.0
117
122
  );
118
- (*gz).ray = ns;
119
- (*gz).maxDistance = nN;
120
- (*gz).triangleIndex = (*si).triangleIndex;
121
- (*gz).contribution = fl * kV;
122
- (*gz).lightSelectionPmf = lightSelectionPmf;
123
- (*gz).valid = true;
123
+ (*gj).ray = mY;
124
+ (*gj).maxDistance = nC;
125
+ (*gj).triangleIndex = (*si).triangleIndex;
126
+ (*gj).contribution = misWeight * kB;
127
+ (*gj).lightSelectionPmf = lightSelectionPmf;
128
+ (*gj).valid = true;
124
129
  return true;
125
130
  }
126
131
  return false;
127
132
  }
128
133
 
129
- struct qc {
134
+ struct pX {
130
135
  direction: vec3f,
131
136
  response: vec3f,
132
137
  pdf: f32,
133
138
  transmission: bool,
134
139
  }
135
140
 
136
- fn sW(
141
+ fn sV(
137
142
  si: ptr<function, SurfaceInteraction>,
138
143
  ma: OpenPbrResolvedMaterial,
139
- prepared: ag,
140
- aa: ptr<function, Path>,
144
+ prepared: OpenPbrPreparedBsdf,
145
+ path: ptr<function, Path>,
141
146
  ffnormal: vec3f,
142
- eM: bool
143
- ) -> qc {
144
- let candidateCount = kB();
145
- var selected: ob;
147
+ isSurface: bool
148
+ ) -> pX {
149
+ let candidateCount = ke();
150
+ var selected: nR;
146
151
  selected.valid = false;
147
- var nH = 0.0;
148
- var mq = 0.0;
149
- var result: qc;
152
+ var nq = 0.0;
153
+ var lW = 0.0;
154
+ var result: pX;
150
155
 
151
156
 
152
157
 
153
158
 
154
159
  for (var event = 0u; event <= candidateCount; event++) {
155
- let rX = event == candidateCount;
160
+ let continuation = event == candidateCount;
156
161
  var lightSample: LightSampleRec;
157
162
  var lightDir: vec3f;
158
163
  var scatteringPdf = 0.0;
159
164
  var response = vec3f(0.0);
160
- var tE = false;
161
- if (rX) {
162
- var rU = 1.0;
165
+ var tF = false;
166
+ if (continuation) {
167
+ var oI = 1.0;
163
168
  var valid = selected.valid;
164
169
  if (candidateCount > 1u) {
165
- valid = valid & (nH > 0.0);
170
+ valid = valid & (nq > 0.0);
166
171
  if (valid) {
167
- rU = selected.lightSelectionPmf * mq /
168
- (f32(candidateCount) * nH);
172
+ oI = selected.lightSelectionPmf * lW /
173
+ (f32(candidateCount) * nq);
169
174
  }
170
175
  }
171
- if (valid && !intersectSceneShadow(selected.ray, selected.maxDistance, selected.triangleIndex)) {
172
- (*aa).li += selected.contribution * rU;
176
+ if (valid && !intersectSceneShadow(selected.ray, selected.maxDistance, selected.triangleIndex, (*si).instanceIndex)) {
177
+ ${caustics ? ` var connection=*path;
178
+ if(isSurface&&isCausticSpecular(ma)){causticAdvance(&connection,ma,dot(ffnormal,selected.ray.d)<0.0,true);}
179
+ connection.beta=vec3f(1.0);causticHotRecord(connection,selected.contribution*oI,0u);
180
+ ` : ''} (*path).li += selected.contribution * oI;
173
181
  }
174
- if (!eM) {
175
- result.direction = fH(-(*aa).ray.d,
176
- (*si).mediumAnisotropy, dZ(cE(PHASE_DIRECTION)));
177
- result.pdf = bL(
178
- dot(result.direction, -(*aa).ray.d), (*si).mediumAnisotropy);
182
+ if (!isSurface) {
183
+ result.direction = fj(-(*path).ray.d,
184
+ (*si).mediumAnisotropy, sample2D(bE(PHASE_DIRECTION)));
185
+ result.pdf = bB(
186
+ dot(result.direction, -(*path).ray.d), (*si).mediumAnisotropy);
179
187
  return result;
180
188
  }
181
- let vR = vec3f(dZ(cE(BSDF_DIRECTION)), dp(cE(BSDF_LOBE)));
182
- tE = !prepared.material.thinWalled &
189
+ let wh = vec3f(sample2D(bE(BSDF_DIRECTION)), sample1D(bE(BSDF_LOBE)));
190
+ tF = !prepared.material.thinWalled &
183
191
  (abs(prepared.material.relativeIor - 1.0) <= 1e-6) &
184
192
  (prepared.probabilities[OPENPBR_LOBE_TRANSMISSION] >= 1.0 - 1e-6);
185
- if (tE) {
193
+ if (tF) {
186
194
  lightDir = openpbr_to_world(prepared.basis, -prepared.viewLocal);
187
- response = bh(prepared.material) * cF(prepared,
195
+ response = ba(prepared.material) * cm(prepared,
188
196
  ${hasCoatNormals ? 'select(-prepared.viewLocal.z, dot(prepared.coatBasis.normal, lightDir), prepared.material.coatNormalEnabled)' : '-prepared.viewLocal.z'});
189
197
  scatteringPdf = 1.0;
190
198
  result.transmission = true;
191
199
  } else {
192
200
  var roughness = 1.0; var specular = false; var diffuse = true;
193
- var jT = u32(OPENPBR_LOBE_DIFFUSE);
201
+ var lobe = u32(OPENPBR_LOBE_DIFFUSE);
194
202
 
195
203
  var transmission = false;
196
- if (!jq(prepared, vR, &lightDir, &transmission,
197
- &roughness, &specular, &diffuse, &jT)) { return result; }
204
+ if (!iW(prepared, wh, &lightDir, &transmission,
205
+ &roughness, &specular, &diffuse, &lobe)) { return result; }
198
206
  result.transmission = transmission;
199
207
  }
200
208
  } else {
201
- let lV = vec3f(dZ(sl(event, 1u)), dp(sl(event, 0u)));
202
- nE((*si).position, lV, event, candidateCount, &lightSample);
209
+ let mZ = vec3f(sample2D(sf(event, 1u)), sample1D(sf(event, 0u)));
210
+ nk((*si).position, mZ, event, candidateCount, &lightSample);
203
211
  lightDir = lightSample.direction;
204
212
  if ((lightSample.pdf <= 0.0) | (lightSample.selectionPmf <= 0.0) |
205
213
  (max(max(lightSample.emission.x, lightSample.emission.y), lightSample.emission.z) <= 0.0)) { continue; }
206
214
  ${hasCoatNormals ? /* wgsl */ `var cosThetaL = dot(ffnormal, lightDir);
207
- if (eM & ma.coatNormalEnabled) { cosThetaL = dot(ma.geometricNormal, lightDir); }` : /* wgsl */ `let cosThetaL = dot(ffnormal, lightDir);`}
208
- if (eM & (cosThetaL <= 0.0) & (ma.transmissionWeight <= 0.0) & (ma.subsurfaceWeight <= 0.0)) { continue; }
215
+ if (isSurface & ma.coatNormalEnabled) { cosThetaL = dot(ma.geometricNormal, lightDir); }` : /* wgsl */ `let cosThetaL = dot(ffnormal, lightDir);`}
216
+ if (isSurface & (cosThetaL <= 0.0) & (ma.transmissionWeight <= 0.0) & (ma.subsurfaceWeight <= 0.0)) { continue; }
209
217
  }
210
- if (!tE) {
211
- if (eM) {
212
- response = bO(prepared, lightDir, &scatteringPdf);
218
+ if (!tF) {
219
+ if (isSurface) {
220
+ response = openpbr_eval_prepared(prepared, lightDir, &scatteringPdf);
213
221
  } else {
214
- scatteringPdf = bL(
215
- dot(-(*aa).ray.d, lightDir), (*si).mediumAnisotropy);
222
+ scatteringPdf = bB(
223
+ dot(-(*path).ray.d, lightDir), (*si).mediumAnisotropy);
216
224
  response = vec3f(scatteringPdf);
217
225
  }
218
226
  }
219
- if (rX) {
227
+ if (continuation) {
220
228
  result.direction = lightDir; result.response = response; result.pdf = scatteringPdf;
221
229
  return result;
222
230
  }
223
- var candidate: ob;
224
- let tv = sd(si, ma, aa, ffnormal, eM,
231
+ var candidate: nR;
232
+ let tv = rZ(si, ma, path, ffnormal, isSurface,
225
233
  lightSample, response, scatteringPdf, &candidate);
226
234
  if (!tv) { continue; }
227
235
  if (candidateCount == 1u) {
228
236
  selected = candidate;
229
237
  continue;
230
238
  }
231
- let kO = candidate.risTarget / max(candidate.lightSelectionPmf, 1e-20);
232
- if (!(kO > 0.0) | (kO != kO)) { continue; }
233
- mq += kO;
239
+ let kt = candidate.risTarget / max(candidate.lightSelectionPmf, 1e-20);
240
+ if (!(kt > 0.0) | (kt != kt)) { continue; }
241
+ lW += kt;
234
242
  if (!selected.valid ||
235
- qx(event) * mq <= kO) {
243
+ qp(event) * lW <= kt) {
236
244
  selected = candidate;
237
- nH = candidate.risTarget;
245
+ nq = candidate.risTarget;
238
246
  }
239
247
  }
240
248
  return result;
241
249
  }
242
250
 
243
- fn qm(
251
+ fn emissiveHitMisWeight(
244
252
  si: ptr<function, SurfaceInteraction>,
245
- aa: ptr<function, Path>
246
- ) -> f32 {
247
- if ((*aa).fromEye | (rtUniform.lightWeightTotal <= 0.0) |
253
+ path: ptr<function, Path>
254
+ ) -> f32 {${caustics ? /* wgsl */ `
255
+ if (causticHitOwned(*path, true, true)) { return 0.0; }` : ''}
256
+
257
+
258
+ let om = dot((*si).faceNormal, -(*path).ray.d);
259
+ if (om <= 0.0 && materialsBuffer[(*si).materialIndex].doubleSided < 0.5) { return 0.0; }
260
+ if ((*path).fromEye | (rtUniform.lightWeightTotal <= 0.0) |
248
261
  (i32(materialsBuffer[(*si).materialIndex].matType) == UNLIT)) {
249
262
  return 1.0;
250
263
  }
@@ -252,54 +265,53 @@ let samplingLuminance = dot(
252
265
  materialsBuffer[(*si).materialIndex].emission,
253
266
  luminance
254
267
  );
255
- let qi = dot((*si).faceNormal, -(*aa).ray.d);
256
- if ((samplingLuminance <= 0.0) | (qi <= 0.0)) {
268
+ if ((samplingLuminance <= 0.0) | (om <= 0.0)) {
257
269
  return 1.0;
258
270
  }
259
- let te = distance((*si).position, (*aa).ray.o);
260
- let fA = samplingLuminance / rtUniform.lightWeightTotal *
261
- te * te / max(qi, 1e-8);
262
- return gj((*aa).scatteringPdf, fA);
271
+ let tc = distance((*si).position, (*path).ray.o);
272
+ let lightPdf = samplingLuminance / rtUniform.lightWeightTotal *
273
+ tc * tc / max(om, 1e-8);
274
+ return fV((*path).scatteringPdf, lightPdf);
263
275
  }
264
276
 
265
277
  ${hasCoatNormals ? /* wgsl */ `
266
278
 
267
279
 
268
- fn fT(input: vec3f, face: vec3f, view: vec3f) -> vec3f {
280
+ fn fE(input: vec3f, face: vec3f, view: vec3f) -> vec3f {
269
281
  let front = dot(face, view) >= 0.0;
270
- let vP = select(-face, face, front);
271
- let sc = select(-input, input, front);
272
- if ((dot(input, face) <= 0.0) | (dot(sc, view) <= 1e-6)) { return vP; }
273
- return sc;
282
+ let wd = select(-face, face, front);
283
+ let rY = select(-input, input, front);
284
+ if ((dot(input, face) <= 0.0) | (dot(rY, view) <= 1e-6)) { return wd; }
285
+ return rY;
274
286
  }
275
287
  ` : ''}
276
- fn mL(
288
+ fn mx(
277
289
  si: ptr<function, SurfaceInteraction>,
278
290
  ma: ptr<function, OpenPbrResolvedMaterial>,
279
- aa: ptr<function, Path>
291
+ path: ptr<function, Path>
280
292
  ) {
281
293
  ${hasCoatNormals ? /* wgsl */ `
282
- let bK = (*si).faceNormal;
283
- let nB = (*si).normal;
294
+ let bA = (*si).faceNormal;
295
+ let ni = (*si).normal;
284
296
  ` : ''}
285
- var sO: f32 = -dot((*si).faceNormal, (*aa).ray.d);
286
- var tV: f32 = -dot((*si).normal, (*aa).ray.d);
297
+ var sL: f32 = -dot((*si).faceNormal, (*path).ray.d);
298
+ var tY: f32 = -dot((*si).normal, (*path).ray.d);
287
299
  if ((((*ma).transmissionWeight > 0.0) | ((*ma).subsurfaceWeight > 0.0)) & (*ma).thinWalled) {
288
300
 
289
- if (sO < 0.0) {
301
+ if (sL < 0.0) {
290
302
  (*si).faceNormal = -(*si).faceNormal;
291
- sO = -sO;
303
+ sL = -sL;
292
304
  }
293
- if (tV < 0.0) {
305
+ if (tY < 0.0) {
294
306
  (*si).normal = -(*si).normal;
295
- tV = -tV;
307
+ tY = -tY;
296
308
  }
297
309
  }
298
310
 
299
311
 
300
- var qM: bool = (sO >= 0.0) & (tV < 0.0);
301
- var ndv: f32 = select(tV, sO, qM);
302
- var N: vec3f = select((*si).normal, (*si).faceNormal, qM);
312
+ var qE: bool = (sL >= 0.0) & (tY < 0.0);
313
+ var ndv: f32 = select(tY, sL, qE);
314
+ var N: vec3f = select((*si).normal, (*si).faceNormal, qE);
303
315
 
304
316
  (*ma).inside = (ndv <= 0.0) & !(*ma).thinWalled;
305
317
 
@@ -307,125 +319,130 @@ var N: vec3f = select((*si).normal, (*si).faceNormal, qM);
307
319
  var ffnormal = select(-N, N, ndv >= 0.0);
308
320
  ${hasCoatNormals ? /* wgsl */ `
309
321
  if ((*ma).coatNormalEnabled) {
310
- let view = -(*aa).ray.d;
311
- let gp = dot(bK, view);
312
- (*ma).geometricNormal = select(-bK, bK, gp >= 0.0);
313
- ffnormal = fT(nB, bK, view);
314
- (*ma).coatNormal = fT((*si).coatNormal, bK, view);
315
- (*ma).inside = (gp <= 0.0) & !(*ma).thinWalled;
316
- (*ma).relativeIor = select((*ma).specularIor, 1.0 / (*ma).specularIor, (gp > 0.0) | (*ma).thinWalled);
322
+ let view = -(*path).ray.d;
323
+ let fZ = dot(bA, view);
324
+ (*ma).geometricNormal = select(-bA, bA, fZ >= 0.0);
325
+ ffnormal = fE(ni, bA, view);
326
+ (*ma).coatNormal = fE((*si).coatNormal, bA, view);
327
+ (*ma).inside = (fZ <= 0.0) & !(*ma).thinWalled;
328
+ (*ma).relativeIor = select((*ma).specularIor, 1.0 / (*ma).specularIor, (fZ > 0.0) | (*ma).thinWalled);
317
329
  }
318
330
  ` : ''}
319
331
 
320
- (*aa).scatteringIsDelta = false;
321
- var bs = false;
322
- var hC = false;
332
+ (*path).scatteringIsDelta = false;
333
+ var mediumSampled = false;
334
+ var hj = false;
323
335
  let mediumType = (*si).mediumType;
324
336
 
325
337
  var scatteringPdf: f32;
326
- var dH: vec3f;
338
+ var df: vec3f;
327
339
 
328
340
  if (HAS_MEDIUM) {
329
- let d = distance((*si).position, (*aa).ray.o);
330
- let os = (*aa).ray.o;
341
+ let d = distance((*si).position, (*path).ray.o);
342
+ let od = (*path).ray.o;
331
343
  let extinction = (*si).mediumExtinction;
332
344
  let scattering = min((*si).mediumScattering, extinction);
333
- let tR = max(max(extinction.x, extinction.y), extinction.z);
334
- if ((mediumType > 0) & (tR > 0.0)) {
345
+ let tU = max(max(extinction.x, extinction.y), extinction.z);
346
+ if ((mediumType > 0) & (tU > 0.0)) {
335
347
 
336
348
 
337
- let oi = min(i32(dp(cE(MEDIUM_CHANNEL)) * 3.0), 2);
338
- let fS = extinction[oi];
339
- let iH = select(
349
+ let nX = min(i32(sample1D(bE(MEDIUM_CHANNEL)) * 3.0), 2);
350
+ let fD = extinction[nX];
351
+ let ij = select(
340
352
  d,
341
- min(-log(max(dp(cE(MEDIUM_DISTANCE)), 1e-7)) / fS, d),
342
- fS > 0.0
353
+ min(-log(max(sample1D(bE(MEDIUM_DISTANCE)), 1e-7)) / fD, d),
354
+ fD > 0.0
343
355
  );
344
- bs = iH < d;
345
- let transmittance = exp(-extinction * iH);
346
- let oU = select(
356
+ mediumSampled = ij < d;
357
+ let transmittance = exp(-extinction * ij);
358
+ let oK = select(
347
359
  transmittance,
348
360
  extinction * transmittance,
349
- bs
361
+ mediumSampled
350
362
  );
351
- let oE = max((oU.x + oU.y + oU.z) / 3.0, 1e-8);
352
- if (bs) {
353
- (*aa).beta *= transmittance * scattering / oE;
363
+ let mediumPdf = max((oK.x + oK.y + oK.z) / 3.0, 1e-8);
364
+ if (mediumSampled) {
365
+ (*path).beta *= transmittance * scattering / mediumPdf;
354
366
 
355
- (*aa).ray.o = os + iH * (*aa).ray.d;
356
- (*si).position = (*aa).ray.o;
367
+ (*path).ray.o = od + ij * (*path).ray.d;
368
+ (*si).position = (*path).ray.o;
357
369
  }
358
370
  else {
359
- (*aa).beta *= transmittance / oE;
371
+ (*path).beta *= transmittance / mediumPdf;
360
372
  }
361
373
  }
362
374
  }
363
375
 
364
- if (!bs) {
365
- (*aa).li += qm(si, aa) * (*ma).emission * (*aa).beta;
376
+ if (!mediumSampled) {
377
+ ${caustics ? ` let mM=emissiveHitMisWeight(si,path);
378
+ causticHotRecord(*path,mM*(*ma).emission,1u);causticEmitterRecord(*si,*path,mM,(*ma).emission);
379
+ (*path).li+=mM*(*ma).emission*(*path).beta;` : ' (*path).li += emissiveHitMisWeight(si, path) * (*ma).emission * (*path).beta;'}
366
380
  }
367
381
  if ((*ma).materialType == UNLIT) {
368
- (*aa).abort = true;
382
+ (*path).abort = true;
369
383
  return;
370
384
  }
371
385
 
372
386
 
373
- var prepared: ag;
374
- if (!bs) {
387
+ var prepared: OpenPbrPreparedBsdf;
388
+ if (!mediumSampled) {
375
389
  ${hasAnisotropyDirections ? /* wgsl */ `
376
390
  (*ma).directionTangent = (*si).directionTangent;
377
391
  (*ma).directionBitangent = (*si).directionBitangent;
378
392
  (*ma).geometryTangent = (*si).geometryTangent;
379
393
  (*ma).geometryBitangent = (*si).geometryBitangent;
380
394
  ` : /* wgsl */ ``}
381
- prepared = ds((*si).tangent, *ma, -(*aa).ray.d, ffnormal);
395
+ prepared = bV((*si).tangent, *ma, -(*path).ray.d, ffnormal);
382
396
  }
383
- let qW = sW(si, *ma, prepared, aa, ffnormal, !bs);
384
- dH = qW.direction;
385
- scatteringPdf = qW.pdf;
386
- if (!bs) {
387
- let f = qW.response;
388
- let isNextRefraction = qW.transmission;
397
+ ${researchContribution}${photonMapping ? /* wgsl */ ` if(!mediumSampled){let value=(*path).beta*rI(*si,prepared,(*path).fromEye,!(*path).causticHasReceiver);causticEstimateRecord(value,1u);(*path).li+=value;}
398
+ ` : ''} let qP = sV(si, *ma, prepared, path, ffnormal, !mediumSampled);
399
+ df = qP.direction;
400
+ scatteringPdf = qP.pdf;
401
+ if (!mediumSampled) {
402
+ let f = qP.response;
403
+ let isNextRefraction = qP.transmission;
389
404
 
390
405
 
391
406
 
392
407
 
393
408
  if (!(scatteringPdf > 0.0) |
394
409
  !all(f == f) | !all(abs(f) < vec3f(3.402823e38)) |
395
- (dot(dH, dH) < 0.5)) {
396
- (*aa).scatteringPdf = 0.0;
397
- (*aa).abort = true;
410
+ (dot(df, df) < 0.5)) {
411
+ (*path).scatteringPdf = 0.0;
412
+ (*path).abort = true;
398
413
  return;
399
414
  }
400
415
 
401
416
 
402
- (*aa).scatteringIsDelta = !prepared.material.thinWalled &
417
+ (*path).scatteringIsDelta = !prepared.material.thinWalled &
403
418
  (abs(prepared.material.relativeIor - 1.0) <= 1e-6) &
404
419
  (prepared.probabilities[OPENPBR_LOBE_TRANSMISSION] >= 1.0 - 1e-6);
405
- (*aa).beta *= f / scatteringPdf;
420
+ ${caustics ? /* wgsl */ ` causticAdvance(path, *ma, isNextRefraction, true);
421
+ ` : ''} (*path).beta *= f / scatteringPdf;
406
422
 
407
- hC = isNextRefraction & !(*ma).thinWalled;
408
- (*aa).isNextRefraction = isNextRefraction;
423
+ hj = isNextRefraction & !(*ma).thinWalled;
424
+ (*path).isNextRefraction = isNextRefraction;
409
425
 
410
426
 
411
- (*aa).ray.o = (*si).position + EPS * dH;
427
+ (*path).ray.o = (*si).position + EPS * df;
412
428
  ${hasCoatNormals ? /* wgsl */ `
413
- if ((*ma).coatNormalEnabled) { (*aa).ray.o = (*si).position + EPS * select(-bK, bK, dot(bK, dH) >= 0.0); }
429
+ if ((*ma).coatNormalEnabled) { (*path).ray.o = (*si).position + EPS * select(-bA, bA, dot(bA, df) >= 0.0); }
414
430
  ` : ''}
415
431
  }
416
- (*aa).scatteringPdf = scatteringPdf;
417
- (*aa).ray.d = dH;
418
- if (bs) {
419
- (*aa).isNextRefraction = false;
432
+ (*path).scatteringPdf = scatteringPdf;
433
+ (*path).ray.d = df;
434
+ if (mediumSampled) {${caustics ? /* wgsl */ `
435
+ causticAdvance(path, *ma, false, false);` : ''}
436
+ (*path).isNextRefraction = false;
420
437
  }
421
438
 
422
- (*aa).fromEye = false;
439
+ (*path).fromEye = false;
423
440
 
424
441
  if (HAS_MEDIUM) {
425
442
 
426
443
 
427
- if (!bs & hC & ((*ma).mediumType > 0)) {
428
- if (sO >= 0.0) {
444
+ if (!mediumSampled & hj & ((*ma).mediumType > 0)) {
445
+ if (sL >= 0.0) {
429
446
  (*si).mediumType = (*ma).mediumType;
430
447
  (*si).mediumExtinction = (*ma).mediumExtinction;
431
448
  (*si).mediumScattering = (*ma).mediumScattering;