u-space 0.0.29 → 0.0.31
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.
- package/README.md +9 -0
- package/dist/Viewer-BKNV67Jj.cjs +1 -0
- package/dist/Viewer-Cs_y7IiH.js +1256 -0
- package/dist/getTransferables-C97JPUVf.cjs +1 -0
- package/dist/getTransferables-DrzSmiCR.js +43 -0
- package/dist/index.cjs +3 -3
- package/dist/index.js +2280 -1542
- package/dist/modelDecodeProtocol-D1Apm9iG.cjs +1 -0
- package/dist/modelDecodeProtocol-wDB7ksYw.js +56 -0
- package/dist/plugins/atmosphere/AgxToneMapping.d.ts +1 -1
- package/dist/plugins/atmosphere/index.cjs +1 -1
- package/dist/plugins/atmosphere/index.js +4 -4
- package/dist/plugins/curve-movement/index.cjs +1 -1
- package/dist/plugins/curve-movement/index.js +1 -1
- package/dist/plugins/fire/index.cjs +1 -1
- package/dist/plugins/fire/index.js +5 -5
- package/dist/plugins/object-controls/index.cjs +1 -1
- package/dist/plugins/object-controls/index.js +4 -4
- package/dist/plugins/tiles/index.cjs +1 -1
- package/dist/plugins/tiles/index.js +5 -5
- package/dist/plugins/u-manager/index.cjs +48 -48
- package/dist/plugins/u-manager/index.d.ts +1 -1
- package/dist/plugins/u-manager/index.js +8126 -8660
- package/dist/plugins/u-manager/loaders/SceneEditableBatchLayer.d.ts +17 -0
- package/dist/plugins/u-manager/loaders/SceneInstancedLayer.d.ts +3 -3
- package/dist/plugins/u-manager/loaders/SceneLoader.d.ts +11 -3
- package/dist/plugins/u-manager/semantics/objects/BuildingGroup.d.ts +4 -5
- package/dist/plugins/u-manager/semantics/objects/FacilityInstancedLayer.d.ts +4 -4
- package/dist/plugins/u-manager/semantics/objects/FloorMesh.d.ts +20 -22
- package/dist/plugins/u-manager/semantics/objects/SemanticGroup.d.ts +2 -3
- package/dist/protocol-C-OMPz15.js +10 -0
- package/dist/protocol-IUAzx0lk.cjs +1 -0
- package/dist/src/batches/EditableGeometryBatchLayer.d.ts +50 -0
- package/dist/src/batches/ModelInstancedLayer.d.ts +42 -0
- package/dist/src/batches/index.d.ts +2 -0
- package/dist/src/effects/TSLEffects.d.ts +24 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/instances/InstanceObject.d.ts +57 -0
- package/dist/src/instances/index.d.ts +1 -0
- package/dist/src/interactions/MeshBVHRaycast.d.ts +9 -0
- package/dist/src/interactions/index.d.ts +1 -0
- package/dist/src/loaders/ModelDecodeWorkerClient.d.ts +31 -0
- package/dist/src/loaders/ModelLoaderManager.d.ts +15 -2
- package/dist/src/loaders/buildDecodedGltfModel.d.ts +4 -0
- package/dist/src/loaders/index.d.ts +1 -0
- package/dist/src/objects/Model.d.ts +1 -0
- package/dist/src/viewers/RenderPipeline.d.ts +37 -0
- package/dist/src/viewers/ReversedDepthSSGICompat.d.ts +10 -0
- package/dist/src/viewers/ReversedDepthSSRCompat.d.ts +20 -0
- package/dist/src/viewers/Viewer.d.ts +3 -1
- package/dist/src/viewers/renderInvalidation.d.ts +2 -0
- package/dist/src/worker/FrameTimingWindow.d.ts +16 -0
- package/dist/src/worker/OffscreenViewerHost.d.ts +20 -0
- package/dist/src/worker/WorkerDomTarget.d.ts +44 -0
- package/dist/src/worker/createWorkerViewer.d.ts +18 -0
- package/dist/src/worker/decodeGltfModel.d.ts +10 -0
- package/dist/src/worker/getTransferables.d.ts +1 -0
- package/dist/src/worker/index.d.ts +3 -0
- package/dist/src/worker/installWorkerImageLoader.d.ts +8 -0
- package/dist/src/worker/model-decoder.d.ts +13 -0
- package/dist/src/worker/modelDecodeProtocol.d.ts +205 -0
- package/dist/src/worker/protocol.d.ts +102 -0
- package/dist/src/worker/runtime.d.ts +2 -0
- package/dist/src/worker/workerImageUtils.d.ts +8 -0
- package/dist/worker/index.cjs +1 -0
- package/dist/worker/index.js +226 -0
- package/dist/worker/model-decoder.cjs +1 -0
- package/dist/worker/model-decoder.js +339 -0
- package/dist/worker/runtime.cjs +1 -0
- package/dist/worker/runtime.js +412 -0
- package/dist/workerImageUtils-lmOMyTQN.cjs +1 -0
- package/dist/workerImageUtils-mQD3TQ1N.js +105 -0
- package/docs/api-batches.md +112 -0
- package/docs/api-effects.md +2 -2
- package/docs/api-interactions.md +8 -0
- package/docs/api-managers.md +1 -1
- package/docs/api-objects.md +207 -0
- package/docs/api-plugin-u-manager.md +193 -102
- package/docs/api-render-pipeline.md +103 -5
- package/docs/api-viewer.md +232 -1
- package/docs/changelog.md +68 -12
- package/docs/examples-guide.md +104 -20
- package/docs/getting-started.md +1 -1
- package/docs/index.md +11 -4
- package/docs/mcp.md +30 -14
- package/docs/release.md +97 -0
- package/package.json +35 -4
- package/dist/plugins/u-manager/instances/SemanticInstanceObject.d.ts +0 -51
- package/dist/plugins/u-manager/instances/SemanticModelInstancedLayer.d.ts +0 -42
- package/dist/plugins/u-manager/instances/index.d.ts +0 -2
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# RenderPipeline API(后处理管线)
|
|
2
2
|
|
|
3
|
-
`viewer.renderPipeline` 管理渲染后处理链,内置 Bloom、SSGI、TRAA 支持,并提供自定义后处理覆盖机制。
|
|
3
|
+
`viewer.renderPipeline` 管理渲染后处理链,内置 Bloom、SSGI、SSR、TRAA 支持,并提供自定义后处理覆盖机制。
|
|
4
4
|
|
|
5
5
|
## 渲染节点图
|
|
6
6
|
|
|
7
7
|
```
|
|
8
|
-
Stage 1: pass(scene, camera) + MRT(按需配置 output/emissive/normal/velocity)
|
|
8
|
+
Stage 1: pass(scene, camera) + MRT(按需配置 output/emissive/normal/SSR G-buffer/velocity)
|
|
9
9
|
↓
|
|
10
10
|
Stage 2: 后处理链
|
|
11
|
-
├─ 内置模式: SSGI → Bloom
|
|
11
|
+
├─ 内置模式: SSGI → SSR + Temporal Reproject + Denoise → Bloom
|
|
12
12
|
└─ 自定义模式: outputComposer(scenePass) → Node
|
|
13
13
|
↓
|
|
14
14
|
Stage 3: Output Effects(仅默认/内置模式,插件/扩展追加效果)
|
|
@@ -54,6 +54,10 @@ viewer.renderPipeline.disableBloom();
|
|
|
54
54
|
|
|
55
55
|
> 仅支持 `PerspectiveCamera`,使用 `OrthographicCamera` 时会自动跳过并输出警告。
|
|
56
56
|
|
|
57
|
+
SSGI 分别生成 AO 与 GI 纹理,并按 `scene.rgb × AO + diffuse.rgb × GI` 合成最终颜色。AO 只压暗遮蔽区域,GI 只增加间接漫反射;背景不参与 SSGI。`Viewer` 默认的 reversed depth 和显式配置的标准深度均受支持,应用侧无需转换 depth texture。
|
|
58
|
+
|
|
59
|
+
[在线示例:默认开启的纯 AO](https://u-space-phi.vercel.app/examples/test_ao.html)
|
|
60
|
+
|
|
57
61
|
```typescript
|
|
58
62
|
// 开启 SSGI
|
|
59
63
|
viewer.renderPipeline.enableSSGI({ aoIntensity: 1, giIntensity: 10 });
|
|
@@ -71,11 +75,105 @@ viewer.renderPipeline.disableSSGI();
|
|
|
71
75
|
| :--- | :--- | :----- | :--- | :--- |
|
|
72
76
|
| `sliceCount` | `number` | `1` | 1–4 | 半球切片数 |
|
|
73
77
|
| `stepCount` | `number` | `12` | 1–32 | 每切片采样步数 |
|
|
74
|
-
| `aoIntensity` | `number` | `1` | 0–4 |
|
|
75
|
-
| `giIntensity` | `number` | `10` | 0–100 |
|
|
78
|
+
| `aoIntensity` | `number` | `1` | 0–4 | AO 对遮蔽项的对比度/压暗强度 |
|
|
79
|
+
| `giIntensity` | `number` | `10` | 0–100 | 加到漫反射项上的间接光强度 |
|
|
76
80
|
| `radius` | `number` | `12` | 1–25 | 世界空间采样半径 |
|
|
77
81
|
| `thickness` | `number` | `1` | 0.01–10 | 物体厚度(世界单位) |
|
|
78
82
|
|
|
83
|
+
## SSR(屏幕空间反射)
|
|
84
|
+
|
|
85
|
+
SSR 使用 stochastic ray marching 生成反射,随后通过运动向量执行 Temporal Reproject,并使用 Recurrent Denoise 进行时空降噪。完整链路需要连续帧积累,启用后应将 `viewer.frameloop` 设为 `'always'`。
|
|
86
|
+
|
|
87
|
+
> 仅支持 `PerspectiveCamera`,使用 `OrthographicCamera` 时会自动跳过并输出警告。
|
|
88
|
+
|
|
89
|
+
[在线示例:SSR 时空降噪](https://u-space-phi.vercel.app/examples/test_ssr.html)
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
viewer.frameloop = 'always';
|
|
93
|
+
|
|
94
|
+
viewer.renderPipeline.enableSSR({
|
|
95
|
+
quality: 0.25,
|
|
96
|
+
maxDistance: 0.4,
|
|
97
|
+
temporal: { maxFrames: 16 },
|
|
98
|
+
denoise: { radius: 1.5, strength: 0.725 },
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
viewer.renderPipeline.updateSSR({
|
|
102
|
+
intensity: 1.2,
|
|
103
|
+
denoise: { radius: 1 },
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
viewer.renderPipeline.disableSSR();
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### `SSRConfig`
|
|
110
|
+
|
|
111
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
112
|
+
| :--- | :--- | :----- | :--- |
|
|
113
|
+
| `resolutionScale` | `number` | `1` | SSR 计算分辨率比例,范围 0–1 |
|
|
114
|
+
| `quality` | `number` | `0.25` | Ray marching 采样质量,范围 0–1 |
|
|
115
|
+
| `mirrorBias` | `number` | `0.5` | 将 stochastic GGX 射线收束到镜面主瓣 |
|
|
116
|
+
| `maxDistance` | `number` | `0.4` | 最大反射追踪距离 |
|
|
117
|
+
| `intensity` | `number` | `1` | 反射强度 |
|
|
118
|
+
| `thickness` | `number` | `0.1` | 命中厚度容差 |
|
|
119
|
+
| `maxLuminance` | `number` | `35` | HDR 反射亮度上限 |
|
|
120
|
+
| `stepExponent` | `number` | `3` | Ray marching 步长分布指数;修改会重编译 SSR 材质 |
|
|
121
|
+
| `binaryRefine` | `boolean` | `false` | 是否使用二分子步细化命中;修改会重编译 SSR 材质 |
|
|
122
|
+
| `screenEdgeFade` | `number` | `0.2` | 屏幕边缘淡出宽度 |
|
|
123
|
+
| `screenEdgeFadeBlack` | `boolean` | `true` | 边缘和未命中区域是否淡出到黑色;修改会重编译 SSR 材质 |
|
|
124
|
+
| `temporal` | `SSRTemporalReprojectConfig` | 见下表 | 时域重投影参数 |
|
|
125
|
+
| `denoise` | `SSRDenoiseConfig` | 见下表 | 循环降噪参数 |
|
|
126
|
+
|
|
127
|
+
### `SSRTemporalReprojectConfig`
|
|
128
|
+
|
|
129
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
130
|
+
| :--- | :--- | :----- | :--- |
|
|
131
|
+
| `maxFrames` | `number` | `16` | 历史累积最大帧数 |
|
|
132
|
+
| `clampIntensity` | `number` | `0.25` | 历史颜色方差裁剪强度 |
|
|
133
|
+
| `flickerSuppression` | `number` | `1` | 时域闪烁抑制强度 |
|
|
134
|
+
| `hitPointReprojection` | `boolean` | `true` | 是否启用镜面命中点视差重投影 |
|
|
135
|
+
|
|
136
|
+
### `SSRDenoiseConfig`
|
|
137
|
+
|
|
138
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
139
|
+
| :--- | :--- | :----- | :--- |
|
|
140
|
+
| `lumaPhi` | `number` | `0.75` | 亮度边缘停止权重 |
|
|
141
|
+
| `depthPhi` | `number` | `20` | 深度边缘停止权重 |
|
|
142
|
+
| `normalPhi` | `number` | `0.3` | 法线边缘停止权重 |
|
|
143
|
+
| `roughnessPhi` | `number` | `100` | 粗糙度边缘停止权重 |
|
|
144
|
+
| `radius` | `number` | `1.5` | 空间降噪半径 |
|
|
145
|
+
| `alphaPhi` | `number` | `5` | SSR 射线长度边缘停止权重 |
|
|
146
|
+
| `strength` | `number` | `0.725` | 历史融合强度 |
|
|
147
|
+
| `adapt` | `number` | `0.5` | 自适应历史融合系数 |
|
|
148
|
+
| `smoothDisocclusions` | `boolean` | `true` | 是否平滑遮挡解除区域 |
|
|
149
|
+
| `flickerSuppression` | `number` | `1` | 降噪阶段闪烁抑制强度 |
|
|
150
|
+
| `adaptiveTrust` | `number` | `1` | 历史可信度自适应强度 |
|
|
151
|
+
|
|
152
|
+
SSR 会增加 `ssrDiffuse`、`ssrNormal` 和 `velocity` MRT 通道;其中法线/粗糙度与漫反射/金属度分别打包到两个 8-bit 附件中。SSGI 单独启用时使用 `ssgiDiffuse`,与 SSR 同时启用时则复用 `ssrDiffuse.rgb`,避免为相同的漫反射数据重复分配 MRT 附件。它可以和 SSGI、Bloom、TRAA 组合,但同时启用仍会增加 MRT 带宽和时域 pass 数量。
|
|
153
|
+
|
|
154
|
+
默认的 `scene.environment` 通常是 PMREM 纹理,不能直接作为 SSRNode 的等距柱状 HDR 输入。本封装只叠加屏幕空间命中结果,不修改全局 `PhysicalLightingModel`。
|
|
155
|
+
|
|
156
|
+
### Reversed depth 兼容
|
|
157
|
+
|
|
158
|
+
`Viewer` 默认启用 Three.js `reversedDepthBuffer`。SSGI 会在 clear depth 为 `0` 时跳过背景像素;SSR 封装会为 SSR、Temporal Reproject 和 Recurrent Denoise 三个内部全屏 pass 补充相同的 reversed-depth 背景像素早退。两者都保留原始 reversed depth 供位置重建、ray marching 和历史深度比较使用。应用侧无需关闭 reversed depth,也不需要转换 depth texture。
|
|
159
|
+
|
|
160
|
+
如果通过 `rendererOptions: { reversedDepthBuffer: false }` 使用标准深度,兼容层不会改写 Three.js 原有节点图。
|
|
161
|
+
|
|
162
|
+
`stepExponent`、`binaryRefine` 和 `screenEdgeFadeBlack` 属于编译期 SSR 参数,运行时修改会重编译内部 SSR 材质;其余数值参数直接更新 uniform。
|
|
163
|
+
|
|
164
|
+
### 性能建议
|
|
165
|
+
|
|
166
|
+
`resolutionScale` 只缩放 SSR ray-marching target;Temporal Reproject 和 Recurrent Denoise 仍跟随 renderer 的完整 drawing-buffer 尺寸。在 Retina 屏幕或重型场景中,可在创建 Viewer 时使用 `pixelRatio: 1`:
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
const viewer = new Viewer({
|
|
170
|
+
el: document.getElementById('app')!,
|
|
171
|
+
pixelRatio: 1,
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
建议从默认 `maxDistance: 0.4` 开始调节,并谨慎启用每帧更新的大尺寸动态阴影。`frameloop = 'always'` 仍是时域重投影和循环降噪正确收敛的必要条件。
|
|
176
|
+
|
|
79
177
|
## TRAA(时间抗锯齿)
|
|
80
178
|
|
|
81
179
|
基于运动向量的时间分辨率抗锯齿。
|
package/docs/api-viewer.md
CHANGED
|
@@ -14,6 +14,18 @@ new Viewer(options: ViewerOptions)
|
|
|
14
14
|
| :---------------- | :------------------------- | :--- | :------------------------------------------------------------------------------------------------------------- |
|
|
15
15
|
| `el` | `HTMLElement` | 是 | WebGPURenderer 的 canvas 将被注入到此 DOM 元素中。 |
|
|
16
16
|
| `rendererOptions` | `WebGPURendererParameters` | 否 | 直接传递给底层 `WebGPURenderer` 的选项。默认使用 WebGPU 的高性能配置。 |
|
|
17
|
+
| `pixelRatio` | `number` | 否 | Drawing buffer 像素比;默认 `Math.min(window.devicePixelRatio, 1.5)`。在 Retina 屏幕上使用 SSR、SSGI 或 TRAA 等重型全屏效果时,可设为 `1` 以降低 GPU 开销。 |
|
|
18
|
+
|
|
19
|
+
`pixelRatio` 应为有限正数,并会直接传给 Three.js。数值越高,画面越清晰,但完整 drawing buffer 以及依赖它的全屏后处理成本也会提高。
|
|
20
|
+
|
|
21
|
+
`Viewer` 默认启用 `reversedDepthBuffer`。`RenderPipeline` 内置 SSGI 和 SSR 均兼容该深度模式;只有业务明确需要标准深度时,才需要传入 `rendererOptions: { reversedDepthBuffer: false }`。
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
const viewer = new Viewer({
|
|
25
|
+
el: document.getElementById('app')!,
|
|
26
|
+
pixelRatio: 1,
|
|
27
|
+
});
|
|
28
|
+
```
|
|
17
29
|
|
|
18
30
|
## 属性
|
|
19
31
|
|
|
@@ -35,7 +47,7 @@ new Viewer(options: ViewerOptions)
|
|
|
35
47
|
| `objectManager` | `ObjectManager` | 用于按 ID 或名称注册和检索对象的工具。 |
|
|
36
48
|
| `frameloop` | `'always'` \| `'demand'` | 设置渲染模式。默认为 `'demand'`(仅在需要时渲染)。设置为 `'always'` 可开启持续渲染。 |
|
|
37
49
|
| `cssRenderer` | `CSSRenderer` | CSS 渲染器,支持在 3D 场景中叠加 HTML 元素(CSS2D / CSS2.5D / CSS3D)。 |
|
|
38
|
-
| `frameCount` | `number` |
|
|
50
|
+
| `frameCount` | `number` | 待渲染帧的内部计数器;同一刷新周期内的请求会合并,避免多个动画产生帧积压。 |
|
|
39
51
|
|
|
40
52
|
## 方法
|
|
41
53
|
|
|
@@ -58,6 +70,14 @@ viewer.render();
|
|
|
58
70
|
await viewer.render();
|
|
59
71
|
```
|
|
60
72
|
|
|
73
|
+
### `invalidate(frame?: number)`
|
|
74
|
+
|
|
75
|
+
请求渲染但不创建 Promise。动画循环、插件更新等不需要等待渲染完成的高频路径应优先使用此方法,避免每帧分配 Promise 和一次性事件监听器。`frame` 指定至少保留的待渲染帧数(默认 `1`);同一刷新周期内多次调用会合并,不会累加成渲染积压。
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
viewer.invalidate();
|
|
79
|
+
```
|
|
80
|
+
|
|
61
81
|
### `setCamera(camera: PerspectiveCamera | OrthographicCamera)`
|
|
62
82
|
|
|
63
83
|
为查看器设置自定义相机,并自动更新控制器和交互管理器以使用该相机。
|
|
@@ -251,6 +271,217 @@ viewer.viewerHelper.location.right = null;
|
|
|
251
271
|
viewer.dispose();
|
|
252
272
|
```
|
|
253
273
|
|
|
274
|
+
## OffscreenCanvas Worker(实验性)
|
|
275
|
+
|
|
276
|
+
`u-space/worker` 提供一个独立入口,可将 `Viewer`、Three.js 场景、相机控制和 WebGPU 渲染全部放入 dedicated render Worker。主线程只负责持有可见 canvas、转发输入事件与尺寸,并接收状态或渲染统计。模型默认仍在 render Worker 内加载;大型静态 glTF/SBMX 场景还可以 opt-in 第二个 decode Worker,让网络读取、SBMX 字节还原、JSON/base64 解析和图片解码不阻塞相机与已有场景的渲染。
|
|
277
|
+
|
|
278
|
+
Worker runtime 入口仅提供 ESM,需使用 `{ type: 'module' }` 创建 Worker。构建工具也必须保留 ES module 输出;Vite 项目需配置 `worker: { format: 'es' }`,否则 IIFE Worker 无法编译 top-level await。
|
|
279
|
+
|
|
280
|
+
主线程:
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
import { OffscreenViewerHost } from 'u-space/worker';
|
|
284
|
+
|
|
285
|
+
const worker = new Worker(new URL('./scene.worker.ts', import.meta.url), {
|
|
286
|
+
type: 'module',
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
const host = new OffscreenViewerHost({
|
|
290
|
+
el: document.getElementById('app')!,
|
|
291
|
+
worker,
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
host.addEventListener('ready', (event) => {
|
|
295
|
+
console.log('scene ready', (event as CustomEvent).detail);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
host.addEventListener('stats', (event) => {
|
|
299
|
+
console.log((event as CustomEvent).detail);
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
await host.init();
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
`await host.init()` 只等待 Worker 创建 `Viewer`、完成 `await viewer.init()` 并发送 `initialized`,此时 WebGPU renderer 和内置 command 已可用,但 HDR、业务模型、editable batch、pipeline 预热和业务首帧可能仍在继续。`initialized` 事件与 `host.init()` resolve 表示同一个边界;`ready` 是业务层边界,只会在 Worker 代码显式调用一次 `worker.ready(detail)` 后触发。因此应在 `host.init()` 之前注册 `ready` / `status` / `stats` 等监听,业务 command 则通常在 `ready` 后调用。
|
|
306
|
+
|
|
307
|
+
### Worker 超大贴图保护
|
|
308
|
+
|
|
309
|
+
`createWorkerViewer()` 会在创建 `Viewer` 前安装 Worker 图片加载兼容层,同时覆盖 Three.js `ImageLoader` 和 glTF 常用的 `ImageBitmapLoader`。JPEG、PNG、GIF、WebP 在解码前读取编码尺寸;任一边超过 WebGPU 默认可移植上限 `8192` 时,会在第一次 `createImageBitmap()` 解码时按原宽高比缩小。无法预读尺寸的格式会在首次解码后检查,超限时生成缩放后的 bitmap,并立即 `close()` 临时原图。
|
|
310
|
+
|
|
311
|
+
该处理保留 `ImageBitmapLoader.setOptions()`、Three.js Cache、request headers、credentials 和 Loader/LoadingManager abort 语义,也不会修改磁盘或服务端源贴图。它避免在默认 `maxTextureDimension2D = 8192` 的 WebGPU device 上触发 `Texture size`,以及随后连续出现的 `Invalid TextureView`、`Invalid BindGroup` 和 `Invalid CommandBuffer`。即使 adapter 支持 `16384`,runtime 也不会强制申请更高 limit,以保持不同 GPU 的可移植性并限制超大贴图的显存占用。
|
|
312
|
+
|
|
313
|
+
自动缩放只覆盖经 `ImageLoader` / `ImageBitmapLoader` 加载的普通图片;KTX2 等压缩纹理由各自 loader 处理,业务仍应在资产管线中确保其尺寸不超过目标设备 limit。
|
|
314
|
+
|
|
315
|
+
### 独立模型 Decode Worker
|
|
316
|
+
|
|
317
|
+
在拥有 Three.js/WebGPU 的 render Worker 中,把一个专用 Worker 交给 `ModelLoaderManager`:
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
import { ModelLoaderManager } from 'u-space';
|
|
321
|
+
import { createWorkerViewer } from 'u-space/worker/runtime';
|
|
322
|
+
|
|
323
|
+
const worker = await createWorkerViewer();
|
|
324
|
+
const modelDecodeWorker = new Worker(
|
|
325
|
+
new URL('./model.decode.worker.ts', import.meta.url),
|
|
326
|
+
{ type: 'module' },
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
const disposeModelDecodeWorker = ModelLoaderManager.setDecodeWorker(modelDecodeWorker);
|
|
330
|
+
worker.onDispose(disposeModelDecodeWorker);
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
专用 decode Worker 入口不创建 `Viewer`,只安装解码协议:
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
import { installModelDecodeWorker } from 'u-space/worker/model-decoder';
|
|
337
|
+
|
|
338
|
+
installModelDecodeWorker();
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
启用后,`ModelLoaderManager.loadAsync()` 会把受支持的静态 `.gltf`、`.glb` 和 `.sbmx` 请求排入 decode Worker。decode Worker 负责 fetch/Cache Storage、SBMX nibble swap、glTF JSON/base64/buffer 解析、普通图片解码和超大图片等比缩放;完成后以 transferable `ArrayBuffer` / `ImageBitmap` 把纯数据包发送给 render Worker。render Worker 才创建 `BufferGeometry`、`MeshStandardMaterial`、`Texture` 和 `Object3D`,因此 Three.js 对象和 GPU 资源仍只有一个 owner。
|
|
342
|
+
|
|
343
|
+
协议采用串行队列和 ACK backpressure:render Worker 重建完当前模型后才允许发送下一个大数据包,避免消息队列同时堆积多个模型副本。相同图片会按 SHA-256 内容身份复用已转移的 `ImageBitmap`,保持与 Three.js loader cache 一致的材质签名和 editable batching 数量;身份索引使用有界 LRU,不会随不同贴图持续增长。传输层直接使用浏览器 structured clone/transferable,没有额外二进制序列化依赖。
|
|
344
|
+
|
|
345
|
+
外部 buffer/贴图 URL 会回到 render Worker 经 `LoadingManager.resolveURL()` 处理,并完整触发 `itemStart` / `itemEnd` / `itemError`。模型请求的 headers 与 credentials 只会传给同源依赖;URL modifier 把依赖改写到其他 origin 时会自动去掉敏感 headers 并使用 `credentials: 'omit'`,避免授权信息泄漏给资产文件中声明的第三方地址。
|
|
346
|
+
|
|
347
|
+
当前快速路径只接受无 animation、skin、morph target、camera、sparse accessor、glTF extension/压缩扩展且 primitive mode 为 triangles 的 glTF 2 静态模型;节点图还必须满足无重复 child、无多父节点、无环及安全深度限制。其他受支持但不适合快速路径的模型会自动回退现有 `GLTFLoader` / `SBMXLoader`,不会降级功能;decode Worker 致命错误也会摘除失效 client 并回退当前请求。`ModelLoaderManager` 拥有传入的 Worker;再次调用 `setDecodeWorker()` 或传入 `null` 会 dispose 并 terminate 旧 Worker。`setDecodeWorker(worker)` 返回与该实例绑定的 disposer,建议交给 render runtime 的 `onDispose()`,避免旧清理回调误终止后来替换的 Worker。AbortSignal 同时覆盖 decode Worker 快速路径、普通 loader 顶层 fetch 和 glTF/SBMX 外部资源加载。
|
|
348
|
+
|
|
349
|
+
这个能力也可以在主线程的普通 `Viewer` 中启用,但它的主要收益是在 Offscreen render Worker 中把模型解码进一步拆开,使场景已可交互时仍能继续流式装载。它不减少网络体积、最终 GPU 内存或 draw calls;这些仍由资源压缩、instancing、editable batching、LOD 和裁剪解决。
|
|
350
|
+
|
|
351
|
+
### `OffscreenViewerHost`
|
|
352
|
+
|
|
353
|
+
构造选项:
|
|
354
|
+
|
|
355
|
+
| 选项 | 类型 | 必需 | 说明 |
|
|
356
|
+
| :--- | :--- | :--- | :--- |
|
|
357
|
+
| `el` | `HTMLElement` | 是 | 主线程容器;默认创建的 canvas 会挂载到这里。 |
|
|
358
|
+
| `worker` | `Worker` | 是 | 使用 `{ type: 'module' }` 创建的 dedicated Worker。 |
|
|
359
|
+
| `canvas` | `HTMLCanvasElement` | 否 | 自定义可见 canvas;省略时自动创建。 |
|
|
360
|
+
| `pixelRatio` | `number` | 否 | 发送给 Worker renderer 的 drawing-buffer pixel ratio;省略时使用 `Math.min(window.devicePixelRatio, 1.5)`。 |
|
|
361
|
+
| `terminateWorkerOnDispose` | `boolean` | 否 | `dispose()` 完成后是否终止 Worker,默认 `true`。 |
|
|
362
|
+
|
|
363
|
+
公开方法:
|
|
364
|
+
|
|
365
|
+
| 方法 | 说明 |
|
|
366
|
+
| :--- | :--- |
|
|
367
|
+
| `OffscreenViewerHost.isSupported()` | 检查当前环境是否具备 Worker、OffscreenCanvas 和 `transferControlToOffscreen()`。Worker 内是否暴露 WebGPU 仍会在初始化时检查。 |
|
|
368
|
+
| `init(): Promise<void>` | 绑定输入/resize,转移 canvas 并等待 Worker 的 `initialized` 消息;重复调用返回同一个 Promise。 |
|
|
369
|
+
| `request<T>(command, payload?)` | 调用 Worker 已注册或内置的 command。必须在 `init()` resolve 后调用;业务 command 通常还应等待 `ready`。 |
|
|
370
|
+
| `dispose(): void` | 停止事件与尺寸转发、reject 未完成的 Promise、移除 canvas,并通知 Worker 逆序释放业务资源和 `Viewer`。 |
|
|
371
|
+
|
|
372
|
+
Host 事件:
|
|
373
|
+
|
|
374
|
+
| 事件 | `detail` | 说明 |
|
|
375
|
+
| :--- | :--- | :--- |
|
|
376
|
+
| `initialized` | 无 | 与 `host.init()` resolve 相同的 Viewer 初始化边界。 |
|
|
377
|
+
| `ready` | `unknown` | Worker 调用一次 `worker.ready(detail)` 后的业务就绪边界。 |
|
|
378
|
+
| `status` | `string` | Worker 通过 `worker.status(message)` 上报的加载状态。 |
|
|
379
|
+
| `stats` | `WorkerRendererStats` | renderer 计数和滚动帧间隔统计。 |
|
|
380
|
+
| 自定义事件 | `unknown` | Worker 通过 `worker.emit(type, detail)` 上报;事件名为传入的 `type`。 |
|
|
381
|
+
| `error` | `Error` | Worker 初始化、未捕获异常或资源清理错误。 |
|
|
382
|
+
| `disposed` | 无 | Worker 已完成清理并关闭。 |
|
|
383
|
+
|
|
384
|
+
`WorkerRendererStats` 包含 `drawCalls`、`frameCalls`、`triangles`、`points`、`lines`、作为滚动平均帧间隔的 `frameTime`,以及 `frameTiming.samples` / `fps` / `average` / `p95` / `max` / `missedFramePercent`。其中 `missedFramePercent` 表示滚动窗口内超过 25ms 的样本占比;demand 模式的静止空闲间隔不会被作为渲染帧计入。
|
|
385
|
+
|
|
386
|
+
Worker(runtime 使用独立入口和 top-level await,避免主线程打包 Viewer/Three.js):
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
import { createWorkerViewer } from 'u-space/worker/runtime';
|
|
390
|
+
|
|
391
|
+
const worker = await createWorkerViewer();
|
|
392
|
+
const { viewer } = worker;
|
|
393
|
+
|
|
394
|
+
worker.status('loading scene');
|
|
395
|
+
const scene = await loadScene(viewer);
|
|
396
|
+
viewer.scene.add(scene);
|
|
397
|
+
await viewer.render();
|
|
398
|
+
|
|
399
|
+
worker.registerCommand('getObjectCount', () => viewer.scene.children.length);
|
|
400
|
+
worker.onDispose(() => disposeScene(scene));
|
|
401
|
+
worker.ready({ objects: viewer.scene.children.length });
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
`createWorkerViewer()` 必须在 module Worker 顶层立即调用。函数会先同步注册 host 消息监听,再返回一个等待 OffscreenCanvas 传入和 `viewer.init()` 完成的 Promise,因此可以安全使用 top-level await,不会丢失 `init` 消息。
|
|
405
|
+
|
|
406
|
+
返回的 `WorkerViewerRuntime` 提供:
|
|
407
|
+
|
|
408
|
+
| 属性 / 方法 | 说明 |
|
|
409
|
+
| :---------- | :--- |
|
|
410
|
+
| `viewer` / `canvas` | Worker 内的完整 `Viewer` 和已转移的 `OffscreenCanvas`。 |
|
|
411
|
+
| `status(message)` | 向主线程发送加载状态。 |
|
|
412
|
+
| `emit(type, detail?)` | 向主线程派发自定义事件;detail 必须可 structured clone。 |
|
|
413
|
+
| `registerCommand(name, handler)` | 注册 `host.request()` 可调用的业务命令,返回注销函数;重复命令名会抛错。 |
|
|
414
|
+
| `onDispose(handler)` | 注册 Worker 销毁回调,返回注销函数;多个回调按注册的逆序执行。 |
|
|
415
|
+
| `ready(detail?)` | 场景准备完成后发送一次 `ready` 事件;重复调用会抛错。 |
|
|
416
|
+
|
|
417
|
+
主线程应等待 `ready` 事件后,再用 `await host.request('getObjectCount')` 调用业务命令。runtime 还内置 `getStats`、`getViewpoint`、`setViewpoint` 和 `render` 命令,这些命令在 `host.init()` resolve 后即可调用。命令参数和返回值必须可被 structured clone;返回值中重复引用或嵌套在对象、数组、Map、Set、TypedArray / DataView 中的 `ArrayBuffer` 会去重后零拷贝转移,并从 Worker 端 detach。`Viewer`、`Object3D`、材质和 Geometry 等 Three.js 对象始终留在 Worker 内。
|
|
418
|
+
|
|
419
|
+
`ready()` 前发生的顶层未捕获错误或 Promise rejection 会先发送主线程 `error` 事件,再按逆序执行 `onDispose()`、释放 `Viewer`、发送 `disposed` 并关闭 Worker,避免失败的场景加载继续占用动画循环和 GPU 资源。Host 在初始化完成前被销毁,canvas 转移或初始 `postMessage()` 抛错,或收到 Worker 主动发送的 `disposed` 时,会 reject 尚未完成的 `init()` 和 `request()`,同时解除 DOM/resize 监听、清空待发送 pointer move、移除 canvas,并按 `terminateWorkerOnDispose` 完成 Worker 收尾。Host 一旦进入 disposed 状态,会忽略队列中迟到的 `initialized` / `ready` / `status` / `stats` / 自定义事件和 response,只保留清理阶段的 `error` / `disposed` 通知。
|
|
420
|
+
|
|
421
|
+
### UManager 与 editable batching
|
|
422
|
+
|
|
423
|
+
完整示例 `examples/offscreen/test_umanager2_offscreen.html` 会在 Worker 中加载 HDR、建筑语义模型和场景模型,并将 `SceneLoader.setEditableBatching()` 与 OffscreenCanvas 组合:
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
import { SceneLoader } from 'u-space/plugins/u-manager';
|
|
427
|
+
import { createWorkerViewer } from 'u-space/worker/runtime';
|
|
428
|
+
|
|
429
|
+
const worker = await createWorkerViewer();
|
|
430
|
+
const { viewer } = worker;
|
|
431
|
+
// 在初始静态层级和相机定位完成后冻结每帧场景矩阵遍历。
|
|
432
|
+
viewer.scene.updateMatrixWorld(true);
|
|
433
|
+
viewer.scene.matrixWorldAutoUpdate = false;
|
|
434
|
+
const sceneLoader = new SceneLoader(viewer);
|
|
435
|
+
worker.onDispose(() => sceneLoader.dispose());
|
|
436
|
+
sceneLoader.setPath(SCENE_PATH);
|
|
437
|
+
sceneLoader.setKey(SCENE_KEY);
|
|
438
|
+
sceneLoader.setEditableBatching({
|
|
439
|
+
maxVerticesPerBatch: 1_500_000,
|
|
440
|
+
maxIndicesPerBatch: 4_500_000,
|
|
441
|
+
freezeAnimations: true,
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
const scene = await sceneLoader.loadAsync();
|
|
445
|
+
const controlsEnabled = viewer.controls.enabled;
|
|
446
|
+
viewer.controls.enabled = false;
|
|
447
|
+
try {
|
|
448
|
+
viewer.scene.add(scene);
|
|
449
|
+
scene.updateWorldMatrix(true, true);
|
|
450
|
+
viewer.invalidate();
|
|
451
|
+
await viewer.renderer.compileAsync(viewer.scene, viewer.camera);
|
|
452
|
+
} finally {
|
|
453
|
+
viewer.controls.enabled = controlsEnabled;
|
|
454
|
+
}
|
|
455
|
+
await viewer.render();
|
|
456
|
+
|
|
457
|
+
worker.ready({
|
|
458
|
+
editableBatch: scene.userData.editableBatch,
|
|
459
|
+
semanticOverlayHidden: false,
|
|
460
|
+
});
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
Geometry clone、矩阵烘焙、`mergeGeometries()`、TSL batch material 创建和 WebGPU 渲染提交都会在 Worker 中完成,不阻塞主线程 UI。`ready` 事件中的 `detail.editableBatch` 是普通统计对象,可以安全传回主线程;示例 HUD 同时显示 `drawCalls`、`frameTiming.fps`、1 秒滚动窗口的 `average` / `p95` / `max`、超过 25ms 的 `missedFramePercent`,以及 `sourceMeshes` / `batches` / `drawCallsSaved` / `unsupportedInstances` 和 `static scene matrices` 状态。`frameTime` 保留为滚动平均值;demand 模式长时间静止产生的空闲间隔不会纳入统计。
|
|
464
|
+
|
|
465
|
+
目标场景的压平语义楼层是半透明分析叠加层,并会有意覆盖建筑表面。示例保持 `SemanticGroup.visible = true`,并调用 `showAllFloors().showAllFacilities()`,让楼层、墙体、空间、门窗和设备等全部语义对象默认参与渲染。设备选择、飞向、高亮和清除命令均不改变语义对象显隐,“清除调试”只撤销高亮。业务项目可以按自身展示策略切换语义层,并继续通过跨楼层语义合批或 LOD 降低提交成本。示例保留标准 RenderPipeline scene pass,以维持源模型透明对象的正确离屏合成,不修改 drawing-buffer pixel ratio。
|
|
466
|
+
|
|
467
|
+
目标场景主要由静态普通 Mesh 组成,因此相机定位完成后先调用 Three.js 原生 `viewer.scene.updateMatrixWorld(true)` 提交当前层级,再设置 `viewer.scene.matrixWorldAutoUpdate = false`,移除每个渲染帧的整树更新;加载完场景模型后只调用 `scene.updateWorldMatrix(true, true)` 提交新增子树。后续 Worker command 修改单个普通 Mesh 或 `InstanceObject` 时调用 `object.updateWorldMatrix(true, false)`,修改 Group 时调用 `group.updateWorldMatrix(true, true)`,随后调用 `viewer.invalidate()` 请求渲染。`InstanceObject` 覆盖了 Three.js 原生 `updateWorldMatrix()`,会在显式提交后检测世界矩阵/祖先显隐变化并触发 dirty callback;`ModelInstancedLayer` 因而能同步 instance buffer,editable batch 中与烘焙矩阵不同的 `SceneInstanceObject` 也会按现有规则 materialize。对 Group 使用 `updateChildren: true` 时,其后代 `InstanceObject` 同样会执行该检测。相机矩阵不受此模式影响。
|
|
468
|
+
|
|
469
|
+
OffscreenCanvas 不会自动减少 draw calls;`setEditableBatching()` 也不会把主线程 UI 搬入 Worker。组合使用时,两者分别处理主线程 CPU 压力和 draw submission 压力。需要按 ID 显隐、变色、移动或 `materialize()` 时,应使用 `worker.registerCommand()` 注册业务 command,再由主线程调用 `host.request()`,不要尝试跨线程传输 `SceneInstanceObject`。
|
|
470
|
+
|
|
471
|
+
通过以下命令启动:
|
|
472
|
+
|
|
473
|
+
```bash
|
|
474
|
+
pnpm example:offscreen
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
当前边界:
|
|
478
|
+
|
|
479
|
+
- 需要同时支持 `transferControlToOffscreen()` 和 Worker WebGPU(`WorkerNavigator.gpu`);目前应以最新版 Chromium 为主要目标,并保留普通 `Viewer` 回退路径。
|
|
480
|
+
- CSS2D/CSS3D、`Info` 等真实 DOM 叠加层不能放进 Worker,应在主线程用 Worker 状态/统计消息重建 UI。
|
|
481
|
+
- Worker 能移走场景解析、矩阵更新和渲染提交等主线程 CPU 工作,但不会减少 draw calls、三角形数量或 GPU 时间;GPU 瓶颈仍需用 instancing、LOD、遮挡/视锥裁剪等方式处理。
|
|
482
|
+
- `setEditableBatching()` 与 Worker 兼容,但它会展开重复 Geometry,仍需根据 `vertices` / `indices` 统计评估 GPU 内存;透明、蒙皮、morph 和自定义 shader 子集继续走安全 fallback。
|
|
483
|
+
- WebGPU OffscreenCanvas 截图尚未作为 Worker 内置命令开放;需要截图时应实现独立的 render-target readback 流程。
|
|
484
|
+
|
|
254
485
|
## 事件
|
|
255
486
|
|
|
256
487
|
Viewer 继承自 `EventDispatcher`,会触发以下事件:
|
package/docs/changelog.md
CHANGED
|
@@ -2,15 +2,71 @@
|
|
|
2
2
|
|
|
3
3
|
## 未发布
|
|
4
4
|
|
|
5
|
+
## 0.0.31
|
|
6
|
+
|
|
7
|
+
### 新增
|
|
8
|
+
|
|
9
|
+
- **嵌套模型 Decode Worker** — 新增 `u-space/worker/model-decoder` 和 `ModelLoaderManager.setDecodeWorker()`;静态 glTF/GLB/SBMX 可在 render Worker 之外完成 fetch/cache、SBMX 还原、JSON/base64/buffer 与图片解码,再以 transferable `ArrayBuffer` / `ImageBitmap` 交回 Three.js owner。协议使用单包 ACK backpressure、AbortSignal 和贴图内容身份复用,复杂 glTF 特性自动回退原 loader;Offscreen UManager 示例默认启用,并支持 `?modelDecodeWorker=off` A/B。
|
|
10
|
+
|
|
11
|
+
### 修复与优化
|
|
12
|
+
|
|
13
|
+
- **Offscreen 在线示例** — Vercel 发布现在通过专用 Vite 配置构建 `examples/offscreen/test_umanager2_offscreen.html`,输出可直接运行的主线程 JavaScript、ES module Worker 和 Draco/Basis WASM 资源,不再让生产页面直接加载 TypeScript;Worker 的 HDR URL 同时兼容本地 `/textures/` 与线上 `/examples/textures/` 路径。
|
|
14
|
+
- **Offscreen Worker 超大贴图** — Worker runtime 同时覆盖 Three.js `ImageLoader` 与 `ImageBitmapLoader`;JPEG/PNG/GIF/WebP 任一边超过 WebGPU 默认 `8192` 上限时,在首次 `createImageBitmap()` 解码时等比缩小并保留 loader options/cache/abort 语义,避免 `Texture size` 继续级联为 `Invalid TextureView`、`Invalid BindGroup` 和 `Invalid CommandBuffer`。未知格式在解码后缩放并释放临时原图,源资产不会被修改。
|
|
15
|
+
- **Offscreen UManager 设备调试** — 增加上一个/下一个设备、飞向、高亮和清除命令;语义楼层、墙体、空间、门窗和设备默认全部显示,设备切换、飞向和清除不再改变其他对象显隐。
|
|
16
|
+
- **模型 Decode Worker 稳定性与安全性** — 外部 buffer/贴图恢复 `LoadingManager.resolveURL()` 和完整 item 生命周期,跨域依赖不再继承模型请求的授权 headers/credentials;增加 glTF 节点图规模、深度、环、多父节点与重复 child 校验,并把贴图内容身份缓存改为有界 LRU。decode Worker 崩溃会自动摘除并回退当前请求,`setDecodeWorker()` 返回实例绑定 disposer,AbortSignal 也覆盖普通 loader 路径;失败的 `Model` 内存缓存 Promise 会被清除以允许重试。
|
|
17
|
+
|
|
18
|
+
## 0.0.30
|
|
19
|
+
|
|
20
|
+
### 新增
|
|
21
|
+
|
|
22
|
+
- **AO 示例** — 新增 `examples/test_ao.html`,通过 SSGI 的 `giIntensity: 0` 默认开启纯 AO,并提供遮蔽强度、半径和厚度实时调节。
|
|
23
|
+
- **RenderPipeline SSR** — 新增 `enableSSR()`、`updateSSR()` 和 `disableSSR()`,封装 Stochastic SSR、Temporal Reproject、Recurrent Denoise、velocity 以及双向历史反馈;提供完整 SSR 与降噪参数配置。
|
|
24
|
+
- **Viewer** — 新增可选 `pixelRatio` 构造参数,省略时继续使用 `Math.min(window.devicePixelRatio, 1.5)`。
|
|
25
|
+
- **Offscreen UManager 示例** — `examples/offscreen/test_umanager2_offscreen.html` 现在在 Worker 内启用 `SceneLoader.setEditableBatching()`、预热 WebGPU batch pipeline,并将渲染与 editable batch 统计传回主线程 HUD。
|
|
26
|
+
- **u-manager editable batching** — `SceneLoader.setEditableBatching()` 可把大型、主要静态的普通 Mesh 场景按材质和 Geometry 布局烘焙合并到 `SceneEditableBatchLayer`,同时保留 `SceneInstanceObject` 的显隐、颜色、高亮、bounds 和 raycast 映射;transform 或半透明修改会只 materialize 当前对象,透明/蒙皮/morph/自定义材质等不支持子集保持安全 fallback。
|
|
27
|
+
- **核心 Batches API** — 新增公共 `src/batches` 模块和 `EditableGeometryBatchLayer<T extends InstanceObject>`,提供通用 source/build/unsupported 结果、TSL dirty 状态、typed materialize 事件、lazy BVH hit remap、统计与资源释放;`ModelInstancedLayer` 同步归入该模块,顶层 `u-space` 导入方式保持不变。
|
|
28
|
+
|
|
5
29
|
### 变更
|
|
6
30
|
|
|
7
|
-
- **
|
|
8
|
-
- **
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
31
|
+
- **Offscreen Worker breaking** — 移除 callback 风格的 `defineWorkerViewer()`、`WorkerViewerSetup`、`WorkerViewerSetupResult` 和 `WorkerViewerContext`;改为在 module Worker 顶层 `await createWorkerViewer()`,并通过返回的 `WorkerViewerRuntime` 顺序调用 `status()`、`registerCommand()`、`onDispose()` 和 `ready()`。
|
|
32
|
+
- **InstanceObject materialize** — 将 `SceneInstanceObject` 私有的 materializer delegate 提升为核心 `InstanceObject.setInstanceMaterializer()` / `clearInstanceMaterializer()` / `materialize()` 协议;`SceneEditableBatchLayer` 改为核心 `EditableGeometryBatchLayer` 的 scene-specific 薄适配层,fallback 移除改用 typed `materialize` 事件。
|
|
33
|
+
|
|
34
|
+
### 修复与优化
|
|
35
|
+
|
|
36
|
+
- **Offscreen UManager 帧率与楼壳显示** — 示例保留语义数据用于相机定位,但默认隐藏会半透明覆盖楼壳的高 draw-call 分析层;同时通过 Three.js 原生 `Scene.matrixWorldAutoUpdate` / `Object3D.updateWorldMatrix()` 关闭静态场景每帧整树矩阵遍历,并保留标准 RenderPipeline scene pass 以确保源模型透明对象正确合成。在不调整 pixel ratio 的情况下,目标场景持续拖拽可维持约 59–60 FPS。
|
|
37
|
+
- **Editable Geometry Batch 不透明材质** — 不透明 batch 不再复用动态 opacity 节点同时驱动 alpha 输出和 `maskNode`;源材质 opacity 路径保持不变,对象显隐改用独立布尔遮罩,修复建筑楼壳被错误显示为半透明的问题。
|
|
38
|
+
- **InstanceObject 静态矩阵更新** — 覆盖 Three.js 原生 `updateWorldMatrix()`,与 `updateMatrixWorld()` 共享世界矩阵/祖先显隐 dirty 检测;根 Scene 冻结自动矩阵更新后,显式更新单个实例或父 Group 仍会同步 instanced buffer,并让 editable batch 的变换差异正确触发 materialize。
|
|
39
|
+
- **Editable Geometry Batch 拾取** — 公共 `EditableGeometryBatchLayer` 继承 `BaseGroup`,内部未导出的 `EditableGeometryBatchMesh` 继承 `BaseMesh` 并在自定义 BVH raycast 前保留不可见短路;隐藏整个 editable layer 或单个 merged batch 后不会继续命中逻辑对象。
|
|
40
|
+
- **Editable Geometry Batch 生命周期** — 修复多个 layer 共用 inverse matrix、dirty transform 因旧 bounds 先被视锥裁剪、冻结根 Scene 下新挂载模型错过当帧世界矩阵、跨 layer materialize 后旧副本仍显示、materialize 对象共享模板材质、旧烘焙位置残留 BVH 命中、负缩放实例错误进入 merged/instanced path、重复实例生成幽灵几何、重复 build 累积资源、旧 layer dispose 清除新 materializer,以及 build 期间已 materialize 对象重复进入透明 fallback;`EditableGeometryBatchLayer` 现在是 one-shot builder。
|
|
41
|
+
- **Offscreen HUD** — renderer stats 改为 1 秒滚动窗口的 FPS、平均/p95/最大帧间隔、超过 25ms 的占比和样本数,并排除 demand 模式从静止恢复时的空闲间隔。
|
|
42
|
+
- **Offscreen Worker lifecycle** — 修复初始化期间销毁导致 `host.init()` 永久 pending、canvas 转移/初始 `postMessage()` 失败后未完成本地清理、dispose 后迟到的业务消息仍被派发、待发送 pointer move rAF 未取消、`ready()` 前加载失败未释放 Worker/GPU 资源,以及重复 `ArrayBuffer` transfer list 抛出 `DataCloneError`。
|
|
43
|
+
- **RenderPipeline SSGI** — 修正 AO/GI 合成,改为 `scene × AO + diffuse × GI`,确保 `aoIntensity` 与 `giIntensity` 分别作用于遮蔽和间接漫反射;同时兼容 Viewer 默认的 reversed depth 背景判断,并在与 SSR 同时启用时复用 diffuse MRT 附件。
|
|
44
|
+
- **RenderPipeline SSR** — 兼容 Viewer 默认的 `reversedDepthBuffer`:三个内部全屏 pass 会正确跳过 clear-depth 背景,同时保留 raw reversed depth 用于位置重建、ray marching 和 temporal history。
|
|
45
|
+
- **SSR 示例** — 新增 `examples/test_ssr.html`,并使用 1× drawing buffer、`maxDistance: 0.4`、静态 2048² 阴影和关闭默认性能面板的配置降低 GPU 开销。
|
|
46
|
+
|
|
47
|
+
### 文档
|
|
48
|
+
|
|
49
|
+
- **docs/mcp** — 将核心 `InstanceObject` 的完整 API 归入 Objects 文档,并同步 u-manager 子类引用、LLM 摘要和 MCP 检索索引;运行时 API 未发生变化。
|
|
50
|
+
- **u-manager editable batching** — 补充 `setEditableBatching()` 配置、合并键、TSL 状态纹理、materialize/fallback 边界、统计字段、显存权衡、`test_umanager2.html` 示例和 MCP 检索范围。
|
|
51
|
+
- **OffscreenCanvas Worker** — 补充 `OffscreenViewerHost` 构造选项、方法、事件和统计字段,明确 `host.init()` / `initialized` 与一次性业务 `ready` 的边界,以及 `examples/offscreen/test_umanager2_offscreen.html` 的 editable batching、`compileAsync()` 预热、HUD 统计、静态根节点下 `InstanceObject` 显式矩阵提交、structured-clone/command 边界和 MCP 检索入口。
|
|
52
|
+
- **SSR** — 补充完整 RenderPipeline SSR API、时域/降噪配置、reversed-depth 兼容说明、性能建议与在线示例入口。
|
|
53
|
+
|
|
54
|
+
## 0.0.29
|
|
55
|
+
|
|
56
|
+
### 变更
|
|
57
|
+
|
|
58
|
+
- **u-manager breaking** — 通用实例基类和模型合批层从 `plugins/u-manager/instances` 移入核心;`InstanceObject` 位于 `src/instances`,`ModelInstancedLayer` / `InstanceCullingOptions` 位于 `src/batches`,均继续通过顶层 `u-space` 导出;旧 `SemanticInstanceObject` / `SemanticModelInstancedLayer` 命名不再保留。
|
|
59
|
+
- **u-manager breaking** — `ModelInstancedLayer` 移除旧的 `addSemanticBatch()` 公开入口,改为 `reserveBatch()`、`addInstance()` / `addInstances()`、`getInstanceById()`、`removeInstance()` / `removeInstances()`、`removeBatch()` 和 `clearBatches()`,支持运行时实例新增/删除、按 URL batch 的 capacity 预分配与扩容;`removeInstances()` 支持直接传单个字符串 `instanceId`,并且 layer 内部不再从 `instance.userData` 扫描 ID。
|
|
60
|
+
- **u-manager breaking** — `InstanceObject` 使用独立身份字段 `instanceId`、`instanceKind`、`instanceName` 和 `setInstanceIdentity()`;Scene / Facility instancing 的查询、删除和 raycast remap 都使用这些字段,`userData` 只保留原始业务元数据。
|
|
61
|
+
- **u-manager breaking** — `SemanticGroup`、`BuildingGroup` 和 `FloorMesh` 的 building/floor/facility 索引统一读取语义对象 ID、实例对象 `instanceId` 或显式传入的别名,不再把 `userData.id`、`userData.semanticId`、`userData.facilityId` 自动注册成查询 ID;`ModelInstancedLayer` 会拒绝重复 `instanceId` 的新增实例,并在身份字段变化后按需刷新 id 索引。
|
|
62
|
+
- **u-manager** — `InstanceObject` 新增对象级 `boundingBox`、`boundingSphere`、`computeBoundingBox()` 和 `computeBoundingSphere()`,`SceneInstanceObject`、`FacilityInstanceObject` 以及楼层语义代理可直接传给 `viewer.controls.flyToObject()`。
|
|
63
|
+
- **u-manager** — `ModelInstancedLayer` 的内部实例矩阵同步改为 WebGPU storage instanced buffer 路径,运行时新增或移动实例后会在下一帧立即同步 matrix;外部仍通过修改 `InstanceObject` transform 和 dirty sync 使用,不需要直接写内部 `InstancedMesh.instanceMatrix`。
|
|
12
64
|
- **u-manager** — `SemanticGroup` 新增 `getDefaultFacilityLayer()`,`SceneLoader.loadAsync()` 返回的 `SceneGroup` 新增 `sceneLayer` / `getDefaultSceneLayer()`,外部可直接获取默认 Facilities 和场景模型合批层。
|
|
13
|
-
- **docs/mcp** — 更新 u-manager 文档、Examples Guide、LLM 索引和 MCP 检索说明,推荐通过 `viewer.controls.flyToObject()`
|
|
65
|
+
- **docs/mcp** — 更新 u-manager 文档、Examples Guide、LLM 索引和 MCP 检索说明,推荐通过 `viewer.controls.flyToObject()` 飞向实例;`getInstanceBoundingBox(target, true)` 保留给手动合并或调整世界包围盒的场景。
|
|
66
|
+
|
|
67
|
+
### 示例与文档
|
|
68
|
+
|
|
69
|
+
- **在线示例** — `examples/importmap.js` 的 CDN fallback 版本更新为 `0.0.29`,Vercel 部署会继续按 `package.json` 注入当前版本。
|
|
14
70
|
|
|
15
71
|
## 0.0.28
|
|
16
72
|
|
|
@@ -21,9 +77,9 @@
|
|
|
21
77
|
|
|
22
78
|
### 变更
|
|
23
79
|
|
|
24
|
-
- **u-manager breaking** — `SceneInstanceObject`、`FacilityInstanceObject` 和楼层多边形语义统一到 `
|
|
25
|
-
- **u-manager** — 新增共享 `
|
|
26
|
-
- **ObjectManager / MaterialEffects** — 对语义实例的显隐、透明度和高亮控制统一识别 `
|
|
80
|
+
- **u-manager breaking** — `SceneInstanceObject`、`FacilityInstanceObject` 和楼层多边形语义统一到 `InstanceObject` API:使用 `setInstanceVisible()`、`setInstanceColor()`、`setInstanceOpacity()`、`getInstanceBoundingBox()` 等方法,不再使用 scene/facility 专属实例方法。
|
|
81
|
+
- **u-manager** — 新增共享 `ModelInstancedLayer`,`SceneInstancedLayer` 和 `FacilityInstancedLayer` 共用同一套模型模板 instancing、material groups、多材质、dirty sync、raycast remap 和 fallback wrapper 逻辑。
|
|
82
|
+
- **ObjectManager / MaterialEffects** — 对语义实例的显隐、透明度和高亮控制统一识别 `InstanceObject`,不再维护 SceneInstance/FacilityInstance 两套特殊分支。
|
|
27
83
|
- **u-manager loader** — `SceneLoader` 不再解析场景树里的 `AREA`、`FLOOR`、`ROOM` 语义面;楼层、区域和房间统一由 `SemanticLoader` / `SemanticGroup` 处理,避免同一语义对象在组合加载时重复出现。
|
|
28
84
|
|
|
29
85
|
### 示例与文档
|
|
@@ -42,7 +98,7 @@
|
|
|
42
98
|
- **fire 插件** — 新增 `FireEffect`,封装 Three.js 官方 `webgpu_volume_fire` 体积火焰示例,支持 WebGPU 3D 流体模拟、烟雾散射、动态光照、体积阴影、output effect 叠加和 `cameraChange` 相机切换同步。
|
|
43
99
|
- **u-manager loader** — `SceneLoader` 默认读取同路径 `db/semantic_model.json` 并按语义 `ID` 跳过重复场景树节点,支持与 `SemanticLoader` 同时加载。
|
|
44
100
|
- **u-manager loader** — `SceneLoader` 默认按模型 `path` 合并重复静态 3D 节点,通过 `SceneInstancedLayer` 批量渲染,同时保留 `SceneInstanceObject` 逻辑对象用于单模型 ID 检索、显隐、颜色、透明度、包围盒和事件派发。
|
|
45
|
-
- **docs/mcp** — 补充 `SceneInstanceObject` 和 `FacilityInstanceObject` 通过 `objectManager.getById()` + `
|
|
101
|
+
- **docs/mcp** — 补充 `SceneInstanceObject` 和 `FacilityInstanceObject` 通过 `objectManager.getById()` + `getInstanceBoundingBox()` + `controls.flyToBox()` 飞向单个实例的示例与 MCP 检索说明。
|
|
46
102
|
- **ObjectManager / MaterialEffects** — `setOpacity()`、`show()` / `hide()`、`isolate()`、`showAll()` 以及 `highlightColor()` / `removeHighlightColor()` 支持 `SceneInstanceObject` 的 per-instance 控制。
|
|
47
103
|
- **u-manager loader** — `SceneLoader` 创建的根组、`GROUP` 和 `STUB` 节点改为 `BaseGroup`,隐藏后可通过对象自身 `raycast()` 返回值阻止子级继续参与递归射线检测。
|
|
48
104
|
- **Viewer** — 默认使用 Three.js `reversedDepthBuffer` 替代 `logarithmicDepthBuffer`,减少 WebGPU 顶视角多层透明场景的 fragment 压力,同时保留远距离深度精度。
|
|
@@ -77,8 +133,8 @@
|
|
|
77
133
|
- **u-manager semantics** — `SemanticGroup` 和 `BuildingGroup` 的建筑/设备 ID 查询改为内部 `Map` 索引,并通过楼层设备索引版本自动同步,避免每次查询扫描数组。
|
|
78
134
|
- **u-manager semantics** — `FloorMesh.planish()` / `unplanish()`、`BuildingGroup.planishFloors()` / `unplanishFloors()` 和 `SemanticGroup.planishFloors()` / `unplanishFloors()` 会把所有合并语义实例和 Facilities 都按包围盒贴到楼层平面,而不是围绕实例自身基点压缩。
|
|
79
135
|
- **u-manager semantics** — 新增 scene-level Facilities auto instancing:同模型 URL 的静态设备会合并到 `SemanticGroup.facilityLayer` 的 `InstancedMesh` batch,同时保留楼层下的设备引用用于检索、显隐、颜色和透明度控制;带动画、骨骼、morph target 或多材质 Mesh 的设备自动回退为普通 `Model`。
|
|
80
|
-
- **u-manager semantics** — `SemanticGroup`、`BuildingGroup` 和 `FloorMesh` 新增 `getFacilityById()` 设备检索,返回的 `FacilityInstanceObject` 可通过统一 `
|
|
81
|
-
- **docs/mcp** — 补充 Facilities auto instancing 的材质透明度行为、`
|
|
136
|
+
- **u-manager semantics** — `SemanticGroup`、`BuildingGroup` 和 `FloorMesh` 新增 `getFacilityById()` 设备检索,返回的 `FacilityInstanceObject` 可通过统一 `setInstanceVisible()`、`setInstanceColor()`、`resetInstanceColor()` 和 `setInstanceOpacity()` 控制普通设备模型或 scene-level instanced 设备引用。
|
|
137
|
+
- **docs/mcp** — 补充 Facilities auto instancing 的材质透明度行为、`resetInstanceColor()` 语义,以及多材质 fallback 对颜色/透明度 override 的限制说明。
|
|
82
138
|
|
|
83
139
|
### 修复
|
|
84
140
|
|