Part of the
vfx-water-ripple skill. The skill links here when your agent needs the detail.vfx-magic-glow, optionally substitutable in vfx-hit-spark and vfx-fire if a custom shader is overkill.
BaseMaterial3D is abstract — BaseMaterial3D.new() is a parse error (“Native class
“BaseMaterial3D” cannot be constructed as it is abstract”). Instantiate
StandardMaterial3D; the BaseMaterial3D.* enum constants below are still the right
way to name the values.
Settings
When to use this vs a custom shader
- Use this
StandardMaterial3Dconfig when the effect is just a tinted soft-circle mote (magic glow, sparkles, dust). Less code, faster iteration, free engine-managed billboard math. - Per-particle color over age does NOT need a custom shader.
ParticleProcessMaterialhascolor_ramp,color_initial_ramp,alpha_curveandemission_curve(all present on the shipped engine) — those drive the particle’sCOLORfrom age and feed straight into a plainStandardMaterial3D. Reach for a ramp before reaching for a shader. - Use a custom
ShaderMaterialwhen you need per-fragment shape masks (muzzle flash star burst), noise-distorted UVs (fire, smoke), or anything that varies within the quad. Those are whatStandardMaterial3Dgenuinely can’t express. - If a custom shader does need the particle age, note that the age lives in
INSTANCE_CUSTOM.y(normalized byINSTANCE_CUSTOM.w, the lifetime), thatINSTANCE_CUSTOM.xis the rotation angle — not the age — and thatINSTANCE_CUSTOMis vertex-stage only. Pass it tofragment()through avarying.
Performance note
Additive overdraw is fillrate-bound.draw_pass_1 is a Mesh, so the size dial is on the mesh: keep QuadMesh.size at or under Vector2(0.2, 0.2) for motes/sparks. Larger quads at full additive intensity destroy mobile fillrate budgets fast.
Source:
library/skills/vfx-water-ripple/_building-blocks/additive-billboard-particles.md, rendered from summer-engine@4.3.0 on npm.
