NatureGL Magicv1.0.0

Guides

Portals and spell orbs

Two glow-heavy effects. A portal is two torus emitters inside a swirl field that spins dye and pulls it into the eye. Spell orbs are emitters on tilted orbits that leave coloured trails and light the scene.

#Portals

The portal preset with the camera slowly orbiting. The swirl field fades out about 0.4 m either side of the portal plane (swirl.thickness), so the dye winds into a flat vortex.
js
const portal = magic.addEffect('portal', {
  position: [0, 2.25, 0],
  axis: [0, 0, 1],                // the portal's normal
  colors: ['#a66bff', '#35d4ff'], // outer ring, inner ring
});
portal.retarget({ target: camera.position });   // turn it to face the camera

A portal adds four things to each frame:

  1. An outer torus emitter of radius 1.12 m and tube thickness 0.2 m in colors[0]. Its glow pulses by ±pulse (25 %) at pulseRate 2.2 rad/s.
  2. An inner torus emitter of innerRadius 0.62 m in colors[1]. Its radius wobbles by innerWobble 0.08 m.
  3. A swirl field around the axis. Inside swirl.radius it drives the fluid toward a velocity that spins at speed, pulls toward the axis at pull and lifts along it at lift.
  4. Rim sparks that spawn on a circle of sparks.ringRadius 1.15 m and are attracted to the centre at sparks.attract 1.8 m/s, so they spiral into the eye.

Neither emitter pushes the fluid (velocity zero, blend 0). All the motion comes from the swirl.

#Options

OptionDefault
position, axis[0, 2.25, 0], [0, 0, 1]Centre and normal. retarget() sets axis
radius, thickness1.12, 0.2Outer ring and its tube radius (m)
innerRadius, innerThickness, innerWobble0.62, 0.12, 0.08Inner ring
colors[[0.62, 0.28, 1], [0.2, 0.85, 1]]Outer and inner dye, linear RGB
glow, innerGlow3.2, 2.4Glow per second
density, innerDensity0.55, 0.35Dye density per second
pulse, pulseRate0.25, 2.2Outer glow pulse depth (0 = steady) and rate (rad/s)
swirl{ radius: 1.75, speed: 3.2, pull: 1.35, thickness: 0.4, lift: 0 }speed: 0 removes the swirl field
sparks{ rate: 1.2, radius: 0.12, ringRadius: 1.15, attract: 1.8, life: 0.35, jitter: 0.8, colorA, colorB }rate: 0 removes the sparks

The colors getter returns the colours in effect this frame, with any setColor() override applied. The demo uses it to tint the rune ring.

#Recipes

js
// a calm, wide gate: slower spin, less pull, no pulse
portal.set({ radius: 1.4, pulse: 0, swirl: { speed: 1.6, pull: 0.6 } });

// a floor portal: lie it flat and let it lift smoke upward through the eye
portal.move([0, 0.4, 0]).retarget([0, 1, 0]).set({ swirl: { lift: 1.2 } });

// open it over five seconds (the clip on the Overview page)
magic.clear();
let opened = 0;
function openPortal(dt) {                     // call every frame before magic.update(dt)
  const k = Math.min(1, (opened += dt) / 5);
  portal.setIntensity(k * k * (3 - 2 * k));
}

#Spell orbs

spellOrbs: three orbs at 1.25 rad/s on orbits tilted 0, 0.9 and −0.9 rad. The fluid inside each orb is driven at 60 % of the orb's speed (trail: 0.6), which drags the glow out into ribbons.
js
const orbs = magic.addEffect('spellOrb', {
  position: [0, 2.0, 0],     // orbit centre
  count: 3,
  colors: ['#a66bff', '#35d4ff', '#ffc44a'],
});
orbs.orbs[0].position;       // live world position of each orb

Each orb is an emitter that moves along its orbit. It also gets:

  • a point light (light.intensity 28, scaled by the glow control and the effect's intensity), so the orbs light the floor and props as they pass. Set light: { intensity: 0 } to add no lights.
  • a bright core sphere of visual.size 0.075 m, drawn at three times the orb colour. Set visual: { size: 0 } for none.

The orbs' lights and meshes are ordinary three.js objects in your scene, named MagicOrbLight and MagicOrb. setLightsEnabled(false) hides the lights along with the glow light.

Lights on
Lights off
Lights offLights on
setLightsEnabled(false) against the default. It hides the orbs' point lights and the emission-driven glow light; the rest of the scene's lighting is unchanged.

#Options

OptionDefault
position[0, 2, 0]Orbit centre
count3Number of orbs. Change it live with set({ count })
orbitRadius, speed1.05, 1.25Metres; rad/s
tilts, bob[0, 0.9, -0.9], 0.18Per-orb orbit tilt (cycled); vertical bob (m)
colorsviolet, cyan, goldCycled over the orbs
radius, glow, density0.15, 4.2, 1.2Emitter size, glow and dye per second
temperature, blend, trail0.08, 0.25, 0.6Heat; drive strength; fraction of the orb's velocity given to the fluid
light{ intensity: 28 }One PointLight per orb; 0 = none
visual{ size: 0.075 }Core sphere per orb; 0 = none
sparks{ rate: 0.35, radius: 1.4, needGlow: 0.25, life: 0.6, jitter: 1.2, colorA, colorB }Sparks spawn only where the dye glow exceeds needGlow