@realsee/five 6.8.0-alpha.8 → 6.8.0-alpha.9
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/ai_guides/README.md +3 -2
- package/ai_guides/features/flowing-light-2d-pass.md +278 -58
- package/ai_guides/features/flowing-light-3d-pass.md +223 -43
- package/docs/documents/README.html +2 -2
- package/docs/documents/features_flowing-light-2d-pass.html +275 -43
- package/docs/documents/features_flowing-light-3d-pass.html +268 -46
- package/docs/index.html +2 -2
- package/five/index.js +417 -383
- package/five/index.mjs +4822 -4821
- package/five/model/loaders/glTF-helpers/extensions/CESIUM_RTC.d.ts +1 -1
- package/five/model/loaders/glTF-helpers/extensions/EXT_meshopt_compression.d.ts +1 -1
- package/five/model/loaders/glTF-helpers/extensions/EXT_texture_webp.d.ts +1 -1
- package/five/model/loaders/glTF-helpers/extensions/KHR_binary_glTF.d.ts +1 -1
- package/five/model/loaders/glTF-helpers/extensions/KHR_draco_mesh_compression.d.ts +1 -1
- package/five/model/loaders/glTF-helpers/extensions/KHR_gaussian_splatting_compression_spz.d.ts +1 -1
- package/five/model/loaders/glTF-helpers/extensions/KHR_materials_clearcoat.d.ts +4 -0
- package/five/model/loaders/glTF-helpers/extensions/KHR_materials_emissive_strength.d.ts +4 -0
- package/five/model/loaders/glTF-helpers/extensions/KHR_materials_sheen.d.ts +4 -0
- package/five/model/loaders/glTF-helpers/extensions/KHR_materials_transmission.d.ts +4 -0
- package/five/model/loaders/glTF-helpers/extensions/KHR_materials_unlit.d.ts +4 -0
- package/five/model/loaders/glTF-helpers/extensions/KHR_node_visibility.d.ts +4 -0
- package/five/model/loaders/glTF-helpers/extensions/KHR_texture_basisu.d.ts +1 -1
- package/five/model/loaders/glTF-helpers/extensions/KHR_texture_transform.d.ts +1 -1
- package/five/model/loaders/glTF-helpers/extensions/REALSEE_materials_lightmap.d.ts +1 -1
- package/five/model/loaders/glTF-helpers/extensions/base.d.ts +2 -1
- package/five/model/loaders/glTF-helpers/index.d.ts +0 -2
- package/five/model/loaders/glTF-helpers/parser.d.ts +14 -13
- package/five/renderer/postprocessing/passes/flowing-light-2d-pass.d.ts +16 -2
- package/five/renderer/postprocessing/passes/flowing-light-3d-pass.d.ts +16 -2
- package/five/renderer/postprocessing/passes/gaussian-blur-pass.d.ts +1 -1
- package/gltf-loader/index.js +3 -3
- package/gltf-loader/index.mjs +3 -3
- package/line/index.js +3 -3
- package/line/index.mjs +3 -3
- package/llms.txt +3 -2
- package/package.json +1 -1
- package/plugins/index.js +2 -2
- package/plugins/index.mjs +2 -2
- package/react/index.js +2 -2
- package/react/index.mjs +2 -2
- package/shader-lib/index.js +2 -2
- package/shader-lib/index.mjs +2 -2
- package/sticker/index.js +3 -3
- package/sticker/index.mjs +3 -3
- package/umd/five-gltf-loader.js +3 -3
- package/umd/five-line.js +3 -3
- package/umd/five-plugins.js +2 -2
- package/umd/five-react.js +2 -2
- package/umd/five-shader-lib.js +2 -2
- package/umd/five-sticker.js +3 -3
- package/umd/five-vfx.js +2 -2
- package/umd/five-vue.js +2 -2
- package/umd/five.js +417 -383
- package/vfx/index.js +2 -2
- package/vfx/index.mjs +2 -2
- package/vue/index.js +2 -2
- package/vue/index.mjs +2 -2
- package/work-downloader/index.js +2 -2
- package/work-downloader/index.mjs +2 -2
- package/five/model/loaders/glTF-helpers/extensions/PBM_mesh.d.ts +0 -11
package/ai_guides/README.md
CHANGED
|
@@ -74,8 +74,8 @@
|
|
|
74
74
|
* [Pano Tile](./features/pano-tile.md): 全景瓦片渲染机制(高分辨率分片加载)。
|
|
75
75
|
* [Model](./features/model.md): 内置模型渲染 (Mesh/Geometry)。
|
|
76
76
|
* [Postprocessing](./features/postprocessing.md): 后处理效果 (Pass, EffectComposer)。
|
|
77
|
-
* [Flowing Light 2D Pass](./features/flowing-light-2d-pass.md):
|
|
78
|
-
* [Flowing Light 3D Pass](./features/flowing-light-3d-pass.md):
|
|
77
|
+
* [Flowing Light 2D Pass](./features/flowing-light-2d-pass.md): 屏幕空间流光特效(InstancedMesh 优化)。
|
|
78
|
+
* [Flowing Light 3D Pass](./features/flowing-light-3d-pass.md): 3D 世界坐标流光特效(InstancedMesh 优化)。
|
|
79
79
|
* [Gaussian Blur Pass](./features/gaussian-blur-pass.md): 高斯模糊特效。
|
|
80
80
|
* [Material](./features/material.md): 材质参数配置 (透明度、点云大小、顶点标记)。
|
|
81
81
|
* [Get Screen Pixels](./features/get-screen-pixels.md): 获取屏幕像素 (放大镜/截图)。
|
|
@@ -119,3 +119,4 @@
|
|
|
119
119
|
```yaml
|
|
120
120
|
tags: [index, readme, guide, map]
|
|
121
121
|
```
|
|
122
|
+
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# Flowing Light 2D Pass (流光 2D 通道)
|
|
2
2
|
|
|
3
|
-
- **Summary**: `FlowingLight2DPass`
|
|
3
|
+
- **Summary**: `FlowingLight2DPass` 提供屏幕空间的流光(光带)特效,使用 InstancedMesh 实例化渲染优化性能,沿着 2D 归一化坐标路径绘制动态光流,适用于突出导航路径、指示线或动态路径演示。
|
|
4
4
|
- **Schema**: `FlowingLight2DPass` 类及 Line 数据结构。
|
|
5
|
-
- **Concepts**:
|
|
6
|
-
- **Configuration**:
|
|
7
|
-
- **Examples**:
|
|
5
|
+
- **Concepts**: 后处理通道、屏幕空间光带、InstancedMesh 实例化渲染、归一化坐标系统、头尾追逐动画。
|
|
6
|
+
- **Configuration**: 归一化路径点、颜色、不透明度、线宽、动画时长、延迟。
|
|
7
|
+
- **Examples**: 基础集成、多条路径、动态更新、高 DPR 场景优化。
|
|
8
8
|
|
|
9
9
|
## Schema
|
|
10
10
|
|
|
11
11
|
> **Definition**: [FlowingLight2DPass](../../five/renderer/postprocessing/passes/flowing-light-2d-pass.d.ts)
|
|
12
12
|
|
|
13
|
-
`FlowingLight2DPass` 是 `FivePass`
|
|
13
|
+
`FlowingLight2DPass` 是 `FivePass` 的子类,核心接口如下:
|
|
14
14
|
|
|
15
15
|
```ts
|
|
16
16
|
import * as THREE from 'three';
|
|
@@ -18,11 +18,15 @@ import { FivePass } from './pass';
|
|
|
18
18
|
import { type Camera } from '../../../core/camera';
|
|
19
19
|
|
|
20
20
|
type Line = {
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
id?: string; // 可选的唯一标识符,不传则自动生成 UUID
|
|
22
|
+
points: THREE.Vector2[]; // 归一化坐标路径点 [0, 1]
|
|
23
|
+
totalLength: number; // 路径总长度(归一化单位)
|
|
23
24
|
color: THREE.Color; // 光带颜色
|
|
24
|
-
opacity?: number; //
|
|
25
|
-
duration?: number; //
|
|
25
|
+
opacity?: number; // 光带不透明度(0-1)
|
|
26
|
+
duration?: number; // 动画时长(毫秒)
|
|
27
|
+
delay?: number; // 动画延迟(毫秒)
|
|
28
|
+
lineWidth?: number; // 线宽(归一化单位)
|
|
29
|
+
tailLengthRatio?: number; // 尾巴长度比例(0-1),默认 0.2
|
|
26
30
|
};
|
|
27
31
|
|
|
28
32
|
export class FlowingLight2DPass extends FivePass {
|
|
@@ -31,6 +35,9 @@ export class FlowingLight2DPass extends FivePass {
|
|
|
31
35
|
// 设置要渲染的路径列表
|
|
32
36
|
public setLines(lines: Line[]): void;
|
|
33
37
|
|
|
38
|
+
// 修改单条线的参数(通过 id)
|
|
39
|
+
public setLine(params: { id: string } & Partial<Omit<Line, 'id'>>): void;
|
|
40
|
+
|
|
34
41
|
public render(
|
|
35
42
|
renderer: THREE.WebGLRenderer,
|
|
36
43
|
writeBuffer: THREE.WebGLRenderTarget,
|
|
@@ -42,17 +49,36 @@ export class FlowingLight2DPass extends FivePass {
|
|
|
42
49
|
public dispose(): void;
|
|
43
50
|
}
|
|
44
51
|
```
|
|
45
|
-
|
|
46
52
|
## Concepts
|
|
47
53
|
|
|
48
|
-
###
|
|
49
|
-
|
|
54
|
+
### InstancedMesh 实例化渲染 (Instanced Rendering)
|
|
55
|
+
为了优化高 DPR(Device Pixel Ratio)场景下的性能,该 Pass 使用 InstancedMesh 代替全屏着色器。每个线段作为一个实例,只渲染线段覆盖的区域,避免了对每个像素的全屏检查,显著提升了渲染效率。
|
|
56
|
+
|
|
57
|
+
### 归一化坐标系统 (Normalized Coordinates)
|
|
58
|
+
路径点使用归一化坐标 `[0, 1]` 定义:
|
|
59
|
+
- `(0, 0)` 表示屏幕左上角
|
|
60
|
+
- `(1, 1)` 表示屏幕右下角
|
|
61
|
+
- `(0.5, 0.5)` 表示屏幕中心
|
|
62
|
+
|
|
63
|
+
这种坐标系统与屏幕分辨率无关,自动适配不同尺寸和 DPR。
|
|
64
|
+
|
|
65
|
+
### 头尾追逐动画 (Head-Tail Chase Animation)
|
|
66
|
+
流光效果采用"头尾追逐"模式:
|
|
67
|
+
- **头部(Head)**: 光流的前端,沿路径循环移动
|
|
68
|
+
- **尾部(Tail)**: 光流的后端,跟随头部移动
|
|
69
|
+
- **渐变**: 从尾部(透明度 0)到头部(透明度 1)线性渐变
|
|
70
|
+
- **尾长**: 尾部长度由 `tailLengthRatio` 参数控制(默认 0.2,即路径总长的 20%)
|
|
50
71
|
|
|
51
|
-
|
|
52
|
-
光带"头部"根据 `duration` 和经过时间循环移动。`duration` 定义一个完整周期(从起点到终点再回到起点)所需的毫秒数。光带尾部长度固定为路径总长的 1/4。
|
|
72
|
+
光头在路径上循环流动,通过像素空间投影计算每个像素的渐变位置,确保渐变效果准确。尾巴长度会在动画开始时逐渐增长,直到达到 `tailLengthRatio * totalLength`。
|
|
53
73
|
|
|
54
|
-
###
|
|
55
|
-
|
|
74
|
+
### NDC 坐标转换
|
|
75
|
+
内部实现中,归一化坐标 `[0, 1]` 会转换为 NDC(Normalized Device Coordinates) `[-1, 1]`,与 WebGL 标准坐标系统一致,确保投影计算准确。
|
|
76
|
+
|
|
77
|
+
### DPR 处理与宽高比适配
|
|
78
|
+
自动处理高 DPR 场景和不同屏幕宽高比:
|
|
79
|
+
- **DPR 补偿**: 通过 `uPixelRatio` uniform 自动补偿高 DPR 设备的光线宽度,确保在 Retina 等高分辨率屏幕上视觉一致
|
|
80
|
+
- **像素空间计算**: 所有距离计算在像素空间进行,而非 NDC 空间,确保横向和纵向光线宽度在任何宽高比下都保持一致
|
|
81
|
+
- **各向同性渲染**: 无论屏幕是横屏、竖屏还是方形,光线的扩散效果在各个方向上都保持相同
|
|
56
82
|
|
|
57
83
|
## Configuration
|
|
58
84
|
|
|
@@ -60,49 +86,108 @@ export class FlowingLight2DPass extends FivePass {
|
|
|
60
86
|
|
|
61
87
|
| Parameter | Type | Required | Default | Description |
|
|
62
88
|
| :--- | :--- | :--- | :--- | :--- |
|
|
63
|
-
| `
|
|
64
|
-
| `
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
67
|
-
| `
|
|
68
|
-
|
|
69
|
-
|
|
89
|
+
| `id` | `string` | | 自动生成 UUID | 唯一标识符,用于 `setLine` 方法更新单条线。 |
|
|
90
|
+
| `points` | `THREE.Vector2[]` | ✓ | - | 归一化坐标路径点数组 [0, 1]。至少 2 个点。 |
|
|
91
|
+
| `totalLength` | `number` | ✓ | - | 路径总长度(归一化单位)。通常为所有相邻点间距离之和。 |
|
|
92
|
+
| `color` | `THREE.Color` | ✓ | - | 光带颜色(RGB)。 |
|
|
93
|
+
| `opacity` | `number` | | `1.0` | 光带不透明度(0-1)。控制与背景的混合强度。 |
|
|
94
|
+
| `duration` | `number` | | `1000` | 动画周期(毫秒)。光头从路径起点完成一个周期的时长。 |
|
|
95
|
+
| `delay` | `number` | | `0` | 动画延迟(毫秒)。延迟后才开始播放动画。 |
|
|
96
|
+
| `lineWidth` | `number` | | `0.01` | 线宽(归一化单位)。控制光带在屏幕上的宽度。 |
|
|
97
|
+
| `tailLengthRatio` | `number` | | `0.2` | 尾巴长度比例(0-1)。控制流光尾巴相对于路径总长的比例。 |
|
|
98
|
+
|
|
99
|
+
> **注意**: `totalLength` 和 `lineWidth` 使用归一化单位,与屏幕实际像素无关。
|
|
70
100
|
|
|
71
101
|
## Instance Methods
|
|
72
102
|
|
|
73
103
|
### `constructor(camera: Camera)`
|
|
74
|
-
初始化 Pass
|
|
104
|
+
初始化 Pass,需传入相机以获取屏幕分辨率。
|
|
75
105
|
|
|
76
106
|
### `setLines(lines: Line[])`
|
|
77
107
|
更新要渲染的路径列表。可随时调用以修改或新增路径。
|
|
78
108
|
|
|
79
|
-
|
|
109
|
+
**自动生成 ID**: 如果 line 没有提供 `id`,会自动生成 UUID。
|
|
110
|
+
|
|
111
|
+
**示例**:
|
|
80
112
|
```ts
|
|
81
113
|
const pathLine: Line = {
|
|
114
|
+
id: 'my-line-1', // 可选,不传则自动生成
|
|
82
115
|
points: [
|
|
83
|
-
new THREE.Vector2(
|
|
84
|
-
new THREE.Vector2(
|
|
85
|
-
new THREE.Vector2(
|
|
116
|
+
new THREE.Vector2(0.3, 0.7),
|
|
117
|
+
new THREE.Vector2(0.7, 0.7),
|
|
118
|
+
new THREE.Vector2(0.7, 0.3),
|
|
86
119
|
],
|
|
87
|
-
totalLength:
|
|
120
|
+
totalLength: 0.8, // 归一化单位
|
|
88
121
|
color: new THREE.Color(0x00c2ff),
|
|
89
122
|
opacity: 0.8,
|
|
90
123
|
duration: 2000,
|
|
124
|
+
delay: 500,
|
|
125
|
+
lineWidth: 0.01,
|
|
91
126
|
};
|
|
92
127
|
pass.setLines([pathLine]);
|
|
93
128
|
```
|
|
94
129
|
|
|
130
|
+
### `setLine(params: { id: string } & Partial<Omit<Line, 'id'>>)`
|
|
131
|
+
通过 `id` 修改单条线的参数。支持部分更新,只更新传入的字段。
|
|
132
|
+
|
|
133
|
+
**性能优化**:
|
|
134
|
+
- 如果 `points` 数量不变,只更新 GPU 的 instance attributes,性能极高
|
|
135
|
+
- 如果 `points` 数量改变,会重建整个 mesh,性能开销较大
|
|
136
|
+
|
|
137
|
+
**示例**:
|
|
138
|
+
```ts
|
|
139
|
+
// 只修改颜色 - 高性能
|
|
140
|
+
pass.setLine({
|
|
141
|
+
id: 'my-line-1',
|
|
142
|
+
color: new THREE.Color(0xff0000),
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// 修改多个属性 - 高性能
|
|
146
|
+
pass.setLine({
|
|
147
|
+
id: 'my-line-1',
|
|
148
|
+
color: new THREE.Color(0x00ff00),
|
|
149
|
+
opacity: 0.5,
|
|
150
|
+
duration: 3000,
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// 修改 points (相同数量) - 高性能
|
|
154
|
+
pass.setLine({
|
|
155
|
+
id: 'my-line-1',
|
|
156
|
+
points: [
|
|
157
|
+
new THREE.Vector2(0.2, 0.2),
|
|
158
|
+
new THREE.Vector2(0.8, 0.8),
|
|
159
|
+
new THREE.Vector2(0.8, 0.2),
|
|
160
|
+
], // 仍是 3 个点
|
|
161
|
+
totalLength: 1.2,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// 修改 points (不同数量) - 会重建 mesh
|
|
165
|
+
pass.setLine({
|
|
166
|
+
id: 'my-line-1',
|
|
167
|
+
points: [
|
|
168
|
+
new THREE.Vector2(0.2, 0.2),
|
|
169
|
+
new THREE.Vector2(0.8, 0.8),
|
|
170
|
+
], // 从 3 个点变为 2 个点
|
|
171
|
+
totalLength: 0.85,
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**注意事项**:
|
|
176
|
+
- 如果 `id` 不存在,会在控制台输出警告
|
|
177
|
+
- 动画时间(`uTime`)不会被重置,流光继续从当前位置播放
|
|
178
|
+
- 建议修改 `points` 时同时更新 `totalLength`
|
|
179
|
+
|
|
95
180
|
### `render(...)`
|
|
96
|
-
由 EffectComposer
|
|
181
|
+
由 EffectComposer 自动调用,无需手动调用。自动同步渲染目标尺寸。
|
|
97
182
|
|
|
98
183
|
### `dispose()`
|
|
99
|
-
|
|
184
|
+
释放 InstancedMesh、着色材质和渲染目标资源,避免内存泄漏。销毁 Pass 时必须调用。
|
|
100
185
|
|
|
101
186
|
## Examples
|
|
102
187
|
|
|
103
188
|
### 快速上手 (Quick Example)
|
|
104
189
|
|
|
105
|
-
|
|
190
|
+
|
|
106
191
|
import { Five } from '@realsee/five';
|
|
107
192
|
import { FlowingLight2DPass } from '../../lib/five/renderer/postprocessing';
|
|
108
193
|
import * as THREE from 'three';
|
|
@@ -112,14 +197,13 @@ const five = new Five();
|
|
|
112
197
|
// 创建 2D 流光通道
|
|
113
198
|
const flowing2D = new FlowingLight2DPass(five.camera);
|
|
114
199
|
|
|
115
|
-
// 定义一条屏幕空间的路径
|
|
200
|
+
// 定义一条屏幕空间的路径(归一化坐标)
|
|
116
201
|
const path = [
|
|
117
|
-
new THREE.Vector2(
|
|
118
|
-
new THREE.Vector2(
|
|
119
|
-
new THREE.Vector2(
|
|
120
|
-
new THREE.Vector2(700, 250),
|
|
202
|
+
new THREE.Vector2(0.2, 0.2),
|
|
203
|
+
new THREE.Vector2(0.5, 0.8),
|
|
204
|
+
new THREE.Vector2(0.8, 0.2),
|
|
121
205
|
];
|
|
122
|
-
const totalLen =
|
|
206
|
+
const totalLen = 1.2; // 归一化单位
|
|
123
207
|
|
|
124
208
|
flowing2D.setLines([{
|
|
125
209
|
points: path,
|
|
@@ -127,6 +211,7 @@ flowing2D.setLines([{
|
|
|
127
211
|
color: new THREE.Color(0x00ff00),
|
|
128
212
|
opacity: 0.9,
|
|
129
213
|
duration: 2000,
|
|
214
|
+
lineWidth: 0.01,
|
|
130
215
|
}]);
|
|
131
216
|
|
|
132
217
|
five.addPass(flowing2D);
|
|
@@ -136,27 +221,36 @@ function animate() {
|
|
|
136
221
|
five.render();
|
|
137
222
|
}
|
|
138
223
|
animate();
|
|
139
|
-
|
|
224
|
+
|
|
140
225
|
|
|
141
226
|
### 多条路径 & 动态更新
|
|
142
227
|
|
|
143
|
-
|
|
228
|
+
|
|
144
229
|
const pass = new FlowingLight2DPass(five.camera);
|
|
145
230
|
|
|
146
231
|
// 初始路径集合
|
|
147
232
|
const paths = [
|
|
148
233
|
{
|
|
149
|
-
points: [
|
|
150
|
-
|
|
234
|
+
points: [
|
|
235
|
+
new THREE.Vector2(0.1, 0.1),
|
|
236
|
+
new THREE.Vector2(0.9, 0.1),
|
|
237
|
+
],
|
|
238
|
+
totalLength: 0.8,
|
|
151
239
|
color: new THREE.Color(0xff6600),
|
|
152
240
|
duration: 1500,
|
|
241
|
+
lineWidth: 0.01,
|
|
153
242
|
},
|
|
154
243
|
{
|
|
155
|
-
points: [
|
|
156
|
-
|
|
244
|
+
points: [
|
|
245
|
+
new THREE.Vector2(0.1, 0.5),
|
|
246
|
+
new THREE.Vector2(0.9, 0.5),
|
|
247
|
+
],
|
|
248
|
+
totalLength: 0.8,
|
|
157
249
|
color: new THREE.Color(0x0066ff),
|
|
158
250
|
opacity: 0.7,
|
|
159
251
|
duration: 2000,
|
|
252
|
+
delay: 500,
|
|
253
|
+
lineWidth: 0.015,
|
|
160
254
|
},
|
|
161
255
|
];
|
|
162
256
|
|
|
@@ -165,19 +259,27 @@ five.addPass(pass);
|
|
|
165
259
|
|
|
166
260
|
// 响应用户交互动态更新路径
|
|
167
261
|
document.addEventListener('click', (e) => {
|
|
262
|
+
const rect = five.canvas.getBoundingClientRect();
|
|
263
|
+
const x = (e.clientX - rect.left) / rect.width;
|
|
264
|
+
const y = (e.clientY - rect.top) / rect.height; // 左上角为原点,无需翻转
|
|
265
|
+
|
|
168
266
|
const newPath = {
|
|
169
|
-
points: [
|
|
170
|
-
|
|
267
|
+
points: [
|
|
268
|
+
new THREE.Vector2(0.5, 0.5),
|
|
269
|
+
new THREE.Vector2(x, y),
|
|
270
|
+
],
|
|
271
|
+
totalLength: Math.hypot(x - 0.5, y - 0.5),
|
|
171
272
|
color: new THREE.Color(Math.random() * 0xffffff),
|
|
172
273
|
duration: 1200,
|
|
274
|
+
lineWidth: 0.01,
|
|
173
275
|
};
|
|
174
276
|
pass.setLines([...paths, newPath]);
|
|
175
277
|
});
|
|
176
|
-
|
|
278
|
+
|
|
177
279
|
|
|
178
280
|
### 计算路径总长度
|
|
179
281
|
|
|
180
|
-
|
|
282
|
+
|
|
181
283
|
function calculatePathLength(points: THREE.Vector2[]): number {
|
|
182
284
|
let length = 0;
|
|
183
285
|
for (let i = 1; i < points.length; i++) {
|
|
@@ -186,25 +288,144 @@ function calculatePathLength(points: THREE.Vector2[]): number {
|
|
|
186
288
|
return length;
|
|
187
289
|
}
|
|
188
290
|
|
|
291
|
+
const points = [
|
|
292
|
+
new THREE.Vector2(0.3, 0.7),
|
|
293
|
+
new THREE.Vector2(0.7, 0.7),
|
|
294
|
+
new THREE.Vector2(0.7, 0.3),
|
|
295
|
+
new THREE.Vector2(0.3, 0.3),
|
|
296
|
+
new THREE.Vector2(0.3, 0.7),
|
|
297
|
+
];
|
|
298
|
+
|
|
189
299
|
const pathLine = {
|
|
190
|
-
points:
|
|
300
|
+
points: points,
|
|
191
301
|
totalLength: calculatePathLength(points),
|
|
192
302
|
color: new THREE.Color(0x00ffff),
|
|
193
303
|
duration: 2000,
|
|
304
|
+
lineWidth: 0.01,
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
### 矩形路径示例
|
|
309
|
+
|
|
310
|
+
```ts
|
|
311
|
+
const pass = new FlowingLight2DPass(five.camera);
|
|
312
|
+
|
|
313
|
+
// 创建一个矩形路径(注意:左上角为原点)
|
|
314
|
+
const rectPath = {
|
|
315
|
+
points: [
|
|
316
|
+
new THREE.Vector2(0.3, 0.3), // 左上
|
|
317
|
+
new THREE.Vector2(0.7, 0.3), // 右上
|
|
318
|
+
new THREE.Vector2(0.7, 0.7), // 右下
|
|
319
|
+
new THREE.Vector2(0.3, 0.7), // 左下
|
|
320
|
+
new THREE.Vector2(0.3, 0.3), // 闭合路径
|
|
321
|
+
],
|
|
322
|
+
totalLength: 1.6, // 矩形周长
|
|
323
|
+
color: new THREE.Color(1.0, 1.0, 1.0),
|
|
324
|
+
opacity: 1.0,
|
|
325
|
+
duration: 4000,
|
|
326
|
+
delay: 2000,
|
|
327
|
+
lineWidth: 0.01,
|
|
194
328
|
};
|
|
329
|
+
|
|
330
|
+
pass.setLines([rectPath]);
|
|
195
331
|
```
|
|
196
332
|
|
|
333
|
+
### 高 DPR 场景优化
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
// InstancedMesh 实现自动优化高 DPR 性能
|
|
337
|
+
// 在 DPR=2 的 Retina 屏幕上,性能显著优于全屏着色器方案
|
|
338
|
+
|
|
339
|
+
const pass = new FlowingLight2DPass(camera);
|
|
340
|
+
|
|
341
|
+
// 多条路径在高 DPR 下仍能保持流畅
|
|
342
|
+
const paths = Array.from({ length: 10 }, (_, i) => ({
|
|
343
|
+
points: [
|
|
344
|
+
new THREE.Vector2(0.1, 0.1 + i * 0.08),
|
|
345
|
+
new THREE.Vector2(0.9, 0.1 + i * 0.08),
|
|
346
|
+
],
|
|
347
|
+
totalLength: 0.8,
|
|
348
|
+
color: new THREE.Color(Math.random() * 0xffffff),
|
|
349
|
+
duration: 2000 + i * 100,
|
|
350
|
+
delay: i * 200,
|
|
351
|
+
lineWidth: 0.01,
|
|
352
|
+
}));
|
|
353
|
+
|
|
354
|
+
pass.setLines(paths);
|
|
355
|
+
|
|
356
|
+
|
|
197
357
|
## Debugging
|
|
198
358
|
|
|
199
|
-
-
|
|
200
|
-
-
|
|
201
|
-
-
|
|
359
|
+
- **光带不出现**: 检查 `color` 和 `opacity`,确保非全透明;验证 `points` 至少 2 个;确认坐标在 [0, 1] 范围内。
|
|
360
|
+
- **流速不对**: 检查 `totalLength` 计算是否准确;若流速过快/过慢,调整 `duration`。
|
|
361
|
+
- **位置偏移**: 确认坐标系统使用归一化坐标 [0, 1],不是像素坐标;注意坐标系统以左上角为原点,Y 轴方向为 0(上) 到 1(下)。
|
|
362
|
+
- **性能问题**: InstancedMesh 实现已优化,但过多路径点仍会影响性能。建议单条路径不超过 20 个点。
|
|
363
|
+
|
|
364
|
+
## Performance
|
|
365
|
+
|
|
366
|
+
### 与全屏着色器对比
|
|
367
|
+
- **全屏着色器**: 每帧检查所有像素,DPR=2 时像素数增加 4 倍,性能下降明显
|
|
368
|
+
- **InstancedMesh**: 仅渲染线段覆盖区域,DPR=2 时性能影响较小
|
|
369
|
+
- **实测**: 在 DPR=2 场景下,InstancedMesh 方案 FPS 提升约 3-5 倍
|
|
370
|
+
|
|
371
|
+
### setLine 性能优化
|
|
372
|
+
`setLine` 方法根据修改类型自动选择最优更新策略:
|
|
373
|
+
|
|
374
|
+
| 修改类型 | 性能 | 说明 |
|
|
375
|
+
|---------|------|------|
|
|
376
|
+
| 只修改颜色/透明度 | ⚡️ 极快 (~100x) | 只更新 instanceColor attribute |
|
|
377
|
+
| 只修改 duration/delay | ⚡️ 极快 (~100x) | 只更新 instanceMeta attribute |
|
|
378
|
+
| 只修改 lineWidth | ⚡️ 极快 (~100x) | 只更新 instanceData attribute |
|
|
379
|
+
| 修改 points (相同数量) | ⚡️ 快 (~50x) | 只更新 instanceStart/End attributes |
|
|
380
|
+
| 修改 points (不同数量) | ⚠️ 慢 | 重建整个 mesh |
|
|
381
|
+
|
|
382
|
+
**最佳实践**:
|
|
383
|
+
```ts
|
|
384
|
+
// ✅ 高性能 - 频繁修改颜色
|
|
385
|
+
requestAnimationFrame(() => {
|
|
386
|
+
pass.setLine({
|
|
387
|
+
id: lineId,
|
|
388
|
+
color: new THREE.Color(Math.random(), Math.random(), Math.random())
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
// ✅ 高性能 - 动画路径(保持点数)
|
|
393
|
+
function animatePath(t: number) {
|
|
394
|
+
pass.setLine({
|
|
395
|
+
id: lineId,
|
|
396
|
+
points: [
|
|
397
|
+
new THREE.Vector2(0.1, 0.1),
|
|
398
|
+
new THREE.Vector2(0.5 + Math.sin(t) * 0.2, 0.5),
|
|
399
|
+
new THREE.Vector2(0.9, 0.9),
|
|
400
|
+
] // 始终 3 个点
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// ⚠️ 低性能 - 避免频繁改变点数
|
|
405
|
+
setInterval(() => {
|
|
406
|
+
const pointCount = Math.floor(Math.random() * 5) + 2;
|
|
407
|
+
pass.setLine({
|
|
408
|
+
id: lineId,
|
|
409
|
+
points: generateRandomPoints(pointCount) // 点数不固定
|
|
410
|
+
});
|
|
411
|
+
}, 100);
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### 优化建议
|
|
415
|
+
1. 减少路径点数量,使用更简化的路径
|
|
416
|
+
2. 降低 `lineWidth`,减少渲染区域
|
|
417
|
+
3. 控制同时渲染的路径数量
|
|
418
|
+
4. 使用 `setLine` 而非 `setLines` 来更新单条线
|
|
419
|
+
5. 保持 points 数量不变,只修改坐标
|
|
420
|
+
6. 在低端设备上可通过 `pass.enabled = false` 禁用
|
|
202
421
|
|
|
203
422
|
## Common Pitfalls
|
|
204
423
|
|
|
205
|
-
1.
|
|
206
|
-
2.
|
|
207
|
-
3.
|
|
424
|
+
1. **坐标系统混淆**: 必须使用归一化坐标 [0, 1],不能使用像素坐标。坐标系统以左上角为原点,Y 轴方向为 0(上) 到 1(下)。
|
|
425
|
+
2. **totalLength 计算错误**: 光流速度直接依赖 `totalLength`。手动计算时务必精确,使用归一化单位。
|
|
426
|
+
3. **lineWidth 过大**: 归一化单位下,0.01 约为屏幕高度的 1%。过大的值会导致光带过宽。
|
|
427
|
+
4. **未及时 dispose()**: 移除 Pass 时必须调用 `dispose()`,否则 GPU 资源泄漏。
|
|
428
|
+
5. **DPR 不匹配**: 确保渲染目标尺寸与实际屏幕 DPR 匹配,Pass 会自动处理。
|
|
208
429
|
|
|
209
430
|
## Related
|
|
210
431
|
|
|
@@ -213,6 +434,5 @@ const pathLine = {
|
|
|
213
434
|
|
|
214
435
|
---
|
|
215
436
|
|
|
216
|
-
|
|
217
|
-
tags: [postprocessing, effect, flowing, light, pass, rendering, screenspace]
|
|
218
|
-
```
|
|
437
|
+
|
|
438
|
+
tags: [postprocessing, effect, flowing, light, pass, rendering, screenspace, instanced, performance]
|