@ifc-lite/renderer 1.16.0 → 1.18.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 (47) hide show
  1. package/README.md +73 -15
  2. package/dist/edl-pass.d.ts +52 -0
  3. package/dist/edl-pass.d.ts.map +1 -0
  4. package/dist/edl-pass.js +204 -0
  5. package/dist/edl-pass.js.map +1 -0
  6. package/dist/index.d.ts +77 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +348 -19
  9. package/dist/index.js.map +1 -1
  10. package/dist/picker.d.ts +22 -3
  11. package/dist/picker.d.ts.map +1 -1
  12. package/dist/picker.js +48 -8
  13. package/dist/picker.js.map +1 -1
  14. package/dist/picking-manager.d.ts +14 -1
  15. package/dist/picking-manager.d.ts.map +1 -1
  16. package/dist/picking-manager.js +13 -1
  17. package/dist/picking-manager.js.map +1 -1
  18. package/dist/pipeline.d.ts.map +1 -1
  19. package/dist/pipeline.js +16 -1
  20. package/dist/pipeline.js.map +1 -1
  21. package/dist/point-picker.d.ts +61 -0
  22. package/dist/point-picker.d.ts.map +1 -0
  23. package/dist/point-picker.js +223 -0
  24. package/dist/point-picker.js.map +1 -0
  25. package/dist/pointcloud/point-cloud-node.d.ts +56 -0
  26. package/dist/pointcloud/point-cloud-node.d.ts.map +1 -0
  27. package/dist/pointcloud/point-cloud-node.js +112 -0
  28. package/dist/pointcloud/point-cloud-node.js.map +1 -0
  29. package/dist/pointcloud/point-cloud-renderer.d.ts +135 -0
  30. package/dist/pointcloud/point-cloud-renderer.d.ts.map +1 -0
  31. package/dist/pointcloud/point-cloud-renderer.js +296 -0
  32. package/dist/pointcloud/point-cloud-renderer.js.map +1 -0
  33. package/dist/pointcloud/point-pipeline.d.ts +25 -0
  34. package/dist/pointcloud/point-pipeline.d.ts.map +1 -0
  35. package/dist/pointcloud/point-pipeline.js +111 -0
  36. package/dist/pointcloud/point-pipeline.js.map +1 -0
  37. package/dist/pointcloud/point-shader.wgsl.d.ts +22 -0
  38. package/dist/pointcloud/point-shader.wgsl.d.ts.map +1 -0
  39. package/dist/pointcloud/point-shader.wgsl.js +212 -0
  40. package/dist/pointcloud/point-shader.wgsl.js.map +1 -0
  41. package/dist/shaders/main.wgsl.d.ts +1 -1
  42. package/dist/shaders/main.wgsl.d.ts.map +1 -1
  43. package/dist/shaders/main.wgsl.js +15 -3
  44. package/dist/shaders/main.wgsl.js.map +1 -1
  45. package/dist/types.d.ts +20 -0
  46. package/dist/types.d.ts.map +1 -1
  47. package/package.json +3 -3
@@ -0,0 +1,212 @@
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
+ * WGSL for the point cloud splat pipeline.
6
+ *
7
+ * Draws each point as an instanced quad (6 verts per point, triangle-list
8
+ * topology) so we can give it a real on-screen size — `point-list` has
9
+ * no `gl_PointSize` equivalent in WebGPU, which is why a 1-px point cloud
10
+ * looks like a halftone screen as you zoom in.
11
+ *
12
+ * Three size modes (uniforms.sizing.x):
13
+ * 0 = fixed-px — every point renders at `pointSizePx` pixels
14
+ * 1 = adaptive-world — splat covers `worldRadius` metres, projected
15
+ * 2 = attenuated — adaptive but clamped to [1, pointSizePx] px
16
+ *
17
+ * Color modes (uniforms.colorModeAndExtras.x):
18
+ * 0 = per-vertex RGB, 1 = classification, 2 = intensity ramp,
19
+ * 3 = height ramp, 4 = fixed override.
20
+ *
21
+ * Round shape: fragment discards corners outside the unit disc, so
22
+ * splats render as circles (not squares) at any size > ~3 px.
23
+ */
24
+ export const pointShaderSource = `
25
+ struct PointUniforms {
26
+ viewProj: mat4x4<f32>,
27
+ model: mat4x4<f32>,
28
+ colorOverride: vec4<f32>,
29
+ // x = colorMode, y = pointSizePx, z = heightMin, w = heightMax
30
+ colorModeAndExtras: vec4<f32>,
31
+ // x = sizeMode, y = worldRadius (m), z = viewportWidth, w = viewportHeight
32
+ sizing: vec4<f32>,
33
+ sectionPlane: vec4<f32>,
34
+ // x = assetExpressId (federation-aware globalId), y = sectionEnabled,
35
+ // z = roundShape, w = unused
36
+ flags: vec4<u32>,
37
+ }
38
+ @binding(0) @group(0) var<uniform> uniforms: PointUniforms;
39
+
40
+ struct VertexInput {
41
+ @location(0) position: vec3<f32>,
42
+ @location(1) rgbAndClass: vec4<f32>, // unorm8x4 → 0..1 each
43
+ @location(2) intensityPacked: u32, // low 16 bits = intensity
44
+ @location(3) entityId: u32,
45
+ }
46
+
47
+ struct VertexOutput {
48
+ @builtin(position) position: vec4<f32>,
49
+ @location(0) color: vec4<f32>,
50
+ @location(1) worldPos: vec3<f32>,
51
+ @location(2) @interpolate(flat) entityId: u32,
52
+ @location(3) quadUv: vec2<f32>,
53
+ }
54
+
55
+ fn classification_color(class_id: u32) -> vec3<f32> {
56
+ switch (class_id) {
57
+ case 0u, 1u: { return vec3<f32>(0.65, 0.65, 0.65); }
58
+ case 2u: { return vec3<f32>(0.55, 0.40, 0.25); }
59
+ case 3u: { return vec3<f32>(0.55, 0.85, 0.45); }
60
+ case 4u: { return vec3<f32>(0.30, 0.75, 0.30); }
61
+ case 5u: { return vec3<f32>(0.10, 0.45, 0.15); }
62
+ case 6u: { return vec3<f32>(0.95, 0.55, 0.20); }
63
+ case 7u: { return vec3<f32>(0.95, 0.20, 0.20); }
64
+ case 8u: { return vec3<f32>(0.20, 0.85, 0.95); }
65
+ case 9u: { return vec3<f32>(0.20, 0.40, 0.95); }
66
+ case 10u: { return vec3<f32>(0.55, 0.20, 0.85); }
67
+ case 11u: { return vec3<f32>(0.30, 0.30, 0.30); }
68
+ case 13u: { return vec3<f32>(0.95, 0.85, 0.20); }
69
+ case 14u: { return vec3<f32>(0.95, 0.95, 0.50); }
70
+ case 15u: { return vec3<f32>(0.20, 0.20, 0.55); }
71
+ case 16u: { return vec3<f32>(0.30, 0.65, 0.65); }
72
+ case 17u: { return vec3<f32>(0.85, 0.70, 0.50); }
73
+ case 18u: { return vec3<f32>(0.95, 0.20, 0.20); }
74
+ default: { return vec3<f32>(0.65, 0.65, 0.65); }
75
+ }
76
+ }
77
+
78
+ fn height_ramp(t: f32) -> vec3<f32> {
79
+ let s = clamp(t, 0.0, 1.0);
80
+ if (s < 0.25) {
81
+ let k = s / 0.25;
82
+ return mix(vec3<f32>(0.10, 0.20, 0.85), vec3<f32>(0.10, 0.85, 0.85), k);
83
+ } else if (s < 0.5) {
84
+ let k = (s - 0.25) / 0.25;
85
+ return mix(vec3<f32>(0.10, 0.85, 0.85), vec3<f32>(0.20, 0.85, 0.20), k);
86
+ } else if (s < 0.75) {
87
+ let k = (s - 0.5) / 0.25;
88
+ return mix(vec3<f32>(0.20, 0.85, 0.20), vec3<f32>(0.95, 0.95, 0.20), k);
89
+ } else {
90
+ let k = (s - 0.75) / 0.25;
91
+ return mix(vec3<f32>(0.95, 0.95, 0.20), vec3<f32>(0.95, 0.20, 0.10), k);
92
+ }
93
+ }
94
+
95
+ @vertex
96
+ fn vs_main(input: VertexInput, @builtin(vertex_index) vId: u32) -> VertexOutput {
97
+ // Quad corners (two triangles, CCW) in unit disc coords:
98
+ // tri 1: (-1,-1)(1,-1)(1,1)
99
+ // tri 2: (-1,-1)(1, 1)(-1,1)
100
+ var corners = array<vec2<f32>, 6>(
101
+ vec2<f32>(-1.0, -1.0),
102
+ vec2<f32>( 1.0, -1.0),
103
+ vec2<f32>( 1.0, 1.0),
104
+ vec2<f32>(-1.0, -1.0),
105
+ vec2<f32>( 1.0, 1.0),
106
+ vec2<f32>(-1.0, 1.0),
107
+ );
108
+ let corner = corners[vId];
109
+
110
+ let worldPos4 = uniforms.model * vec4<f32>(input.position, 1.0);
111
+ var clipPos = uniforms.viewProj * worldPos4;
112
+
113
+ // Compute splat half-extent in pixels for the active size mode.
114
+ let sizeMode = u32(uniforms.sizing.x);
115
+ let worldRadius = uniforms.sizing.y;
116
+ let viewport = uniforms.sizing.zw;
117
+ let pointSizePx = uniforms.colorModeAndExtras.y;
118
+
119
+ // halfPx is the splat RADIUS in pixels. The user-facing
120
+ // pointSizePx is the diameter ("8 px point"), so divide by 2
121
+ // when feeding it to the pipeline. Without this the fixed and
122
+ // attenuated branches render splats at ~2x their requested size.
123
+ var halfPx: f32;
124
+ if (sizeMode == 0u) {
125
+ halfPx = max(0.5, pointSizePx * 0.5);
126
+ } else {
127
+ // Project a world-radius offset to clip space, take pixel delta.
128
+ // worldRadius is already a radius — no /2 needed here.
129
+ let edgePos = uniforms.viewProj * (worldPos4 + vec4<f32>(worldRadius, 0.0, 0.0, 0.0));
130
+ let centerNdcX = clipPos.x / max(abs(clipPos.w), 1e-6);
131
+ let edgeNdcX = edgePos.x / max(abs(edgePos.w), 1e-6);
132
+ let projectedPx = abs(edgeNdcX - centerNdcX) * 0.5 * viewport.x;
133
+ if (sizeMode == 2u) {
134
+ halfPx = clamp(projectedPx, 0.5, max(0.5, pointSizePx * 0.5));
135
+ } else {
136
+ halfPx = max(0.5, projectedPx);
137
+ }
138
+ }
139
+
140
+ // Convert pixel offset to clip-space offset. Multiply by clipPos.w
141
+ // because the GPU divides by w during the perspective divide.
142
+ let halfClip = vec2<f32>(halfPx) / max(viewport, vec2<f32>(1.0)) * 2.0 * abs(clipPos.w);
143
+ clipPos.x = clipPos.x + corner.x * halfClip.x;
144
+ clipPos.y = clipPos.y + corner.y * halfClip.y;
145
+
146
+ // Color selection
147
+ let mode = u32(uniforms.colorModeAndExtras.x);
148
+ let intensity01 = f32(input.intensityPacked & 0xffffu) / 65535.0;
149
+ let classId = u32(round(input.rgbAndClass.a * 255.0));
150
+ let heightT =
151
+ (worldPos4.y - uniforms.colorModeAndExtras.z) /
152
+ max(1e-6, uniforms.colorModeAndExtras.w - uniforms.colorModeAndExtras.z);
153
+
154
+ var rgb: vec3<f32>;
155
+ switch (mode) {
156
+ case 0u: { rgb = input.rgbAndClass.rgb; }
157
+ case 1u: { rgb = classification_color(classId); }
158
+ case 2u: { rgb = vec3<f32>(intensity01, intensity01, intensity01); }
159
+ case 3u: { rgb = height_ramp(heightT); }
160
+ case 4u: { rgb = uniforms.colorOverride.rgb; }
161
+ default: { rgb = input.rgbAndClass.rgb; }
162
+ }
163
+
164
+ var output: VertexOutput;
165
+ output.position = clipPos;
166
+ output.color = vec4<f32>(rgb, 1.0);
167
+ output.worldPos = worldPos4.xyz;
168
+ output.entityId = input.entityId;
169
+ output.quadUv = corner;
170
+ return output;
171
+ }
172
+
173
+ struct FragmentOutput {
174
+ @location(0) color: vec4<f32>,
175
+ @location(1) objectId: vec4<f32>,
176
+ }
177
+
178
+ @fragment
179
+ fn fs_main(input: VertexOutput) -> FragmentOutput {
180
+ // Round shape — discard corners outside the unit disc.
181
+ if (uniforms.flags.z == 1u) {
182
+ if (dot(input.quadUv, input.quadUv) > 1.0) {
183
+ discard;
184
+ }
185
+ }
186
+
187
+ // Section-plane clipping
188
+ if (uniforms.flags.y == 1u) {
189
+ let d = dot(uniforms.sectionPlane.xyz, input.worldPos) - uniforms.sectionPlane.w;
190
+ if (d > 0.0) {
191
+ discard;
192
+ }
193
+ }
194
+
195
+ var output: FragmentOutput;
196
+ output.color = input.color;
197
+ // Prefer the asset-level expressId from the uniform when it's set
198
+ // (federation needs to relabel post-stream, so we can't rely on
199
+ // the per-vertex attribute that was baked at upload time).
200
+ // flags.x == 0 → fall back to per-vertex value to preserve the
201
+ // legacy contract during the upload-only rendering window.
202
+ let id = select(input.entityId, uniforms.flags.x, uniforms.flags.x != 0u);
203
+ output.objectId = vec4<f32>(
204
+ f32((id >> 0u) & 0xffu) / 255.0,
205
+ f32((id >> 8u) & 0xffu) / 255.0,
206
+ f32((id >> 16u) & 0xffu) / 255.0,
207
+ f32((id >> 24u) & 0xffu) / 255.0,
208
+ );
209
+ return output;
210
+ }
211
+ `;
212
+ //# sourceMappingURL=point-shader.wgsl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"point-shader.wgsl.js","sourceRoot":"","sources":["../../src/pointcloud/point-shader.wgsl.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2LhC,CAAC"}
@@ -3,5 +3,5 @@
3
3
  * Features: PBR lighting, section plane clipping, selection highlight,
4
4
  * glass fresnel, ACES tone mapping, screen-space edge enhancement.
5
5
  */
6
- export declare const mainShaderSource = "\n struct Uniforms {\n viewProj: mat4x4<f32>,\n model: mat4x4<f32>,\n baseColor: vec4<f32>,\n metallicRoughness: vec2<f32>, // x = metallic, y = roughness\n _padding1: vec2<f32>,\n sectionPlane: vec4<f32>, // xyz = plane normal, w = plane distance\n flags: vec4<u32>, // x = isSelected, y = sectionEnabled, z = edgeEnabled, w = edgeIntensityMilli\n }\n @binding(0) @group(0) var<uniform> uniforms: Uniforms;\n\n struct VertexInput {\n @location(0) position: vec3<f32>,\n @location(1) normal: vec3<f32>,\n @location(2) entityId: u32,\n }\n\n struct VertexOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) worldPos: vec3<f32>,\n @location(1) normal: vec3<f32>,\n @location(2) @interpolate(flat) entityId: u32,\n @location(3) viewPos: vec3<f32>, // For edge detection\n }\n\n @vertex\n fn vs_main(input: VertexInput, @builtin(instance_index) instanceIndex: u32) -> VertexOutput {\n var output: VertexOutput;\n let worldPos = uniforms.model * vec4<f32>(input.position, 1.0);\n output.position = uniforms.viewProj * worldPos;\n // Anti z-fighting: deterministic depth nudge per entity.\n // Knuth multiplicative hash spreads sequential IDs across 0-255\n // so coplanar faces from different entities always get distinct depths.\n // At 1e-6 per step the max world-space offset is <3mm at 10m \u2014 invisible.\n let zHash = (input.entityId * 2654435761u) & 255u;\n output.position.z *= 1.0 + f32(zHash) * 1e-6;\n output.worldPos = worldPos.xyz;\n output.normal = normalize((uniforms.model * vec4<f32>(input.normal, 0.0)).xyz);\n output.entityId = input.entityId;\n // Store view-space position for edge detection\n output.viewPos = (uniforms.viewProj * worldPos).xyz;\n return output;\n }\n\n // PBR helper functions\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 num = a2;\n let denomBase = (NdotH2 * (a2 - 1.0) + 1.0);\n let denom = 3.14159265 * denomBase * denomBase;\n return num / max(denom, 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 let num = NdotV;\n let denom = NdotV * (1.0 - k) + k;\n return num / max(denom, 0.0000001);\n }\n\n fn geometrySmith(NdotV: f32, NdotL: f32, roughness: f32) -> f32 {\n let ggx2 = geometrySchlickGGX(NdotV, roughness);\n let ggx1 = geometrySchlickGGX(NdotL, roughness);\n return ggx1 * ggx2;\n }\n\n fn encodeId24(id: u32) -> vec4<f32> {\n let r = f32((id >> 16u) & 255u) / 255.0;\n let g = f32((id >> 8u) & 255u) / 255.0;\n let b = f32(id & 255u) / 255.0;\n return vec4<f32>(r, g, b, 1.0);\n }\n\n struct FragmentOutput {\n @location(0) color: vec4<f32>,\n @location(1) objectIdEncoded: vec4<f32>,\n }\n\n @fragment\n fn fs_main(input: VertexOutput) -> FragmentOutput {\n // Section plane clipping - discard fragments ABOVE the plane.\n // flags.y packs two bits: bit 0 = enabled, bit 1 = flipped.\n let sectionEnabled = (uniforms.flags.y & 1u) == 1u;\n if (sectionEnabled) {\n let planeNormal = uniforms.sectionPlane.xyz;\n let planeDistance = uniforms.sectionPlane.w;\n let flipped = (uniforms.flags.y & 2u) == 2u;\n let side = select(1.0, -1.0, flipped);\n let distToPlane = (dot(input.worldPos, planeNormal) - planeDistance) * side;\n if (distToPlane > 0.0) {\n discard;\n }\n }\n\n // Compute normal \u2014 with fallback for zero normals\n // dpdx/dpdy must be called outside non-uniform control flow (WGSL spec),\n // so we compute the flat normal unconditionally and select below.\n let faceN = cross(dpdx(input.worldPos), dpdy(input.worldPos));\n var N = input.normal;\n let nLen2 = dot(N, N);\n if (nLen2 < 0.0001) {\n // Fallback: use flat normal from screen-space derivatives\n let fLen2 = dot(faceN, faceN);\n N = select(vec3<f32>(0.0, 1.0, 0.0), faceN * inverseSqrt(fLen2), fLen2 > 1e-10);\n } else {\n N = N * inverseSqrt(nLen2);\n }\n\n // Enhanced lighting with multiple sources\n let sunLight = normalize(vec3<f32>(0.5, 1.0, 0.3)); // Main directional light\n let fillLight = normalize(vec3<f32>(-0.5, 0.3, -0.3)); // Fill light\n let rimLight = normalize(vec3<f32>(0.0, 0.2, -1.0)); // Rim light for edge definition\n\n // Hemisphere ambient - reduced for less washed-out look\n let skyColor = vec3<f32>(0.3, 0.35, 0.4); // Darker sky\n let groundColor = vec3<f32>(0.15, 0.1, 0.08); // Darker ground\n let hemisphereFactor = N.y * 0.5 + 0.5;\n let ambient = mix(groundColor, skyColor, hemisphereFactor) * 0.25;\n\n // Two-sided sun light so inner faces (I-beam channels) stay visible\n let NdotL = abs(dot(N, sunLight));\n let wrap = 0.3;\n let diffuseSun = max((NdotL + wrap) / (1.0 + wrap), 0.0) * 0.55;\n\n // Fill light - two-sided\n let NdotFill = abs(dot(N, fillLight));\n let diffuseFill = NdotFill * 0.15;\n\n // Rim light for edge definition\n let NdotRim = max(dot(N, rimLight), 0.0);\n let rim = pow(NdotRim, 4.0) * 0.15;\n\n var baseColor = uniforms.baseColor.rgb;\n\n // Detect if the color is close to white/gray (low saturation)\n let baseGray = dot(baseColor, vec3<f32>(0.299, 0.587, 0.114));\n let baseSaturation = length(baseColor - vec3<f32>(baseGray)) / max(baseGray, 0.001);\n let isWhiteish = 1.0 - smoothstep(0.0, 0.3, baseSaturation);\n\n // Darken whites/grays more to reduce washed-out appearance\n baseColor = mix(baseColor, baseColor * 0.7, isWhiteish * 0.4);\n\n // Combine all lighting\n var color = baseColor * (ambient + diffuseSun + diffuseFill + rim);\n\n // Selection highlight - add glow/fresnel effect\n if (uniforms.flags.x == 1u) {\n let V = normalize(-input.worldPos);\n let NdotV = max(dot(N, V), 0.0);\n let fresnel = pow(1.0 - NdotV, 2.0);\n let highlightColor = vec3<f32>(0.3, 0.6, 1.0);\n color = mix(color, highlightColor, fresnel * 0.5 + 0.2);\n }\n\n // Beautiful fresnel effect for transparent materials (glass)\n // Skip when selected \u2014 the glass shine and desaturation wash out the\n // blue highlight, making it appear white instead of blue.\n // Also force alpha to 1.0 for selected objects so the highlight is\n // fully opaque (the selection pipeline has no alpha blending).\n var finalAlpha = select(uniforms.baseColor.a, 1.0, uniforms.flags.x == 1u);\n if (finalAlpha < 0.99 && uniforms.flags.x != 1u) {\n // Calculate view direction for fresnel\n let V = normalize(-input.worldPos);\n let NdotV = max(dot(N, V), 0.0);\n\n // Enhanced fresnel effect - stronger at edges (grazing angles)\n // Using Schlick's approximation for realistic glass reflection\n let fresnelPower = 1.5; // Higher = softer edge reflections\n let fresnel = pow(1.0 - NdotV, fresnelPower);\n\n // Glass reflection tint (sky/environment reflection at edges)\n let reflectionTint = vec3<f32>(0.92, 0.96, 1.0); // Cool sky reflection\n let reflectionStrength = fresnel * 0.6; // Strong edge reflections\n\n // Mix in reflection tint at edges\n color = mix(color, color * reflectionTint, reflectionStrength);\n\n // Add realistic glass shine - brighter at edges where light reflects\n let glassShine = fresnel * 0.12;\n color += glassShine;\n\n // Slight desaturation at edges (glass reflects environment, not just color)\n let edgeDesaturation = fresnel * 0.25;\n let gray = dot(color, vec3<f32>(0.299, 0.587, 0.114));\n color = mix(color, vec3<f32>(gray), edgeDesaturation);\n\n // Make glass more transparent (reduce opacity by 30%)\n finalAlpha = finalAlpha * 0.7;\n }\n\n // Exposure adjustment - darken overall\n color *= 0.85;\n\n // Contrast enhancement\n color = (color - 0.5) * 1.15 + 0.5;\n color = max(color, vec3<f32>(0.0));\n\n // Saturation boost - stronger for colored surfaces, less for whites\n let gray = dot(color, vec3<f32>(0.299, 0.587, 0.114));\n let satBoost = mix(1.4, 1.1, isWhiteish); // More saturation for colored surfaces\n color = mix(vec3<f32>(gray), color, satBoost);\n\n // ACES filmic tone mapping\n let a = 2.51;\n let b = 0.03;\n let c = 2.43;\n let d = 0.59;\n let e = 0.14;\n color = clamp((color * (a * color + b)) / (color * (c * color + d) + e), vec3<f32>(0.0), vec3<f32>(1.0));\n\n // Subtle edge enhancement using screen-space derivatives\n let depthGradient = length(vec2<f32>(\n dpdx(input.viewPos.z),\n dpdy(input.viewPos.z)\n ));\n let normalGradient = length(vec2<f32>(\n length(dpdx(input.normal)),\n length(dpdy(input.normal))\n ));\n\n if (uniforms.flags.z == 1u) {\n // Threshold filters subtle normal discontinuities at internal\n // triangle edges between coplanar entities in the same batch.\n let edgeFactor = smoothstep(0.02, 0.12, depthGradient * 10.0 + normalGradient * 5.0);\n let edgeIntensity = f32(uniforms.flags.w) / 1000.0;\n let edgeDarkenStrength = clamp(0.25 * edgeIntensity, 0.0, 0.85);\n let edgeDarken = mix(1.0, 1.0 - edgeDarkenStrength, edgeFactor);\n color *= edgeDarken;\n }\n\n // Gamma correction\n color = pow(color, vec3<f32>(1.0 / 2.2));\n\n var out: FragmentOutput;\n out.color = vec4<f32>(color, finalAlpha);\n out.objectIdEncoded = encodeId24(input.entityId);\n return out;\n }\n ";
6
+ export declare const mainShaderSource = "\n struct Uniforms {\n viewProj: mat4x4<f32>,\n model: mat4x4<f32>,\n baseColor: vec4<f32>,\n metallicRoughness: vec2<f32>, // x = metallic, y = roughness\n _padding1: vec2<f32>,\n sectionPlane: vec4<f32>, // xyz = plane normal, w = plane distance\n flags: vec4<u32>, // x = isSelected, y = sectionEnabled, z = edgeEnabled, w = edgeIntensityMilli\n }\n @binding(0) @group(0) var<uniform> uniforms: Uniforms;\n\n struct VertexInput {\n @location(0) position: vec3<f32>,\n @location(1) normal: vec3<f32>,\n @location(2) entityId: u32,\n }\n\n struct VertexOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) worldPos: vec3<f32>,\n @location(1) normal: vec3<f32>,\n @location(2) @interpolate(flat) entityId: u32,\n @location(3) viewPos: vec3<f32>, // For edge detection\n }\n\n @vertex\n fn vs_main(input: VertexInput, @builtin(instance_index) instanceIndex: u32) -> VertexOutput {\n var output: VertexOutput;\n let worldPos = uniforms.model * vec4<f32>(input.position, 1.0);\n output.position = uniforms.viewProj * worldPos;\n // Anti z-fighting: deterministic depth nudge per entity.\n // Knuth multiplicative hash spreads sequential IDs across 0-255\n // so coplanar faces from different entities always get distinct depths.\n // At 1e-6 per step the max world-space offset is <3mm at 10m \u2014 invisible.\n let zHash = (input.entityId * 2654435761u) & 255u;\n output.position.z *= 1.0 + f32(zHash) * 1e-6;\n output.worldPos = worldPos.xyz;\n output.normal = normalize((uniforms.model * vec4<f32>(input.normal, 0.0)).xyz);\n output.entityId = input.entityId;\n // Store view-space position for edge detection\n output.viewPos = (uniforms.viewProj * worldPos).xyz;\n return output;\n }\n\n // PBR helper functions\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 num = a2;\n let denomBase = (NdotH2 * (a2 - 1.0) + 1.0);\n let denom = 3.14159265 * denomBase * denomBase;\n return num / max(denom, 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 let num = NdotV;\n let denom = NdotV * (1.0 - k) + k;\n return num / max(denom, 0.0000001);\n }\n\n fn geometrySmith(NdotV: f32, NdotL: f32, roughness: f32) -> f32 {\n let ggx2 = geometrySchlickGGX(NdotV, roughness);\n let ggx1 = geometrySchlickGGX(NdotL, roughness);\n return ggx1 * ggx2;\n }\n\n fn encodeId24(id: u32) -> vec4<f32> {\n let r = f32((id >> 16u) & 255u) / 255.0;\n let g = f32((id >> 8u) & 255u) / 255.0;\n let b = f32(id & 255u) / 255.0;\n return vec4<f32>(r, g, b, 1.0);\n }\n\n struct FragmentOutput {\n @location(0) color: vec4<f32>,\n @location(1) objectIdEncoded: vec4<f32>,\n }\n\n @fragment\n fn fs_main(input: VertexOutput) -> FragmentOutput {\n // Section plane clipping - discard fragments ABOVE the plane.\n // flags.y packs two bits: bit 0 = enabled, bit 1 = flipped.\n let sectionEnabled = (uniforms.flags.y & 1u) == 1u;\n if (sectionEnabled) {\n let planeNormal = uniforms.sectionPlane.xyz;\n let planeDistance = uniforms.sectionPlane.w;\n let flipped = (uniforms.flags.y & 2u) == 2u;\n let side = select(1.0, -1.0, flipped);\n let distToPlane = (dot(input.worldPos, planeNormal) - planeDistance) * side;\n if (distToPlane > 0.0) {\n discard;\n }\n }\n\n // Compute normal \u2014 with fallback for zero normals\n // dpdx/dpdy must be called outside non-uniform control flow (WGSL spec),\n // so we compute the flat normal unconditionally and select below.\n let faceN = cross(dpdx(input.worldPos), dpdy(input.worldPos));\n var N = input.normal;\n let nLen2 = dot(N, N);\n if (nLen2 < 0.0001) {\n // Fallback: use flat normal from screen-space derivatives\n let fLen2 = dot(faceN, faceN);\n N = select(vec3<f32>(0.0, 1.0, 0.0), faceN * inverseSqrt(fLen2), fLen2 > 1e-10);\n } else {\n N = N * inverseSqrt(nLen2);\n }\n\n // Enhanced lighting with multiple sources\n let sunLight = normalize(vec3<f32>(0.5, 1.0, 0.3)); // Main directional light\n let fillLight = normalize(vec3<f32>(-0.5, 0.3, -0.3)); // Fill light\n let rimLight = normalize(vec3<f32>(0.0, 0.2, -1.0)); // Rim light for edge definition\n\n // Hemisphere ambient - reduced for less washed-out look\n let skyColor = vec3<f32>(0.3, 0.35, 0.4); // Darker sky\n let groundColor = vec3<f32>(0.15, 0.1, 0.08); // Darker ground\n let hemisphereFactor = N.y * 0.5 + 0.5;\n let ambient = mix(groundColor, skyColor, hemisphereFactor) * 0.25;\n\n // Two-sided sun light so inner faces (I-beam channels) stay visible\n let NdotL = abs(dot(N, sunLight));\n let wrap = 0.3;\n let diffuseSun = max((NdotL + wrap) / (1.0 + wrap), 0.0) * 0.55;\n\n // Fill light - two-sided\n let NdotFill = abs(dot(N, fillLight));\n let diffuseFill = NdotFill * 0.15;\n\n // Rim light for edge definition\n let NdotRim = max(dot(N, rimLight), 0.0);\n let rim = pow(NdotRim, 4.0) * 0.15;\n\n var baseColor = uniforms.baseColor.rgb;\n\n // Detect if the color is close to white/gray (low saturation)\n let baseGray = dot(baseColor, vec3<f32>(0.299, 0.587, 0.114));\n let baseSaturation = length(baseColor - vec3<f32>(baseGray)) / max(baseGray, 0.001);\n let isWhiteish = 1.0 - smoothstep(0.0, 0.3, baseSaturation);\n\n // Darken whites/grays more to reduce washed-out appearance\n baseColor = mix(baseColor, baseColor * 0.7, isWhiteish * 0.4);\n\n // Combine all lighting\n var color = baseColor * (ambient + diffuseSun + diffuseFill + rim);\n\n // flags.x is a bitfield:\n // bit 0 (value 1) = isSelected \u2192 selection-highlight + force opaque\n // bit 1 (value 2) = isOverlay \u2192 color-override pass; preserve\n // baseColor.a (overlay pipeline has\n // src-alpha blending) AND skip the\n // glass-fresnel branch so low-alpha\n // ghost tints don't pick up the\n // near-white reflection tint meant\n // for real glass materials.\n let isSelected = (uniforms.flags.x & 1u) == 1u;\n let isOverlay = (uniforms.flags.x & 2u) == 2u;\n\n // Selection highlight - add glow/fresnel effect\n if (isSelected) {\n let V = normalize(-input.worldPos);\n let NdotV = max(dot(N, V), 0.0);\n let fresnel = pow(1.0 - NdotV, 2.0);\n let highlightColor = vec3<f32>(0.3, 0.6, 1.0);\n color = mix(color, highlightColor, fresnel * 0.5 + 0.2);\n }\n\n // Beautiful fresnel effect for transparent materials (glass)\n // Skip when selected \u2014 the glass shine and desaturation wash out the\n // blue highlight, making it appear white instead of blue.\n // Also force alpha to 1.0 for selected objects so the highlight is\n // fully opaque (the selection pipeline has no alpha blending).\n var finalAlpha = select(uniforms.baseColor.a, 1.0, isSelected);\n if (finalAlpha < 0.99 && !isSelected && !isOverlay) {\n // Calculate view direction for fresnel\n let V = normalize(-input.worldPos);\n let NdotV = max(dot(N, V), 0.0);\n\n // Enhanced fresnel effect - stronger at edges (grazing angles)\n // Using Schlick's approximation for realistic glass reflection\n let fresnelPower = 1.5; // Higher = softer edge reflections\n let fresnel = pow(1.0 - NdotV, fresnelPower);\n\n // Glass reflection tint (sky/environment reflection at edges)\n let reflectionTint = vec3<f32>(0.92, 0.96, 1.0); // Cool sky reflection\n let reflectionStrength = fresnel * 0.6; // Strong edge reflections\n\n // Mix in reflection tint at edges\n color = mix(color, color * reflectionTint, reflectionStrength);\n\n // Add realistic glass shine - brighter at edges where light reflects\n let glassShine = fresnel * 0.12;\n color += glassShine;\n\n // Slight desaturation at edges (glass reflects environment, not just color)\n let edgeDesaturation = fresnel * 0.25;\n let gray = dot(color, vec3<f32>(0.299, 0.587, 0.114));\n color = mix(color, vec3<f32>(gray), edgeDesaturation);\n\n // Make glass more transparent (reduce opacity by 30%)\n finalAlpha = finalAlpha * 0.7;\n }\n\n // Exposure adjustment - darken overall\n color *= 0.85;\n\n // Contrast enhancement\n color = (color - 0.5) * 1.15 + 0.5;\n color = max(color, vec3<f32>(0.0));\n\n // Saturation boost - stronger for colored surfaces, less for whites\n let gray = dot(color, vec3<f32>(0.299, 0.587, 0.114));\n let satBoost = mix(1.4, 1.1, isWhiteish); // More saturation for colored surfaces\n color = mix(vec3<f32>(gray), color, satBoost);\n\n // ACES filmic tone mapping\n let a = 2.51;\n let b = 0.03;\n let c = 2.43;\n let d = 0.59;\n let e = 0.14;\n color = clamp((color * (a * color + b)) / (color * (c * color + d) + e), vec3<f32>(0.0), vec3<f32>(1.0));\n\n // Subtle edge enhancement using screen-space derivatives\n let depthGradient = length(vec2<f32>(\n dpdx(input.viewPos.z),\n dpdy(input.viewPos.z)\n ));\n let normalGradient = length(vec2<f32>(\n length(dpdx(input.normal)),\n length(dpdy(input.normal))\n ));\n\n if (uniforms.flags.z == 1u) {\n // Threshold filters subtle normal discontinuities at internal\n // triangle edges between coplanar entities in the same batch.\n let edgeFactor = smoothstep(0.02, 0.12, depthGradient * 10.0 + normalGradient * 5.0);\n let edgeIntensity = f32(uniforms.flags.w) / 1000.0;\n let edgeDarkenStrength = clamp(0.25 * edgeIntensity, 0.0, 0.85);\n let edgeDarken = mix(1.0, 1.0 - edgeDarkenStrength, edgeFactor);\n color *= edgeDarken;\n }\n\n // Gamma correction\n color = pow(color, vec3<f32>(1.0 / 2.2));\n\n var out: FragmentOutput;\n out.color = vec4<f32>(color, finalAlpha);\n out.objectIdEncoded = encodeId24(input.entityId);\n return out;\n }\n ";
7
7
  //# sourceMappingURL=main.wgsl.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.wgsl.d.ts","sourceRoot":"","sources":["../../src/shaders/main.wgsl.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,mzVAsPtB,CAAC"}
1
+ {"version":3,"file":"main.wgsl.d.ts","sourceRoot":"","sources":["../../src/shaders/main.wgsl.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,ykXAkQtB,CAAC"}
@@ -159,8 +159,20 @@ export const mainShaderSource = `
159
159
  // Combine all lighting
160
160
  var color = baseColor * (ambient + diffuseSun + diffuseFill + rim);
161
161
 
162
+ // flags.x is a bitfield:
163
+ // bit 0 (value 1) = isSelected → selection-highlight + force opaque
164
+ // bit 1 (value 2) = isOverlay → color-override pass; preserve
165
+ // baseColor.a (overlay pipeline has
166
+ // src-alpha blending) AND skip the
167
+ // glass-fresnel branch so low-alpha
168
+ // ghost tints don't pick up the
169
+ // near-white reflection tint meant
170
+ // for real glass materials.
171
+ let isSelected = (uniforms.flags.x & 1u) == 1u;
172
+ let isOverlay = (uniforms.flags.x & 2u) == 2u;
173
+
162
174
  // Selection highlight - add glow/fresnel effect
163
- if (uniforms.flags.x == 1u) {
175
+ if (isSelected) {
164
176
  let V = normalize(-input.worldPos);
165
177
  let NdotV = max(dot(N, V), 0.0);
166
178
  let fresnel = pow(1.0 - NdotV, 2.0);
@@ -173,8 +185,8 @@ export const mainShaderSource = `
173
185
  // blue highlight, making it appear white instead of blue.
174
186
  // Also force alpha to 1.0 for selected objects so the highlight is
175
187
  // fully opaque (the selection pipeline has no alpha blending).
176
- var finalAlpha = select(uniforms.baseColor.a, 1.0, uniforms.flags.x == 1u);
177
- if (finalAlpha < 0.99 && uniforms.flags.x != 1u) {
188
+ var finalAlpha = select(uniforms.baseColor.a, 1.0, isSelected);
189
+ if (finalAlpha < 0.99 && !isSelected && !isOverlay) {
178
190
  // Calculate view direction for fresnel
179
191
  let V = normalize(-input.worldPos);
180
192
  let NdotV = max(dot(N, V), 0.0);
@@ -1 +1 @@
1
- {"version":3,"file":"main.wgsl.js","sourceRoot":"","sources":["../../src/shaders/main.wgsl.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAsPzB,CAAC"}
1
+ {"version":3,"file":"main.wgsl.js","sourceRoot":"","sources":["../../src/shaders/main.wgsl.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkQzB,CAAC"}
package/dist/types.d.ts CHANGED
@@ -146,6 +146,26 @@ export interface RenderOptions {
146
146
  isolatedIds?: Set<number> | null;
147
147
  selectedId?: number | null;
148
148
  selectedIds?: Set<number>;
149
+ /**
150
+ * Per-frame alpha overrides — primary use case is X-Ray mode.
151
+ *
152
+ * Map<expressId, alpha 0..1>. Non-selected meshes/batches whose expressId
153
+ * appears in this map render at the override alpha through the transparent
154
+ * pipeline. Selected meshes (`selectedId` / `selectedIds`) are exempt at
155
+ * every site, so highlights always paint with their own alpha.
156
+ *
157
+ * Mixed batches (some entries overridden, some not) take the minimum
158
+ * override alpha across non-selected ids; selected meshes in the batch
159
+ * are then redrawn on top by the highlight pass.
160
+ *
161
+ * The renderer snapshots this map at frame start, so callers may freely
162
+ * mutate or recycle their copy after `render()` returns.
163
+ *
164
+ * Note: alphas `>= 0.99` are treated as opaque (the cutoff for switching to
165
+ * the transparent pipeline). Entries at or above that threshold are no-ops
166
+ * — keep them out of the map to avoid unnecessary work.
167
+ */
168
+ transparencyOverrides?: Map<number, number> | null;
149
169
  buildingRotation?: number;
150
170
  selectedModelIndex?: number;
151
171
  sectionPlane?: SectionPlane;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ifc-lite/renderer",
3
- "version": "1.16.0",
3
+ "version": "1.18.0",
4
4
  "description": "WebGPU renderer for IFC-Lite",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -12,9 +12,9 @@
12
12
  }
13
13
  },
14
14
  "dependencies": {
15
- "@ifc-lite/geometry": "^1.16.5",
15
+ "@ifc-lite/geometry": "^1.17.0",
16
16
  "@ifc-lite/spatial": "^1.14.5",
17
- "@ifc-lite/wasm": "^1.16.6"
17
+ "@ifc-lite/wasm": "^1.16.8"
18
18
  },
19
19
  "devDependencies": {
20
20
  "@webgpu/types": "^0.1.69",