Skip to main content
vfx-magic-glow is a skill from the Summer skill library: a guide your AI agent reads when the task matches, so it builds the good version on the first try. Magic-glow effect: a pulsing OmniLight3D, drifting additive motes and an optional emission shader.

When your agent uses it

  • Authoring a magic-glow effect — enchanted item, soul gem, pulsing aura, rune glow, magical orb, wisp
  • An item, altar, or portal should read as magical or important with a pulsing light and drifting motes

Install

summer setup installs every skill for your agent. To add only this one:
Swap claude-code for your agent, such as codex or cursor. See Skills for every option.

The skill

Three layered cues that together read as “magical”: a pulsing OmniLight3D (sin-wave energy), drifting additive billboard motes orbiting the source, and optional emission on the source mesh itself. Used for: enchanted items, soul gems, runes, summoning circles, wisps, fairies, magical waypoints. The recipe writes a single controller that builds and animates all three layers from one node.

When to use

  • “This sword is enchanted — add a glow.”
  • “Make the soul gem pulse with light.”
  • “Magic rune on the floor glowing.”
  • “Wisp / fairy / firefly companion.”
  • “The summoning circle is active.”
  • “Quest item glows so the player notices it.”
  • Pre-charge phase before casting vfx-lightning or vfx-muzzle-flash (charge-up beam).

When NOT to use

  • The user wants a static, non-animated glow — just enable emission on the mesh’s material; this recipe is overkill.
  • The user wants flames, not a glow — use vfx-fire (or magic-fire variant of vfx-fire).
  • The user wants a beam shooting out, not an aura — use vfx-lightning with the plasma-laser variant.
  • The user wants a screen-space bloom on the whole scene — that’s WorldEnvironment.glow_*, not a per-object recipe.
  • The user wants a 2D glow on a UI sprite — use canvas_item shader with a radial gradient, not this 3D recipe.

Recipe

1. Files to create

No custom shader — uses canonical additive billboard motes (see _building-blocks/additive-billboard-particles.md) plus an OmniLight3D. Optional: pair with the source mesh’s existing material’s emission.

2. GDScript controller

addons/vfx/magic-glow/magic_glow.gd:

3. Node tree

4. Wire it in (MCP calls)

Write the script once, then wire each glow with ONE summer_run_script call with an explicit scenePath — one transactional run instead of a chain of summer_set_prop calls. For an enchanted sword:
For a soul gem on a pedestal (computed placement, such as a glow per gem in a ring, is a loop in the same script):
Judge the pulse with summer_screenshot framing:"camera" — emissive glow does not survive the preset framings’ substitute environment. Then verify — this recipe is one script, so a parse error is the whole effect:
For a charge-up before casting:

5. Parameters to tune

Cookbook — named variants

enchanted-sword (default)

Cool blue, gentle pulse, few tight motes.

soul-gem

Deeper purple, slow heartbeat pulse, many motes.

summoning-circle

Strong, broad, many motes drifting upward.

wisp-companion

Tiny floating orb. Attach to a PathFollow3D for the wandering motion.

charge-up (paired with lightning/muzzle-flash)

Author the fully-charged values here; set_intensity(0.0 → 1.0) scales them at runtime. Leaving light_energy_base at 0.0 means the fully-charged glow is also 0.0.

Anti-patterns

  • light_shadow_enabled = true on every magical item. A player carrying a glowing sword adds a fast-moving shadow caster; expensive. Default off.
  • Light range too large (10+ m for a small item). The glow lights up an entire room and the player loses sense of location. Match light_range to the item’s importance.
  • Mote material set to BLEND_MODE_MIX. Motes look like opaque dots, not glowing dust. Always BLEND_MODE_ADD.
  • Motes parented in world space (local_coords = false) for an item the player carries. Motes trail behind as the player walks. Default local_coords = true.
  • Forgetting to enable the source mesh’s emission before assigning the glow color. The shader’s emission stays black. The controller’s _resolve_source_mesh enables it.
  • pulse_hz too high. Above 3 Hz it strobes — accessibility issue (photosensitivity). Default 0.7 is calm.
  • Generating an “aura” PNG and using as a billboard sprite. The misroute. The procedural light + motes are alive and scale to any item.
  • BaseMaterial3D.new() for the mote material. BaseMaterial3D is abstract — that line is a parse error and takes the whole script down. Instantiate StandardMaterial3D; keep using the BaseMaterial3D.* enum constants.
  • A multiplicative set_intensity (light_energy_base *= scale). One set_intensity(0.0) pins the field to 0.0 permanently, so the charge-up tween from 0 to 1 does nothing. Hold the scale in its own variable and apply it where the energy is written.

Performance notes

  • One glow = 1 light + 16–32 particles. Sub-millisecond — an order-of-magnitude expectation, not a measurement.
  • N glowing items in a scene: budget ~12 active OmniLight3Ds before you start culling. The current Summer build has no LightOccluder3D (ClassDB.class_exists is false; LightOccluder2D is 2D-only). Cull with distance_fade_enabled / distance_fade_begin or a smaller omni_range.
  • Mobile: drop mote_count to 8, light_range × 0.5, light_shadow_enabled = false always.
  • LOD: in _process, scale _motes.amount_ratio and _light.light_energy by clamp(1.5 - dist_to_camera / 20.0, 0.10, 1.0). Past 20 m, drop motes entirely; keep light.

Edge cases

  • Glow on a moving NPC’s head (wisp follower). Set local_coords = true (default) and parent under the NPC. The light moves with the character.
  • Glow on a particle system (e.g., the wisp is a particle itself). Don’t — combine into a single Node3D with the glow attached, or the light won’t track the particle’s position.
  • Multiple glows on the same object (sword pommel + blade). Two MagicGlow children, different pulse_hz and slightly offset phases → richer feel. Use pulse_easing curve to sync if you want them to beat together.
  • Glow visible underwater. Reduce light_range 50% (water absorbs light); tint slightly green.
  • Pulse needs to sync with audio (heartbeat). Drive pulse_hz from your audio system’s BPM, or replace _process with an AnimationPlayer track timed to a music event.

Fallback (no MCP)

Section 4 is fully automatable — summer_write_file writes the controller, summer_add_node + summer_set_prop attach and tune it, and summer_create_scene + summer_save_scene produce magic_glow.tscn. Do not hand these steps to the user when the MCP tools are available. Without the MCP connection there is no engine to drive, so the user does it manually in Summer Engine:
  1. Create addons/vfx/magic-glow/ with the two files above.
  2. Add a Node3D child to the glowing object, attach magic_glow.gd. Save as magic_glow.tscn if you want a scene to instantiate.
  3. Tune the exported parameters in the inspector or via script.
  4. Check the Errors dock before tuning anything.

Handoff

After firing this recipe, suggest:
  • vfx-lightning — pre-cast charge-up. Use this skill’s charge-up variant, ramp set_intensity(0→1) then call Lightning.cast_lightning.
  • vfx-dissolve — pair summon-arrival (materialize_object) with the summoning-circle variant.
  • vfx-fire (the magic-fire variant) — for items that should glow AND flame.
  • game-feel — slight time-dilation when picking up a pulsing quest item adds weight.
  • sound-effect — generate magical hum, ethereal shimmer, 2s loop and play on the same anchor.

See also

  • _building-blocks/additive-billboard-particles.md — canonical additive material settings (this recipe uses them for motes)
  • vfx-lightning — pre-cast charge-up partner
  • vfx-dissolve — for summon arrival pairing
  • vfx-fire — for the magic-fire variant
  • gdscript-patterns — for the controller idioms (signals, exports, @tool)

From a shell

No Summer MCP tools in this session? Run each one as a command; when summer --version is missing or below 4.0, use npx -y summer-engine@latest in place of summer. Fields are flags in kebab-case (--scene-path res://main.tscn) or one --input '<json>', and summer ops describe <op> prints the exact input. The summer-cli skill has the rest.

Files in this skill

  • scene-scripting: Build scenes, levels, HUDs and wiring with one editor GDScript (summer_run_script) instead of call chains.
  • sound-effect: Make sound effects (swings, hits, whooshes, reloads, UI): three versions to pick from, then wire them.
  • game-feel: Add juice: hit-flash, trauma camera shake and audio ducking, one hit fires all three.
  • vfx-dissolve: Dissolve effect: a mesh burns away with a glowing edge, from a noise-threshold ShaderMaterial.
  • vfx-fire: Fire effect: animated flames from GPUParticles3D, a particle shader and a noise color ramp.
  • vfx-lightning: Lightning bolt effect: a jagged procedural path with a glow shader, end sparks and screen shake.
  • vfx-muzzle-flash: Muzzle-flash effect: a one-shot ~80 ms burst at a gun barrel, from particles or a star-burst quad.

Source: library/skills/vfx-magic-glow/SKILL.md, rendered from summer-engine@4.3.0 on npm.