@meimu/mutracer 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/CHANGELOG.md +222 -0
  2. package/LICENSES/FidelityFX-FSR.txt +19 -0
  3. package/LICENSES/pbrt-v4-Apache-2.0.txt +202 -0
  4. package/THIRD_PARTY_NOTICES.md +18 -4
  5. package/dist/assets/bvh.worker.js +1 -1
  6. package/dist/mutracer.umd.js +6260 -5580
  7. package/docs/api.md +45 -18
  8. package/docs/materials.md +4 -2
  9. package/docs/performance.md +7 -0
  10. package/docs/post-processing.md +62 -9
  11. package/docs/progressive-rendering.md +3 -0
  12. package/docs/sampling.md +4 -0
  13. package/docs/technical/acceleration.md +52 -0
  14. package/docs/technical/aovs.md +79 -0
  15. package/docs/technical/caustics.md +109 -0
  16. package/docs/technical/continuous-spectrum.md +29 -0
  17. package/docs/technical/display-upscale.md +82 -0
  18. package/docs/technical/openpbr.md +99 -0
  19. package/docs/technical/pbrt-import.md +168 -0
  20. package/docs/technical/tiling.md +74 -0
  21. package/docs/technical/webgl.md +53 -0
  22. package/docs/viewer.md +11 -1
  23. package/lib/Display.d.ts +19 -5
  24. package/lib/Display.js +10 -7
  25. package/lib/Display.js.map +1 -1
  26. package/lib/Engine.d.ts +2 -1
  27. package/lib/Engine.js +30 -2
  28. package/lib/Engine.js.map +1 -1
  29. package/lib/Render.d.ts +20 -11
  30. package/lib/Render.js +32 -7
  31. package/lib/Render.js.map +1 -1
  32. package/lib/main.d.ts +3 -1
  33. package/lib/main.js +1 -0
  34. package/lib/main.js.map +1 -1
  35. package/lib/oidn.d.ts +1 -1
  36. package/lib/renderer/AovPrimitiveCache.js +39 -8
  37. package/lib/renderer/AovPrimitiveCache.js.map +1 -1
  38. package/lib/renderer/DisplayPostProcess.d.ts +8 -3
  39. package/lib/renderer/DisplayPostProcess.js +51 -18
  40. package/lib/renderer/DisplayPostProcess.js.map +1 -1
  41. package/lib/renderer/MaterialData.js +7 -2
  42. package/lib/renderer/MaterialData.js.map +1 -1
  43. package/lib/renderer/RenderingPipeline.d.ts +7 -1
  44. package/lib/renderer/RenderingPipeline.js.map +1 -1
  45. package/lib/renderer/TileRender.d.ts +2 -2
  46. package/lib/renderer/TileRender.js +128 -7
  47. package/lib/renderer/TileRender.js.map +1 -1
  48. package/lib/renderer/WGPUAov.d.ts +6 -1
  49. package/lib/renderer/WGPUAov.js +108 -14
  50. package/lib/renderer/WGPUAov.js.map +1 -1
  51. package/lib/renderer/WGPUCanvasSurface.js +12 -1
  52. package/lib/renderer/WGPUCanvasSurface.js.map +1 -1
  53. package/lib/renderer/WGPUEnvMapDistribution.js +19 -19
  54. package/lib/renderer/WGPUFullQuadPass.js +3 -3
  55. package/lib/renderer/WGPURayTraceOutput.js +12 -12
  56. package/lib/renderer/WGPURayTracePass.d.ts +17 -4
  57. package/lib/renderer/WGPURayTracePass.js +194 -71
  58. package/lib/renderer/WGPURayTracePass.js.map +1 -1
  59. package/lib/renderer/WGPURenderingPipeline.js +46 -40
  60. package/lib/renderer/WGPURenderingPipeline.js.map +1 -1
  61. package/lib/renderer/WebGLAov.js +3 -3
  62. package/lib/renderer/WebGLAov.js.map +1 -1
  63. package/lib/renderer/WebGLFullQuadPass.d.ts +1 -1
  64. package/lib/renderer/WebGLFullQuadPass.js +8 -2
  65. package/lib/renderer/WebGLFullQuadPass.js.map +1 -1
  66. package/lib/renderer/WebGLJNLMDenoiser.js +66 -66
  67. package/lib/renderer/WebGLJNLMDenoiser.js.map +1 -1
  68. package/lib/renderer/WebGLRayTraceOutputPass.js +4 -4
  69. package/lib/renderer/WebGLRayTracePass.d.ts +14 -10
  70. package/lib/renderer/WebGLRayTracePass.js +115 -111
  71. package/lib/renderer/WebGLRayTracePass.js.map +1 -1
  72. package/lib/renderer/WebGLRenderingPipeline.js +10 -3
  73. package/lib/renderer/WebGLRenderingPipeline.js.map +1 -1
  74. package/lib/renderer/WebGLSkyBaker.js +57 -57
  75. package/lib/renderer/aov.d.ts +13 -1
  76. package/lib/renderer/aov.js +21 -2
  77. package/lib/renderer/aov.js.map +1 -1
  78. package/lib/renderer/aovDisplay.js +2 -2
  79. package/lib/renderer/aovDisplay.js.map +1 -1
  80. package/lib/renderer/binnedSahBvh.d.ts +2 -1
  81. package/lib/renderer/binnedSahBvh.js +24 -17
  82. package/lib/renderer/binnedSahBvh.js.map +1 -1
  83. package/lib/renderer/bvhAccel.d.ts +3 -1
  84. package/lib/renderer/bvhAccel.js +36 -6
  85. package/lib/renderer/bvhAccel.js.map +1 -1
  86. package/lib/renderer/cameraUniform.d.ts +1 -1
  87. package/lib/renderer/cameraUniform.js +6 -2
  88. package/lib/renderer/cameraUniform.js.map +1 -1
  89. package/lib/renderer/compactVertices.d.ts +14 -0
  90. package/lib/renderer/compactVertices.js +124 -0
  91. package/lib/renderer/compactVertices.js.map +1 -0
  92. package/lib/renderer/easu.d.ts +11 -0
  93. package/lib/renderer/easu.js +156 -0
  94. package/lib/renderer/easu.js.map +1 -0
  95. package/lib/renderer/geometryUpdateState.d.ts +1 -0
  96. package/lib/renderer/geometryUpdateState.js.map +1 -1
  97. package/lib/renderer/geometryUpdates.js +3 -2
  98. package/lib/renderer/geometryUpdates.js.map +1 -1
  99. package/lib/renderer/glsl/aovDisplay.frag.js +5 -5
  100. package/lib/renderer/glsl/aovReflectance.glsl.js +35 -35
  101. package/lib/renderer/glsl/aovReflectanceSamples.glsl.js +1 -1
  102. package/lib/renderer/glsl/aovTrace.frag.js +44 -36
  103. package/lib/renderer/glsl/aovTrace.frag.js.map +1 -1
  104. package/lib/renderer/glsl/chunks/cameraProjection.glsl.d.ts +2 -0
  105. package/lib/renderer/glsl/chunks/cameraProjection.glsl.js +16 -0
  106. package/lib/renderer/glsl/chunks/cameraProjection.glsl.js.map +1 -0
  107. package/lib/renderer/glsl/chunks/cameraRay.glsl.d.ts +1 -1
  108. package/lib/renderer/glsl/chunks/cameraRay.glsl.js +9 -16
  109. package/lib/renderer/glsl/chunks/cameraRay.glsl.js.map +1 -1
  110. package/lib/renderer/glsl/chunks/emissiveLight.glsl.js +8 -8
  111. package/lib/renderer/glsl/chunks/envMap.glsl.js +67 -67
  112. package/lib/renderer/glsl/chunks/intersect.glsl.js +390 -375
  113. package/lib/renderer/glsl/chunks/intersect.glsl.js.map +1 -1
  114. package/lib/renderer/glsl/chunks/materialBuffer.glsl.js +120 -120
  115. package/lib/renderer/glsl/chunks/openPbrBsdf.glsl.js +562 -562
  116. package/lib/renderer/glsl/chunks/rand.glsl.js +3 -3
  117. package/lib/renderer/glsl/chunks/random.glsl.js +4 -4
  118. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js +37 -35
  119. package/lib/renderer/glsl/chunks/rayTraceCore.glsl.js.map +1 -1
  120. package/lib/renderer/glsl/chunks/sampleLight.glsl.js +70 -74
  121. package/lib/renderer/glsl/chunks/sampleLight.glsl.js.map +1 -1
  122. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.d.ts +1 -1
  123. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js +107 -88
  124. package/lib/renderer/glsl/chunks/sampleMaterial.glsl.js.map +1 -1
  125. package/lib/renderer/glsl/chunks/sampleShadowCatcher.glsl.js +11 -11
  126. package/lib/renderer/glsl/chunks/sampling.glsl.js +77 -77
  127. package/lib/renderer/glsl/chunks/sobol.glsl.js +70 -70
  128. package/lib/renderer/glsl/chunks/spectralPrefix.glsl.d.ts +6 -0
  129. package/lib/renderer/glsl/chunks/spectralPrefix.glsl.js +47 -0
  130. package/lib/renderer/glsl/chunks/spectralPrefix.glsl.js.map +1 -0
  131. package/lib/renderer/glsl/chunks/textureLinear.glsl.js +5 -5
  132. package/lib/renderer/glsl/chunks/uvProjection.glsl.js +11 -11
  133. package/lib/renderer/glsl/depthQuery.frag.js +12 -6
  134. package/lib/renderer/glsl/depthQuery.frag.js.map +1 -1
  135. package/lib/renderer/glsl/normalizeRayTraceOutput.frag.js +10 -10
  136. package/lib/renderer/glsl/rayTrace.frag.js +233 -170
  137. package/lib/renderer/glsl/rayTrace.frag.js.map +1 -1
  138. package/lib/renderer/glsl/shadowCatcher.frag.js +10 -9
  139. package/lib/renderer/glsl/shadowCatcher.frag.js.map +1 -1
  140. package/lib/renderer/glsl/webglPipeline.frag.js +58 -58
  141. package/lib/renderer/gpuMemory.js +1 -1
  142. package/lib/renderer/gpuMemory.js.map +1 -1
  143. package/lib/renderer/openPbrEnergyLut.d.ts +2 -1
  144. package/lib/renderer/openPbrEnergyLut.js +18 -1
  145. package/lib/renderer/openPbrEnergyLut.js.map +1 -1
  146. package/lib/renderer/pathLimits.d.ts +5 -4
  147. package/lib/renderer/pathLimits.js +6 -5
  148. package/lib/renderer/pathLimits.js.map +1 -1
  149. package/lib/renderer/prepareMeshBVH.d.ts +2 -0
  150. package/lib/renderer/prepareMeshBVH.js +5 -3
  151. package/lib/renderer/prepareMeshBVH.js.map +1 -1
  152. package/lib/renderer/progressiveScheduler.js +1 -1
  153. package/lib/renderer/progressiveScheduler.js.map +1 -1
  154. package/lib/renderer/renderPipeline.d.ts +4 -0
  155. package/lib/renderer/renderPipeline.js +1 -0
  156. package/lib/renderer/renderPipeline.js.map +1 -1
  157. package/lib/renderer/researchTransport.d.ts +1 -1
  158. package/lib/renderer/researchTransport.js.map +1 -1
  159. package/lib/renderer/sceneAssembly.d.ts +1 -1
  160. package/lib/renderer/sceneAssembly.js +4 -3
  161. package/lib/renderer/sceneAssembly.js.map +1 -1
  162. package/lib/renderer/sceneChangeDetector.d.ts +1 -1
  163. package/lib/renderer/sceneChangeDetector.js +3 -1
  164. package/lib/renderer/sceneChangeDetector.js.map +1 -1
  165. package/lib/renderer/sceneLayoutSchema.d.ts +1 -0
  166. package/lib/renderer/sceneLayoutSchema.js +2 -2
  167. package/lib/renderer/sceneLayoutSchema.js.map +1 -1
  168. package/lib/renderer/scenePreparation.d.ts +3 -2
  169. package/lib/renderer/scenePreparation.js +18 -2
  170. package/lib/renderer/scenePreparation.js.map +1 -1
  171. package/lib/renderer/scratchSampling.js +6 -6
  172. package/lib/renderer/spectrum.js +2 -2
  173. package/lib/renderer/staticBvhPreparation.d.ts +9 -0
  174. package/lib/renderer/staticBvhPreparation.js +8 -2
  175. package/lib/renderer/staticBvhPreparation.js.map +1 -1
  176. package/lib/renderer/surfaceHit.d.ts +10 -0
  177. package/lib/renderer/surfaceHit.js +22 -0
  178. package/lib/renderer/surfaceHit.js.map +1 -0
  179. package/lib/renderer/tangentRequirements.d.ts +2 -0
  180. package/lib/renderer/tangentRequirements.js +7 -0
  181. package/lib/renderer/tangentRequirements.js.map +1 -0
  182. package/lib/renderer/textureAtlas.d.ts +4 -0
  183. package/lib/renderer/textureAtlas.js +48 -2
  184. package/lib/renderer/textureAtlas.js.map +1 -1
  185. package/lib/renderer/webgl.js +4 -0
  186. package/lib/renderer/webgl.js.map +1 -1
  187. package/lib/renderer/webglVertexAttributes.d.ts +17 -0
  188. package/lib/renderer/webglVertexAttributes.js +44 -0
  189. package/lib/renderer/webglVertexAttributes.js.map +1 -0
  190. package/lib/renderer/wgpuBindlessSource.js +2 -2
  191. package/lib/renderer/wgpuMaterialConstants.js +4 -3
  192. package/lib/renderer/wgpuMaterialConstants.js.map +1 -1
  193. package/lib/renderer/wgpuSceneUniform.js +2 -2
  194. package/lib/renderer/wgpuSceneUniform.js.map +1 -1
  195. package/lib/renderer/wgpuShaderSource.d.ts +15 -0
  196. package/lib/renderer/wgpuShaderSource.js +1 -1
  197. package/lib/renderer/wgpuShaderSource.js.map +1 -1
  198. package/lib/renderer/wgsl/aovCompact.wgsl.d.ts +4 -0
  199. package/lib/renderer/wgsl/aovCompact.wgsl.js +26 -0
  200. package/lib/renderer/wgsl/aovCompact.wgsl.js.map +1 -0
  201. package/lib/renderer/wgsl/aovDisplay.wgsl.js +9 -9
  202. package/lib/renderer/wgsl/aovReflectance.wgsl.js +39 -39
  203. package/lib/renderer/wgsl/aovReflectanceSamples.wgsl.js +1 -1
  204. package/lib/renderer/wgsl/aovResolve.wgsl.d.ts +4 -0
  205. package/lib/renderer/wgsl/aovResolve.wgsl.js +21 -2
  206. package/lib/renderer/wgsl/aovResolve.wgsl.js.map +1 -1
  207. package/lib/renderer/wgsl/aovSnapshot.wgsl.js +2 -2
  208. package/lib/renderer/wgsl/aovSnapshot.wgsl.js.map +1 -1
  209. package/lib/renderer/wgsl/aovTrace.wgsl.js +31 -31
  210. package/lib/renderer/wgsl/aovTraceDisplay.wgsl.d.ts +2 -0
  211. package/lib/renderer/wgsl/aovTraceDisplay.wgsl.js +56 -0
  212. package/lib/renderer/wgsl/aovTraceDisplay.wgsl.js.map +1 -0
  213. package/lib/renderer/wgsl/bloom.wgsl.js +18 -18
  214. package/lib/renderer/wgsl/causticLight.compute.d.ts +1 -1
  215. package/lib/renderer/wgsl/causticLight.compute.js +121 -119
  216. package/lib/renderer/wgsl/causticLight.compute.js.map +1 -1
  217. package/lib/renderer/wgsl/chunks/background.wgsl.js +46 -46
  218. package/lib/renderer/wgsl/chunks/causticAdjoint.wgsl.js +4 -4
  219. package/lib/renderer/wgsl/chunks/causticAtomic.wgsl.js +3 -3
  220. package/lib/renderer/wgsl/chunks/caustics.wgsl.js +3 -3
  221. package/lib/renderer/wgsl/chunks/common.wgsl.js +4 -4
  222. package/lib/renderer/wgsl/chunks/envMap.wgsl.js +30 -30
  223. package/lib/renderer/wgsl/chunks/intersect.wgsl.d.ts +6 -2
  224. package/lib/renderer/wgsl/chunks/intersect.wgsl.js +550 -542
  225. package/lib/renderer/wgsl/chunks/intersect.wgsl.js.map +1 -1
  226. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.d.ts +1 -1
  227. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js +18 -16
  228. package/lib/renderer/wgsl/chunks/intersectionAlpha.wgsl.js.map +1 -1
  229. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.d.ts +2 -1
  230. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js +70 -69
  231. package/lib/renderer/wgsl/chunks/materialBuffer.wgsl.js.map +1 -1
  232. package/lib/renderer/wgsl/chunks/openPbrBsdf.wgsl.js +593 -593
  233. package/lib/renderer/wgsl/chunks/pdm_displacement.wgsl.js +118 -118
  234. package/lib/renderer/wgsl/chunks/rand.wgsl.js +3 -3
  235. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.d.ts +4 -1
  236. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js +32 -26
  237. package/lib/renderer/wgsl/chunks/rayTraceCore.wgsl.js.map +1 -1
  238. package/lib/renderer/wgsl/chunks/sampleLight.wgsl.js +114 -114
  239. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.d.ts +1 -1
  240. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js +159 -137
  241. package/lib/renderer/wgsl/chunks/sampleMaterial.wgsl.js.map +1 -1
  242. package/lib/renderer/wgsl/chunks/sampleShadowCatcher.wgsl.js +8 -8
  243. package/lib/renderer/wgsl/chunks/sampling.wgsl.js +74 -74
  244. package/lib/renderer/wgsl/chunks/sobol.wgsl.js +74 -74
  245. package/lib/renderer/wgsl/chunks/spectralPrefix.wgsl.d.ts +6 -0
  246. package/lib/renderer/wgsl/chunks/spectralPrefix.wgsl.js +66 -0
  247. package/lib/renderer/wgsl/chunks/spectralPrefix.wgsl.js.map +1 -0
  248. package/lib/renderer/wgsl/chunks/uvProjection.wgsl.js +11 -11
  249. package/lib/renderer/wgsl/chunks/vertexAttributes.wgsl.d.ts +2 -0
  250. package/lib/renderer/wgsl/chunks/vertexAttributes.wgsl.js +61 -0
  251. package/lib/renderer/wgsl/chunks/vertexAttributes.wgsl.js.map +1 -0
  252. package/lib/renderer/wgsl/compose.frag.wgsl.d.ts +2 -0
  253. package/lib/renderer/wgsl/compose.frag.wgsl.js +99 -97
  254. package/lib/renderer/wgsl/compose.frag.wgsl.js.map +1 -1
  255. package/lib/renderer/wgsl/customDenoise.wgsl.js +10 -10
  256. package/lib/renderer/wgsl/depthQuery.wgsl.d.ts +1 -1
  257. package/lib/renderer/wgsl/depthQuery.wgsl.js +11 -2
  258. package/lib/renderer/wgsl/depthQuery.wgsl.js.map +1 -1
  259. package/lib/renderer/wgsl/easu.wgsl.d.ts +2 -0
  260. package/lib/renderer/wgsl/easu.wgsl.js +80 -0
  261. package/lib/renderer/wgsl/easu.wgsl.js.map +1 -0
  262. package/lib/renderer/wgsl/easuDetail.wgsl.d.ts +21 -0
  263. package/lib/renderer/wgsl/easuDetail.wgsl.js +230 -0
  264. package/lib/renderer/wgsl/easuDetail.wgsl.js.map +1 -0
  265. package/lib/renderer/wgsl/jnlm.compute.js +74 -74
  266. package/lib/renderer/wgsl/jnlm.compute.js.map +1 -1
  267. package/lib/renderer/wgsl/offlineAdaptive.compute.js +26 -26
  268. package/lib/renderer/wgsl/oidnAuxiliary.wgsl.js +3 -3
  269. package/lib/renderer/wgsl/photonMap.compute.js +89 -89
  270. package/lib/renderer/wgsl/proceduralSky.compute.js +61 -61
  271. package/lib/renderer/wgsl/rayTrace.compute.d.ts +14 -0
  272. package/lib/renderer/wgsl/rayTrace.compute.js +395 -333
  273. package/lib/renderer/wgsl/rayTrace.compute.js.map +1 -1
  274. package/lib/scene/Scene.js.map +1 -1
  275. package/lib/settings/render.d.ts +11 -0
  276. package/lib/settings/render.js +1 -0
  277. package/lib/settings/render.js.map +1 -1
  278. package/lib/util/fromTHREE.js +21 -14
  279. package/lib/util/fromTHREE.js.map +1 -1
  280. package/lib/version.d.ts +1 -1
  281. package/lib/version.js +1 -1
  282. package/lib/version.js.map +1 -1
  283. package/package.json +5 -2
  284. package/lib/oidnBundledWeights.cdn.d.ts +0 -2
  285. package/lib/oidnBundledWeights.cdn.js +0 -5
  286. package/lib/oidnBundledWeights.cdn.js.map +0 -1
  287. package/lib/renderer/bvh.worker.d.ts +0 -1
  288. package/lib/renderer/bvh.worker.js +0 -16
  289. package/lib/renderer/bvh.worker.js.map +0 -1
  290. package/lib/renderer/bvhWorkerBuild.d.ts +0 -13
  291. package/lib/renderer/bvhWorkerBuild.js +0 -17
  292. package/lib/renderer/bvhWorkerBuild.js.map +0 -1
  293. package/lib/renderer/lightCore.d.ts +0 -12
  294. package/lib/renderer/lightCore.js +0 -13
  295. package/lib/renderer/lightCore.js.map +0 -1
  296. package/lib/renderer/materialCore.d.ts +0 -8
  297. package/lib/renderer/materialCore.js +0 -9
  298. package/lib/renderer/materialCore.js.map +0 -1
  299. package/lib/scene/PixelTexture.d.ts +0 -6
  300. package/lib/scene/PixelTexture.js +0 -10
  301. package/lib/scene/PixelTexture.js.map +0 -1
  302. package/lib/util/studioLighting.d.ts +0 -18
  303. package/lib/util/studioLighting.js +0 -36
  304. package/lib/util/studioLighting.js.map +0 -1
@@ -0,0 +1,156 @@
1
+ import { areaDownsampleShader, easuShader } from './wgsl/easu.wgsl.js';
2
+ import { albedoDownsampleShader, easuDetailShader, guidedCoefficientShader, toneLutShader, EASU_DETAIL, TONE_LUT_SIZE } from './wgsl/easuDetail.wgsl.js';
3
+ import { borrowedAovRevision } from './WGPUAov.js';
4
+ import { TONE_MAPPING_MODES } from './wgsl/compose.frag.wgsl.js';
5
+ /** Creates an edge-adaptive display-space upscale pass (AMD FSR 1 EASU), without sharpening. Register with outputSize: (_, display) => display. WebGPU only; supports rgba8unorm and extended-range rgba16float, including alpha. Copies inputs that already have the output size and area-averages larger ones. Default EASU alone. */
6
+ export function createEasuPass(options = {}) { return createEasuPassImpl({ albedoDetail: options.albedoDetail }); }
7
+ const DETAIL_AOVS = ['diffuseColor', 'specularColor', 'depth'];
8
+ /** @internal Plain albedo ratios (guided false), the separate-lobe approximation and depth-guided silhouettes are retained for comparisons; not package exports. */
9
+ export function createEasuPassImpl(options = {}, separate = false, silhouettes = false, guided = true) {
10
+ const detailEnabled = options.albedoDetail ?? false;
11
+ let warnedConfiguration = false;
12
+ const [min, max] = options.ratioRange ?? EASU_DETAIL.ratioRange;
13
+ const depth = options.depthThreshold ?? EASU_DETAIL.depthThreshold, coverage = options.coverageThreshold ?? EASU_DETAIL.coverageThreshold;
14
+ if (![min, max, depth, coverage].every(Number.isFinite) || min <= 0 || max < min || depth <= 0 || coverage <= 0 || coverage > 1)
15
+ throw new RangeError('Invalid EASU detail compensation options.');
16
+ const devices = new Map();
17
+ const retire = (device, resources) => {
18
+ // This callback's encoder is submitted after it returns.
19
+ void Promise.resolve().then(() => device.queue.onSubmittedWorkDone()).catch(() => { }).then(() => resources.forEach(resource => resource.destroy()));
20
+ };
21
+ const guideFormats = silhouettes ? ['rgba16float', 'rgba16float', 'rg32float'] : ['rgba16float', 'rgba16float'];
22
+ const owned = (state) => [...(state.scratch ?? []), ...(state.tone ? [state.tone] : []), ...(state.fit ?? [])];
23
+ const pass = ctx => {
24
+ const { device, encoder, input, output, render } = ctx;
25
+ // Nothing to upscale, for example a full-resolution render beside a reduced preview.
26
+ if (input.width === output.width && input.height === output.height) {
27
+ encoder.copyTextureToTexture({ texture: input }, { texture: output }, [input.width, input.height]);
28
+ return;
29
+ }
30
+ for (const [previous, old] of devices)
31
+ if (previous !== device) {
32
+ retire(previous, owned(old));
33
+ devices.delete(previous);
34
+ }
35
+ let state = devices.get(device);
36
+ if (!state) {
37
+ state = { pipelines: new Map() };
38
+ devices.set(device, state);
39
+ }
40
+ const pipeline = (key, code, formats) => {
41
+ let value = state.pipelines.get(key);
42
+ if (!value) {
43
+ const module = device.createShaderModule({ label: key, code });
44
+ value = device.createRenderPipeline({ label: key, layout: 'auto', vertex: { module, entryPoint: 'vertex' },
45
+ fragment: { module, entryPoint: 'fragment', targets: formats.map(format => ({ format })) } });
46
+ state.pipelines.set(key, value);
47
+ }
48
+ return value;
49
+ };
50
+ const buffer = (values) => {
51
+ const value = device.createBuffer({ size: 16, usage: GPUBufferUsage.UNIFORM, mappedAtCreation: true });
52
+ new Float32Array(value.getMappedRange()).set(values);
53
+ value.unmap();
54
+ retire(device, [value]);
55
+ return value;
56
+ };
57
+ if (input.width >= output.width && input.height >= output.height) {
58
+ // EASU is an enlargement filter; larger renders are area averaged instead.
59
+ const down = pipeline(`Area downsample ${output.format}`, areaDownsampleShader, [output.format]);
60
+ const group = device.createBindGroup({ layout: down.getBindGroupLayout(0), entries: [{ binding: 0, resource: input.createView() }, { binding: 1, resource: { buffer: buffer([output.width, output.height, 0, 0]) } }] });
61
+ const draw = encoder.beginRenderPass({ label: 'Area downsample', colorAttachments: [{ view: output.createView(), loadOp: 'clear', storeOp: 'store' }] });
62
+ draw.setPipeline(down);
63
+ draw.setBindGroup(0, group);
64
+ draw.draw(3);
65
+ draw.end();
66
+ return;
67
+ }
68
+ if (detailEnabled && !warnedConfiguration && (render.aovResolution !== 'display' || !DETAIL_AOVS.every(kind => render.aovs.includes(kind)))) {
69
+ warnedConfiguration = true;
70
+ console.warn("EASU albedoDetail needs the displayed render to enable diffuseColor, specularColor and depth AOVs with aovResolution 'display'; upscaling without detail.");
71
+ }
72
+ const aovs = detailEnabled ? DETAIL_AOVS.map(kind => render.getAovTexture(kind)) : [];
73
+ const detail = aovs.length === 3 && aovs.every(image => image && image.width === output.width && image.height === output.height);
74
+ const entries = [{ binding: 0, resource: input.createView() }, { binding: 1, resource: { buffer: buffer([output.width, output.height, min, max]) } }];
75
+ if (detail) {
76
+ // Cached images are recorded on their own submission so a failed chain cannot leave them stale.
77
+ let cache;
78
+ const cached = () => cache ??= device.createCommandEncoder({ label: 'EASU cache' });
79
+ if (!state.scratch || state.scratch.length !== guideFormats.length || state.scratch[0].width !== input.width || state.scratch[0].height !== input.height) {
80
+ if (state.scratch)
81
+ retire(device, state.scratch);
82
+ // Low diffuse and specular albedo, then (for silhouettes) nearest hit depth with hit coverage.
83
+ state.scratch = guideFormats.map((format, index) => device.createTexture({ label: `EASU low guide ${index}`, size: [input.width, input.height], format, usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT }));
84
+ state.key = undefined;
85
+ }
86
+ // Low albedo depends only on the AOV contents and beauty size; reuse it across presents.
87
+ const key = [state.scratch[0], ...aovs, ...aovs.map(image => borrowedAovRevision.get(image))];
88
+ if (!state.key || key.some((value, index) => value !== state.key[index])) {
89
+ const down = pipeline(`Albedo area downsample ${silhouettes}`, albedoDownsampleShader(silhouettes), guideFormats);
90
+ const group = device.createBindGroup({ layout: down.getBindGroupLayout(0), entries: [
91
+ { binding: 0, resource: aovs[0].createView() }, { binding: 1, resource: aovs[1].createView() },
92
+ { binding: 2, resource: { buffer: buffer([input.width, input.height, 0, 0]) } }, { binding: 3, resource: aovs[2].createView() }
93
+ ] });
94
+ const draw = cached().beginRenderPass({ label: 'Albedo area downsample', colorAttachments: state.scratch.map(image => ({ view: image.createView(), loadOp: 'clear', storeOp: 'store' })) });
95
+ draw.setPipeline(down);
96
+ draw.setBindGroup(0, group);
97
+ draw.draw(3);
98
+ draw.end();
99
+ state.key = key;
100
+ }
101
+ aovs.forEach((image, index) => entries.push({ binding: 2 + index, resource: image.createView() }));
102
+ entries.push({ binding: 5, resource: state.scratch[0].createView() }, { binding: 6, resource: state.scratch[1].createView() });
103
+ if (silhouettes)
104
+ entries.push({ binding: 10, resource: state.scratch[2].createView() });
105
+ entries.push({ binding: 7, resource: { buffer: buffer([EASU_DETAIL.minimumAlbedo, coverage, depth, EASU_DETAIL.depthTolerance]) } });
106
+ // The ratio is applied through the same grading and tone mapping as the composed image,
107
+ // tabulated once per display setting.
108
+ const display = render._engine.display, extended = output.format === 'rgba16float';
109
+ const tone = [TONE_MAPPING_MODES[display.toneMapping] ?? 0, extended ? 16 : 1, display.toneMappingExposure, extended ? 1 : 0];
110
+ const grading = [display.contrast, display.saturation, display.temperature, display.tint];
111
+ const toneKey = [...tone, ...grading].join(',');
112
+ state.tone ??= device.createTexture({ label: 'EASU tone table', size: [TONE_LUT_SIZE, 2], format: 'rgba32float', usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT });
113
+ if (state.toneKey !== toneKey) {
114
+ const build = pipeline('EASU tone table', toneLutShader, ['rgba32float']);
115
+ const group = device.createBindGroup({ layout: build.getBindGroupLayout(0), entries: [{ binding: 0, resource: { buffer: buffer(tone) } }, { binding: 1, resource: { buffer: buffer(grading) } }] });
116
+ const draw = cached().beginRenderPass({ label: 'EASU tone table', colorAttachments: [{ view: state.tone.createView(), loadOp: 'clear', storeOp: 'store' }] });
117
+ draw.setPipeline(build);
118
+ draw.setBindGroup(0, group);
119
+ draw.draw(3);
120
+ draw.end();
121
+ state.toneKey = toneKey;
122
+ }
123
+ const toneEntries = [{ binding: 8, resource: state.tone.createView() }, { binding: 9, resource: { buffer: buffer([tone[1], EASU_DETAIL.guidedEpsilon, 0, 0]) } }];
124
+ entries.push(...toneEntries);
125
+ if (cache)
126
+ device.queue.submit([cache.finish()]);
127
+ if (guided) {
128
+ // The local albedo-radiance fit depends on this frame's image, so it runs on every present.
129
+ if (!state.fit || state.fit[0].width !== input.width || state.fit[0].height !== input.height) {
130
+ if (state.fit)
131
+ retire(device, state.fit);
132
+ state.fit = ['slope', 'offset'].map(name => device.createTexture({ label: `EASU albedo ${name}`, size: [input.width, input.height], format: 'rgba16float', usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT }));
133
+ }
134
+ const fit = pipeline('EASU albedo fit', guidedCoefficientShader, ['rgba16float', 'rgba16float']);
135
+ const group = device.createBindGroup({ layout: fit.getBindGroupLayout(0), entries: [{ binding: 0, resource: input.createView() },
136
+ { binding: 1, resource: state.scratch[0].createView() }, { binding: 2, resource: state.scratch[1].createView() }, ...toneEntries] });
137
+ const draw = encoder.beginRenderPass({ label: 'EASU albedo fit', colorAttachments: state.fit.map(image => ({ view: image.createView(), loadOp: 'clear', storeOp: 'store' })) });
138
+ draw.setPipeline(fit);
139
+ draw.setBindGroup(0, group);
140
+ draw.draw(3);
141
+ draw.end();
142
+ entries.push({ binding: 11, resource: state.fit[0].createView() }, { binding: 12, resource: state.fit[1].createView() });
143
+ }
144
+ }
145
+ const upscale = pipeline(`FSR 1 EASU ${detail ? `detail ${separate} ${silhouettes} ${guided}` : 'color'} ${output.format}`, detail ? easuDetailShader(separate, silhouettes, guided) : easuShader, [output.format]);
146
+ const group = device.createBindGroup({ layout: upscale.getBindGroupLayout(0), entries });
147
+ const draw = encoder.beginRenderPass({ label: 'FSR 1 EASU', colorAttachments: [{ view: output.createView(), loadOp: 'clear', storeOp: 'store' }] });
148
+ draw.setPipeline(upscale);
149
+ draw.setBindGroup(0, group);
150
+ draw.draw(3);
151
+ draw.end();
152
+ };
153
+ return Object.assign(pass, { dispose() { for (const [device, state] of devices)
154
+ retire(device, owned(state)); devices.clear(); } });
155
+ }
156
+ //# sourceMappingURL=easu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"easu.js","sourceRoot":"","sources":["../../src/renderer/easu.ts"],"names":[],"mappings":"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","sourcesContent":["import type {PostProcess} from '../Display.js';\nimport {areaDownsampleShader, easuShader} from './wgsl/easu.wgsl.js';\nimport {albedoDownsampleShader, easuDetailShader, guidedCoefficientShader, toneLutShader, EASU_DETAIL, TONE_LUT_SIZE} from './wgsl/easuDetail.wgsl.js';\nimport {borrowedAovRevision} from './WGPUAov.js';\nimport {TONE_MAPPING_MODES} from './wgsl/compose.frag.wgsl.js';\n\n/** createEasuPass options. */\nexport interface EasuOptions {\n /** Recover surface texture detail from the displayed render's diffuseColor, specularColor and depth AOVs, traced with aovResolution 'display'. Default false. Warns once when the displayed render lacks that configuration; frames whose AOVs are not ready or do not match the output size use EASU alone. Unsupported surfaces and silhouettes receive no compensation. */ albedoDetail?: boolean;\n}\n/** @internal Detail tuning kept for comparisons; not package options. */\nexport interface EasuTuning extends EasuOptions {\n /** Per-channel linear compensation bounds, positive finite min <= max. Default [0.7, 1.43]. */ ratioRange?: readonly [number, number];\n /** Relative departure of neighboring inverse depth from a plane that marks a silhouette, positive finite. Default 0.02. */ depthThreshold?: number;\n /** Minimum valid AOV coverage in (0,1]. Default 0.95. */ coverageThreshold?: number;\n}\n/** A display pass with optional scratch images. Dispose after unregistering; it may be used again. */\nexport type EasuPass = PostProcess & {dispose(): void};\n/** Creates an edge-adaptive display-space upscale pass (AMD FSR 1 EASU), without sharpening. Register with outputSize: (_, display) => display. WebGPU only; supports rgba8unorm and extended-range rgba16float, including alpha. Copies inputs that already have the output size and area-averages larger ones. Default EASU alone. */\nexport function createEasuPass(options: EasuOptions = {}): EasuPass { return createEasuPassImpl({albedoDetail: options.albedoDetail}); }\n\nconst DETAIL_AOVS = ['diffuseColor', 'specularColor', 'depth'] as const;\n\n/** @internal Plain albedo ratios (guided false), the separate-lobe approximation and depth-guided silhouettes are retained for comparisons; not package exports. */\nexport function createEasuPassImpl(options: EasuTuning = {}, separate = false, silhouettes = false, guided = true): EasuPass {\n const detailEnabled = options.albedoDetail ?? false;\n let warnedConfiguration = false;\n const [min, max] = options.ratioRange ?? EASU_DETAIL.ratioRange;\n const depth = options.depthThreshold ?? EASU_DETAIL.depthThreshold, coverage = options.coverageThreshold ?? EASU_DETAIL.coverageThreshold;\n if (![min,max,depth,coverage].every(Number.isFinite) || min <= 0 || max < min || depth <= 0 || coverage <= 0 || coverage > 1) throw new RangeError('Invalid EASU detail compensation options.');\n const devices = new Map<GPUDevice, {pipelines: Map<string, GPURenderPipeline>; scratch?: GPUTexture[]; key?: unknown[]; tone?: GPUTexture; toneKey?: string; fit?: GPUTexture[]}>();\n const retire = (device: GPUDevice, resources: (GPUTexture | GPUBuffer)[]) => {\n // This callback's encoder is submitted after it returns.\n void Promise.resolve().then(() => device.queue.onSubmittedWorkDone()).catch(() => {}).then(() => resources.forEach(resource => resource.destroy()));\n };\n const guideFormats: GPUTextureFormat[] = silhouettes ? ['rgba16float','rgba16float','rg32float'] : ['rgba16float','rgba16float'];\n const owned = (state: {scratch?: GPUTexture[]; tone?: GPUTexture; fit?: GPUTexture[]}) => [...(state.scratch ?? []), ...(state.tone ? [state.tone] : []), ...(state.fit ?? [])];\n const pass: PostProcess = ctx => {\n const {device, encoder, input, output, render} = ctx;\n // Nothing to upscale, for example a full-resolution render beside a reduced preview.\n if (input.width === output.width && input.height === output.height) {\n encoder.copyTextureToTexture({texture: input}, {texture: output}, [input.width, input.height]);\n return;\n }\n for (const [previous, old] of devices) if (previous !== device) {retire(previous,owned(old));devices.delete(previous);}\n let state = devices.get(device);\n if (!state) {state = {pipelines: new Map()}; devices.set(device, state);}\n const pipeline = (key: string, code: string, formats: GPUTextureFormat[]) => {\n let value = state!.pipelines.get(key);\n if (!value) {\n const module = device.createShaderModule({label: key, code});\n value = device.createRenderPipeline({label: key, layout: 'auto', vertex: {module,entryPoint:'vertex'},\n fragment: {module,entryPoint:'fragment',targets:formats.map(format => ({format}))}});\n state!.pipelines.set(key, value);\n }\n return value;\n };\n const buffer = (values: number[]) => {\n const value = device.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM,mappedAtCreation:true});\n new Float32Array(value.getMappedRange()).set(values);value.unmap();retire(device,[value]);return value;\n };\n if (input.width >= output.width && input.height >= output.height) {\n // EASU is an enlargement filter; larger renders are area averaged instead.\n const down = pipeline(`Area downsample ${output.format}`,areaDownsampleShader,[output.format]);\n const group = device.createBindGroup({layout:down.getBindGroupLayout(0),entries:[{binding:0,resource:input.createView()},{binding:1,resource:{buffer:buffer([output.width,output.height,0,0])}}]});\n const draw = encoder.beginRenderPass({label:'Area downsample',colorAttachments:[{view:output.createView(),loadOp:'clear',storeOp:'store'}]});\n draw.setPipeline(down);draw.setBindGroup(0,group);draw.draw(3);draw.end();\n return;\n }\n if (detailEnabled && !warnedConfiguration && (render.aovResolution !== 'display' || !DETAIL_AOVS.every(kind => render.aovs.includes(kind)))) {\n warnedConfiguration = true;\n console.warn(\"EASU albedoDetail needs the displayed render to enable diffuseColor, specularColor and depth AOVs with aovResolution 'display'; upscaling without detail.\");\n }\n const aovs = detailEnabled ? DETAIL_AOVS.map(kind => render.getAovTexture(kind)) : [];\n const detail = aovs.length === 3 && aovs.every(image => image && image.width === output.width && image.height === output.height);\n const entries: GPUBindGroupEntry[] = [{binding:0,resource:input.createView()}, {binding:1,resource:{buffer:buffer([output.width,output.height,min,max])}}];\n if (detail) {\n // Cached images are recorded on their own submission so a failed chain cannot leave them stale.\n let cache: GPUCommandEncoder | undefined;\n const cached = () => cache ??= device.createCommandEncoder({label: 'EASU cache'});\n if (!state.scratch || state.scratch.length !== guideFormats.length || state.scratch[0].width !== input.width || state.scratch[0].height !== input.height) {\n if(state.scratch)retire(device,state.scratch);\n // Low diffuse and specular albedo, then (for silhouettes) nearest hit depth with hit coverage.\n state.scratch = guideFormats.map((format, index) => device.createTexture({label:`EASU low guide ${index}`,size:[input.width,input.height],format,usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT}));\n state.key = undefined;\n }\n // Low albedo depends only on the AOV contents and beauty size; reuse it across presents.\n const key = [state.scratch[0], ...aovs, ...aovs.map(image => borrowedAovRevision.get(image!))];\n if (!state.key || key.some((value, index) => value !== state.key![index])) {\n const down = pipeline(`Albedo area downsample ${silhouettes}`,albedoDownsampleShader(silhouettes),guideFormats);\n const group = device.createBindGroup({layout:down.getBindGroupLayout(0),entries:[\n {binding:0,resource:aovs[0]!.createView()},{binding:1,resource:aovs[1]!.createView()},\n {binding:2,resource:{buffer:buffer([input.width,input.height,0,0])}},{binding:3,resource:aovs[2]!.createView()}\n ]});\n const draw = cached().beginRenderPass({label:'Albedo area downsample',colorAttachments:state.scratch.map(image=>({view:image.createView(),loadOp:'clear',storeOp:'store'}))});\n draw.setPipeline(down);draw.setBindGroup(0,group);draw.draw(3);draw.end();\n state.key = key;\n }\n aovs.forEach((image,index)=>entries.push({binding:2+index,resource:image!.createView()}));\n entries.push({binding:5,resource:state.scratch[0].createView()},{binding:6,resource:state.scratch[1].createView()});\n if (silhouettes) entries.push({binding:10,resource:state.scratch[2].createView()});\n entries.push({binding:7,resource:{buffer:buffer([EASU_DETAIL.minimumAlbedo,coverage,depth,EASU_DETAIL.depthTolerance])}});\n // The ratio is applied through the same grading and tone mapping as the composed image,\n // tabulated once per display setting.\n const display = render._engine.display, extended = output.format === 'rgba16float';\n const tone = [TONE_MAPPING_MODES[display.toneMapping] ?? 0, extended ? 16 : 1, display.toneMappingExposure, extended ? 1 : 0];\n const grading = [display.contrast, display.saturation, display.temperature, display.tint];\n const toneKey = [...tone, ...grading].join(',');\n state.tone ??= device.createTexture({label:'EASU tone table',size:[TONE_LUT_SIZE,2],format:'rgba32float',usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT});\n if (state.toneKey !== toneKey) {\n const build = pipeline('EASU tone table',toneLutShader,['rgba32float']);\n const group = device.createBindGroup({layout:build.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:buffer(tone)}},{binding:1,resource:{buffer:buffer(grading)}}]});\n const draw = cached().beginRenderPass({label:'EASU tone table',colorAttachments:[{view:state.tone.createView(),loadOp:'clear',storeOp:'store'}]});\n draw.setPipeline(build);draw.setBindGroup(0,group);draw.draw(3);draw.end();\n state.toneKey = toneKey;\n }\n const toneEntries: GPUBindGroupEntry[] = [{binding:8,resource:state.tone.createView()},{binding:9,resource:{buffer:buffer([tone[1],EASU_DETAIL.guidedEpsilon,0,0])}}];\n entries.push(...toneEntries);\n if (cache) device.queue.submit([cache.finish()]);\n if (guided) {\n // The local albedo-radiance fit depends on this frame's image, so it runs on every present.\n if (!state.fit || state.fit[0].width !== input.width || state.fit[0].height !== input.height) {\n if (state.fit) retire(device, state.fit);\n state.fit = ['slope','offset'].map(name => device.createTexture({label:`EASU albedo ${name}`,size:[input.width,input.height],format:'rgba16float',usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT}));\n }\n const fit = pipeline('EASU albedo fit',guidedCoefficientShader,['rgba16float','rgba16float']);\n const group = device.createBindGroup({layout:fit.getBindGroupLayout(0),entries:[{binding:0,resource:input.createView()},\n {binding:1,resource:state.scratch[0].createView()},{binding:2,resource:state.scratch[1].createView()},...toneEntries]});\n const draw = encoder.beginRenderPass({label:'EASU albedo fit',colorAttachments:state.fit.map(image=>({view:image.createView(),loadOp:'clear',storeOp:'store'}))});\n draw.setPipeline(fit);draw.setBindGroup(0,group);draw.draw(3);draw.end();\n entries.push({binding:11,resource:state.fit[0].createView()},{binding:12,resource:state.fit[1].createView()});\n }\n }\n const upscale = pipeline(`FSR 1 EASU ${detail ? `detail ${separate} ${silhouettes} ${guided}` : 'color'} ${output.format}`,detail ? easuDetailShader(separate, silhouettes, guided) : easuShader,[output.format]);\n const group = device.createBindGroup({layout:upscale.getBindGroupLayout(0),entries});\n const draw = encoder.beginRenderPass({label:'FSR 1 EASU',colorAttachments:[{view:output.createView(),loadOp:'clear',storeOp:'store'}]});\n draw.setPipeline(upscale);draw.setBindGroup(0,group);draw.draw(3);draw.end();\n };\n return Object.assign(pass, {dispose() {for(const [device,state] of devices) retire(device,owned(state));devices.clear();}});\n}\n"]}
@@ -18,6 +18,7 @@ export interface GeometryUpdateRegion {
18
18
  }
19
19
  export interface GeometryUpdateState<M extends GeometryUpdateMesh = GeometryUpdateMesh> {
20
20
  geometry: Geometry;
21
+ mergedAttributes?: boolean;
21
22
  geometries: Geometry[];
22
23
  geometryRegions: Map<Geometry, GeometryUpdateRegion>;
23
24
  geometryStates: Map<Geometry, {
@@ -1 +1 @@
1
- {"version":3,"file":"geometryUpdateState.js","sourceRoot":"","sources":["../../src/renderer/geometryUpdateState.ts"],"names":[],"mappings":"","sourcesContent":["import type Geometry from '../scene/Geometry.js';\nimport type MaterialState from '../scene/MaterialState.js';\nimport type { vec3 } from '../math.js';\nimport type { FlattendBVH } from './bvhAccel.js';\n\n// The update algorithm needs no renderer resources or browser scene facade.\nexport interface GeometryUpdateMesh { geometry: Geometry; materials: MaterialState[]; }\nexport interface GeometryUpdateBinding<M extends GeometryUpdateMesh = GeometryUpdateMesh> {\n mesh: M;\n geometry: Geometry;\n bvhBounds: [vec3.Vec3Array, vec3.Vec3Array];\n}\nexport interface GeometryUpdateRegion { vertexOffset: number; indexOffset: number; materialIndices: number[]; }\nexport interface GeometryUpdateState<M extends GeometryUpdateMesh = GeometryUpdateMesh> {\n geometry: Geometry;\n geometries: Geometry[];\n geometryRegions: Map<Geometry, GeometryUpdateRegion>;\n geometryStates: Map<Geometry, {topologyVersion: number; indices: Geometry['indices']['array']; indexCount: number}>;\n instanceBindings: GeometryUpdateBinding<M>[];\n blases: {bvh: FlattendBVH}[];\n}\n"]}
1
+ {"version":3,"file":"geometryUpdateState.js","sourceRoot":"","sources":["../../src/renderer/geometryUpdateState.ts"],"names":[],"mappings":"","sourcesContent":["import type Geometry from '../scene/Geometry.js';\nimport type MaterialState from '../scene/MaterialState.js';\nimport type { vec3 } from '../math.js';\nimport type { FlattendBVH } from './bvhAccel.js';\n\n// The update algorithm needs no renderer resources or browser scene facade.\nexport interface GeometryUpdateMesh { geometry: Geometry; materials: MaterialState[]; }\nexport interface GeometryUpdateBinding<M extends GeometryUpdateMesh = GeometryUpdateMesh> {\n mesh: M;\n geometry: Geometry;\n bvhBounds: [vec3.Vec3Array, vec3.Vec3Array];\n}\nexport interface GeometryUpdateRegion { vertexOffset: number; indexOffset: number; materialIndices: number[]; }\nexport interface GeometryUpdateState<M extends GeometryUpdateMesh = GeometryUpdateMesh> {\n geometry: Geometry;\n mergedAttributes?: boolean;\n geometries: Geometry[];\n geometryRegions: Map<Geometry, GeometryUpdateRegion>;\n geometryStates: Map<Geometry, {topologyVersion: number; indices: Geometry['indices']['array']; indexCount: number}>;\n instanceBindings: GeometryUpdateBinding<M>[];\n blases: {bvh: FlattendBVH}[];\n}\n"]}
@@ -107,9 +107,10 @@ export function updatePreparedGeometries(prepared, changed, options = {}) {
107
107
  blases.push({ blas: bvh, offset });
108
108
  }
109
109
  geometry.version = source.version;
110
- copyRegion(source, prepared.geometry, region, topologyChanged, deformationOnly);
110
+ if (prepared.mergedAttributes !== false)
111
+ copyRegion(source, prepared.geometry, region, topologyChanged, deformationOnly);
111
112
  const count = source.vertexCount, previousVertices = vertices[vertices.length - 1];
112
- if (previousVertices && previousVertices.first + previousVertices.count === region.vertexOffset && previousVertices.topologyChanged === topologyChanged && previousVertices.deformationOnly === deformationOnly)
113
+ if (prepared.mergedAttributes !== false && previousVertices && previousVertices.first + previousVertices.count === region.vertexOffset && previousVertices.topologyChanged === topologyChanged && previousVertices.deformationOnly === deformationOnly)
113
114
  previousVertices.count += count;
114
115
  else
115
116
  vertices.push({ first: region.vertexOffset, count, topologyChanged, deformationOnly });
@@ -1 +1 @@
1
- {"version":3,"file":"geometryUpdates.js","sourceRoot":"","sources":["../../src/renderer/geometryUpdates.ts"],"names":[],"mappings":"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","sourcesContent":["import {matrixStorage, copyNumericStorage} from '../math/storage.js';\nimport { getGeometryBvh, setGeometryBvh } from './geometryBvh.js';\nimport { writeMaterialIndices } from './materialIndices.js';\nimport { isDeformationUpdate } from '../scene/geometryChanges.js';\nimport type Geometry from '../scene/Geometry.js';\nimport { Attribute } from '../scene/Geometry.js';\nimport { attributeValue, type AttributeData } from '../scene/attributeData.js';\nimport { hasGeneratedVertexTangents } from '../util/geometry.js';\nimport { buildBLAS, refitBLAS, type FlattendBVH } from './bvhAccel.js';\nimport type { GeometryUpdateState, GeometryUpdateMesh, GeometryUpdateRegion, GeometryUpdateBinding } from './geometryUpdateState.js';\nimport {computeGeometryBounds, getBvhBounds } from './geometryBvhBounds.js';\n\ntype Prepared = GeometryUpdateState;\ntype BindingIndices<M extends GeometryUpdateMesh> = {source: Map<Geometry, GeometryUpdateBinding<M>[]>; prepared: Map<Geometry, GeometryUpdateBinding<M>[]>};\nconst vertexAttributes = ['position', 'normal', 'uv', 'uv1', 'color', 'tangent', 'materialIndex'] as const;\n// Box only the identity: widening a generic preparation record for a native\n// WeakMap key can otherwise make a copy instead of retaining the caller's key.\nconst bindingIndices = new WeakMap<object, BindingIndices<GeometryUpdateMesh>>();\nfunction indices<M extends GeometryUpdateMesh>(prepared: GeometryUpdateState<M>) {\n // The prepared object's identity owns its binding type; entries are never\n // shared between preparations with different mesh types.\n let maps = bindingIndices.get(prepared) as BindingIndices<M> | undefined;\n if (!maps) {\n maps = { source: new Map(), prepared: new Map() };\n for (const binding of prepared.instanceBindings) {\n for (const [map, geometry] of [[maps.source, binding.mesh.geometry], [maps.prepared, binding.geometry]] as const) {\n let bindings = map.get(geometry);\n if (!bindings) map.set(geometry, bindings = []);\n bindings.push(binding);\n }\n }\n bindingIndices.set(prepared, maps);\n }\n return maps;\n}\n\n/** Displaced geometry must be prepared as a whole. */\nexport function canUpdateGeometries<M extends GeometryUpdateMesh>(prepared: GeometryUpdateState<M>, geometries: readonly Geometry[]) {\n return geometries.every(geometry => {\n const bindings = indices(prepared).source.get(geometry) ?? [];\n return bindings.length > 0 && bindings.every(b => !b.mesh.materials.some(m => m.displacementMap) &&\n b.geometry.position.array === geometry.position.array);\n });\n}\n\n/** Rewrites only a geometry's existing region, preserving global material indices. */\nfunction copyRegion(source: Geometry, merged: Geometry, region: GeometryUpdateRegion, topologyChanged: boolean, deformationOnly: boolean) {\n const { vertexOffset, indexOffset, materialIndices } = region;\n const count = source.vertexCount;\n for (const name of vertexAttributes) {\n if (name === 'materialIndex' || deformationOnly && name !== 'position' && name !== 'normal' && name !== 'tangent') continue;\n const target = merged[name]; if (!target) continue;\n const attribute = name === 'uv1' ? source.uv1 ?? source.uv : source[name];\n const offset = vertexOffset * target.itemSize;\n if (attribute && attribute.itemSize !== target.itemSize) {\n for (let v = 0; v < count; v++) for (let c = 0; c < target.itemSize; c++) {\n target.array[offset + v * target.itemSize + c] = c < attribute.itemSize ? attribute.array[v * attribute.itemSize + c] : name === 'tangent' && !hasGeneratedVertexTangents(source) ? 2 : 0;\n }\n }\n else if (attribute) target.array.set(attribute.array, offset);\n else target.array.fill(name === 'color' ? 1 : 0, offset, offset + count * target.itemSize);\n }\n if (!topologyChanged) return;\n writeMaterialIndices(source, materialIndices, merged.materialIndex!.array, vertexOffset);\n const indices = source.indexArray;\n for (let i = 0; i < indices.length; i++) writeIndex(merged, indexOffset + i, indices[i] + vertexOffset);\n}\n\n/** Constant-time topology detection; markUpdated also covers in-place index edits. */\nexport function geometryTopologyChanged(prepared: {geometryStates: Prepared['geometryStates']} | undefined, source: Geometry) {\n const state = prepared?.geometryStates.get(source);\n return !!state && (state.topologyVersion !== source.topologyVersion ||\n state.indices !== source.indices.array || state.indexCount !== source.indexArray.length);\n}\n\nexport interface GeometryUpdateOptions {\n softwareBvhs?: boolean;\n displacement?: Map<Geometry, {scale: number; ranges: Float32Array}>;\n}\n\n/** Refits/rebuilds changed BLASes and refreshes all shared instances' cached bounds. */\nexport function updatePreparedGeometries<M extends GeometryUpdateMesh>(prepared: GeometryUpdateState<M>, changed: ReadonlySet<Geometry>, options: GeometryUpdateOptions = {}) {\n const vertices: { first: number; count: number; topologyChanged: boolean; deformationOnly: boolean }[] = [];\n const blases: { blas: FlattendBVH; offset: number }[] = [];\n const meshes = new Set<M>();\n let resized = false, relocated = false, offset = 0;\n const updated = new Map<Geometry, FlattendBVH>();\n prepared.geometries.forEach((geometry, i) => {\n const source = indices(prepared).prepared.get(geometry)?.[0].mesh.geometry ?? geometry;\n const previous = i < prepared.blases.length ? prepared.blases[i].bvh : undefined;\n if (changed.has(source)) {\n const region = prepared.geometryRegions.get(geometry)!;\n const topologyChanged = geometryTopologyChanged(prepared, source);\n const deformationOnly = !topologyChanged && isDeformationUpdate(source);\n if (options.softwareBvhs !== false) {\n const displacement = options.displacement?.get(geometry);\n const key = displacement ? geometry : source;\n let bvh = updated.get(key);\n if (!bvh) {\n bvh = displacement ? getGeometryBvh(geometry) ?? getGeometryBvh(source) : getGeometryBvh(source);\n const detail = displacement ? {normal: source.normal.array,\n scale: displacement.scale, ranges: displacement.ranges} : undefined;\n if (topologyChanged || !bvh || source.dynamic && bvh.builder !== 'builtin' || !refitBLAS(bvh, source, detail)) {\n bvh = buildBLAS(source, displacement?.scale, displacement?.ranges);\n }\n setGeometryBvh(source, bvh); updated.set(key, bvh);\n }\n setGeometryBvh(geometry, bvh);\n prepared.blases[i].bvh = bvh;\n resized ||= previous?.buffer.byteLength !== bvh.buffer.byteLength;\n relocated ||= previous?.buffer.byteLength !== bvh.buffer.byteLength || previous?.layout !== bvh.layout;\n blases.push({blas: bvh, offset});\n }\n geometry.version = source.version;\n copyRegion(source, prepared.geometry, region, topologyChanged, deformationOnly);\n const count = source.vertexCount, previousVertices = vertices[vertices.length - 1];\n if (previousVertices && previousVertices.first + previousVertices.count === region.vertexOffset && previousVertices.topologyChanged === topologyChanged && previousVertices.deformationOnly === deformationOnly) previousVertices.count += count;\n else vertices.push({first: region.vertexOffset, count, topologyChanged, deformationOnly});\n for (const binding of indices(prepared).prepared.get(geometry) ?? []) {\n const bounds = options.softwareBvhs === false ? computeGeometryBounds(geometry) : getBvhBounds(geometry);\n // Keep shared bound arrays: native generic-record values read from a Map\n // can be copies, so replacing their tuple does not update the owner view.\n copyNumericStorage(binding.bvhBounds[0], matrixStorage(bounds[0]));\n copyNumericStorage(binding.bvhBounds[1], matrixStorage(bounds[1]));\n meshes.add(binding.mesh);\n }\n }\n if (i < prepared.blases.length) offset += prepared.blases[i].bvh.buffer.byteLength;\n });\n for (const source of changed) prepared.geometryStates.set(source, { topologyVersion: source.topologyVersion,\n indices: source.indices.array, indexCount: source.indexArray.length });\n return { vertices, blases, meshes, resized, relocated };\n}\n\nfunction writeIndex(geometry: Geometry, index: number, value: number) {\n const array = geometry.indexArray;\n array[index] = value;\n}\n\nfunction packAttribute<T extends AttributeData>(attribute: Attribute<T> | undefined,\n output: Float32Array, stride: number, offset: number, first: number, count: number, outputFirst = first) {\n if (!attribute) return;\n const array = attribute.array, size = attribute.itemSize;\n let destination = outputFirst * stride + offset, source = first * size;\n if (size === 1) {\n for (let i = 0; i < count; i++, destination += stride, source += size) {\n output[destination] = attributeValue(array, source);\n }\n return;\n }\n if (size === 2) {\n for (let i = 0; i < count; i++, destination += stride, source += size) {\n output[destination] = attributeValue(array, source);\n output[destination + 1] = attributeValue(array, source + 1);\n }\n return;\n }\n if (size === 3) {\n for (let i = 0; i < count; i++, destination += stride, source += size) {\n output[destination] = attributeValue(array, source);\n output[destination + 1] = attributeValue(array, source + 1);\n output[destination + 2] = attributeValue(array, source + 2);\n }\n return;\n }\n if (size === 4) {\n for (let i = 0; i < count; i++, destination += stride, source += size) {\n output[destination] = attributeValue(array, source);\n output[destination + 1] = attributeValue(array, source + 1);\n output[destination + 2] = attributeValue(array, source + 2);\n output[destination + 3] = attributeValue(array, source + 3);\n }\n return;\n }\n for (let i = 0; i < count; i++, destination += stride, source += size) {\n for (let c = 0; c < size; c++) output[destination + c] = attributeValue(array, source + c);\n }\n}\n\n/** Packs the same interleaved vertex layout for full and partial GPU uploads. */\nexport function packVertexAttributes(geometry: Geometry, output: Float32Array, stride: number,\n offsets: readonly number[], first: number, count: number, includeMaterialIndex = true, deformationOnly = false, outputFirst = first) {\n packAttribute(geometry.position, output, stride, offsets[0], first, count, outputFirst);\n packAttribute(geometry.normal, output, stride, offsets[1], first, count, outputFirst);\n if (!deformationOnly) {\n packAttribute(geometry.uv, output, stride, offsets[2], first, count, outputFirst);\n packAttribute(geometry.uv1, output, stride, offsets[3], first, count, outputFirst);\n packAttribute(geometry.color, output, stride, offsets[4], first, count, outputFirst);\n }\n packAttribute(geometry.tangent, output, stride, offsets[5], first, count, outputFirst);\n if (includeMaterialIndex) packAttribute(geometry.materialIndex, output, stride, offsets[6], first, count, outputFirst);\n}\n"]}
1
+ {"version":3,"file":"geometryUpdates.js","sourceRoot":"","sources":["../../src/renderer/geometryUpdates.ts"],"names":[],"mappings":"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","sourcesContent":["import {matrixStorage, copyNumericStorage} from '../math/storage.js';\nimport { getGeometryBvh, setGeometryBvh } from './geometryBvh.js';\nimport { writeMaterialIndices } from './materialIndices.js';\nimport { isDeformationUpdate } from '../scene/geometryChanges.js';\nimport type Geometry from '../scene/Geometry.js';\nimport { Attribute } from '../scene/Geometry.js';\nimport { attributeValue, type AttributeData } from '../scene/attributeData.js';\nimport { hasGeneratedVertexTangents } from '../util/geometry.js';\nimport { buildBLAS, refitBLAS, type FlattendBVH } from './bvhAccel.js';\nimport type { GeometryUpdateState, GeometryUpdateMesh, GeometryUpdateRegion, GeometryUpdateBinding } from './geometryUpdateState.js';\nimport {computeGeometryBounds, getBvhBounds } from './geometryBvhBounds.js';\n\ntype Prepared = GeometryUpdateState;\ntype BindingIndices<M extends GeometryUpdateMesh> = {source: Map<Geometry, GeometryUpdateBinding<M>[]>; prepared: Map<Geometry, GeometryUpdateBinding<M>[]>};\nconst vertexAttributes = ['position', 'normal', 'uv', 'uv1', 'color', 'tangent', 'materialIndex'] as const;\n// Box only the identity: widening a generic preparation record for a native\n// WeakMap key can otherwise make a copy instead of retaining the caller's key.\nconst bindingIndices = new WeakMap<object, BindingIndices<GeometryUpdateMesh>>();\nfunction indices<M extends GeometryUpdateMesh>(prepared: GeometryUpdateState<M>) {\n // The prepared object's identity owns its binding type; entries are never\n // shared between preparations with different mesh types.\n let maps = bindingIndices.get(prepared) as BindingIndices<M> | undefined;\n if (!maps) {\n maps = { source: new Map(), prepared: new Map() };\n for (const binding of prepared.instanceBindings) {\n for (const [map, geometry] of [[maps.source, binding.mesh.geometry], [maps.prepared, binding.geometry]] as const) {\n let bindings = map.get(geometry);\n if (!bindings) map.set(geometry, bindings = []);\n bindings.push(binding);\n }\n }\n bindingIndices.set(prepared, maps);\n }\n return maps;\n}\n\n/** Displaced geometry must be prepared as a whole. */\nexport function canUpdateGeometries<M extends GeometryUpdateMesh>(prepared: GeometryUpdateState<M>, geometries: readonly Geometry[]) {\n return geometries.every(geometry => {\n const bindings = indices(prepared).source.get(geometry) ?? [];\n return bindings.length > 0 && bindings.every(b => !b.mesh.materials.some(m => m.displacementMap) &&\n b.geometry.position.array === geometry.position.array);\n });\n}\n\n/** Rewrites only a geometry's existing region, preserving global material indices. */\nfunction copyRegion(source: Geometry, merged: Geometry, region: GeometryUpdateRegion, topologyChanged: boolean, deformationOnly: boolean) {\n const { vertexOffset, indexOffset, materialIndices } = region;\n const count = source.vertexCount;\n for (const name of vertexAttributes) {\n if (name === 'materialIndex' || deformationOnly && name !== 'position' && name !== 'normal' && name !== 'tangent') continue;\n const target = merged[name]; if (!target) continue;\n const attribute = name === 'uv1' ? source.uv1 ?? source.uv : source[name];\n const offset = vertexOffset * target.itemSize;\n if (attribute && attribute.itemSize !== target.itemSize) {\n for (let v = 0; v < count; v++) for (let c = 0; c < target.itemSize; c++) {\n target.array[offset + v * target.itemSize + c] = c < attribute.itemSize ? attribute.array[v * attribute.itemSize + c] : name === 'tangent' && !hasGeneratedVertexTangents(source) ? 2 : 0;\n }\n }\n else if (attribute) target.array.set(attribute.array, offset);\n else target.array.fill(name === 'color' ? 1 : 0, offset, offset + count * target.itemSize);\n }\n if (!topologyChanged) return;\n writeMaterialIndices(source, materialIndices, merged.materialIndex!.array, vertexOffset);\n const indices = source.indexArray;\n for (let i = 0; i < indices.length; i++) writeIndex(merged, indexOffset + i, indices[i] + vertexOffset);\n}\n\n/** Constant-time topology detection; markUpdated also covers in-place index edits. */\nexport function geometryTopologyChanged(prepared: {geometryStates: Prepared['geometryStates']} | undefined, source: Geometry) {\n const state = prepared?.geometryStates.get(source);\n return !!state && (state.topologyVersion !== source.topologyVersion ||\n state.indices !== source.indices.array || state.indexCount !== source.indexArray.length);\n}\n\nexport interface GeometryUpdateOptions {\n softwareBvhs?: boolean;\n displacement?: Map<Geometry, {scale: number; ranges: Float32Array}>;\n}\n\n/** Refits/rebuilds changed BLASes and refreshes all shared instances' cached bounds. */\nexport function updatePreparedGeometries<M extends GeometryUpdateMesh>(prepared: GeometryUpdateState<M>, changed: ReadonlySet<Geometry>, options: GeometryUpdateOptions = {}) {\n const vertices: { first: number; count: number; topologyChanged: boolean; deformationOnly: boolean }[] = [];\n const blases: { blas: FlattendBVH; offset: number }[] = [];\n const meshes = new Set<M>();\n let resized = false, relocated = false, offset = 0;\n const updated = new Map<Geometry, FlattendBVH>();\n prepared.geometries.forEach((geometry, i) => {\n const source = indices(prepared).prepared.get(geometry)?.[0].mesh.geometry ?? geometry;\n const previous = i < prepared.blases.length ? prepared.blases[i].bvh : undefined;\n if (changed.has(source)) {\n const region = prepared.geometryRegions.get(geometry)!;\n const topologyChanged = geometryTopologyChanged(prepared, source);\n const deformationOnly = !topologyChanged && isDeformationUpdate(source);\n if (options.softwareBvhs !== false) {\n const displacement = options.displacement?.get(geometry);\n const key = displacement ? geometry : source;\n let bvh = updated.get(key);\n if (!bvh) {\n bvh = displacement ? getGeometryBvh(geometry) ?? getGeometryBvh(source) : getGeometryBvh(source);\n const detail = displacement ? {normal: source.normal.array,\n scale: displacement.scale, ranges: displacement.ranges} : undefined;\n if (topologyChanged || !bvh || source.dynamic && bvh.builder !== 'builtin' || !refitBLAS(bvh, source, detail)) {\n bvh = buildBLAS(source, displacement?.scale, displacement?.ranges);\n }\n setGeometryBvh(source, bvh); updated.set(key, bvh);\n }\n setGeometryBvh(geometry, bvh);\n prepared.blases[i].bvh = bvh;\n resized ||= previous?.buffer.byteLength !== bvh.buffer.byteLength;\n relocated ||= previous?.buffer.byteLength !== bvh.buffer.byteLength || previous?.layout !== bvh.layout;\n blases.push({blas: bvh, offset});\n }\n geometry.version = source.version;\n if (prepared.mergedAttributes !== false) copyRegion(source, prepared.geometry, region, topologyChanged, deformationOnly);\n const count = source.vertexCount, previousVertices = vertices[vertices.length - 1];\n if (prepared.mergedAttributes !== false && previousVertices && previousVertices.first + previousVertices.count === region.vertexOffset && previousVertices.topologyChanged === topologyChanged && previousVertices.deformationOnly === deformationOnly) previousVertices.count += count;\n else vertices.push({first: region.vertexOffset, count, topologyChanged, deformationOnly});\n for (const binding of indices(prepared).prepared.get(geometry) ?? []) {\n const bounds = options.softwareBvhs === false ? computeGeometryBounds(geometry) : getBvhBounds(geometry);\n // Keep shared bound arrays: native generic-record values read from a Map\n // can be copies, so replacing their tuple does not update the owner view.\n copyNumericStorage(binding.bvhBounds[0], matrixStorage(bounds[0]));\n copyNumericStorage(binding.bvhBounds[1], matrixStorage(bounds[1]));\n meshes.add(binding.mesh);\n }\n }\n if (i < prepared.blases.length) offset += prepared.blases[i].bvh.buffer.byteLength;\n });\n for (const source of changed) prepared.geometryStates.set(source, { topologyVersion: source.topologyVersion,\n indices: source.indices.array, indexCount: source.indexArray.length });\n return { vertices, blases, meshes, resized, relocated };\n}\n\nfunction writeIndex(geometry: Geometry, index: number, value: number) {\n const array = geometry.indexArray;\n array[index] = value;\n}\n\nfunction packAttribute<T extends AttributeData>(attribute: Attribute<T> | undefined,\n output: Float32Array, stride: number, offset: number, first: number, count: number, outputFirst = first) {\n if (!attribute) return;\n const array = attribute.array, size = attribute.itemSize;\n let destination = outputFirst * stride + offset, source = first * size;\n if (size === 1) {\n for (let i = 0; i < count; i++, destination += stride, source += size) {\n output[destination] = attributeValue(array, source);\n }\n return;\n }\n if (size === 2) {\n for (let i = 0; i < count; i++, destination += stride, source += size) {\n output[destination] = attributeValue(array, source);\n output[destination + 1] = attributeValue(array, source + 1);\n }\n return;\n }\n if (size === 3) {\n for (let i = 0; i < count; i++, destination += stride, source += size) {\n output[destination] = attributeValue(array, source);\n output[destination + 1] = attributeValue(array, source + 1);\n output[destination + 2] = attributeValue(array, source + 2);\n }\n return;\n }\n if (size === 4) {\n for (let i = 0; i < count; i++, destination += stride, source += size) {\n output[destination] = attributeValue(array, source);\n output[destination + 1] = attributeValue(array, source + 1);\n output[destination + 2] = attributeValue(array, source + 2);\n output[destination + 3] = attributeValue(array, source + 3);\n }\n return;\n }\n for (let i = 0; i < count; i++, destination += stride, source += size) {\n for (let c = 0; c < size; c++) output[destination + c] = attributeValue(array, source + c);\n }\n}\n\n/** Packs the same interleaved vertex layout for full and partial GPU uploads. */\nexport function packVertexAttributes(geometry: Geometry, output: Float32Array, stride: number,\n offsets: readonly number[], first: number, count: number, includeMaterialIndex = true, deformationOnly = false, outputFirst = first) {\n packAttribute(geometry.position, output, stride, offsets[0], first, count, outputFirst);\n packAttribute(geometry.normal, output, stride, offsets[1], first, count, outputFirst);\n if (!deformationOnly) {\n packAttribute(geometry.uv, output, stride, offsets[2], first, count, outputFirst);\n packAttribute(geometry.uv1, output, stride, offsets[3], first, count, outputFirst);\n packAttribute(geometry.color, output, stride, offsets[4], first, count, outputFirst);\n }\n packAttribute(geometry.tangent, output, stride, offsets[5], first, count, outputFirst);\n if (includeMaterialIndex) packAttribute(geometry.materialIndex, output, stride, offsets[6], first, count, outputFirst);\n}\n"]}
@@ -9,7 +9,7 @@ export default new FragmentShader({
9
9
  mapping: Shader.uniform('vec4'), idComponent: Shader.uniform('int')
10
10
  },
11
11
  main: /* glsl */ `
12
- uint vB(uint v) {
12
+ uint xo(uint v) {
13
13
  v = (v ^ (v >> 16u)) * 0x7feb352du;
14
14
  v = (v ^ (v >> 15u)) * 0x846ca68bu;
15
15
  return v ^ (v >> 16u);
@@ -36,16 +36,16 @@ color = srgb(clamp(r.xyz / max(r.w, 1.0), 0.0, 1.0));
36
36
  } else if (kind == 5) {
37
37
  uvec4 ids = texelFetch(identity, p, 0);
38
38
  alpha = ids.x == 0xffffffffu ? 0.0 : 1.0;
39
- uint h = vB(ids[idComponent]);
39
+ uint h = xo(ids[idComponent]);
40
40
  color = .2 + .8 * vec3(float(h & 255u), float((h >> 8u) & 255u),
41
41
  float((h >> 16u) & 255u)) / 255.0;
42
42
  } else {
43
43
  vec4 m = texelFetch(motion, p, 0);
44
44
  alpha = m.w == 3.0 ? 1.0 : 0.0;
45
- float gz = length(m.xy), hue = 0.0;
46
- if (gz > 0.0) hue = fract(atan(m.y, m.x) / 6.28318530718 + 1.0);
45
+ float gT = length(m.xy), hue = 0.0;
46
+ if (gT > 0.0) hue = fract(atan(m.y, m.x) / 6.28318530718 + 1.0);
47
47
  vec3 v = abs(fract(vec3(hue) + vec3(0.0, 2.0 / 3.0, 1.0 / 3.0)) * 6.0 - 3.0);
48
- color = clamp(v - 1.0, 0.0, 1.0) * clamp(gz / mapping.w, 0.0, 1.0);
48
+ color = clamp(v - 1.0, 0.0, 1.0) * clamp(gT / mapping.w, 0.0, 1.0);
49
49
  }
50
50
  if (alpha <= 0.0) color = vec3(0.0);
51
51
  out_color = vec4(color, clamp(alpha, 0.0, 1.0));
@@ -1,58 +1,58 @@
1
1
  import proposals from './aovReflectanceSamples.glsl.js';
2
2
  // GLSL mirror of the shared 256-proposal, fused OpenPBR reflection quadrature.
3
3
  export default proposals + /* glsl */ `
4
- void aovReflectance(OpenPbrPreparedBsdf prepared, bool qH, bool kE, out vec3 diffuse, out vec3 specular) {
4
+ void aovReflectance(OpenPbrPreparedBsdf prepared, bool rV, bool lp, out vec3 diffuse, out vec3 specular) {
5
5
  diffuse=vec3(0.0); specular=vec3(0.0);
6
6
  vec3 view = prepared.viewLocal;
7
7
  if (view.z <= 1e-6) { return; }
8
8
  OpenPbrResolvedMaterial material = prepared.material;
9
9
  vec2 alpha = vec2(material.alphaX, material.alphaY);
10
- float lN = aD(view, alpha);
11
- float iR = prepared.weights[OPENPBR_LOBE_DIFFUSE];
12
- float fN = prepared.weights[OPENPBR_LOBE_METAL];
10
+ float mG = aD(view, alpha);
11
+ float jw = prepared.weights[OPENPBR_LOBE_DIFFUSE];
12
+ float fZ = prepared.weights[OPENPBR_LOBE_METAL];
13
13
  float specularWeight = prepared.weights[OPENPBR_LOBE_SPECULAR];
14
- float dS = 1.0;
15
- if (kE && prepared.dielectricMsProbability > 0.0) {
16
- dS = max(aY(prepared.refractionEtaTOverEtaI, prepared.specularAlpha), 1e-12);
14
+ float dY = 1.0;
15
+ if (lp && prepared.dielectricMsProbability > 0.0) {
16
+ dY = max(aZ(prepared.refractionEtaTOverEtaI, prepared.specularAlpha), 1e-12);
17
17
  }
18
- vec3 ce = normalize(vec3(alpha, 1.0) * view);
19
- float qG = min(ce.z, 1.0);
20
- float jN = 1.0 + qG;
18
+ vec3 cf = normalize(vec3(alpha, 1.0) * view);
19
+ float rU = min(cf.z, 1.0);
20
+ float ku = 1.0 + rU;
21
21
  uint count = 256u;
22
22
  for (uint i = 0u; i < uint(NO_UNROLL(256)); i++) {
23
- uint wn = i / 2u;
24
- vec2 u = vec2((float(wn) + 0.5) / float(count / 2u),
25
- fract(float(reverseBits(wn)) * 2.3283064365386963e-10 + 0.37));
26
- vec4 proposal = gV[wn];
23
+ uint pair = i / 2u;
24
+ vec2 u = vec2((float(pair) + 0.5) / float(count / 2u),
25
+ fract(float(reverseBits(pair)) * 2.3283064365386963e-10 + 0.37));
26
+ vec4 proposal = ht[pair];
27
27
 
28
- bool hv = prepared.specularAlpha < 0.001;
28
+ bool hP = prepared.specularAlpha < 0.001;
29
29
  vec3 light = vec3(proposal.xy, sqrt(max(0.0, 1.0 - dot(proposal.xy, proposal.xy))));
30
- if (hv) { light = aM(u); }
30
+ if (hP) { light = aM(u); }
31
31
  if ((i & 1u) != 0u) {
32
- float kf = (1.0 - u.y) * jN;
33
- float dr = sqrt(max(0.0, (kf + (1.0 - qG)) * (u.y * jN)));
34
- vec3 aa = normalize(vec3(alpha, 1.0) * vec3(ce.xy + dr * proposal.zw, kf));
35
- if (hv) { aa = aA(view, alpha, u); }
32
+ float kM = (1.0 - u.y) * ku;
33
+ float dw = sqrt(max(0.0, (kM + (1.0 - rU)) * (u.y * ku)));
34
+ vec3 aa = normalize(vec3(alpha, 1.0) * vec3(cf.xy + dw * proposal.zw, kM));
35
+ if (hP) { aa = aA(view, alpha, u); }
36
36
  light = reflect(-view, aa);
37
37
  }
38
38
 
39
39
  if (light.z <= 0.0) { continue; }
40
40
  vec3 aa = normalize(view + light);
41
- float specularPdf = lN * sampling_ggx_ndf(aa, alpha) / (4.0 * view.z);
41
+ float specularPdf = mG * sampling_ggx_ndf(aa, alpha) / (4.0 * view.z);
42
42
  float pdf = 0.5 * (light.z * INVPI + specularPdf);
43
43
 
44
44
 
45
45
  vec3 au = openpbr_to_local(prepared.basis, openpbr_to_world(prepared.basis, light));
46
46
  if (au.z <= 0.0) { continue; }
47
47
  float scale = abs(au.z) / (pdf * float(count));
48
- if (qH && iR > 0.0) {
48
+ if (rV && jw > 0.0) {
49
49
  float compensation = prepared.diffuseSpecularEnergyCompensation * ar(
50
50
  prepared.specularEtaTOverEtaI, prepared.specularAlpha, abs(au.z));
51
51
  float unusedPdf = 0.0;
52
- diffuse += iR * bw(material, prepared.diffuseColor,
52
+ diffuse += jw * bB(material, prepared.diffuseColor,
53
53
  view, au, compensation, unusedPdf) * scale;
54
54
  }
55
- if (kE) {
55
+ if (lp) {
56
56
  vec3 evaluatedHalf = normalize(view + au);
57
57
  float viewHalf = abs(dot(view, evaluatedHalf));
58
58
  vec3 fresnel = vec3(0.0);
@@ -61,22 +61,22 @@ vec3 dielectric = vec3(ae(viewHalf, material.relativeIor));
61
61
  if (material.thinWalled) { dielectric = aq(dielectric, material.transmissionWeight); }
62
62
  fresnel += specularWeight * material.specularColor * dielectric;
63
63
  }
64
- if (fN > 0.0) {
65
- fresnel += fN * material.specularWeight * openpbr_metal_fresnel(viewHalf,
64
+ if (fZ > 0.0) {
65
+ fresnel += fZ * material.specularWeight * openpbr_metal_fresnel(viewHalf,
66
66
  material.baseWeight * material.baseColor, material.specularColor);
67
67
  }
68
- float rE = sampling_ggx_ndf(evaluatedHalf, alpha) * lN
68
+ float sT = sampling_ggx_ndf(evaluatedHalf, alpha) * mG
69
69
  * aD(au, alpha) / (4.0 * max(au.z * view.z, 1e-8));
70
- vec3 reflection = fresnel * rE;
71
- if (fN > 0.0 && prepared.metalMsFactor > 0.0) {
72
- float cv = min(prepared.metalMsFactor * aR(prepared.specularAlpha, au.z), 1.0 / max(au.z, 1e-8));
73
- reflection += fN * prepared.metalMsScale * cv * INVPI;
70
+ vec3 reflection = fresnel * sT;
71
+ if (fZ > 0.0 && prepared.metalMsFactor > 0.0) {
72
+ float cA = min(prepared.metalMsFactor * aR(prepared.specularAlpha, au.z), 1.0 / max(au.z, 1e-8));
73
+ reflection += fZ * prepared.metalMsScale * cA * INVPI;
74
74
  }
75
75
  if (prepared.dielectricMsProbability > 0.0) {
76
- float oP = prepared.dielectricMsViewLoss * aV(
77
- prepared.refractionEtaTOverEtaI, prepared.specularAlpha, abs(au.z)) / dS;
78
- float cv = min(oP * prepared.dielectricMsReflectionRatio, 1.0 / abs(au.z));
79
- reflection += prepared.dielectricMsReflectionScale * cv * INVPI;
76
+ float pX = prepared.dielectricMsViewLoss * aV(
77
+ prepared.refractionEtaTOverEtaI, prepared.specularAlpha, abs(au.z)) / dY;
78
+ float cA = min(pX * prepared.dielectricMsReflectionRatio, 1.0 / abs(au.z));
79
+ reflection += prepared.dielectricMsReflectionScale * cA * INVPI;
80
80
  }
81
81
  specular += reflection * scale;
82
82
  }
@@ -1,7 +1,7 @@
1
1
  // Generated by scripts/generate-aov-reflectance-samples.mjs; do not edit.
2
2
  // xy: concentric cosine disk; zw: spherical-cap azimuth cosine/sine.
3
3
  export default /* glsl */ `
4
- const vec4 gV[128] = vec4[128](
4
+ const vec4 ht[128] = vec4[128](
5
5
  vec4(-0.971247852, -0.202764958, 0.999698818, 0.0245412290),
6
6
  vec4(-0.808660269, 0.547487736, 0.997290432, 0.0735645667),
7
7
  vec4(-0.942509234, 0.187289074, 0.992479563, 0.122410677),