@ifc-lite/renderer 4.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 (74) hide show
  1. package/dist/edge-params.d.ts +43 -0
  2. package/dist/edge-params.d.ts.map +1 -0
  3. package/dist/edge-params.js +63 -0
  4. package/dist/edge-params.js.map +1 -0
  5. package/dist/edge-pass.d.ts +38 -0
  6. package/dist/edge-pass.d.ts.map +1 -0
  7. package/dist/edge-pass.js +111 -0
  8. package/dist/edge-pass.js.map +1 -0
  9. package/dist/index.d.ts +29 -14
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +56 -34
  12. package/dist/index.js.map +1 -1
  13. package/dist/instanced-render.d.ts +3 -3
  14. package/dist/instanced-render.js +3 -3
  15. package/dist/mesh-material.d.ts +26 -0
  16. package/dist/mesh-material.d.ts.map +1 -0
  17. package/dist/mesh-material.js +52 -0
  18. package/dist/mesh-material.js.map +1 -0
  19. package/dist/mesh-rte-uniforms.d.ts +1 -0
  20. package/dist/mesh-rte-uniforms.d.ts.map +1 -1
  21. package/dist/mesh-rte-uniforms.js +1 -0
  22. package/dist/mesh-rte-uniforms.js.map +1 -1
  23. package/dist/overlay-theme-uniforms.d.ts +54 -0
  24. package/dist/overlay-theme-uniforms.d.ts.map +1 -0
  25. package/dist/overlay-theme-uniforms.js +89 -0
  26. package/dist/overlay-theme-uniforms.js.map +1 -0
  27. package/dist/overlay-theme.d.ts +73 -0
  28. package/dist/overlay-theme.d.ts.map +1 -0
  29. package/dist/overlay-theme.js +24 -0
  30. package/dist/overlay-theme.js.map +1 -0
  31. package/dist/pipeline.d.ts +2 -0
  32. package/dist/pipeline.d.ts.map +1 -1
  33. package/dist/pipeline.js +10 -11
  34. package/dist/pipeline.js.map +1 -1
  35. package/dist/post-pass-chain.d.ts +1 -1
  36. package/dist/post-pass-chain.d.ts.map +1 -1
  37. package/dist/post-pass-chain.js +19 -13
  38. package/dist/post-pass-chain.js.map +1 -1
  39. package/dist/renderer-overlays.d.ts +8 -7
  40. package/dist/renderer-overlays.d.ts.map +1 -1
  41. package/dist/renderer-overlays.js +11 -14
  42. package/dist/renderer-overlays.js.map +1 -1
  43. package/dist/scene.d.ts +10 -1
  44. package/dist/scene.d.ts.map +1 -1
  45. package/dist/scene.js.map +1 -1
  46. package/dist/section-plane.d.ts +3 -0
  47. package/dist/section-plane.d.ts.map +1 -1
  48. package/dist/section-plane.js +15 -24
  49. package/dist/section-plane.js.map +1 -1
  50. package/dist/shaders/color-transfer.wgsl.d.ts +5 -3
  51. package/dist/shaders/color-transfer.wgsl.d.ts.map +1 -1
  52. package/dist/shaders/color-transfer.wgsl.js +5 -3
  53. package/dist/shaders/color-transfer.wgsl.js.map +1 -1
  54. package/dist/shaders/edges.wgsl.d.ts +2 -0
  55. package/dist/shaders/edges.wgsl.d.ts.map +1 -0
  56. package/dist/shaders/edges.wgsl.js +158 -0
  57. package/dist/shaders/edges.wgsl.js.map +1 -0
  58. package/dist/shaders/main.wgsl.d.ts +1 -1
  59. package/dist/shaders/main.wgsl.d.ts.map +1 -1
  60. package/dist/shaders/main.wgsl.js +81 -77
  61. package/dist/shaders/main.wgsl.js.map +1 -1
  62. package/dist/shaders/specular.wgsl.d.ts +34 -0
  63. package/dist/shaders/specular.wgsl.d.ts.map +1 -0
  64. package/dist/shaders/specular.wgsl.js +134 -0
  65. package/dist/shaders/specular.wgsl.js.map +1 -0
  66. package/dist/visual-enhancement.d.ts +10 -3
  67. package/dist/visual-enhancement.d.ts.map +1 -1
  68. package/dist/visual-enhancement.js +9 -3
  69. package/dist/visual-enhancement.js.map +1 -1
  70. package/package.json +2 -2
  71. package/dist/post-processor.d.ts +0 -46
  72. package/dist/post-processor.d.ts.map +0 -1
  73. package/dist/post-processor.js +0 -295
  74. package/dist/post-processor.js.map +0 -1
package/dist/index.js CHANGED
@@ -43,6 +43,8 @@ export { hostsOtherEntities } from './mesh-entity-hosting.js';
43
43
  export { FederationRegistry, federationRegistry } from './federation-registry.js';
44
44
  export * from './types.js';
45
45
  export { resolveEnvironment, deriveSkyGradient, packEnvironmentUniforms, ENVIRONMENT_UNIFORM_SIZE, } from './environment.js';
46
+ export { DEFAULT_OVERLAY_THEME } from './overlay-theme.js';
47
+ import { DEFAULT_OVERLAY_THEME } from './overlay-theme.js';
46
48
  export { resolveContributionThresholdPx, projectedAabbRadiusPx } from './contribution-cull.js';
47
49
  export { chunkCellKey, bucketBaseKeyFor, DEFAULT_CHUNK_CELL_SIZE } from './chunk-grid.js';
48
50
  export { selectEvictions, MIN_EVICTION_AGE_FRAMES } from './residency.js';
@@ -83,6 +85,7 @@ import { isRteAabbVisible, rteFrustum, sourceFrustumFromRte } from './rte-frustu
83
85
  import { VisualEnhancementResolver, livePostEffects } from './visual-enhancement.js';
84
86
  import { packClipBox } from './clip-box.js';
85
87
  import { MESH_FLAGS_BYTE_OFFSET, MESH_FLAG_RTE_DRAWABLE, MESH_UNIFORM_FLOATS, MESH_UNIFORM_OFFSET, packRteCameraOrigin, packRteFragmentSpace, } from './mesh-rte-uniforms.js';
88
+ import { packMeshMaterial } from './mesh-material.js';
86
89
  import { RendererOverlays } from './renderer-overlays.js';
87
90
  import { resolveSectionPlaneFrame } from './render-section-plane.js';
88
91
  import { PickingManager } from './picking-manager.js';
@@ -138,10 +141,13 @@ export class Renderer {
138
141
  scene;
139
142
  picker = null;
140
143
  canvas;
144
+ // The overlay theme (#5484), kept so a pre-init `setOverlayTheme` call
145
+ // (and a later re-init) still lands — `init()` re-applies it to `pipeline`.
146
+ overlayTheme = DEFAULT_OVERLAY_THEME;
141
147
  /**
142
148
  * Section-plane gizmo, 2D section drawing/cap, and the standalone 3D line
143
149
  * + symbolic annotation overlays (issue #2425). Created here rather than in
144
- * `init()` so a pre-init `setOverlayLineColor` still lands — the GPU
150
+ * `init()` so a pre-init `setOverlayTheme` still lands — the GPU
145
151
  * objects inside stay null until `init()` calls `overlays.init()`.
146
152
  */
147
153
  overlays = new RendererOverlays({
@@ -505,6 +511,9 @@ export class Renderer {
505
511
  this.canvas.height = height;
506
512
  }
507
513
  this.pipeline = new RenderPipeline(this.device, width, height);
514
+ // Re-apply any theme set before this (re)creation, or set by a prior
515
+ // init() before a device-loss re-init, so it isn't lost (#5484).
516
+ this.pipeline.selectionColorUniform.update(this.overlayTheme.selection);
508
517
  this.picker = new Picker(this.device, width, height);
509
518
  this.overlays.init(this.device.getDevice(), this.device.getFormat(), this.pipeline.getSampleCount());
510
519
  this.referenceImages.init(this.device.getDevice(), this.device.getFormat(), this.pipeline.getSampleCount());
@@ -1518,8 +1527,8 @@ export class Renderer {
1518
1527
  const edgeIntensity = Math.min(3.0, Math.max(0.0, visualEnhancement.edgeContrast.intensity));
1519
1528
  const edgeEnabledU32 = edgeEnabled ? 1 : 0;
1520
1529
  const edgeIntensityMilliU32 = Math.round(edgeIntensity * 1000);
1521
- // Only the separation lines read the object-id attachment after the pass.
1522
- const needsObjectIdPass = livePostEffects(visualEnhancement, effectsLive).separationLines;
1530
+ // Only the edge pass reads the object-id attachment after the pass.
1531
+ const needsObjectIdPass = livePostEffects(visualEnhancement, effectsLive).edges;
1523
1532
  // Check if visibility filtering is active
1524
1533
  const hasHiddenFilter = options.hiddenIds && options.hiddenIds.size > 0;
1525
1534
  const hasIsolatedFilter = options.isolatedIds !== null && options.isolatedIds !== undefined;
@@ -1764,10 +1773,7 @@ export class Renderer {
1764
1773
  meshBuf[34] = mesh.color[2];
1765
1774
  // Selected meshes always keep their own alpha so highlights stay opaque
1766
1775
  meshBuf[35] = isSelected ? mesh.color[3] : alphaForMesh(mesh.expressId, mesh.color[3]);
1767
- meshBuf[36] = mesh.material?.metallic ?? 0.0;
1768
- meshBuf[37] = mesh.material?.roughness ?? 0.6;
1769
- meshBuf[38] = 0;
1770
- meshBuf[39] = 0;
1776
+ packMeshMaterial(meshBuf, mesh.color[3], mesh.material);
1771
1777
  // Section plane data (offset 40-43)
1772
1778
  if (sectionPlaneData) {
1773
1779
  meshBuf[40] = sectionPlaneData.normal[0];
@@ -2244,12 +2250,9 @@ export class Renderer {
2244
2250
  tpl[29] = 0;
2245
2251
  tpl[30] = 0;
2246
2252
  tpl[31] = 1;
2247
- // Color placeholder — overwritten per batch
2248
- // tpl[32..35] set per batch
2249
- tpl[36] = 0.0; // metallic
2250
- tpl[37] = 0.6; // roughness
2251
- tpl[38] = 0;
2252
- tpl[39] = 0; // padding
2253
+ // Colour + material row (tpl[32..39]) are patched per draw; the
2254
+ // instanced passes keep this opaque default.
2255
+ packMeshMaterial(tpl);
2253
2256
  if (sectionPlaneData) {
2254
2257
  tpl[40] = sectionPlaneData.normal[0];
2255
2258
  tpl[41] = sectionPlaneData.normal[1];
@@ -2286,11 +2289,13 @@ export class Renderer {
2286
2289
  const renderBatch = (batch) => {
2287
2290
  if (!batch.bindGroup || !batch.uniformBuffer)
2288
2291
  return;
2289
- // Patch only the per-batch color (4 floats at offset 32)
2292
+ // Patch the per-batch colour, and the material its AUTHORED
2293
+ // alpha implies: an X-Ray fade is not glass (#5386).
2290
2294
  tpl[32] = batch.color[0];
2291
2295
  tpl[33] = batch.color[1];
2292
2296
  tpl[34] = batch.color[2];
2293
2297
  tpl[35] = alphaForBatch(batch, batch.color[3]);
2298
+ packMeshMaterial(tpl, batch.color[3]);
2294
2299
  // Per-batch local frame: the batch's vertices are stored
2295
2300
  // RELATIVE to batch.origin (f32-small), so set the model
2296
2301
  // matrix translation column to origin (world = origin + pos).
@@ -2474,6 +2479,16 @@ export class Renderer {
2474
2479
  tpl[33] = txOverride ? txOverride[1] : tm.color[1];
2475
2480
  tpl[34] = txOverride ? txOverride[2] : tm.color[2];
2476
2481
  tpl[35] = txAlpha;
2482
+ // Same authored-alpha + material contract as the flat/batched
2483
+ // paths (mesh-material.ts) — a call with neither argument
2484
+ // silently gave every textured metal or translucent mesh the
2485
+ // opaque dielectric default (#5623 review). The pipeline
2486
+ // itself is still opaque/depth-write only (no blend state,
2487
+ // see `txAlpha` above), so a translucent authored alpha still
2488
+ // never actually blends here — only the glass/roughness
2489
+ // CHOICE in the shader follows the same rule as everywhere
2490
+ // else, for the same reason `tm.material` does.
2491
+ packMeshMaterial(tpl, tm.color[3], tm.material);
2477
2492
  device.queue.writeBuffer(tm.uniformBuffer, 0, tpl);
2478
2493
  pass.setBindGroup(0, tm.bindGroup);
2479
2494
  pass.setVertexBuffer(0, tm.vertexBuffer);
@@ -2536,7 +2551,7 @@ export class Renderer {
2536
2551
  // flags.x bit 1 = overlay: tells the shader to preserve baseColor.a
2537
2552
  // (the overlay pipeline now has src-alpha blending so low-alpha ghost
2538
2553
  // tints composite correctly against the opaque pass) AND skip the
2539
- // glass-fresnel branch (which is meant for real glass materials and
2554
+ // specular term (glass reflections are meant for real glass and
2540
2555
  // would whiten low-alpha colour overrides at grazing angles).
2541
2556
  const overrideBatches = this.scene.getOverrideBatches();
2542
2557
  if (overrideBatches.length > 0) {
@@ -2650,10 +2665,7 @@ export class Renderer {
2650
2665
  tpl[33] = mesh.color[1];
2651
2666
  tpl[34] = mesh.color[2];
2652
2667
  tpl[35] = alphaForMesh(mesh.expressId, mesh.color[3]);
2653
- tpl[36] = mesh.material?.metallic ?? 0.0;
2654
- tpl[37] = mesh.material?.roughness ?? 0.6;
2655
- tpl[38] = 0;
2656
- tpl[39] = 0;
2668
+ packMeshMaterial(tpl, mesh.color[3], mesh.material);
2657
2669
  if (sectionPlaneData) {
2658
2670
  tpl[40] = sectionPlaneData.normal[0];
2659
2671
  tpl[41] = sectionPlaneData.normal[1];
@@ -2714,10 +2726,7 @@ export class Renderer {
2714
2726
  tpl[33] = mesh.color[1];
2715
2727
  tpl[34] = mesh.color[2];
2716
2728
  tpl[35] = mesh.color[3];
2717
- tpl[36] = mesh.material?.metallic ?? 0.0;
2718
- tpl[37] = mesh.material?.roughness ?? 0.6;
2719
- tpl[38] = 0;
2720
- tpl[39] = 0;
2729
+ packMeshMaterial(tpl, mesh.color[3], mesh.material);
2721
2730
  if (sectionPlaneData) {
2722
2731
  tpl[40] = sectionPlaneData.normal[0];
2723
2732
  tpl[41] = sectionPlaneData.normal[1];
@@ -3076,13 +3085,21 @@ export class Renderer {
3076
3085
  this.overlays.clearSection2DOverlay();
3077
3086
  }
3078
3087
  /**
3079
- * Set the colour of the overlay lines (annotation / alignment / grid) and the
3080
- * section-cut outline (RGBA, 0..1). Defaults to opaque black; theme it to keep
3081
- * lines legible on a dark canvas. The matching label colour is per-text via
3088
+ * Set the one colour vocabulary every overlay draws in (#5484): the selection
3089
+ * highlight, the section-plane preview (one accent for every axis), every
3090
+ * overlay line channel (section-cut outline, IfcAnnotation, alignment,
3091
+ * IfcGrid, DXF / LandXML) and the clash pair / overlap tints. Call this on
3092
+ * theme change and once after `init()`; the underlying GPU uniforms are
3093
+ * written only here, never per frame. Supersedes `setOverlayLineColor`
3094
+ * (deleted — the app never called it with a themed colour). See
3095
+ * `OverlayTheme` for which fields want linear-light RGBA and which want
3096
+ * sRGB-direct RGBA. The matching label colour is per-text via
3082
3097
  * `SymbolicTextInput.color` on `uploadAnnotationTexts3D`.
3083
3098
  */
3084
- setOverlayLineColor(color) {
3085
- this.overlays.setOverlayLineColor(color);
3099
+ setOverlayTheme(theme) {
3100
+ this.overlayTheme = theme;
3101
+ this.pipeline?.selectionColorUniform.update(theme.selection);
3102
+ this.overlays.setTheme(theme);
3086
3103
  }
3087
3104
  /**
3088
3105
  * Set one standalone 3D line overlay, or clear it by passing `null`.
@@ -3095,7 +3112,7 @@ export class Renderer {
3095
3112
  *
3096
3113
  * Every channel is an independent buffer with its own visibility, so
3097
3114
  * setting one leaves the other three untouched. All four share the colour
3098
- * set by {@link setOverlayLineColor}; label colour is per-text via
3115
+ * set by `Renderer.setOverlayTheme`'s `overlayLine` field; label colour is per-text via
3099
3116
  * `SymbolicTextInput.color` on `uploadAnnotationTexts3D`.
3100
3117
  *
3101
3118
  * The channels differ in exactly one way — whether they grow the scene
@@ -3115,8 +3132,10 @@ export class Renderer {
3115
3132
  /**
3116
3133
  * Show (or clear) the clash-overlap box: the wireframe AABB of a focused
3117
3134
  * clash, drawn in `color` so the overlap region reads as a distinct third
3118
- * colour next to the two glowing clash elements (#1277). Pass `null` to
3119
- * clear. `min`/`max` are world-space corners (clash works in world frame).
3135
+ * colour next to the two glowing clash elements (#1277). Omit `color` to
3136
+ * draw it in the overlay theme's `clashOverlap` and keep following it
3137
+ * across `setOverlayTheme` calls (#5490). Pass `null` to clear.
3138
+ * `min`/`max` are world-space corners (clash works in world frame).
3120
3139
  */
3121
3140
  setClashOverlapBox(box) {
3122
3141
  this.overlays.setClashOverlapBox(box);
@@ -3125,8 +3144,10 @@ export class Renderer {
3125
3144
  * Draw the focused clash's CONTACT geometry as 3D line segments — the real
3126
3145
  * shared-face polygon outlines / intersection lines, not the AABB box.
3127
3146
  * `vertices` is a flat line-list (x,y,z per endpoint, 2 endpoints per
3128
- * segment) in world frame. Pass `null` to clear. Shares the clash-box line
3129
- * buffer, so only one of this / setClashOverlapBox is shown at a time.
3147
+ * segment) in world frame. Omit `color` to follow the overlay theme's
3148
+ * `clashOverlap`, as for `setClashOverlapBox`. Pass `null` to clear. Shares
3149
+ * the clash-box line buffer, so only one of this / setClashOverlapBox is
3150
+ * shown at a time.
3130
3151
  */
3131
3152
  setClashContactLines(lines) {
3132
3153
  this.overlays.setClashContactLines(lines);
@@ -3138,7 +3159,8 @@ export class Renderer {
3138
3159
  * BIMcollab Zoom / Solibri presentation). Pass `null` to clear. Independent
3139
3160
  * of `setClashOverlapBox` / `setClashContactLines`: the caller decides
3140
3161
  * which one is current for a given clash (solid when the kernel resolved
3141
- * one, box/lines as the fallback when it didn't).
3162
+ * one, box/lines as the fallback when it didn't). Omit `color` to follow
3163
+ * the overlay theme's `clashOverlap`, as for `setClashOverlapBox`.
3142
3164
  */
3143
3165
  setClashIntersectionSolid(solid) {
3144
3166
  this.overlays.setClashIntersectionSolid(solid);