Skip to main content

使用 Quick3D Particles 实现雨滴效果

Comments

以下是 Quick3D.Particles 模块在 Qt 6.10 和 6.11 中新增功能的概述。本次更新的目标是支持与场景产生视觉交互效果的粒子特效,同时避免引入高开销的模拟计算。本文将以雨滴效果为例,逐步介绍各项新特性。

雨滴效果由两部分构成:粒子撞击场景模型上的过程,以及撞击后触发的飞溅粒子效果。

那么,如何在不进行高开销光线-模型交点计算的前提下,让粒子“命中”模型?这里需要用到一个名为 ParticleModelShape3D 的类型,它可以按照指定模型的轮廓发射粒子,并通过在发射器中设置速度,将其发射到特定方向 。只要将速度方向朝向天空,并令粒子系统时间倒流,就会产生粒子从上方落下、撞击模型的视觉效果。

reversedSnow

使用零速度轨迹发射器(Trail Emitter)实现雪花积累效果。

ParticleEmitter3D.reversed 属性

若将整个系统时序倒转运行,则会给同一系统中添加其他粒子效果带来不便 。为此,我们在发射器上新增了 reversed 属性,允许仅对该发射器启用时序倒转,而其他粒子发射器仍按照正常时间顺序运行。

以下示例展示了如何使用线条粒子(Line Particles)、模型形状(Model Shape)与轨迹发射器(Trail Emitter)来实现雨滴及溅水效果。


// Rain particle
LineParticle3D {
    id: rainParticle
    ...
}

Component {
    id: modelComponent
    Model {
        // The mesh containing only the top parts of the sphere
        source: "meshes/sphere_top.mesh"
    }
}

// Rain particle emitter
ParticleEmitter3D {
    id: emitter
    particle: rainParticle
    reversed: true
    shape: ParticleModelShape3D {
        model: modelComponent
        fill: false
    }
    velocity: VectorDirection3D {
        direction: Qt.vector3d(0, 800, 0)
        directionVariation: Qt.vector3d(2, 0, 2)
    }
}

// Splash particle
SpriteParticle3D {
    id: splashParticle
    ...
}

// Splash particle trail emitter following the rain particle
TrailEmitter3D {
    follow: rainParticle
    DynamicBurst3D {
        id: splashBurst
        amount: 20
        amountVariation: 2
        triggerMode: DynamicBurst3D.TriggerEnd
    }
    emitBursts: splashBurst
    particle: splashParticle
    velocity: VectorDirection3D {
        direction: Qt.vector3d(0, 0, 10)
        directionVariation: Qt.vector3d(50, 50, 1)
    }
}

现在我们可以实现雨水击中模型并向特定方向溅起水花的效果。但如果溅水能随模型表面形状自适应——即粒子以特定角度击中曲面时,沿反射角度溅出——效果会更理想。

ParticleEmitter3D.EmitMode

发射器的发射模式(EmitMode)支持更精细的粒子方向控制。在默认模式之外,新增了两种基于模型形状的方向控制模式。

ParticleEmitter3D.SurfaceNormal :将发射方向改为遵循表面法线。当发射速度朝向 Z 轴时,粒子将沿表面法线方向发射。

ParticleEmitter3D.SurfaceReflected:用于轨迹发射器,发射方向为根据表面法线与被跟随粒子速度计算所得的反射向量

emitModes

Default 与 SurfaceNormal 发射模式在 Suzanne 网格上的对比效果。

将轨迹发射器的发射模式设置为 ParticleEmitter3D.SurfaceReflected ,溅水粒子即可从模型表面产生反射效果。


TrailEmitter3D {
    ...
    emitMode: ParticleEmitter3D.SurfaceReflected
}

reflectedParticles

粒子在球体表面使用 SurfaceReflected 模式弹射的效果演示。

至此,我们已具备针对单个模型实现雨滴效果的基本构件。但如何将其扩展到包含多个模型的应用场景?若为每个模型单独添加雨滴效果,会带来副作用:各模型拥有各自的雨滴密度,导致场景雨势不均匀;此外,雨水还会穿透彼此重叠的模型 —— 例如,当模型位于地面上方时,地面仍会在模型正下方产生雨滴。为解决上述问题,可以提前计算整个场景的网格,但这样得到的是静态网格,导致模型无法在场景中移动 。

ParticleSceneShape3D

场景形状(Scene Shape) 可以根据场景中的模型,动态计算整个场景的形状。
该形状以一张覆盖在场景上方的网格来表示,网格的每个顶点对应其下方所有模型多边形的最高点。当相邻顶点之间高度差过大,或网格顶点下方不存在模型多边形时,将在网格中创建孔洞。
当场景中的模型发生移动时,形状会自动重新计算,因此也适用于动态场景。开发者可以设置网格分辨率、网格范围(决定形状大小)、中心位置,以及指定需要从计算中排除的节点。此外,还可以通过属性获取几何数据,例如用于调试目的。

ParticleEmitter3D {
        id: emitter
        shape: ParticleSceneShape3D {
            id: sceneShape
            scene: sceneRoot
            sceneCenter: Qt.vector3d(0, 0, 0)
            sceneExtents: Qt.vector3d(1000, 500, 1000)
            excludedNodes: [debugNode]
            shapeResolution: 50
        }
    }

    Model {
        id: debugNode
        geometry: sceneShape.geometry
    }

car-rain

雨滴效果在汽车配置器演示项目中的应用。

汽车配置器演示项目已随 Qt 6.11 加入雨滴效果,并同步附带了雪花效果。

Comments

Subscribe to our blog

Try Qt 6.11 Now!

Download the latest release here: www.qt.io/download

Qt 6.11 is now available, with new features and improvements for application developers and device creators.

We're Hiring

Check out all our open positions here and follow us on Instagram to see what it's like to be #QtPeople.