第16章 - 粒子系统与特效

第16章:粒子系统与特效

16.1 粒子系统基础

16.1.1 ParticleSystem 概述

// 创建基本粒子系统
const particleSystem = new Cesium.ParticleSystem({
    image: 'particle.png',
    
    // 发射器
    emitter: new Cesium.CircleEmitter(2.0),
    
    // 发射速率
    emissionRate: 50,
    
    // 粒子属性
    startScale: 1.0,
    endScale: 4.0,
    startColor: Cesium.Color.RED.withAlpha(0.7),
    endColor: Cesium.Color.YELLOW.withAlpha(0.0),
    
    // 速度
    speed: 5.0,
    
    // 生命周期
    lifetime: 1.6,
    
    // 模型矩阵
    modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(
        Cesium.Cartesian3.fromDegrees(116.4, 39.9, 100)
    )
});

viewer.scene.primitives.add(particleSystem);

16.1.2 发射器类型

// 圆形发射器
new Cesium.CircleEmitter(radius)

// 球形发射器
new Cesium.SphereEmitter(radius)

// 盒子发射器
new Cesium.BoxEmitter(new Cesium.Cartesian3(width, height, depth))

// 锥形发射器
new Cesium.ConeEmitter(angle)

16.2 常见特效实现

16.2.1 火焰效果

function createFireEffect(viewer, position) {
    const particleSystem = new Cesium.ParticleSystem({
        image: getFireParticle(),
        startScale: 1.0,
        endScale: 4.0,
        particleLife: 1.5,
        speed: 5.0,
        emitter: new Cesium.ConeEmitter(Cesium.Math.toRadians(30)),
        emissionRate: 30.0,
        startColor: new Cesium.Color(1, 1, 0, 0.7),
        endColor: new Cesium.Color(1, 0, 0, 0.0),
        imageSize: new Cesium.Cartesian2(25, 25),
        modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(
            Cesium.Cartesian3.fromDegrees(position.lon, position.lat, position.height)
        ),
        lifetime: 16.0,
        loop: true
    });
    
    viewer.scene.primitives.add(particleSystem);
    return particleSystem;
}

function getFireParticle() {
    const canvas = document.createElement('canvas');
    canvas.width = 64;
    canvas.height = 64;
    const ctx = canvas.getContext('2d');
    
    const gradient = ctx.createRadialGradient(32, 32, 0, 32, 32, 32);
    gradient.addColorStop(0, 'rgba(255, 255, 200, 1)');
    gradient.addColorStop(0.3, 'rgba(255, 200, 0, 0.8)');
    gradient.addColorStop(1, 'rgba(255, 100, 0, 0)');
    
    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, 64, 64);
    
    return canvas;
}

16.2.2 烟雾效果

function createSmokeEffect(viewer, position) {
    return new Cesium.ParticleSystem({
        image: getSmokeParticle(),
        startScale: 1.0,
        endScale: 8.0,
        particleLife: 4.0,
        speed: 3.0,
        emitter: new Cesium.CircleEmitter(5.0),
        emissionRate: 10.0,
        startColor: new Cesium.Color(0.5, 0.5, 0.5, 0.5),
        endColor: new Cesium.Color(0.8, 0.8, 0.8, 0.0),
        imageSize: new Cesium.Cartesian2(30, 30),
        modelMatrix: Cesium.Transforms.eastNorthUpToFixedFrame(
            Cesium.Cartesian3.fromDegrees(position.lon, position.lat, position.height)
        ),
        lifetime: 16.0,
        loop: true
    });
}

16.2.3 雨雪效果

// 雨效果
function createRainEffect(viewer) {
    const rainParticle = createRainParticle();
    
    const particleSystem = new Cesium.ParticleSystem({
        image: rainParticle,
        startScale: 1.0,
        endScale: 1.0,
        particleLife: 1.5,
        emitter: new Cesium.BoxEmitter(new Cesium.Cartesian3(1000, 1000, 50)),
        emissionRate: 2000,
        startColor: Cesium.Color.WHITE.withAlpha(0.5),
        endColor: Cesium.Color.WHITE.withAlpha(0.3),
        imageSize: new Cesium.Cartesian2(2, 20),
        gravity: new Cesium.Cartesian3(0, 0, -9.8),
        lifetime: 16.0,
        loop: true,
        modelMatrix: computeRainMatrix()
    });
    
    viewer.scene.primitives.add(particleSystem);
    
    // 跟随相机
    viewer.scene.preRender.addEventListener(function() {
        particleSystem.modelMatrix = computeRainMatrix();
    });
    
    return particleSystem;
}

function computeRainMatrix() {
    const camera = viewer.camera;
    const offset = Cesium.Cartesian3.multiplyByScalar(
        camera.direction, 500, new Cesium.Cartesian3()
    );
    const position = Cesium.Cartesian3.add(camera.position, offset, new Cesium.Cartesian3());
    return Cesium.Transforms.eastNorthUpToFixedFrame(position);
}

// 雪效果
function createSnowEffect(viewer) {
    const particleSystem = new Cesium.ParticleSystem({
        image: getSnowParticle(),
        startScale: 1.0,
        endScale: 1.0,
        particleLife: 6.0,
        emitter: new Cesium.BoxEmitter(new Cesium.Cartesian3(1000, 1000, 50)),
        emissionRate: 500,
        startColor: Cesium.Color.WHITE,
        endColor: Cesium.Color.WHITE.withAlpha(0.0),
        imageSize: new Cesium.Cartesian2(8, 8),
        gravity: new Cesium.Cartesian3(0, 0, -1),
        lifetime: 16.0,
        loop: true
    });
    
    viewer.scene.primitives.add(particleSystem);
    return particleSystem;
}

16.3 动态线效果

// 流动线效果
class FlowingLineMaterial {
    constructor(options = {}) {
        this.color = options.color || Cesium.Color.CYAN;
        this.speed = options.speed || 5.0;
        this.percent = options.percent || 0.1;
        this.gradient = options.gradient || 0.05;
    }
    
    getMaterial() {
        return new Cesium.Material({
            fabric: {
                type: 'FlowingLine',
                uniforms: {
                    color: this.color,
                    speed: this.speed,
                    percent: this.percent,
                    gradient: this.gradient
                },
                source: `
                    uniform vec4 color;
                    uniform float speed;
                    uniform float percent;
                    uniform float gradient;
                    
                    czm_material czm_getMaterial(czm_materialInput materialInput) {
                        czm_material material = czm_getDefaultMaterial(materialInput);
                        vec2 st = materialInput.st;
                        float t = fract(czm_frameNumber * speed / 1000.0);
                        t *= (1.0 + percent);
                        float alpha = smoothstep(t - percent, t, st.s) * step(-t, -st.s);
                        alpha += gradient;
                        material.diffuse = color.rgb;
                        material.alpha = alpha * color.a;
                        return material;
                    }
                `
            }
        });
    }
}

// 使用
const flowingMaterial = new FlowingLineMaterial({
    color: Cesium.Color.CYAN,
    speed: 10.0
});

viewer.entities.add({
    polyline: {
        positions: Cesium.Cartesian3.fromDegreesArray([116, 39, 117, 40]),
        width: 5,
        material: flowingMaterial.getMaterial()
    }
});

16.4 本章小结

本章介绍了粒子系统与特效:

  1. 粒子系统:ParticleSystem、发射器类型
  2. 火焰烟雾:火焰、烟雾效果实现
  3. 天气效果:雨、雪效果
  4. 动态线:流动线效果

在下一章中,我们将详细介绍性能优化与最佳实践。

16.5 思考与练习

  1. 实现爆炸效果。
  2. 创建喷泉效果。
  3. 开发雾效天气。
  4. 实现光束扫描效果。
  5. 创建轨迹拖尾效果。
posted @ 2026-01-08 11:13  我才是银古  阅读(16)  评论(0)    收藏  举报