如视 Five SDK
    Preparing search index...

    Flowing Fireworks 3D Pass (流光烟花 3D 通道)

    • Summary: FlowingFireworks3DPassFlowingLight3DPass 配套使用,在每条流光线条的「尾部位置」(渐变淡出处)持续喷射出烟花状向四周发散的粒子,适合为流光拖尾增加飞溅火花、星点爆裂等增强效果。
    • Schema: FlowingFireworks3DPass 类及 FireworksLine 数据结构。
    • Concepts: GPU 粒子运动积分、环形缓冲发射、与流光尾部位置同步、加法混合发光。
    • Configuration: 3D 路径点、颜色、动画周期、尾长比例、粒子数量/发射率/扩散/重力等调优参数。
    • Examples: 流光拖尾火花、多条 3D 路径烟花、与 FlowingLight3DPass 配合、参数调优。

    Definition: FlowingFireworks3DPass

    FlowingFireworks3DPass 继承自 FivePass,与 FlowingLight3DPass 共享同一套线条数据结构(points / totalLength / duration / startTime / tailLengthRatio),并额外提供烟花粒子调优参数。核心接口如下:

    import * as THREE from 'three';
    import { FivePass } from './pass';
    import { type Camera } from '../../../core/camera';

    type FireworksLine = {
    id?: string; // 可选的唯一标识符,不传则自动生成 UUID
    points: THREE.Vector3[]; // 世界坐标系路径点
    totalLength: number; // 路径总长度(世界单位)
    color: THREE.Color; // 粒子颜色
    opacity?: number; // 粒子不透明度(0-1)
    tailLengthRatio?: number; // 尾巴长度比例(0-1),默认 0.2,与 FlowingLight3DPass 含义一致
    duration?: number; // 动画周期(毫秒),默认 1000
    startTime?: number; // 线条开始时间(毫秒),默认使用当前内部时间

    // ---- 烟花粒子调优参数(可选) ----
    particleCount?: number; // 该线条的粒子池大小,默认 200
    emissionRate?: number; // 每秒发射的粒子数量,默认 300
    spread?: number; // 扩散尺度(世界单位),默认 0.1
    particleSize?: number; // 粒子尺寸(世界单位),默认 spread * 0.12
    particleLife?: number; // 粒子最大寿命(秒),默认 0.5
    gravity?: THREE.Vector3; // 粒子加速度(世界单位/秒²),默认沿 -Y 缓慢下落
    leadRatio?: number; // 发射点相对尾部向前(头部方向)的提前比例,默认 0.04
    };

    export class FlowingFireworks3DPass extends FivePass {
    constructor(camera: Camera);

    // 批量设置路径列表(替换所有现有线条)
    public setLines(lines: FireworksLine[]): void;

    // 追加一条或多条线,返回生成的 id 数组
    public addLine(...lines: FireworksLine[]): string[];

    // 按 id 移除一条或多条线,返回实际移除的数量
    public removeLine(...ids: string[]): number;

    // 修改单条线的参数(通过 id),支持部分更新
    public setLine(params: { id: string } & Partial<Omit<FireworksLine, 'id'>>): void;

    public render(
    renderer: THREE.WebGLRenderer,
    writeBuffer: THREE.WebGLRenderTarget,
    readBuffer: THREE.WebGLRenderTarget,
    deltaTime: number,
    maskActive?: boolean,
    ): void;

    public dispose(): void;
    }

    该 Pass 的粒子发射点与 FlowingLight3DPass 的「尾部位置」(tailPosWorld)保持一致:

    • 流光的头部(Head)是前进方向的亮端,尾部(Tail)是渐变淡出的末端。
    • tailLengthRatio 表示从头部到渐变结束所占路径比例(默认 0.2)。粒子在「渐变结束的位置」喷射,即 headPos - tailLengthRatio * totalLength
    • 把本 Pass 与 FlowingLight3DPass 配置完全相同的线条数据(points/totalLength/duration/startTime/tailLengthRatio),即可让烟花精准跟随流光尾部。

    由于尾部沿路径滞后于头部,在视觉上粒子有时会显得「晚一拍」。leadRatio 让发射点相对尾部向头部方向提前一小段(占 totalLength 的比例,默认 0.04),使火花出现时机更早。提前量会被限制在当前尾长以内,不会越过头部。设为 0 即严格在尾部位置喷射。

    每个粒子在 CPU 端发射时仅写入「出生世界坐标 / 初速度 / 加速度 / 出生时间 / 寿命」等属性,后续运动完全在顶点着色器中按 p = p0 + v·t + ½·a·t² 积分计算,并随寿命淡出与缩小。CPU 每帧只需计算尾部位置并发射少量新粒子,性能开销低。

    每条线条拥有独立的粒子池(particleCount),按环形缓冲循环复用槽位。emissionRate(粒子/秒)结合每帧 deltaTime 决定发射数量,寿命到期的粒子自动被新粒子覆盖。

    粒子使用 AdditiveBlending 渲染到离屏缓冲并累加,再叠加到场景输出,自然形成重叠处更亮的发光效果。粒子为圆形柔光点,中心亮、边缘柔和。

    FlowingLight3DPass 一致,Pass 自动同步相机投影/视图矩阵,并根据 readBuffer 尺寸自动调整离屏渲染目标,适配高 DPR 屏幕。

    Parameter Type Required Default Description
    id string 自动生成 UUID 唯一标识符,用于 setLine 更新单条线。
    points THREE.Vector3[] - 世界坐标系路径点数组。至少 2 个点。
    totalLength number - 路径总长度(世界单位)。通常为相邻点间距离之和。
    color THREE.Color - 粒子颜色(RGB)。
    opacity number 1.0 粒子不透明度(0-1)。
    tailLengthRatio number 0.2 尾巴长度比例(0-1)。决定粒子喷射点(渐变结束处)相对头部的距离。
    duration number 1000 动画周期(毫秒)。尾部完成一个循环所需时长。
    startTime number 当前内部时间 线条开始时间(毫秒)。可用于多条线错开起始时间。
    particleCount number 200 该线条粒子池大小。越大可同时存在的火花越多。
    emissionRate number 300 每秒发射的粒子数量。控制火花密度。
    spread number 0.1 扩散尺度(世界单位)。控制火花向四周飞散的范围。
    particleSize number spread * 0.12 粒子尺寸(世界单位)。
    particleLife number 0.5 粒子最大寿命(秒)。越长火花拖得越远。
    gravity THREE.Vector3 沿 -Y 缓慢下落 粒子加速度(世界单位/秒²)。可制造下坠或上升效果。
    leadRatio number 0.04 发射点相对尾部的提前比例(占 totalLength)。增大可让火花更早出现,0 表示严格在尾部。

    注意: spread / particleSize / gravity 均为世界坐标单位,需要结合场景尺度调整。默认值适配米级小场景,大场景应相应放大。

    初始化 Pass,需传入相机以获取投影矩阵和视图矩阵。

    批量设置路径列表,替换所有现有线条。

    自动生成 ID: 没有 id 时自动生成 UUID。 自动设置 startTime: 没有 startTime 时使用当前内部时间。

    pass.setLines([{
    points: path,
    totalLength: 12,
    color: new THREE.Color(0xff6600),
    duration: 3000,
    tailLengthRatio: 0.2,
    }]);

    追加一条或多条线,返回新增线条的 id 数组,不影响已有线条。

    按 id 移除一条或多条线,返回实际移除的数量。id 不存在时输出警告。

    通过 id 部分更新单条线。

    性能说明:

    • 大多数字段(pointscolortotalLengthdurationspreadgravity 等)会在下一帧发射时即时生效,无需重建
    • 仅当 particleCount 改变时才会重建粒子缓冲。
    // 即时生效,无需重建
    pass.setLine({ id: 'line-1', color: new THREE.Color(0x00ff00), emissionRate: 500 });

    // 改变粒子池大小,会重建缓冲
    pass.setLine({ id: 'line-1', particleCount: 400 });

    由 EffectComposer 自动调用,无需手动调用。自动同步相机矩阵与渲染目标尺寸。

    释放粒子缓冲、着色材质、渲染目标等资源,销毁 Pass 时必须调用。

    烟花跟随流光尾部的标准用法:为两个 Pass 配置相同的线条数据。

    import { Five } from '@realsee/five';
    import { FlowingLight3DPass, FlowingFireworks3DPass } from '../../lib/five/renderer/postprocessing';
    import { calculatePath3DLength } from '@realsee/five/plugins';
    import * as THREE from 'three';

    const five = new Five();

    const flowingLight = new FlowingLight3DPass(five.camera);
    const fireworks = new FlowingFireworks3DPass(five.camera);

    const path = [
    new THREE.Vector3(-5, 0, 0),
    new THREE.Vector3(-2, 3, 2),
    new THREE.Vector3(2, 3, -2),
    new THREE.Vector3(5, 0, 0),
    ];

    const lineData = {
    points: path,
    totalLength: calculatePath3DLength(path),
    color: new THREE.Color(0xff00ee),
    duration: 8000,
    tailLengthRatio: 0.2,
    };

    flowingLight.setLines([lineData]);
    fireworks.setLines([lineData]); // 相同数据 => 烟花精准跟随流光尾部

    // 注意添加顺序:烟花叠加在流光之上
    five.addPass(flowingLight);
    five.addPass(fireworks);

    function animate() {
    requestAnimationFrame(animate);
    five.render();
    }
    animate();
    const fireworks = new FlowingFireworks3DPass(camera);

    fireworks.setLines([
    {
    points: [new THREE.Vector3(0, 0, 0), new THREE.Vector3(10, 5, 0)],
    totalLength: 11,
    color: new THREE.Color(0xff0000),
    duration: 2000,
    },
    {
    points: [new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 10, 5)],
    totalLength: 12,
    color: new THREE.Color(0x00ff00),
    duration: 2500,
    startTime: 500,
    },
    ]);
    fireworks.setLines([{
    points: path,
    totalLength: calculatePath3DLength(path),
    color: new THREE.Color(0xffaa00),
    duration: 6000,
    emissionRate: 600, // 更密集
    spread: 0.25, // 飞散更广
    particleLife: 0.9, // 拖得更远
    particleSize: 0.04,
    gravity: new THREE.Vector3(0, -0.5, 0), // 明显下坠
    leadRatio: 0.08, // 出现更早
    }]);
    // 视觉上火花偏晚 => 增大 leadRatio 让其更早出现
    pass.setLine({ id: lineId, leadRatio: 0.1 });

    // 严格落在流光尾部(渐变结束处)
    pass.setLine({ id: lineId, leadRatio: 0 });
    • 看不到粒子: 检查路径是否在相机视锥内;确认 color / opacity 非全透明;确认已调用 addPass
    • 火花太稀疏: 增大 emissionRateparticleCount(注意 particleCount 是上限,过小会限制同时存在的粒子数)。
    • 火花范围太小/太大: 调整 spread(世界单位),需结合场景尺度。
    • 火花出现偏晚/偏早: 调整 leadRatio(增大更早,0 严格在尾部)。
    • 位置与流光尾部不一致: 确认两个 Pass 使用了完全相同points/totalLength/duration/startTime/tailLengthRatio
    • 粒子不下落或方向不对: 检查 gravity 向量;默认沿 -Y(世界上方向取决于场景坐标系)。
    • GPU 积分: 粒子运动全部在着色器中完成,CPU 每帧只发射少量新粒子,开销低。
    • 环形缓冲: 粒子池大小固定(particleCount),不会随时间增长,显存稳定。
    • 加法混合: 重叠粒子会累加亮度,过高的 emissionRate × particleCount 会增加片元填充率,建议按需调节。
    1. 控制 particleCountemissionRate,避免不必要的高密度。
    2. 大场景适当放大 spread / particleSize,小场景调小,保持视觉比例。
    3. 使用 setLine 而非 setLines 更新单条线;除 particleCount 外的修改无需重建。
    4. 低端设备可通过 pass.enabled = false 禁用。
    1. 数据不一致: 烟花与流光必须共享相同的线条参数,否则尾部位置不对齐。
    2. 添加顺序: 应在流光 Pass 之后 addPass 烟花 Pass,使火花叠加在流光之上。
    3. 单位混淆: spread / particleSize / gravity 为世界单位,totalLength 也是世界单位,不要混用像素。
    4. particleCount 过小: 它是同时存在粒子数的上限,过小会使高 emissionRate 失效。
    5. 未调用 dispose(): 销毁 Pass 时必须调用 dispose(),避免 GPU 资源泄漏。

    tags: [烟花, 火花, 粒子, 流光拖尾, 发散, 爆裂, 特效, postprocessing, effect, fireworks, particle, sparks, flowing, pass, rendering, worldspace, 3d, world-space, additive, gpu-particles]