@ifc-lite/renderer 3.2.0 → 5.0.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 (399) hide show
  1. package/dist/aabb-edges.d.ts +10 -0
  2. package/dist/aabb-edges.d.ts.map +1 -1
  3. package/dist/aabb-edges.js +13 -0
  4. package/dist/aabb-edges.js.map +1 -1
  5. package/dist/ao-params.d.ts +85 -0
  6. package/dist/ao-params.d.ts.map +1 -0
  7. package/dist/ao-params.js +109 -0
  8. package/dist/ao-params.js.map +1 -0
  9. package/dist/ao-pass.d.ts +47 -0
  10. package/dist/ao-pass.d.ts.map +1 -0
  11. package/dist/ao-pass.js +157 -0
  12. package/dist/ao-pass.js.map +1 -0
  13. package/dist/camera-matrices.d.ts +3 -0
  14. package/dist/camera-matrices.d.ts.map +1 -1
  15. package/dist/camera-matrices.js +12 -1
  16. package/dist/camera-matrices.js.map +1 -1
  17. package/dist/camera-orientation.d.ts +62 -0
  18. package/dist/camera-orientation.d.ts.map +1 -0
  19. package/dist/camera-orientation.js +155 -0
  20. package/dist/camera-orientation.js.map +1 -0
  21. package/dist/camera-projection.d.ts +3 -1
  22. package/dist/camera-projection.d.ts.map +1 -1
  23. package/dist/camera-projection.js +26 -20
  24. package/dist/camera-projection.js.map +1 -1
  25. package/dist/camera-surface-zoom.d.ts +32 -0
  26. package/dist/camera-surface-zoom.d.ts.map +1 -0
  27. package/dist/camera-surface-zoom.js +37 -0
  28. package/dist/camera-surface-zoom.js.map +1 -0
  29. package/dist/camera.d.ts +32 -61
  30. package/dist/camera.d.ts.map +1 -1
  31. package/dist/camera.js +71 -167
  32. package/dist/camera.js.map +1 -1
  33. package/dist/clash-solid-pipeline.d.ts +9 -3
  34. package/dist/clash-solid-pipeline.d.ts.map +1 -1
  35. package/dist/clash-solid-pipeline.js +31 -8
  36. package/dist/clash-solid-pipeline.js.map +1 -1
  37. package/dist/constants.d.ts +1 -1
  38. package/dist/constants.d.ts.map +1 -1
  39. package/dist/constants.js +4 -3
  40. package/dist/constants.js.map +1 -1
  41. package/dist/depth-reconstruct.d.ts +43 -0
  42. package/dist/depth-reconstruct.d.ts.map +1 -0
  43. package/dist/depth-reconstruct.js +35 -0
  44. package/dist/depth-reconstruct.js.map +1 -0
  45. package/dist/device.js +1 -1
  46. package/dist/device.js.map +1 -1
  47. package/dist/edge-params.d.ts +43 -0
  48. package/dist/edge-params.d.ts.map +1 -0
  49. package/dist/edge-params.js +63 -0
  50. package/dist/edge-params.js.map +1 -0
  51. package/dist/edge-pass.d.ts +38 -0
  52. package/dist/edge-pass.d.ts.map +1 -0
  53. package/dist/edge-pass.js +111 -0
  54. package/dist/edge-pass.js.map +1 -0
  55. package/dist/environment.d.ts +26 -15
  56. package/dist/environment.d.ts.map +1 -1
  57. package/dist/environment.js +24 -13
  58. package/dist/environment.js.map +1 -1
  59. package/dist/federation-registry.d.ts +16 -0
  60. package/dist/federation-registry.d.ts.map +1 -1
  61. package/dist/federation-registry.js +80 -9
  62. package/dist/federation-registry.js.map +1 -1
  63. package/dist/gpu-static-upload.d.ts +39 -0
  64. package/dist/gpu-static-upload.d.ts.map +1 -0
  65. package/dist/gpu-static-upload.js +70 -0
  66. package/dist/gpu-static-upload.js.map +1 -0
  67. package/dist/gpu-upload-guard.d.ts +12 -23
  68. package/dist/gpu-upload-guard.d.ts.map +1 -1
  69. package/dist/gpu-upload-guard.js +12 -26
  70. package/dist/gpu-upload-guard.js.map +1 -1
  71. package/dist/index.d.ts +58 -35
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js +255 -284
  74. package/dist/index.js.map +1 -1
  75. package/dist/instanced-render.d.ts +25 -5
  76. package/dist/instanced-render.d.ts.map +1 -1
  77. package/dist/instanced-render.js +50 -13
  78. package/dist/instanced-render.js.map +1 -1
  79. package/dist/instanced-rte.d.ts +17 -0
  80. package/dist/instanced-rte.d.ts.map +1 -0
  81. package/dist/instanced-rte.js +32 -0
  82. package/dist/instanced-rte.js.map +1 -0
  83. package/dist/mesh-material.d.ts +26 -0
  84. package/dist/mesh-material.d.ts.map +1 -0
  85. package/dist/mesh-material.js +52 -0
  86. package/dist/mesh-material.js.map +1 -0
  87. package/dist/mesh-rte-uniforms.d.ts +47 -0
  88. package/dist/mesh-rte-uniforms.d.ts.map +1 -0
  89. package/dist/mesh-rte-uniforms.js +60 -0
  90. package/dist/mesh-rte-uniforms.js.map +1 -0
  91. package/dist/model-bounds-tracker.d.ts +7 -0
  92. package/dist/model-bounds-tracker.d.ts.map +1 -1
  93. package/dist/model-bounds-tracker.js +16 -5
  94. package/dist/model-bounds-tracker.js.map +1 -1
  95. package/dist/model-translation.d.ts +1 -1
  96. package/dist/model-translation.d.ts.map +1 -1
  97. package/dist/model-translation.js +50 -2
  98. package/dist/model-translation.js.map +1 -1
  99. package/dist/overlay-theme-uniforms.d.ts +54 -0
  100. package/dist/overlay-theme-uniforms.d.ts.map +1 -0
  101. package/dist/overlay-theme-uniforms.js +89 -0
  102. package/dist/overlay-theme-uniforms.js.map +1 -0
  103. package/dist/overlay-theme.d.ts +73 -0
  104. package/dist/overlay-theme.d.ts.map +1 -0
  105. package/dist/overlay-theme.js +24 -0
  106. package/dist/overlay-theme.js.map +1 -0
  107. package/dist/pick-rte-snapshot.d.ts +7 -0
  108. package/dist/pick-rte-snapshot.d.ts.map +1 -0
  109. package/dist/pick-rte-snapshot.js +15 -0
  110. package/dist/pick-rte-snapshot.js.map +1 -0
  111. package/dist/pick-types.d.ts +17 -0
  112. package/dist/pick-types.d.ts.map +1 -0
  113. package/dist/pick-types.js +5 -0
  114. package/dist/pick-types.js.map +1 -0
  115. package/dist/pick-uniforms.d.ts +6 -0
  116. package/dist/pick-uniforms.d.ts.map +1 -1
  117. package/dist/pick-uniforms.js +22 -18
  118. package/dist/pick-uniforms.js.map +1 -1
  119. package/dist/pick-world-position.d.ts +18 -0
  120. package/dist/pick-world-position.d.ts.map +1 -0
  121. package/dist/pick-world-position.js +21 -0
  122. package/dist/pick-world-position.js.map +1 -0
  123. package/dist/picker-readbacks.d.ts +6 -0
  124. package/dist/picker-readbacks.d.ts.map +1 -0
  125. package/dist/picker-readbacks.js +20 -0
  126. package/dist/picker-readbacks.js.map +1 -0
  127. package/dist/picker-rte-uniforms.d.ts +6 -0
  128. package/dist/picker-rte-uniforms.d.ts.map +1 -0
  129. package/dist/picker-rte-uniforms.js +41 -0
  130. package/dist/picker-rte-uniforms.js.map +1 -0
  131. package/dist/picker.d.ts +6 -7
  132. package/dist/picker.d.ts.map +1 -1
  133. package/dist/picker.js +88 -115
  134. package/dist/picker.js.map +1 -1
  135. package/dist/picking-manager.d.ts +8 -0
  136. package/dist/picking-manager.d.ts.map +1 -1
  137. package/dist/picking-manager.js +46 -19
  138. package/dist/picking-manager.js.map +1 -1
  139. package/dist/pipeline.d.ts +3 -7
  140. package/dist/pipeline.d.ts.map +1 -1
  141. package/dist/pipeline.js +27 -31
  142. package/dist/pipeline.js.map +1 -1
  143. package/dist/point-picker.d.ts +5 -1
  144. package/dist/point-picker.d.ts.map +1 -1
  145. package/dist/point-picker.js +49 -9
  146. package/dist/point-picker.js.map +1 -1
  147. package/dist/pointcloud/point-cloud-handle-ids.d.ts +22 -0
  148. package/dist/pointcloud/point-cloud-handle-ids.d.ts.map +1 -0
  149. package/dist/pointcloud/point-cloud-handle-ids.js +31 -0
  150. package/dist/pointcloud/point-cloud-handle-ids.js.map +1 -0
  151. package/dist/pointcloud/point-cloud-node.d.ts +14 -6
  152. package/dist/pointcloud/point-cloud-node.d.ts.map +1 -1
  153. package/dist/pointcloud/point-cloud-node.js.map +1 -1
  154. package/dist/pointcloud/point-cloud-pick-sources.d.ts +47 -0
  155. package/dist/pointcloud/point-cloud-pick-sources.d.ts.map +1 -0
  156. package/dist/pointcloud/point-cloud-pick-sources.js +32 -0
  157. package/dist/pointcloud/point-cloud-pick-sources.js.map +1 -0
  158. package/dist/pointcloud/point-cloud-placement.d.ts.map +1 -1
  159. package/dist/pointcloud/point-cloud-placement.js +20 -5
  160. package/dist/pointcloud/point-cloud-placement.js.map +1 -1
  161. package/dist/pointcloud/point-cloud-ray-transform.d.ts +78 -4
  162. package/dist/pointcloud/point-cloud-ray-transform.d.ts.map +1 -1
  163. package/dist/pointcloud/point-cloud-ray-transform.js +31 -84
  164. package/dist/pointcloud/point-cloud-ray-transform.js.map +1 -1
  165. package/dist/pointcloud/point-cloud-renderer.d.ts +21 -19
  166. package/dist/pointcloud/point-cloud-renderer.d.ts.map +1 -1
  167. package/dist/pointcloud/point-cloud-renderer.js +46 -52
  168. package/dist/pointcloud/point-cloud-renderer.js.map +1 -1
  169. package/dist/pointcloud/point-cloud-stream-lifecycle.d.ts +44 -0
  170. package/dist/pointcloud/point-cloud-stream-lifecycle.d.ts.map +1 -0
  171. package/dist/pointcloud/point-cloud-stream-lifecycle.js +44 -0
  172. package/dist/pointcloud/point-cloud-stream-lifecycle.js.map +1 -0
  173. package/dist/pointcloud/point-cloud-uniforms.d.ts +5 -0
  174. package/dist/pointcloud/point-cloud-uniforms.d.ts.map +1 -1
  175. package/dist/pointcloud/point-cloud-uniforms.js +55 -44
  176. package/dist/pointcloud/point-cloud-uniforms.js.map +1 -1
  177. package/dist/pointcloud/point-cloud-visibility.d.ts +10 -0
  178. package/dist/pointcloud/point-cloud-visibility.d.ts.map +1 -0
  179. package/dist/pointcloud/point-cloud-visibility.js +18 -0
  180. package/dist/pointcloud/point-cloud-visibility.js.map +1 -0
  181. package/dist/pointcloud/point-pipeline.d.ts +4 -9
  182. package/dist/pointcloud/point-pipeline.d.ts.map +1 -1
  183. package/dist/pointcloud/point-pipeline.js +4 -9
  184. package/dist/pointcloud/point-pipeline.js.map +1 -1
  185. package/dist/pointcloud/point-shader.wgsl.d.ts +1 -21
  186. package/dist/pointcloud/point-shader.wgsl.d.ts.map +1 -1
  187. package/dist/pointcloud/point-shader.wgsl.js +25 -5
  188. package/dist/pointcloud/point-shader.wgsl.js.map +1 -1
  189. package/dist/post-pass-chain.d.ts +38 -0
  190. package/dist/post-pass-chain.d.ts.map +1 -0
  191. package/dist/post-pass-chain.js +105 -0
  192. package/dist/post-pass-chain.js.map +1 -0
  193. package/dist/raycast-engine.d.ts +7 -5
  194. package/dist/raycast-engine.d.ts.map +1 -1
  195. package/dist/raycast-engine.js +17 -20
  196. package/dist/raycast-engine.js.map +1 -1
  197. package/dist/raycast-point-cloud-query.d.ts +1 -1
  198. package/dist/raycast-point-cloud-query.d.ts.map +1 -1
  199. package/dist/reference-image-pipeline.d.ts +1 -1
  200. package/dist/reference-image-pipeline.d.ts.map +1 -1
  201. package/dist/reference-image-pipeline.js +25 -7
  202. package/dist/reference-image-pipeline.js.map +1 -1
  203. package/dist/reference-images.d.ts +1 -1
  204. package/dist/reference-images.d.ts.map +1 -1
  205. package/dist/reference-images.js +13 -5
  206. package/dist/reference-images.js.map +1 -1
  207. package/dist/relative-to-eye.d.ts +146 -0
  208. package/dist/relative-to-eye.d.ts.map +1 -0
  209. package/dist/relative-to-eye.js +326 -0
  210. package/dist/relative-to-eye.js.map +1 -0
  211. package/dist/render-section-draw.d.ts +11 -0
  212. package/dist/render-section-draw.d.ts.map +1 -1
  213. package/dist/render-section-draw.js +6 -3
  214. package/dist/render-section-draw.js.map +1 -1
  215. package/dist/renderer-color-readback.d.ts +50 -0
  216. package/dist/renderer-color-readback.d.ts.map +1 -0
  217. package/dist/renderer-color-readback.js +145 -0
  218. package/dist/renderer-color-readback.js.map +1 -0
  219. package/dist/renderer-overlays.d.ts +20 -10
  220. package/dist/renderer-overlays.d.ts.map +1 -1
  221. package/dist/renderer-overlays.js +44 -34
  222. package/dist/renderer-overlays.js.map +1 -1
  223. package/dist/renderer-screenshot.d.ts +4 -0
  224. package/dist/renderer-screenshot.d.ts.map +1 -0
  225. package/dist/renderer-screenshot.js +17 -0
  226. package/dist/renderer-screenshot.js.map +1 -0
  227. package/dist/renderer-symbolic-overlays.d.ts +4 -2
  228. package/dist/renderer-symbolic-overlays.d.ts.map +1 -1
  229. package/dist/renderer-symbolic-overlays.js +33 -13
  230. package/dist/renderer-symbolic-overlays.js.map +1 -1
  231. package/dist/renderer-viewport.d.ts +45 -0
  232. package/dist/renderer-viewport.d.ts.map +1 -1
  233. package/dist/renderer-viewport.js +44 -0
  234. package/dist/renderer-viewport.js.map +1 -1
  235. package/dist/rte-clip-space.d.ts +12 -0
  236. package/dist/rte-clip-space.d.ts.map +1 -0
  237. package/dist/rte-clip-space.js +22 -0
  238. package/dist/rte-clip-space.js.map +1 -0
  239. package/dist/rte-frustum.d.ts +24 -0
  240. package/dist/rte-frustum.d.ts.map +1 -0
  241. package/dist/rte-frustum.js +45 -0
  242. package/dist/rte-frustum.js.map +1 -0
  243. package/dist/scene-batch-upload.d.ts.map +1 -1
  244. package/dist/scene-batch-upload.js +14 -38
  245. package/dist/scene-batch-upload.js.map +1 -1
  246. package/dist/scene-device-recovery.d.ts.map +1 -1
  247. package/dist/scene-device-recovery.js +5 -9
  248. package/dist/scene-device-recovery.js.map +1 -1
  249. package/dist/scene-finalize-regroup.d.ts +54 -0
  250. package/dist/scene-finalize-regroup.d.ts.map +1 -0
  251. package/dist/scene-finalize-regroup.js +136 -0
  252. package/dist/scene-finalize-regroup.js.map +1 -0
  253. package/dist/scene-instance-bounds.d.ts +12 -0
  254. package/dist/scene-instance-bounds.d.ts.map +1 -0
  255. package/dist/scene-instance-bounds.js +48 -0
  256. package/dist/scene-instance-bounds.js.map +1 -0
  257. package/dist/scene-instance-materialization.d.ts +4 -1
  258. package/dist/scene-instance-materialization.d.ts.map +1 -1
  259. package/dist/scene-instance-materialization.js +21 -6
  260. package/dist/scene-instance-materialization.js.map +1 -1
  261. package/dist/scene-instance-translation.d.ts +17 -0
  262. package/dist/scene-instance-translation.d.ts.map +1 -0
  263. package/dist/scene-instance-translation.js +50 -0
  264. package/dist/scene-instance-translation.js.map +1 -0
  265. package/dist/scene-instance-types.d.ts +6 -0
  266. package/dist/scene-instance-types.d.ts.map +1 -1
  267. package/dist/scene-model-translation.d.ts +2 -0
  268. package/dist/scene-model-translation.d.ts.map +1 -1
  269. package/dist/scene-model-translation.js +1 -1
  270. package/dist/scene-model-translation.js.map +1 -1
  271. package/dist/scene-rect-select.d.ts +11 -1
  272. package/dist/scene-rect-select.d.ts.map +1 -1
  273. package/dist/scene-rect-select.js +7 -4
  274. package/dist/scene-rect-select.js.map +1 -1
  275. package/dist/scene.d.ts +27 -20
  276. package/dist/scene.d.ts.map +1 -1
  277. package/dist/scene.js +109 -238
  278. package/dist/scene.js.map +1 -1
  279. package/dist/section-2d-lift.d.ts +10 -2
  280. package/dist/section-2d-lift.d.ts.map +1 -1
  281. package/dist/section-2d-lift.js +14 -6
  282. package/dist/section-2d-lift.js.map +1 -1
  283. package/dist/section-2d-line-buffer.d.ts +12 -4
  284. package/dist/section-2d-line-buffer.d.ts.map +1 -1
  285. package/dist/section-2d-line-buffer.js +59 -33
  286. package/dist/section-2d-line-buffer.js.map +1 -1
  287. package/dist/section-2d-overlay.d.ts +18 -72
  288. package/dist/section-2d-overlay.d.ts.map +1 -1
  289. package/dist/section-2d-overlay.js +72 -103
  290. package/dist/section-2d-overlay.js.map +1 -1
  291. package/dist/section-2d-types.d.ts +38 -0
  292. package/dist/section-2d-types.d.ts.map +1 -0
  293. package/dist/section-2d-types.js +6 -0
  294. package/dist/section-2d-types.js.map +1 -0
  295. package/dist/section-cap-pipelines.d.ts +6 -0
  296. package/dist/section-cap-pipelines.d.ts.map +1 -0
  297. package/dist/section-cap-pipelines.js +87 -0
  298. package/dist/section-cap-pipelines.js.map +1 -0
  299. package/dist/section-plane-geometry.d.ts +24 -0
  300. package/dist/section-plane-geometry.d.ts.map +1 -0
  301. package/dist/section-plane-geometry.js +93 -0
  302. package/dist/section-plane-geometry.js.map +1 -0
  303. package/dist/section-plane.d.ts +26 -24
  304. package/dist/section-plane.d.ts.map +1 -1
  305. package/dist/section-plane.js +57 -182
  306. package/dist/section-plane.js.map +1 -1
  307. package/dist/shaders/ao.wgsl.d.ts +2 -0
  308. package/dist/shaders/ao.wgsl.d.ts.map +1 -0
  309. package/dist/shaders/ao.wgsl.js +234 -0
  310. package/dist/shaders/ao.wgsl.js.map +1 -0
  311. package/dist/shaders/color-transfer.wgsl.d.ts +28 -0
  312. package/dist/shaders/color-transfer.wgsl.d.ts.map +1 -0
  313. package/dist/shaders/color-transfer.wgsl.js +55 -0
  314. package/dist/shaders/color-transfer.wgsl.js.map +1 -0
  315. package/dist/shaders/depth-reconstruct.wgsl.d.ts +16 -0
  316. package/dist/shaders/depth-reconstruct.wgsl.d.ts.map +1 -0
  317. package/dist/shaders/depth-reconstruct.wgsl.js +69 -0
  318. package/dist/shaders/depth-reconstruct.wgsl.js.map +1 -0
  319. package/dist/shaders/edges.wgsl.d.ts +2 -0
  320. package/dist/shaders/edges.wgsl.d.ts.map +1 -0
  321. package/dist/shaders/edges.wgsl.js +158 -0
  322. package/dist/shaders/edges.wgsl.js.map +1 -0
  323. package/dist/shaders/main-rte-shadow.wgsl.d.ts +4 -0
  324. package/dist/shaders/main-rte-shadow.wgsl.d.ts.map +1 -0
  325. package/dist/shaders/main-rte-shadow.wgsl.js +54 -0
  326. package/dist/shaders/main-rte-shadow.wgsl.js.map +1 -0
  327. package/dist/shaders/main.wgsl.d.ts +1 -6
  328. package/dist/shaders/main.wgsl.d.ts.map +1 -1
  329. package/dist/shaders/main.wgsl.js +183 -228
  330. package/dist/shaders/main.wgsl.js.map +1 -1
  331. package/dist/shaders/relative-to-eye.wgsl.d.ts +12 -0
  332. package/dist/shaders/relative-to-eye.wgsl.d.ts.map +1 -0
  333. package/dist/shaders/relative-to-eye.wgsl.js +40 -0
  334. package/dist/shaders/relative-to-eye.wgsl.js.map +1 -0
  335. package/dist/shaders/section-2d-overlay.wgsl.d.ts +28 -12
  336. package/dist/shaders/section-2d-overlay.wgsl.d.ts.map +1 -1
  337. package/dist/shaders/section-2d-overlay.wgsl.js +40 -13
  338. package/dist/shaders/section-2d-overlay.wgsl.js.map +1 -1
  339. package/dist/shaders/shadow.wgsl.d.ts +1 -1
  340. package/dist/shaders/shadow.wgsl.d.ts.map +1 -1
  341. package/dist/shaders/shadow.wgsl.js +25 -7
  342. package/dist/shaders/shadow.wgsl.js.map +1 -1
  343. package/dist/shaders/sky.wgsl.d.ts +1 -11
  344. package/dist/shaders/sky.wgsl.d.ts.map +1 -1
  345. package/dist/shaders/sky.wgsl.js +17 -19
  346. package/dist/shaders/sky.wgsl.js.map +1 -1
  347. package/dist/shaders/specular.wgsl.d.ts +34 -0
  348. package/dist/shaders/specular.wgsl.d.ts.map +1 -0
  349. package/dist/shaders/specular.wgsl.js +134 -0
  350. package/dist/shaders/specular.wgsl.js.map +1 -0
  351. package/dist/shaders/symbolic-overlay.wgsl.d.ts +2 -9
  352. package/dist/shaders/symbolic-overlay.wgsl.d.ts.map +1 -1
  353. package/dist/shaders/symbolic-overlay.wgsl.js +88 -17
  354. package/dist/shaders/symbolic-overlay.wgsl.js.map +1 -1
  355. package/dist/shaders/textured.wgsl.d.ts.map +1 -1
  356. package/dist/shaders/textured.wgsl.js +11 -9
  357. package/dist/shaders/textured.wgsl.js.map +1 -1
  358. package/dist/shadow-light-matrix.d.ts +7 -0
  359. package/dist/shadow-light-matrix.d.ts.map +1 -1
  360. package/dist/shadow-light-matrix.js +11 -0
  361. package/dist/shadow-light-matrix.js.map +1 -1
  362. package/dist/shadow-occluder-batches.d.ts +10 -0
  363. package/dist/shadow-occluder-batches.d.ts.map +1 -0
  364. package/dist/shadow-occluder-batches.js +39 -0
  365. package/dist/shadow-occluder-batches.js.map +1 -0
  366. package/dist/shadow-occluders.d.ts.map +1 -1
  367. package/dist/shadow-occluders.js +4 -0
  368. package/dist/shadow-occluders.js.map +1 -1
  369. package/dist/shadow-pass.d.ts +5 -51
  370. package/dist/shadow-pass.d.ts.map +1 -1
  371. package/dist/shadow-pass.js +49 -45
  372. package/dist/shadow-pass.js.map +1 -1
  373. package/dist/shadow-types.d.ts +39 -0
  374. package/dist/shadow-types.d.ts.map +1 -0
  375. package/dist/shadow-types.js +15 -0
  376. package/dist/shadow-types.js.map +1 -0
  377. package/dist/symbolic-overlay-geometry.d.ts +7 -0
  378. package/dist/symbolic-overlay-geometry.d.ts.map +1 -0
  379. package/dist/symbolic-overlay-geometry.js +43 -0
  380. package/dist/symbolic-overlay-geometry.js.map +1 -0
  381. package/dist/symbolic-overlay-pipelines.d.ts +24 -36
  382. package/dist/symbolic-overlay-pipelines.d.ts.map +1 -1
  383. package/dist/symbolic-overlay-pipelines.js +175 -182
  384. package/dist/symbolic-overlay-pipelines.js.map +1 -1
  385. package/dist/symbolic-text-atlas.d.ts +21 -0
  386. package/dist/symbolic-text-atlas.d.ts.map +1 -1
  387. package/dist/symbolic-text-atlas.js +29 -1
  388. package/dist/symbolic-text-atlas.js.map +1 -1
  389. package/dist/types.d.ts +20 -26
  390. package/dist/types.d.ts.map +1 -1
  391. package/dist/visual-enhancement.d.ts +30 -1
  392. package/dist/visual-enhancement.d.ts.map +1 -1
  393. package/dist/visual-enhancement.js +44 -12
  394. package/dist/visual-enhancement.js.map +1 -1
  395. package/package.json +3 -3
  396. package/dist/post-processor.d.ts +0 -60
  397. package/dist/post-processor.d.ts.map +0 -1
  398. package/dist/post-processor.js +0 -353
  399. package/dist/post-processor.js.map +0 -1
@@ -0,0 +1,40 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * Shared WGSL half of the renderer RTE contract.
6
+ *
7
+ * A pass owns its binding declarations, but imports this verbatim into its
8
+ * shader source and uses `rteWorldPosition` before projection. The layouts
9
+ * match `RelativeToEyeFrame.packUniforms` and `packRteOrigin` exactly: a
10
+ * translation-free `viewProj` per frame, then two vec4 drawable-camera delta
11
+ * lanes per draw. Origins are world/source f64 values on the CPU; `local` is
12
+ * the element-local f32 vertex already resident in a vertex buffer.
13
+ */
14
+ export const relativeToEyeWgsl = `
15
+ struct RteFrameUniform {
16
+ // Camera translation is intentionally absent. This projects positions
17
+ // returned by rteWorldPosition, which are already relative to the eye.
18
+ viewProj: mat4x4<f32>,
19
+ }
20
+
21
+ struct RteDrawableUniform {
22
+ // CPU computes (drawable origin - camera origin) in f64 and splits it.
23
+ // This data must be refreshed whenever the RTE camera frame changes.
24
+ drawableDeltaHigh: vec4<f32>,
25
+ drawableDeltaLow: vec4<f32>,
26
+ }
27
+
28
+ fn rteWorldPosition(
29
+ local: vec3<f32>,
30
+ drawable: RteDrawableUniform,
31
+ ) -> vec4<f32> {
32
+ // Do not subtract a camera origin here: this delta was formed in CPU f64.
33
+ let highDelta = drawable.drawableDeltaHigh.xyz;
34
+ let lowDelta = drawable.drawableDeltaLow.xyz;
35
+ // A drawable template can span kilometres. Keep local with high first;
36
+ // The local-plus-(high-plus-low) association is not equivalent in f32.
37
+ return vec4<f32>((local + highDelta) + lowDelta, 1.0);
38
+ }
39
+ `;
40
+ //# sourceMappingURL=relative-to-eye.wgsl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relative-to-eye.wgsl.js","sourceRoot":"","sources":["../../src/shaders/relative-to-eye.wgsl.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;CAyBhC,CAAC"}
@@ -36,20 +36,25 @@ export declare const SECTION_2D_UNIFORM_SLOTS: {
36
36
  readonly params2: 32;
37
37
  /** vec4<f32> overlay / section-cut line colour — floats 36..39 (bytes 144..159) */
38
38
  readonly lineColor: 36;
39
+ /** mat4 camera-relative projection for opt-in anchored overlays. */
40
+ readonly rteViewProj: 40;
41
+ /** split f64-like (origin - eye) delta; w = 1 enables RTE. */
42
+ readonly originDeltaHigh: 56;
43
+ readonly originDeltaLow: 60;
39
44
  };
40
45
  /** Total float count of one uniform record (40 floats = 160 bytes). */
41
- export declare const SECTION_2D_UNIFORM_FLOATS = 40;
46
+ export declare const SECTION_2D_UNIFORM_FLOATS = 64;
42
47
  /** Total byte size of one uniform record. */
43
48
  export declare const SECTION_2D_UNIFORM_BYTES: number;
44
49
  /**
45
50
  * One uniform slot per draw site.
46
51
  *
47
- * The overlay renderer issues up to six draws into a **single** render pass —
48
- * the section cut cap plus five world-space line families — and every one of
52
+ * The overlay renderer issues up to seven draw sites into a **single** render pass —
53
+ * the section cut cap plus six world-space line families — and every one of
49
54
  * them needs a different `lineColor` (and, for the cap, a different
50
55
  * `planeOffset` and the whole cap-style tail). With one record shared between
51
56
  * them the last `queue.writeBuffer` before submit is what the GPU sees for all
52
- * six: `writeBuffer` is a *queue* operation, so it is applied before the
57
+ * seven: `writeBuffer` is a *queue* operation, so it is applied before the
53
58
  * command buffer that references it executes, no matter where in the encoding
54
59
  * it was issued. Every earlier draw therefore rendered with the last draw's
55
60
  * uniforms — most visibly, the clash box's colour bleeding onto the annotation,
@@ -57,21 +62,32 @@ export declare const SECTION_2D_UNIFORM_BYTES: number;
57
62
  * hatch to the zeroed tail the line draws write.
58
63
  *
59
64
  * Each site owning a fixed slot, addressed with a dynamic bind-group offset,
60
- * is what makes the six draws independent while keeping the buffer, the layout
65
+ * is what makes the seven draw sites independent while keeping the buffer, the layout
61
66
  * and the bind group under the single owner issue #2456 insisted on. A slot per
62
67
  * site (rather than a bump allocator) needs no per-frame reset hook: each site
63
68
  * draws at most once per pass.
64
69
  */
70
+ /**
71
+ * Max independently-anchored line partitions per channel in one pass.
72
+ *
73
+ * Spatial batching normally keeps this close to one. The explicit 256-record
74
+ * ceiling still bounds the shared dynamic-uniform allocation (384 KiB at the
75
+ * WebGPU-guaranteed 256-byte stride) while accepting genuinely disjoint survey
76
+ * features instead of making the old 32-record implementation throw midway
77
+ * through a render submission.
78
+ */
79
+ export declare const SECTION_2D_MAX_LINE_PARTITIONS = 256;
65
80
  export declare const SECTION_2D_UNIFORM_SLOT_INDEX: {
66
81
  /** The section cut cap: fill + outline, which share one record by design. */
67
82
  readonly sectionCut: 0;
68
83
  readonly annotation: 1;
69
- readonly alignment: 2;
70
- readonly grid: 3;
71
- readonly dxf: 4;
72
- readonly clashBox: 5;
84
+ readonly alignment: number;
85
+ readonly grid: number;
86
+ readonly dxf: number;
87
+ readonly terrain: number;
88
+ readonly clashBox: number;
73
89
  };
74
- /** How many uniform records the shared buffer holds — one per entry above. */
90
+ /** One cap record plus a partition range for every line family. */
75
91
  export declare const SECTION_2D_UNIFORM_SLOT_COUNT: number;
76
92
  /**
77
93
  * Byte stride between uniform slots for `device`.
@@ -93,10 +109,10 @@ export declare function sectionUniformSlotStride(device: GPUDevice): number;
93
109
  * cap style, so single-material cuts read as one architectural section exactly
94
110
  * as before. Hatch + stroke apply over either base.
95
111
  */
96
- export declare const SECTION_2D_CAP_FILL_WGSL = "\n struct Uniforms {\n viewProj: mat4x4<f32>,\n planeOffset: vec4<f32>, // Small offset to render slightly in front of section plane\n capFillColor: vec4<f32>,\n capStrokeColor: vec4<f32>,\n // x=patternId, y=spacingPx, z=angleRad, w=widthPx\n params: vec4<f32>,\n // x=secondaryAngleRad, y,z,w reserved\n params2: vec4<f32>,\n }\n @binding(0) @group(0) var<uniform> uniforms: Uniforms;\n\n struct VertexInput {\n @location(0) position: vec3<f32>,\n @location(1) color: vec4<f32>,\n }\n\n struct VertexOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) color: vec4<f32>,\n }\n\n @vertex\n fn vs_main(input: VertexInput) -> VertexOutput {\n var output: VertexOutput;\n let offsetPos = input.position + uniforms.planeOffset.xyz;\n output.position = uniforms.viewProj * vec4<f32>(offsetPos, 1.0);\n output.color = input.color;\n return output;\n }\n\n // Screen-space hatch pattern helpers (ported from section-cap.wgsl).\n fn lineMask(u: f32, s: f32, w: f32) -> f32 {\n let f = fract(u / s) * s;\n let d = min(f, s - f);\n return 1.0 - smoothstep(w * 0.5, w * 0.5 + 1.0, d);\n }\n fn rotate(p: vec2<f32>, a: f32) -> vec2<f32> {\n let c = cos(a);\n let s = sin(a);\n return vec2<f32>(c * p.x - s * p.y, s * p.x + c * p.y);\n }\n fn hatchIntensity(fragCoord: vec2<f32>, patternId: u32, spacing: f32, angle: f32, width: f32, angle2: f32) -> f32 {\n let p = fragCoord;\n if (patternId == 0u) { return 0.0; } // solid\n if (patternId == 1u) { // diagonal\n let r = rotate(p, angle);\n return lineMask(r.x, spacing, width);\n }\n if (patternId == 2u) { // cross-hatch\n let r = rotate(p, angle);\n let r2 = rotate(p, angle2);\n return max(lineMask(r.x, spacing, width), lineMask(r2.x, spacing, width));\n }\n if (patternId == 3u) { return lineMask(p.y, spacing, width); } // horizontal\n if (patternId == 4u) { return lineMask(p.x, spacing, width); } // vertical\n if (patternId == 5u) {\n // Concrete (ISO 128-50): clean regular dot grid. The previous\n // version layered dashes on top which looked noisy and broken.\n // Dots sit at every grid intersection; radius scales with\n // stroke width so the user's width slider works consistently.\n let gx = p.x - round(p.x / spacing) * spacing;\n let gy = p.y - round(p.y / spacing) * spacing;\n let d = sqrt(gx * gx + gy * gy);\n let radius = max(1.0, width * 1.2);\n return 1.0 - smoothstep(radius, radius + 1.0, d);\n }\n if (patternId == 6u) { // brick\n let bandH = spacing;\n let band = floor(p.y / bandH);\n // Signed parity. p is @builtin(position) today, so it is a\n // framebuffer coordinate and never negative \u2014 but u32() of a\n // negative float is an out-of-range conversion in WGSL, and the\n // moment this hatch is fed anything but fragCoord (a world- or\n // drawing-space variant) the running bond would break across\n // y = 0 in a backend-dependent way. i32(-1) & 1 is 1, so the\n // parity alternates correctly in both directions.\n let offset = select(0.0, bandH, (i32(band) & 1) == 1);\n let horiz = lineMask(p.y, bandH, width);\n let vertPos = p.x + offset * 0.5;\n let vert = step(fract(vertPos / (bandH * 2.0)), 0.02);\n return max(horiz, vert);\n }\n if (patternId == 7u) { // insulation\n let y = spacing * 0.5 * sin(p.x * 6.2831853 / spacing) + p.y;\n return lineMask(y, spacing, width);\n }\n return 0.0;\n }\n\n struct FragOut {\n @location(0) color: vec4<f32>,\n @location(1) objectId: vec4<f32>,\n }\n\n @fragment\n fn fs_main(input: VertexOutput) -> FragOut {\n let patternId = u32(uniforms.params.x + 0.5);\n let spacing = max(2.0, uniforms.params.y);\n let angle = uniforms.params.z;\n let width = max(1.0, uniforms.params.w);\n let angle2 = uniforms.params2.x;\n\n let h = hatchIntensity(input.position.xy, patternId, spacing, angle, width, angle2);\n // Per-polygon colour (a material-layer slab fills with its own\n // IfcMaterial RGBA) overrides the uniform cap fill when present.\n // Polygons without a colour carry the sentinel alpha -1 and fall back\n // to the user's cap style, byte-identically. Hatch + stroke apply over\n // whichever base is chosen, so the architectural hatch still works.\n let useVertex = input.color.a >= 0.0;\n let baseFill = select(uniforms.capFillColor, input.color, useVertex);\n let rgb = mix(baseFill.rgb, uniforms.capStrokeColor.rgb, h * uniforms.capStrokeColor.a);\n let a = max(baseFill.a, h * uniforms.capStrokeColor.a);\n\n var out: FragOut;\n out.color = vec4<f32>(rgb, a);\n out.objectId = vec4<f32>(0.0, 0.0, 0.0, 0.0);\n return out;\n }\n ";
112
+ export declare const SECTION_2D_CAP_FILL_WGSL = "\n struct Uniforms {\n viewProj: mat4x4<f32>,\n planeOffset: vec4<f32>, // Small offset to render slightly in front of section plane\n capFillColor: vec4<f32>,\n capStrokeColor: vec4<f32>,\n // x=patternId, y=spacingPx, z=angleRad, w=widthPx\n params: vec4<f32>,\n // x=secondaryAngleRad, y,z,w reserved\n params2: vec4<f32>,\n lineColor: vec4<f32>,\n rteViewProj: mat4x4<f32>,\n originDeltaHigh: vec4<f32>,\n originDeltaLow: vec4<f32>,\n }\n @binding(0) @group(0) var<uniform> uniforms: Uniforms;\n\n struct VertexInput {\n @location(0) position: vec3<f32>,\n @location(1) color: vec4<f32>,\n }\n\n struct VertexOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) color: vec4<f32>,\n }\n\n @vertex\n fn vs_main(input: VertexInput) -> VertexOutput {\n var output: VertexOutput;\n let offsetPos = input.position + uniforms.planeOffset.xyz;\n let global = uniforms.viewProj * vec4<f32>(offsetPos, 1.0);\n let relative = (offsetPos + uniforms.originDeltaHigh.xyz) + uniforms.originDeltaLow.xyz;\n output.position = select(global, uniforms.rteViewProj * vec4<f32>(relative, 1.0), uniforms.originDeltaHigh.w == 1.0);\n output.color = input.color;\n return output;\n }\n\n // Screen-space hatch pattern helpers (ported from section-cap.wgsl).\n fn lineMask(u: f32, s: f32, w: f32) -> f32 {\n let f = fract(u / s) * s;\n let d = min(f, s - f);\n return 1.0 - smoothstep(w * 0.5, w * 0.5 + 1.0, d);\n }\n fn rotate(p: vec2<f32>, a: f32) -> vec2<f32> {\n let c = cos(a);\n let s = sin(a);\n return vec2<f32>(c * p.x - s * p.y, s * p.x + c * p.y);\n }\n fn hatchIntensity(fragCoord: vec2<f32>, patternId: u32, spacing: f32, angle: f32, width: f32, angle2: f32) -> f32 {\n let p = fragCoord;\n if (patternId == 0u) { return 0.0; } // solid\n if (patternId == 1u) { // diagonal\n let r = rotate(p, angle);\n return lineMask(r.x, spacing, width);\n }\n if (patternId == 2u) { // cross-hatch\n let r = rotate(p, angle);\n let r2 = rotate(p, angle2);\n return max(lineMask(r.x, spacing, width), lineMask(r2.x, spacing, width));\n }\n if (patternId == 3u) { return lineMask(p.y, spacing, width); } // horizontal\n if (patternId == 4u) { return lineMask(p.x, spacing, width); } // vertical\n if (patternId == 5u) {\n // Concrete (ISO 128-50): clean regular dot grid. The previous\n // version layered dashes on top which looked noisy and broken.\n // Dots sit at every grid intersection; radius scales with\n // stroke width so the user's width slider works consistently.\n let gx = p.x - round(p.x / spacing) * spacing;\n let gy = p.y - round(p.y / spacing) * spacing;\n let d = sqrt(gx * gx + gy * gy);\n let radius = max(1.0, width * 1.2);\n return 1.0 - smoothstep(radius, radius + 1.0, d);\n }\n if (patternId == 6u) { // brick\n let bandH = spacing;\n let band = floor(p.y / bandH);\n // Signed parity. p is @builtin(position) today, so it is a\n // framebuffer coordinate and never negative \u2014 but u32() of a\n // negative float is an out-of-range conversion in WGSL, and the\n // moment this hatch is fed anything but fragCoord (a world- or\n // drawing-space variant) the running bond would break across\n // y = 0 in a backend-dependent way. i32(-1) & 1 is 1, so the\n // parity alternates correctly in both directions.\n let offset = select(0.0, bandH, (i32(band) & 1) == 1);\n let horiz = lineMask(p.y, bandH, width);\n let vertPos = p.x + offset * 0.5;\n let vert = step(fract(vertPos / (bandH * 2.0)), 0.02);\n return max(horiz, vert);\n }\n if (patternId == 7u) { // insulation\n let y = spacing * 0.5 * sin(p.x * 6.2831853 / spacing) + p.y;\n return lineMask(y, spacing, width);\n }\n return 0.0;\n }\n\n struct FragOut {\n @location(0) color: vec4<f32>,\n @location(1) objectId: vec4<f32>,\n }\n\n @fragment\n fn fs_main(input: VertexOutput) -> FragOut {\n let patternId = u32(uniforms.params.x + 0.5);\n let spacing = max(2.0, uniforms.params.y);\n let angle = uniforms.params.z;\n let width = max(1.0, uniforms.params.w);\n let angle2 = uniforms.params2.x;\n\n let h = hatchIntensity(input.position.xy, patternId, spacing, angle, width, angle2);\n // Per-polygon colour (a material-layer slab fills with its own\n // IfcMaterial RGBA) overrides the uniform cap fill when present.\n // Polygons without a colour carry the sentinel alpha -1 and fall back\n // to the user's cap style, byte-identically. Hatch + stroke apply over\n // whichever base is chosen, so the architectural hatch still works.\n let useVertex = input.color.a >= 0.0;\n let baseFill = select(uniforms.capFillColor, input.color, useVertex);\n let rgb = mix(baseFill.rgb, uniforms.capStrokeColor.rgb, h * uniforms.capStrokeColor.a);\n let a = max(baseFill.a, h * uniforms.capStrokeColor.a);\n\n var out: FragOut;\n out.color = vec4<f32>(rgb, a);\n out.objectId = vec4<f32>(0.0, 0.0, 0.0, 0.0);\n return out;\n }\n ";
97
113
  /**
98
114
  * Line shader for the section-cut outline and the standalone world-space line
99
115
  * overlays (annotation / alignment / grid / DXF / clash box).
100
116
  */
101
- export declare const SECTION_2D_OVERLAY_LINE_WGSL = "\n // Mirrors the fill shader's uniform layout so both pipelines can share\n // one buffer; the line shader only reads viewProj, planeOffset and the\n // appended lineColor (byte offset 144). capFillColor/\u2026 are unused here but\n // declared for correct field offsets.\n struct Uniforms {\n viewProj: mat4x4<f32>,\n planeOffset: vec4<f32>,\n capFillColor: vec4<f32>,\n capStrokeColor: vec4<f32>,\n params: vec4<f32>,\n params2: vec4<f32>,\n lineColor: vec4<f32>,\n }\n @binding(0) @group(0) var<uniform> uniforms: Uniforms;\n\n struct VertexInput {\n @location(0) position: vec3<f32>,\n }\n\n struct VertexOutput {\n @builtin(position) position: vec4<f32>,\n }\n\n @vertex\n fn vs_main(input: VertexInput) -> VertexOutput {\n var output: VertexOutput;\n let offsetPos = input.position + uniforms.planeOffset.xyz;\n let clip = uniforms.viewProj * vec4<f32>(offsetPos, 1.0);\n // Reverse-Z decal nudge for lines coplanar with model faces\n // (issue #812). WebGPU forbids depthStencil.depthBias on non-\n // triangle topologies, so we do the equivalent in clip space:\n // adding a small positive multiple of clip.w raises NDC z by a\n // constant after the w-divide, which under reverse-Z means\n // \"slightly closer\" \u2014 enough to beat MSAA jitter on annotation\n // lines that ride exactly on a wall/floor.\n output.position = vec4<f32>(clip.x, clip.y, clip.z + 5e-5 * clip.w, clip.w);\n return output;\n }\n\n struct FragOutLine {\n @location(0) color: vec4<f32>,\n @location(1) objectId: vec4<f32>,\n }\n\n @fragment\n fn fs_main(input: VertexOutput) -> FragOutLine {\n var out: FragOutLine;\n out.color = uniforms.lineColor; // consumer-themeable (defaults black)\n out.objectId = vec4<f32>(0.0, 0.0, 0.0, 0.0);\n return out;\n }\n ";
117
+ export declare const SECTION_2D_OVERLAY_LINE_WGSL = "\n // Mirrors the fill shader's uniform layout so both pipelines can share\n // one buffer; the line shader only reads viewProj, planeOffset and the\n // appended lineColor (byte offset 144). capFillColor/\u2026 are unused here but\n // declared for correct field offsets.\n struct Uniforms {\n viewProj: mat4x4<f32>,\n planeOffset: vec4<f32>,\n capFillColor: vec4<f32>,\n capStrokeColor: vec4<f32>,\n params: vec4<f32>,\n params2: vec4<f32>,\n lineColor: vec4<f32>,\n rteViewProj: mat4x4<f32>,\n originDeltaHigh: vec4<f32>,\n originDeltaLow: vec4<f32>,\n }\n @binding(0) @group(0) var<uniform> uniforms: Uniforms;\n\n struct VertexInput {\n @location(0) position: vec3<f32>,\n }\n\n struct VertexOutput {\n @builtin(position) position: vec4<f32>,\n }\n\n @vertex\n fn vs_main(input: VertexInput) -> VertexOutput {\n var output: VertexOutput;\n let offsetPos = input.position + uniforms.planeOffset.xyz;\n let global = uniforms.viewProj * vec4<f32>(offsetPos, 1.0);\n let relative = (offsetPos + uniforms.originDeltaHigh.xyz) + uniforms.originDeltaLow.xyz;\n let clip = select(global, uniforms.rteViewProj * vec4<f32>(relative, 1.0), uniforms.originDeltaHigh.w == 1.0);\n // Reverse-Z decal nudge for lines coplanar with model faces\n // (issue #812). WebGPU forbids depthStencil.depthBias on non-\n // triangle topologies, so we do the equivalent in clip space:\n // adding a small positive multiple of clip.w raises NDC z by a\n // constant after the w-divide, which under reverse-Z means\n // \"slightly closer\" \u2014 enough to beat MSAA jitter on annotation\n // lines that ride exactly on a wall/floor.\n output.position = vec4<f32>(clip.x, clip.y, clip.z + 5e-5 * clip.w, clip.w);\n return output;\n }\n\n struct FragOutLine {\n @location(0) color: vec4<f32>,\n @location(1) objectId: vec4<f32>,\n }\n\n @fragment\n fn fs_main(input: VertexOutput) -> FragOutLine {\n var out: FragOutLine;\n out.color = uniforms.lineColor; // consumer-themeable (defaults black)\n out.objectId = vec4<f32>(0.0, 0.0, 0.0, 0.0);\n return out;\n }\n ";
102
118
  //# sourceMappingURL=section-2d-overlay.wgsl.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"section-2d-overlay.wgsl.d.ts","sourceRoot":"","sources":["../../src/shaders/section-2d-overlay.wgsl.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB;IACnC,+CAA+C;;IAE/C,+CAA+C;;IAE/C,+CAA+C;;IAE/C,gDAAgD;;IAEhD,gFAAgF;;IAEhF,oEAAoE;;IAEpE,mFAAmF;;CAE3E,CAAC;AAEX,uEAAuE;AACvE,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAE5C,6CAA6C;AAC7C,eAAO,MAAM,wBAAwB,QAAgC,CAAC;AAEtE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,6BAA6B;IACxC,6EAA6E;;;;;;;CAOrE,CAAC;AAEX,8EAA8E;AAC9E,eAAO,MAAM,6BAA6B,QAAoD,CAAC;AAE/F;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAIlE;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,ojLAwH9B,CAAC;AAER;;;GAGG;AACH,eAAO,MAAM,4BAA4B,0lEAoDlC,CAAC"}
1
+ {"version":3,"file":"section-2d-overlay.wgsl.d.ts","sourceRoot":"","sources":["../../src/shaders/section-2d-overlay.wgsl.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB;IACnC,+CAA+C;;IAE/C,+CAA+C;;IAE/C,+CAA+C;;IAE/C,gDAAgD;;IAEhD,gFAAgF;;IAEhF,oEAAoE;;IAEpE,mFAAmF;;IAEnF,oEAAoE;;IAEpE,8DAA8D;;;CAGtD,CAAC;AAEX,uEAAuE;AACvE,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAE5C,6CAA6C;AAC7C,eAAO,MAAM,wBAAwB,QAAgC,CAAC;AAEtE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH;;;;;;;;GAQG;AACH,eAAO,MAAM,8BAA8B,MAAM,CAAC;AAElD,eAAO,MAAM,6BAA6B;IACxC,6EAA6E;;;;;;;;CAQrE,CAAC;AAEX,mEAAmE;AACnE,eAAO,MAAM,6BAA6B,QAAyC,CAAC;AAEpF;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAIlE;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,k7LA8H9B,CAAC;AAER;;;GAGG;AACH,eAAO,MAAM,4BAA4B,46EAyDlC,CAAC"}
@@ -39,20 +39,25 @@ export const SECTION_2D_UNIFORM_SLOTS = {
39
39
  params2: 32,
40
40
  /** vec4<f32> overlay / section-cut line colour — floats 36..39 (bytes 144..159) */
41
41
  lineColor: 36,
42
+ /** mat4 camera-relative projection for opt-in anchored overlays. */
43
+ rteViewProj: 40,
44
+ /** split f64-like (origin - eye) delta; w = 1 enables RTE. */
45
+ originDeltaHigh: 56,
46
+ originDeltaLow: 60,
42
47
  };
43
48
  /** Total float count of one uniform record (40 floats = 160 bytes). */
44
- export const SECTION_2D_UNIFORM_FLOATS = 40;
49
+ export const SECTION_2D_UNIFORM_FLOATS = 64;
45
50
  /** Total byte size of one uniform record. */
46
51
  export const SECTION_2D_UNIFORM_BYTES = SECTION_2D_UNIFORM_FLOATS * 4;
47
52
  /**
48
53
  * One uniform slot per draw site.
49
54
  *
50
- * The overlay renderer issues up to six draws into a **single** render pass —
51
- * the section cut cap plus five world-space line families — and every one of
55
+ * The overlay renderer issues up to seven draw sites into a **single** render pass —
56
+ * the section cut cap plus six world-space line families — and every one of
52
57
  * them needs a different `lineColor` (and, for the cap, a different
53
58
  * `planeOffset` and the whole cap-style tail). With one record shared between
54
59
  * them the last `queue.writeBuffer` before submit is what the GPU sees for all
55
- * six: `writeBuffer` is a *queue* operation, so it is applied before the
60
+ * seven: `writeBuffer` is a *queue* operation, so it is applied before the
56
61
  * command buffer that references it executes, no matter where in the encoding
57
62
  * it was issued. Every earlier draw therefore rendered with the last draw's
58
63
  * uniforms — most visibly, the clash box's colour bleeding onto the annotation,
@@ -60,22 +65,33 @@ export const SECTION_2D_UNIFORM_BYTES = SECTION_2D_UNIFORM_FLOATS * 4;
60
65
  * hatch to the zeroed tail the line draws write.
61
66
  *
62
67
  * Each site owning a fixed slot, addressed with a dynamic bind-group offset,
63
- * is what makes the six draws independent while keeping the buffer, the layout
68
+ * is what makes the seven draw sites independent while keeping the buffer, the layout
64
69
  * and the bind group under the single owner issue #2456 insisted on. A slot per
65
70
  * site (rather than a bump allocator) needs no per-frame reset hook: each site
66
71
  * draws at most once per pass.
67
72
  */
73
+ /**
74
+ * Max independently-anchored line partitions per channel in one pass.
75
+ *
76
+ * Spatial batching normally keeps this close to one. The explicit 256-record
77
+ * ceiling still bounds the shared dynamic-uniform allocation (384 KiB at the
78
+ * WebGPU-guaranteed 256-byte stride) while accepting genuinely disjoint survey
79
+ * features instead of making the old 32-record implementation throw midway
80
+ * through a render submission.
81
+ */
82
+ export const SECTION_2D_MAX_LINE_PARTITIONS = 256;
68
83
  export const SECTION_2D_UNIFORM_SLOT_INDEX = {
69
84
  /** The section cut cap: fill + outline, which share one record by design. */
70
85
  sectionCut: 0,
71
86
  annotation: 1,
72
- alignment: 2,
73
- grid: 3,
74
- dxf: 4,
75
- clashBox: 5,
87
+ alignment: 1 + SECTION_2D_MAX_LINE_PARTITIONS,
88
+ grid: 1 + SECTION_2D_MAX_LINE_PARTITIONS * 2,
89
+ dxf: 1 + SECTION_2D_MAX_LINE_PARTITIONS * 3,
90
+ terrain: 1 + SECTION_2D_MAX_LINE_PARTITIONS * 4,
91
+ clashBox: 1 + SECTION_2D_MAX_LINE_PARTITIONS * 5,
76
92
  };
77
- /** How many uniform records the shared buffer holds — one per entry above. */
78
- export const SECTION_2D_UNIFORM_SLOT_COUNT = Object.keys(SECTION_2D_UNIFORM_SLOT_INDEX).length;
93
+ /** One cap record plus a partition range for every line family. */
94
+ export const SECTION_2D_UNIFORM_SLOT_COUNT = 1 + SECTION_2D_MAX_LINE_PARTITIONS * 6;
79
95
  /**
80
96
  * Byte stride between uniform slots for `device`.
81
97
  *
@@ -110,6 +126,10 @@ export const SECTION_2D_CAP_FILL_WGSL = /* wgsl */ `
110
126
  params: vec4<f32>,
111
127
  // x=secondaryAngleRad, y,z,w reserved
112
128
  params2: vec4<f32>,
129
+ lineColor: vec4<f32>,
130
+ rteViewProj: mat4x4<f32>,
131
+ originDeltaHigh: vec4<f32>,
132
+ originDeltaLow: vec4<f32>,
113
133
  }
114
134
  @binding(0) @group(0) var<uniform> uniforms: Uniforms;
115
135
 
@@ -127,7 +147,9 @@ export const SECTION_2D_CAP_FILL_WGSL = /* wgsl */ `
127
147
  fn vs_main(input: VertexInput) -> VertexOutput {
128
148
  var output: VertexOutput;
129
149
  let offsetPos = input.position + uniforms.planeOffset.xyz;
130
- output.position = uniforms.viewProj * vec4<f32>(offsetPos, 1.0);
150
+ let global = uniforms.viewProj * vec4<f32>(offsetPos, 1.0);
151
+ let relative = (offsetPos + uniforms.originDeltaHigh.xyz) + uniforms.originDeltaLow.xyz;
152
+ output.position = select(global, uniforms.rteViewProj * vec4<f32>(relative, 1.0), uniforms.originDeltaHigh.w == 1.0);
131
153
  output.color = input.color;
132
154
  return output;
133
155
  }
@@ -238,6 +260,9 @@ export const SECTION_2D_OVERLAY_LINE_WGSL = /* wgsl */ `
238
260
  params: vec4<f32>,
239
261
  params2: vec4<f32>,
240
262
  lineColor: vec4<f32>,
263
+ rteViewProj: mat4x4<f32>,
264
+ originDeltaHigh: vec4<f32>,
265
+ originDeltaLow: vec4<f32>,
241
266
  }
242
267
  @binding(0) @group(0) var<uniform> uniforms: Uniforms;
243
268
 
@@ -253,7 +278,9 @@ export const SECTION_2D_OVERLAY_LINE_WGSL = /* wgsl */ `
253
278
  fn vs_main(input: VertexInput) -> VertexOutput {
254
279
  var output: VertexOutput;
255
280
  let offsetPos = input.position + uniforms.planeOffset.xyz;
256
- let clip = uniforms.viewProj * vec4<f32>(offsetPos, 1.0);
281
+ let global = uniforms.viewProj * vec4<f32>(offsetPos, 1.0);
282
+ let relative = (offsetPos + uniforms.originDeltaHigh.xyz) + uniforms.originDeltaLow.xyz;
283
+ let clip = select(global, uniforms.rteViewProj * vec4<f32>(relative, 1.0), uniforms.originDeltaHigh.w == 1.0);
257
284
  // Reverse-Z decal nudge for lines coplanar with model faces
258
285
  // (issue #812). WebGPU forbids depthStencil.depthBias on non-
259
286
  // triangle topologies, so we do the equivalent in clip space:
@@ -1 +1 @@
1
- {"version":3,"file":"section-2d-overlay.wgsl.js","sourceRoot":"","sources":["../../src/shaders/section-2d-overlay.wgsl.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,+CAA+C;IAC/C,QAAQ,EAAE,CAAC;IACX,+CAA+C;IAC/C,WAAW,EAAE,EAAE;IACf,+CAA+C;IAC/C,YAAY,EAAE,EAAE;IAChB,gDAAgD;IAChD,cAAc,EAAE,EAAE;IAClB,gFAAgF;IAChF,MAAM,EAAE,EAAE;IACV,oEAAoE;IACpE,OAAO,EAAE,EAAE;IACX,mFAAmF;IACnF,SAAS,EAAE,EAAE;CACL,CAAC;AAEX,uEAAuE;AACvE,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAE5C,6CAA6C;AAC7C,MAAM,CAAC,MAAM,wBAAwB,GAAG,yBAAyB,GAAG,CAAC,CAAC;AAEtE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG;IAC3C,6EAA6E;IAC7E,UAAU,EAAE,CAAC;IACb,UAAU,EAAE,CAAC;IACb,SAAS,EAAE,CAAC;IACZ,IAAI,EAAE,CAAC;IACP,GAAG,EAAE,CAAC;IACN,QAAQ,EAAE,CAAC;CACH,CAAC;AAEX,8EAA8E;AAC9E,MAAM,CAAC,MAAM,6BAA6B,GAAG,MAAM,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,MAAM,CAAC;AAE/F;;;;;;;GAOG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAAiB;IACxD,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,+BAA+B,IAAI,GAAG,CAAC;IACxE,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC;IAC3E,OAAO,IAAI,CAAC,IAAI,CAAC,wBAAwB,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;AAC3D,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAwH5C,CAAC;AAER;;;GAGG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoDhD,CAAC"}
1
+ {"version":3,"file":"section-2d-overlay.wgsl.js","sourceRoot":"","sources":["../../src/shaders/section-2d-overlay.wgsl.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,+CAA+C;IAC/C,QAAQ,EAAE,CAAC;IACX,+CAA+C;IAC/C,WAAW,EAAE,EAAE;IACf,+CAA+C;IAC/C,YAAY,EAAE,EAAE;IAChB,gDAAgD;IAChD,cAAc,EAAE,EAAE;IAClB,gFAAgF;IAChF,MAAM,EAAE,EAAE;IACV,oEAAoE;IACpE,OAAO,EAAE,EAAE;IACX,mFAAmF;IACnF,SAAS,EAAE,EAAE;IACb,oEAAoE;IACpE,WAAW,EAAE,EAAE;IACf,8DAA8D;IAC9D,eAAe,EAAE,EAAE;IACnB,cAAc,EAAE,EAAE;CACV,CAAC;AAEX,uEAAuE;AACvE,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAE5C,6CAA6C;AAC7C,MAAM,CAAC,MAAM,wBAAwB,GAAG,yBAAyB,GAAG,CAAC,CAAC;AAEtE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,GAAG,CAAC;AAElD,MAAM,CAAC,MAAM,6BAA6B,GAAG;IAC3C,6EAA6E;IAC7E,UAAU,EAAE,CAAC;IACb,UAAU,EAAE,CAAC;IACb,SAAS,EAAE,CAAC,GAAG,8BAA8B;IAC7C,IAAI,EAAE,CAAC,GAAG,8BAA8B,GAAG,CAAC;IAC5C,GAAG,EAAE,CAAC,GAAG,8BAA8B,GAAG,CAAC;IAC3C,OAAO,EAAE,CAAC,GAAG,8BAA8B,GAAG,CAAC;IAC/C,QAAQ,EAAE,CAAC,GAAG,8BAA8B,GAAG,CAAC;CACxC,CAAC;AAEX,mEAAmE;AACnE,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,GAAG,8BAA8B,GAAG,CAAC,CAAC;AAEpF;;;;;;;GAOG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAAiB;IACxD,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,+BAA+B,IAAI,GAAG,CAAC;IACxE,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC;IAC3E,OAAO,IAAI,CAAC,IAAI,CAAC,wBAAwB,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;AAC3D,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8H5C,CAAC;AAER;;;GAGG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAyDhD,CAAC"}
@@ -27,5 +27,5 @@
27
27
  * the unused `worldPos` output on those pipelines costs an interpolator, not a
28
28
  * shader stage.
29
29
  */
30
- export declare const shadowShaderSource = "\n struct Light {\n lightViewProj: mat4x4<f32>,\n }\n @binding(0) @group(0) var<uniform> light: Light;\n\n struct Draw {\n model: mat4x4<f32>,\n // xyz = lattice-aligned quantMin (batch-origin-relative), w = step.\n // Read only by vs_shadow_quantized; zero for the other paths.\n quantParams: vec4<f32>,\n }\n @binding(1) @group(0) var<uniform> draw: Draw;\n\n struct Clip {\n // xyz = plane normal, w = plane distance (world space).\n sectionPlane: vec4<f32>,\n clipBoxMin: vec4<f32>,\n clipBoxMax: vec4<f32>,\n // x packs: bit 0 = section enabled, bit 1 = section flipped,\n // bit 2 = clip box enabled. Mirrors main.wgsl's flags.y.\n flags: vec4<u32>,\n }\n @binding(2) @group(0) var<uniform> clip: Clip;\n\n struct FlatIn {\n @location(0) position: vec3<f32>,\n }\n\n struct QuantIn {\n @location(0) q: vec4<u32>, // uint16x4: lattice x, y, z, packedOct\n }\n\n struct InstanceIn {\n @location(3) m0: vec4<f32>,\n @location(4) m1: vec4<f32>,\n @location(5) m2: vec4<f32>,\n @location(6) m3: vec4<f32>,\n // Per-occurrence flags lane (bit 1 = hidden), same instance buffer the\n // colour pass reads. Locations 7 (entityId) and 8 (rgba) are unused by\n // the depth pass and left unbound.\n @location(9) flags: u32,\n }\n\n struct ShadowOut {\n @builtin(position) position: vec4<f32>,\n @location(0) worldPos: vec3<f32>,\n }\n\n fn emit(worldPos: vec4<f32>) -> ShadowOut {\n var out: ShadowOut;\n out.position = light.lightViewProj * worldPos;\n out.worldPos = worldPos.xyz;\n return out;\n }\n\n @vertex\n fn vs_shadow_flat(input: FlatIn) -> ShadowOut {\n return emit(draw.model * vec4<f32>(input.position, 1.0));\n }\n\n @vertex\n fn vs_shadow_quantized(input: QuantIn) -> ShadowOut {\n let p = draw.quantParams.xyz\n + vec3<f32>(f32(input.q.x), f32(input.q.y), f32(input.q.z)) * draw.quantParams.w;\n return emit(draw.model * vec4<f32>(p, 1.0));\n }\n\n @vertex\n fn vs_shadow_instanced(input: FlatIn, inst: InstanceIn) -> ShadowOut {\n // A hidden / isolation-excluded occurrence (flags bit 1) must not cast:\n // the colour pass discards it in fs_main, so collapse it to a zero-area\n // triangle here (every vertex to one clip point) \u2014 the rasterizer drops\n // it and it writes no depth. Mirrors main.wgsl's instSelected & 2u check.\n if ((inst.flags & 2u) != 0u) {\n var out: ShadowOut;\n out.position = vec4<f32>(0.0, 0.0, 0.0, 1.0);\n out.worldPos = vec3<f32>(0.0, 0.0, 0.0);\n return out;\n }\n let instMat = mat4x4<f32>(inst.m0, inst.m1, inst.m2, inst.m3);\n return emit(instMat * vec4<f32>(input.position, 1.0));\n }\n\n @vertex\n fn vs_shadow_textured(input: FlatIn) -> ShadowOut {\n return emit(draw.model * vec4<f32>(input.position, 1.0));\n }\n\n // Clipped variant: discard before the depth write, so a clipped-away\n // occluder leaves the shadow map untouched. Kept byte-for-byte in step\n // with the fs_main section/clip-box branches.\n @fragment\n fn fs_shadow_clip(@location(0) worldPos: vec3<f32>) {\n if ((clip.flags.x & 1u) == 1u) {\n let side = select(1.0, -1.0, (clip.flags.x & 2u) == 2u);\n let distToPlane = (dot(worldPos, clip.sectionPlane.xyz) - clip.sectionPlane.w) * side;\n if (distToPlane > 0.0) {\n discard;\n }\n }\n if ((clip.flags.x & 4u) != 0u) {\n if (any(worldPos < clip.clipBoxMin.xyz) || any(worldPos > clip.clipBoxMax.xyz)) {\n discard;\n }\n }\n }\n";
30
+ export declare const shadowShaderSource = "\n \nstruct RteFrameUniform {\n // Camera translation is intentionally absent. This projects positions\n // returned by rteWorldPosition, which are already relative to the eye.\n viewProj: mat4x4<f32>,\n}\n\nstruct RteDrawableUniform {\n // CPU computes (drawable origin - camera origin) in f64 and splits it.\n // This data must be refreshed whenever the RTE camera frame changes.\n drawableDeltaHigh: vec4<f32>,\n drawableDeltaLow: vec4<f32>,\n}\n\nfn rteWorldPosition(\n local: vec3<f32>,\n drawable: RteDrawableUniform,\n) -> vec4<f32> {\n // Do not subtract a camera origin here: this delta was formed in CPU f64.\n let highDelta = drawable.drawableDeltaHigh.xyz;\n let lowDelta = drawable.drawableDeltaLow.xyz;\n // A drawable template can span kilometres. Keep local with high first;\n // The local-plus-(high-plus-low) association is not equivalent in f32.\n return vec4<f32>((local + highDelta) + lowDelta, 1.0);\n}\n\n struct Light {\n lightViewProj: mat4x4<f32>,\n cameraHigh: vec4<f32>,\n cameraLow: vec4<f32>,\n }\n @binding(0) @group(0) var<uniform> light: Light;\n\n struct Draw {\n model: mat4x4<f32>,\n // xyz = lattice-aligned quantMin (batch-origin-relative), w = step.\n // Read only by vs_shadow_quantized; zero for the other paths.\n quantParams: vec4<f32>,\n originHigh: vec4<f32>,\n originLow: vec4<f32>,\n }\n @binding(1) @group(0) var<uniform> draw: Draw;\n\n struct Clip {\n // xyz = plane normal, w = plane distance (world space).\n sectionPlane: vec4<f32>,\n clipBoxMin: vec4<f32>,\n clipBoxMax: vec4<f32>,\n // x packs: bit 0 = section enabled, bit 1 = section flipped,\n // bit 2 = clip box enabled. Mirrors main.wgsl's flags.y.\n flags: vec4<u32>,\n }\n @binding(2) @group(0) var<uniform> clip: Clip;\n\n struct FlatIn {\n @location(0) position: vec3<f32>,\n }\n\n struct QuantIn {\n @location(0) q: vec4<u32>, // uint16x4: lattice x, y, z, packedOct\n }\n\n struct InstanceIn {\n @location(3) m0: vec4<f32>,\n @location(4) m1: vec4<f32>,\n @location(5) m2: vec4<f32>,\n @location(6) m3: vec4<f32>,\n // Per-occurrence flags lane (bit 1 = hidden), same instance buffer the\n // colour pass reads. Locations 7 (entityId) and 8 (rgba) are unused by\n // the depth pass and left unbound.\n @location(9) flags: u32,\n // V2 split drawable-minus-camera delta, byte offsets 88 and 104.\n @location(10) anchorHigh: vec4<f32>,\n @location(11) anchorLow: vec4<f32>,\n }\n\n struct ShadowOut {\n @builtin(position) position: vec4<f32>,\n @location(0) worldPos: vec3<f32>,\n }\n\n fn emit(eyePos: vec4<f32>) -> ShadowOut {\n var out: ShadowOut;\n out.position = light.lightViewProj * eyePos;\n out.worldPos = eyePos.xyz;\n return out;\n }\n\n @vertex\n fn vs_shadow_flat(input: FlatIn) -> ShadowOut {\n let linear = (draw.model * vec4<f32>(input.position, 0.0)).xyz;\n return emit(rteWorldPosition(linear, RteDrawableUniform(draw.originHigh, draw.originLow)));\n }\n\n @vertex\n fn vs_shadow_quantized(input: QuantIn) -> ShadowOut {\n let p = draw.quantParams.xyz\n + vec3<f32>(f32(input.q.x), f32(input.q.y), f32(input.q.z)) * draw.quantParams.w;\n let linear = (draw.model * vec4<f32>(p, 0.0)).xyz;\n return emit(rteWorldPosition(linear, RteDrawableUniform(draw.originHigh, draw.originLow)));\n }\n\n @vertex\n fn vs_shadow_instanced(input: FlatIn, inst: InstanceIn) -> ShadowOut {\n // A hidden / isolation-excluded occurrence (flags bit 1) must not cast:\n // the colour pass discards it in fs_main, so collapse it to a zero-area\n // triangle here (every vertex to one clip point) \u2014 the rasterizer drops\n // it and it writes no depth. Mirrors main.wgsl's instSelected & 2u check.\n if ((inst.flags & 2u) != 0u) {\n var out: ShadowOut;\n out.position = vec4<f32>(0.0, 0.0, 0.0, 1.0);\n out.worldPos = vec3<f32>(0.0, 0.0, 0.0);\n return out;\n }\n let instMat = mat4x4<f32>(inst.m0, inst.m1, inst.m2, inst.m3);\n // Keep the local placement from the V1 matrix and add the shared\n // CPU-packed drawable-minus-camera delta. The light projection uses\n // the same RTE frame as the colour and picker submissions.\n let linear = (instMat * vec4<f32>(input.position, 0.0)).xyz;\n return emit(rteWorldPosition(linear, RteDrawableUniform(\n inst.anchorHigh, inst.anchorLow,\n )));\n }\n\n @vertex\n fn vs_shadow_textured(input: FlatIn) -> ShadowOut {\n let linear = (draw.model * vec4<f32>(input.position, 0.0)).xyz;\n return emit(rteWorldPosition(linear, RteDrawableUniform(draw.originHigh, draw.originLow)));\n }\n\n // Clipped variant: discard before the depth write, so a clipped-away\n // occluder leaves the shadow map untouched. Kept byte-for-byte in step\n // with the fs_main section/clip-box branches.\n @fragment\n fn fs_shadow_clip(@location(0) worldPos: vec3<f32>) {\n if ((clip.flags.x & 1u) == 1u) {\n let side = select(1.0, -1.0, (clip.flags.x & 2u) == 2u);\n let distToPlane = (dot(worldPos, clip.sectionPlane.xyz) - clip.sectionPlane.w) * side;\n if (distToPlane > 0.0) {\n discard;\n }\n }\n if ((clip.flags.x & 4u) != 0u) {\n if (any(worldPos < clip.clipBoxMin.xyz) || any(worldPos > clip.clipBoxMax.xyz)) {\n discard;\n }\n }\n }\n";
31
31
  //# sourceMappingURL=shadow.wgsl.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shadow.wgsl.d.ts","sourceRoot":"","sources":["../../src/shaders/shadow.wgsl.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,kBAAkB,4hIA2G9B,CAAC"}
1
+ {"version":3,"file":"shadow.wgsl.d.ts","sourceRoot":"","sources":["../../src/shaders/shadow.wgsl.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,kBAAkB,+6LA4H9B,CAAC"}
@@ -1,6 +1,7 @@
1
1
  /* This Source Code Form is subject to the terms of the Mozilla Public
2
2
  * License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ import { relativeToEyeWgsl } from './relative-to-eye.wgsl.js';
4
5
  /**
5
6
  * Sun shadow-map depth pre-pass shaders (issue #2670, Phase 2).
6
7
  *
@@ -31,8 +32,11 @@
31
32
  * shader stage.
32
33
  */
33
34
  export const shadowShaderSource = `
35
+ ${relativeToEyeWgsl}
34
36
  struct Light {
35
37
  lightViewProj: mat4x4<f32>,
38
+ cameraHigh: vec4<f32>,
39
+ cameraLow: vec4<f32>,
36
40
  }
37
41
  @binding(0) @group(0) var<uniform> light: Light;
38
42
 
@@ -41,6 +45,8 @@ export const shadowShaderSource = `
41
45
  // xyz = lattice-aligned quantMin (batch-origin-relative), w = step.
42
46
  // Read only by vs_shadow_quantized; zero for the other paths.
43
47
  quantParams: vec4<f32>,
48
+ originHigh: vec4<f32>,
49
+ originLow: vec4<f32>,
44
50
  }
45
51
  @binding(1) @group(0) var<uniform> draw: Draw;
46
52
 
@@ -72,6 +78,9 @@ export const shadowShaderSource = `
72
78
  // colour pass reads. Locations 7 (entityId) and 8 (rgba) are unused by
73
79
  // the depth pass and left unbound.
74
80
  @location(9) flags: u32,
81
+ // V2 split drawable-minus-camera delta, byte offsets 88 and 104.
82
+ @location(10) anchorHigh: vec4<f32>,
83
+ @location(11) anchorLow: vec4<f32>,
75
84
  }
76
85
 
77
86
  struct ShadowOut {
@@ -79,23 +88,25 @@ export const shadowShaderSource = `
79
88
  @location(0) worldPos: vec3<f32>,
80
89
  }
81
90
 
82
- fn emit(worldPos: vec4<f32>) -> ShadowOut {
91
+ fn emit(eyePos: vec4<f32>) -> ShadowOut {
83
92
  var out: ShadowOut;
84
- out.position = light.lightViewProj * worldPos;
85
- out.worldPos = worldPos.xyz;
93
+ out.position = light.lightViewProj * eyePos;
94
+ out.worldPos = eyePos.xyz;
86
95
  return out;
87
96
  }
88
97
 
89
98
  @vertex
90
99
  fn vs_shadow_flat(input: FlatIn) -> ShadowOut {
91
- return emit(draw.model * vec4<f32>(input.position, 1.0));
100
+ let linear = (draw.model * vec4<f32>(input.position, 0.0)).xyz;
101
+ return emit(rteWorldPosition(linear, RteDrawableUniform(draw.originHigh, draw.originLow)));
92
102
  }
93
103
 
94
104
  @vertex
95
105
  fn vs_shadow_quantized(input: QuantIn) -> ShadowOut {
96
106
  let p = draw.quantParams.xyz
97
107
  + vec3<f32>(f32(input.q.x), f32(input.q.y), f32(input.q.z)) * draw.quantParams.w;
98
- return emit(draw.model * vec4<f32>(p, 1.0));
108
+ let linear = (draw.model * vec4<f32>(p, 0.0)).xyz;
109
+ return emit(rteWorldPosition(linear, RteDrawableUniform(draw.originHigh, draw.originLow)));
99
110
  }
100
111
 
101
112
  @vertex
@@ -111,12 +122,19 @@ export const shadowShaderSource = `
111
122
  return out;
112
123
  }
113
124
  let instMat = mat4x4<f32>(inst.m0, inst.m1, inst.m2, inst.m3);
114
- return emit(instMat * vec4<f32>(input.position, 1.0));
125
+ // Keep the local placement from the V1 matrix and add the shared
126
+ // CPU-packed drawable-minus-camera delta. The light projection uses
127
+ // the same RTE frame as the colour and picker submissions.
128
+ let linear = (instMat * vec4<f32>(input.position, 0.0)).xyz;
129
+ return emit(rteWorldPosition(linear, RteDrawableUniform(
130
+ inst.anchorHigh, inst.anchorLow,
131
+ )));
115
132
  }
116
133
 
117
134
  @vertex
118
135
  fn vs_shadow_textured(input: FlatIn) -> ShadowOut {
119
- return emit(draw.model * vec4<f32>(input.position, 1.0));
136
+ let linear = (draw.model * vec4<f32>(input.position, 0.0)).xyz;
137
+ return emit(rteWorldPosition(linear, RteDrawableUniform(draw.originHigh, draw.originLow)));
120
138
  }
121
139
 
122
140
  // Clipped variant: discard before the depth write, so a clipped-away
@@ -1 +1 @@
1
- {"version":3,"file":"shadow.wgsl.js","sourceRoot":"","sources":["../../src/shaders/shadow.wgsl.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2GjC,CAAC"}
1
+ {"version":3,"file":"shadow.wgsl.js","sourceRoot":"","sources":["../../src/shaders/shadow.wgsl.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;UACxB,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2H1B,CAAC"}
@@ -1,12 +1,2 @@
1
- /**
2
- * Procedural sky background — a single fullscreen triangle drawn at the far
3
- * plane (reverse-Z: z = 0) before any geometry. Analytic zenith/horizon/
4
- * ground gradient plus a sun disc + glow, driven by the same sun direction
5
- * the geometry lighting uses.
6
- *
7
- * Tonemapping note: the geometry shader applies ACES + gamma at the end of
8
- * its fragment stage (not in a post pass), so the sky must apply the same
9
- * curve here or it would read as a different "film stock" than the model.
10
- */
11
- export declare const skyShaderSource = "\n struct SkyUniforms {\n camRight: vec3<f32>,\n tanHalfFovX: f32,\n camUp: vec3<f32>,\n tanHalfFovY: f32,\n camForward: vec3<f32>,\n exposure: f32,\n sunDirection: vec3<f32>,\n sunIntensity: f32,\n zenithColor: vec3<f32>,\n _pad0: f32,\n horizonColor: vec3<f32>,\n _pad1: f32,\n groundColor: vec3<f32>,\n _pad2: f32,\n }\n @binding(0) @group(0) var<uniform> sky: SkyUniforms;\n\n struct VertexOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) ndc: vec2<f32>,\n }\n\n @vertex\n fn vs_main(@builtin(vertex_index) vi: u32) -> VertexOutput {\n // Fullscreen triangle: (-1,-1), (3,-1), (-1,3).\n let x = f32((vi << 1u) & 2u) * 2.0 - 1.0;\n let y = f32(vi & 2u) * 2.0 - 1.0;\n var out: VertexOutput;\n // z = 0 is the far plane under reverse-Z, so any geometry drawn\n // later wins the depth test without the sky writing depth.\n out.position = vec4<f32>(x, y, 0.0, 1.0);\n out.ndc = vec2<f32>(x, y);\n return out;\n }\n\n // Same ACES filmic curve as the geometry fragment shader.\n fn acesTonemap(c: vec3<f32>) -> vec3<f32> {\n let a = 2.51;\n let b = 0.03;\n let cc = 2.43;\n let d = 0.59;\n let e = 0.14;\n return clamp((c * (a * c + b)) / (c * (cc * c + d) + e), vec3<f32>(0.0), vec3<f32>(1.0));\n }\n\n struct FragmentOutput {\n @location(0) color: vec4<f32>,\n // Matches the pass's object-id attachment clear value so the sky\n // never registers as a pickable entity.\n @location(1) objectIdEncoded: vec4<f32>,\n }\n\n @fragment\n fn fs_main(input: VertexOutput) -> FragmentOutput {\n // Per-pixel view ray from the camera basis. Used for orthographic\n // cameras too \u2014 parallel rays would collapse the sky to a single\n // colour, so a perspective-style fan reads better in both modes.\n let dir = normalize(\n sky.camForward\n + input.ndc.x * sky.tanHalfFovX * sky.camRight\n + input.ndc.y * sky.tanHalfFovY * sky.camUp\n );\n let elevation = dir.y;\n\n // Horizon \u2192 zenith gradient with a slow falloff near the horizon.\n let zenithMix = pow(clamp(elevation, 0.0, 1.0), 0.45);\n var color = mix(sky.horizonColor, sky.zenithColor, zenithMix);\n\n // Below the horizon: fade quickly into the ground colour.\n // WGSL requires smoothstep's low < high, so express the\n // downward ramp (0 at the horizon \u2192 1 at elevation -0.1) as the\n // complement of an ascending smoothstep rather than passing\n // reversed edges, which Tint rejects as a shader-compile error\n // (low 0.0 not less than high -0.1) \u2014 that invalidated the whole\n // sky pipeline and blanked the frame on strict drivers.\n let groundMix = 1.0 - smoothstep(-0.1, 0.0, elevation);\n color = mix(color, sky.groundColor, groundMix);\n\n // Sun disc + glow. The disc is slightly oversized vs the real\n // ~0.53\u00B0 sun so it stays visible at typical canvas resolutions.\n let cosSun = dot(dir, sky.sunDirection);\n let disc = smoothstep(0.99985, 0.99995, cosSun);\n let glow = pow(max(cosSun, 0.0), 350.0) * 0.5\n + pow(max(cosSun, 0.0), 24.0) * 0.12;\n // Hide the disc once the sun sets, and never draw it on the ground.\n let sunVisible = smoothstep(-0.06, 0.02, sky.sunDirection.y) * (1.0 - groundMix);\n let sunTint = vec3<f32>(1.0, 0.92, 0.78);\n color += (disc * 6.0 + glow) * max(sky.sunIntensity, 0.0) * sunVisible * sunTint;\n\n // Match the geometry pipeline: exposure \u2192 ACES \u2192 gamma.\n color *= sky.exposure;\n color = acesTonemap(color);\n color = pow(color, vec3<f32>(1.0 / 2.2));\n\n var out: FragmentOutput;\n out.color = vec4<f32>(color, 1.0);\n out.objectIdEncoded = vec4<f32>(0.0, 0.0, 0.0, 0.0);\n return out;\n }\n ";
1
+ export declare const skyShaderSource = "\n struct SkyUniforms {\n camRight: vec3<f32>,\n tanHalfFovX: f32,\n camUp: vec3<f32>,\n tanHalfFovY: f32,\n camForward: vec3<f32>,\n exposure: f32,\n sunDirection: vec3<f32>,\n sunIntensity: f32,\n zenithColor: vec3<f32>,\n _pad0: f32,\n horizonColor: vec3<f32>,\n _pad1: f32,\n groundColor: vec3<f32>,\n _pad2: f32,\n }\n @binding(0) @group(0) var<uniform> sky: SkyUniforms;\n\n struct VertexOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) ndc: vec2<f32>,\n }\n\n @vertex\n fn vs_main(@builtin(vertex_index) vi: u32) -> VertexOutput {\n // Fullscreen triangle: (-1,-1), (3,-1), (-1,3).\n let x = f32((vi << 1u) & 2u) * 2.0 - 1.0;\n let y = f32(vi & 2u) * 2.0 - 1.0;\n var out: VertexOutput;\n // z = 0 is the far plane under reverse-Z, so any geometry drawn\n // later wins the depth test without the sky writing depth.\n out.position = vec4<f32>(x, y, 0.0, 1.0);\n out.ndc = vec2<f32>(x, y);\n return out;\n }\n\n \n fn srgbToLinear(c: vec3<f32>) -> vec3<f32> {\n let lo = c / 12.92;\n let hi = pow((max(c, vec3<f32>(0.0)) + 0.055) / 1.055, vec3<f32>(2.4));\n return select(hi, lo, c <= vec3<f32>(0.04045));\n }\n\n fn linearToSrgb(c: vec3<f32>) -> vec3<f32> {\n let lo = c * 12.92;\n let hi = 1.055 * pow(max(c, vec3<f32>(0.0)), vec3<f32>(1.0 / 2.4)) - 0.055;\n return select(hi, lo, c <= vec3<f32>(0.0031308));\n }\n\n fn neutralCompress(cIn: vec3<f32>) -> vec3<f32> {\n let startCompression = 0.76;\n let desaturation = 0.15;\n let c = max(cIn, vec3<f32>(0.0));\n let peak = max(c.r, max(c.g, c.b));\n if (peak < startCompression) { return c; }\n let d = 1.0 - startCompression;\n let newPeak = 1.0 - d * d / (peak + d - startCompression);\n let g = 1.0 - 1.0 / (desaturation * (peak - newPeak) + 1.0);\n return mix(c * (newPeak / peak), vec3<f32>(newPeak), g);\n }\n\n\n struct FragmentOutput {\n @location(0) color: vec4<f32>,\n // Matches the pass's object-id attachment clear value so the sky\n // never registers as a pickable entity.\n @location(1) objectIdEncoded: vec4<f32>,\n }\n\n @fragment\n fn fs_main(input: VertexOutput) -> FragmentOutput {\n // Per-pixel view ray from the camera basis. Used for orthographic\n // cameras too \u2014 parallel rays would collapse the sky to a single\n // colour, so a perspective-style fan reads better in both modes.\n let dir = normalize(\n sky.camForward\n + input.ndc.x * sky.tanHalfFovX * sky.camRight\n + input.ndc.y * sky.tanHalfFovY * sky.camUp\n );\n let elevation = dir.y;\n\n // Horizon \u2192 zenith gradient with a slow falloff near the horizon.\n let zenithMix = pow(clamp(elevation, 0.0, 1.0), 0.45);\n var color = mix(sky.horizonColor, sky.zenithColor, zenithMix);\n\n // Below the horizon: fade gradually into the ground colour. The\n // falloff spans elevation -0.5..0 (rather than a near-instant\n // -0.1..0) so the ordinary downward-pitched BIM camera sees a\n // gradient from the horizon tone into the ground tone instead of\n // an abrupt flat-colour wall a few degrees below the horizon\n // (#5583); only a near-vertical look-down reaches pure groundColor.\n // WGSL requires smoothstep's low < high, so express the\n // downward ramp (0 at the horizon \u2192 1 at elevation -0.5) as the\n // complement of an ascending smoothstep rather than passing\n // reversed edges, which Tint rejects as a shader-compile error\n // (low 0.0 not less than high -0.5) \u2014 that invalidated the whole\n // sky pipeline and blanked the frame on strict drivers.\n let groundMix = 1.0 - smoothstep(-0.5, 0.0, elevation);\n color = mix(color, sky.groundColor, groundMix);\n\n // Sun disc + glow. The disc is slightly oversized vs the real\n // ~0.53\u00B0 sun so it stays visible at typical canvas resolutions.\n let cosSun = dot(dir, sky.sunDirection);\n let disc = smoothstep(0.99985, 0.99995, cosSun);\n let glow = pow(max(cosSun, 0.0), 350.0) * 0.5\n + pow(max(cosSun, 0.0), 24.0) * 0.12;\n // Hide the disc once the sun sets, and never draw it on the ground.\n let sunVisible = smoothstep(-0.06, 0.02, sky.sunDirection.y) * (1.0 - groundMix);\n let sunTint = vec3<f32>(1.0, 0.92, 0.78);\n color += (disc * 6.0 + glow) * max(sky.sunIntensity, 0.0) * sunVisible * sunTint;\n\n // Match the geometry pipeline: exposure \u2192 highlight roll-off \u2192 sRGB.\n color *= sky.exposure;\n color = linearToSrgb(clamp(neutralCompress(color), vec3<f32>(0.0), vec3<f32>(1.0)));\n\n var out: FragmentOutput;\n out.color = vec4<f32>(color, 1.0);\n out.objectIdEncoded = vec4<f32>(0.0, 0.0, 0.0, 0.0);\n return out;\n }\n ";
12
2
  //# sourceMappingURL=sky.wgsl.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sky.wgsl.d.ts","sourceRoot":"","sources":["../../src/shaders/sky.wgsl.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,swIAqGrB,CAAC"}
1
+ {"version":3,"file":"sky.wgsl.d.ts","sourceRoot":"","sources":["../../src/shaders/sky.wgsl.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,eAAe,m0KAiGrB,CAAC"}
@@ -7,10 +7,12 @@
7
7
  * ground gradient plus a sun disc + glow, driven by the same sun direction
8
8
  * the geometry lighting uses.
9
9
  *
10
- * Tonemapping note: the geometry shader applies ACES + gamma at the end of
11
- * its fragment stage (not in a post pass), so the sky must apply the same
12
- * curve here or it would read as a different "film stock" than the model.
10
+ * Tonemapping note: the geometry shader applies its highlight roll-off and
11
+ * sRGB encode at the end of its fragment stage (not in a post pass), so the
12
+ * sky runs the same shared functions or it would read as a different "film
13
+ * stock" than the model. The gradient colours are linear radiance.
13
14
  */
15
+ import { colorTransferWgsl } from './color-transfer.wgsl.js';
14
16
  export const skyShaderSource = `
15
17
  struct SkyUniforms {
16
18
  camRight: vec3<f32>,
@@ -48,15 +50,7 @@ export const skyShaderSource = `
48
50
  return out;
49
51
  }
50
52
 
51
- // Same ACES filmic curve as the geometry fragment shader.
52
- fn acesTonemap(c: vec3<f32>) -> vec3<f32> {
53
- let a = 2.51;
54
- let b = 0.03;
55
- let cc = 2.43;
56
- let d = 0.59;
57
- let e = 0.14;
58
- return clamp((c * (a * c + b)) / (c * (cc * c + d) + e), vec3<f32>(0.0), vec3<f32>(1.0));
59
- }
53
+ ${colorTransferWgsl}
60
54
 
61
55
  struct FragmentOutput {
62
56
  @location(0) color: vec4<f32>,
@@ -81,14 +75,19 @@ export const skyShaderSource = `
81
75
  let zenithMix = pow(clamp(elevation, 0.0, 1.0), 0.45);
82
76
  var color = mix(sky.horizonColor, sky.zenithColor, zenithMix);
83
77
 
84
- // Below the horizon: fade quickly into the ground colour.
78
+ // Below the horizon: fade gradually into the ground colour. The
79
+ // falloff spans elevation -0.5..0 (rather than a near-instant
80
+ // -0.1..0) so the ordinary downward-pitched BIM camera sees a
81
+ // gradient from the horizon tone into the ground tone instead of
82
+ // an abrupt flat-colour wall a few degrees below the horizon
83
+ // (#5583); only a near-vertical look-down reaches pure groundColor.
85
84
  // WGSL requires smoothstep's low < high, so express the
86
- // downward ramp (0 at the horizon → 1 at elevation -0.1) as the
85
+ // downward ramp (0 at the horizon → 1 at elevation -0.5) as the
87
86
  // complement of an ascending smoothstep rather than passing
88
87
  // reversed edges, which Tint rejects as a shader-compile error
89
- // (low 0.0 not less than high -0.1) — that invalidated the whole
88
+ // (low 0.0 not less than high -0.5) — that invalidated the whole
90
89
  // sky pipeline and blanked the frame on strict drivers.
91
- let groundMix = 1.0 - smoothstep(-0.1, 0.0, elevation);
90
+ let groundMix = 1.0 - smoothstep(-0.5, 0.0, elevation);
92
91
  color = mix(color, sky.groundColor, groundMix);
93
92
 
94
93
  // Sun disc + glow. The disc is slightly oversized vs the real
@@ -102,10 +101,9 @@ export const skyShaderSource = `
102
101
  let sunTint = vec3<f32>(1.0, 0.92, 0.78);
103
102
  color += (disc * 6.0 + glow) * max(sky.sunIntensity, 0.0) * sunVisible * sunTint;
104
103
 
105
- // Match the geometry pipeline: exposure → ACES → gamma.
104
+ // Match the geometry pipeline: exposure → highlight roll-off → sRGB.
106
105
  color *= sky.exposure;
107
- color = acesTonemap(color);
108
- color = pow(color, vec3<f32>(1.0 / 2.2));
106
+ color = linearToSrgb(clamp(neutralCompress(color), vec3<f32>(0.0), vec3<f32>(1.0)));
109
107
 
110
108
  var out: FragmentOutput;
111
109
  out.color = vec4<f32>(color, 1.0);
@@ -1 +1 @@
1
- {"version":3,"file":"sky.wgsl.js","sourceRoot":"","sources":["../../src/shaders/sky.wgsl.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqGxB,CAAC"}
1
+ {"version":3,"file":"sky.wgsl.js","sourceRoot":"","sources":["../../src/shaders/sky.wgsl.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;GAUG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAqCrB,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4DpB,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Specular reflection for the geometry fragment stage (#5386).
3
+ *
4
+ * Two terms, both in the units of `fs_main`'s `lightTerm`, so the caller
5
+ * scales them by the same exposure and `IRRADIANCE_CALIBRATION` as the
6
+ * diffuse light and every preset stays consistent:
7
+ *
8
+ * - the sun: a Cook-Torrance lobe (GGX distribution, Smith-Schlick
9
+ * visibility, Schlick Fresnel). `fs_main` lights a Lambertian albedo as
10
+ * `albedo * intensity`, i.e. the sun's irradiance is `pi * intensity`, so
11
+ * the lobe is scaled by the same `pi` and a white dielectric reflects no
12
+ * more than physics allows next to its diffuse.
13
+ * - the environment: the same two-colour hemisphere that lights the diffuse
14
+ * ambient, read along the reflection vector and weighted by the
15
+ * split-sum environment BRDF (Karis's analytic fit, "Physically Based
16
+ * Shading on Mobile", 2014). The fit already accounts for the lobe's
17
+ * shadowing, so a rough surface picks up almost nothing at grazing angles
18
+ * while a smooth one (glass) turns into a mirror there.
19
+ *
20
+ * `reflectance` is that directional albedo of the specular lobe. The caller
21
+ * takes it off the diffuse (`1 - reflectance`), so a highlight never adds
22
+ * energy on top of a full diffuse, and glass uses it as the light it no
23
+ * longer transmits.
24
+ *
25
+ * Reads the `env` lighting uniform, like `sunShadowFactor`.
26
+ */
27
+ /**
28
+ * Smallest roughness the lobe is evaluated at. Below this the GGX peak is a
29
+ * sub-pixel spike that flickers from frame to frame. The value is Filament's
30
+ * `MIN_PERCEPTUAL_ROUGHNESS` for 32-bit floats.
31
+ */
32
+ export declare const MIN_SPECULAR_ROUGHNESS = 0.045;
33
+ export declare const specularWgsl = "\n const MIN_SPECULAR_ROUGHNESS: f32 = 0.045;\n const DIELECTRIC_F0: f32 = 0.04;\n const PI: f32 = 3.14159265;\n\n fn fresnelSchlick(cosTheta: f32, F0: vec3<f32>) -> vec3<f32> {\n return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);\n }\n\n fn distributionGGX(NdotH: f32, roughness: f32) -> f32 {\n let a = roughness * roughness;\n let a2 = a * a;\n let NdotH2 = NdotH * NdotH;\n let denomBase = (NdotH2 * (a2 - 1.0) + 1.0);\n return a2 / max(PI * denomBase * denomBase, 0.0000001);\n }\n\n fn geometrySchlickGGX(NdotV: f32, roughness: f32) -> f32 {\n let r = (roughness + 1.0);\n let k = (r * r) / 8.0;\n return NdotV / max(NdotV * (1.0 - k) + k, 0.0000001);\n }\n\n fn geometrySmith(NdotV: f32, NdotL: f32, roughness: f32) -> f32 {\n return geometrySchlickGGX(NdotL, roughness) * geometrySchlickGGX(NdotV, roughness);\n }\n\n // Split-sum environment BRDF, analytic fit (Karis 2014).\n fn envBrdfApprox(F0: vec3<f32>, roughness: f32, NdotV: f32) -> vec3<f32> {\n let r = roughness * vec4<f32>(-1.0, -0.0275, -0.572, 0.022) + vec4<f32>(1.0, 0.0425, 1.04, -0.04);\n let a004 = min(r.x * r.x, exp2(-9.28 * NdotV)) * r.x + r.y;\n let ab = vec2<f32>(-1.04, 1.04) * a004 + r.zw;\n return F0 * ab.x + ab.y;\n }\n\n struct SurfaceSpecular {\n // Reflected light, in lightTerm units (unexposed, uncalibrated).\n light: vec3<f32>,\n // Directional albedo of the specular lobe for this view.\n reflectance: vec3<f32>,\n }\n\n // N and V are unit vectors; V points from the surface to the eye.\n // sunLight is the sun's diffuse-equivalent intensity: sunColor *\n // sunIntensity * sunShadow, exactly what scales the diffuse sun term.\n fn surfaceSpecular(\n N: vec3<f32>,\n V: vec3<f32>,\n albedo: vec3<f32>,\n metallic: f32,\n roughnessIn: f32,\n sunLight: vec3<f32>,\n ) -> SurfaceSpecular {\n var out: SurfaceSpecular;\n let NdotV = dot(N, V);\n // A face turned away from the eye is its back side: nothing it\n // reflects can reach the eye, and its diffuse keeps full weight.\n if (NdotV <= 0.0) {\n out.light = vec3<f32>(0.0);\n out.reflectance = vec3<f32>(0.0);\n return out;\n }\n let roughness = clamp(roughnessIn, MIN_SPECULAR_ROUGHNESS, 1.0);\n let F0 = mix(vec3<f32>(DIELECTRIC_F0), albedo, metallic);\n\n let L = env.sunDirection;\n let rawNdotL = dot(N, L);\n let NdotL = max(rawNdotL, 0.0);\n // A face the sun is behind (rawNdotL <= 0) contributes nothing to\n // the direct lobe anyway (NdotL clamps it to 0 below), but V + L\n // can be exactly zero there \u2014 the sun exactly opposite the eye\n // reflection, e.g. N = V = (0,-1,0), sun = (0,1,0), both satisfy\n // NdotV > 0 above. normalize(vec3(0)) is NaN in WGSL, and NaN * 0\n // is NaN, not 0, so it would poison sun and everything summed with\n // it instead of being multiplied away. Skip the half-vector\n // entirely in that case rather than relying on the NdotL factor.\n var sun = vec3<f32>(0.0);\n if (rawNdotL > 0.0) {\n let H = normalize(V + L);\n let D = distributionGGX(max(dot(N, H), 0.0), roughness);\n let G = geometrySmith(NdotV, NdotL, roughness);\n let F = fresnelSchlick(max(dot(V, H), 0.0), F0);\n // BRDF * NdotL * (pi * intensity); the NdotL cancels the BRDF's.\n sun = F * (D * G * PI / (4.0 * NdotV)) * sunLight;\n }\n\n // The hemisphere ambient, looked up along the reflection. A rough\n // lobe gathers from around the normal, so lean the lookup toward N.\n let R = reflect(-V, N);\n let Rd = normalize(mix(R, N, roughness * roughness));\n let sky = mix(env.groundColor, env.skyColor, Rd.y * 0.5 + 0.5) * env.ambientIntensity;\n let reflectance = envBrdfApprox(F0, roughness, NdotV);\n\n out.light = sun + sky * reflectance;\n out.reflectance = reflectance;\n return out;\n }\n";
34
+ //# sourceMappingURL=specular.wgsl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specular.wgsl.d.ts","sourceRoot":"","sources":["../../src/shaders/specular.wgsl.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,QAAQ,CAAC;AAE5C,eAAO,MAAM,YAAY,u1IAiGxB,CAAC"}