Shape Fireworks with Vex
Introduction
This technique explores an approach to shaping fireworks using VEX in Houdini. By combining particle simulation with post-simulation modifications, we can adjust various particle attributes to create firework effects that aim to resemble real-world displays.
Wrangle 01: Color and Sparkles
Fireworks particles exhibit slight variations in both size and luminous intensity. To mimic this, we can assign a random luma value to each particle based on its ID. Fireworks are also characteristically sparkly. To achieve this effect, we randomize the luminance value over time. However, this effect should be gradual as sparkles typically appear late in the firework’s life. Therefore, we use a threshold value to gradually introduce this behavior.
Next, contrast is enhanced to create a flickering on/off effect, and this value is assigned to the Alpha attribute. Lastly, we apply a color gradient over the particle’s life, typically transitioning from high to low luminance values.
float randC, randT, randS, thresh;
randC = rand(@id + chf('color_seed'));
//assign random luma based on id
randT = rand(@id + chf('color_seed') + @Frame);
//assign random luma based on id + time = sparkles
randS = rand(@id + chf('selection_seed'));
//new random value for sparkles behavior aquisition
thresh = chf('sparkliness');
//dial in sparkles over time with this slider
@Cd = randC;
if (thresh > randS) @Cd = randT;
//sparkly behavior assignation
@Cd = clamp(chramp('add_contrast', float(@Cd)), 0, 1);
f@Alpha = float(@Cd);
f@agen = @age/@life;
@Cd = vector(chramp('grade_fireworks', @agen));
Wrangle 02: Get age Range
To shape each trail with a more luminous head, we’ll increase the size of the particles at the front. This requires determining the age range of the particles, as the head consists of the oldest ones. We’ll store the age attribute in an array using a detail wrangle, since this operation only needs to be performed once.
float ages[];
for (int i = 0; i < @numpt; i++)
{
float age = point(0, "age", i);
append(ages, age);
}
f[]@ages = ages;
f@min = min(ages);
f@max = max(ages);
Wrangle 03: Resize Particles
This wrangle is responsible for adjusting the size and appearance of individual particles:
- It introduces size variation among particles using a random factor.
- It adjusts particle size over the particle’s lifetime.
- It creates a “bump” effect at the trail head, making the front of each trail appear larger and more prominent.
- It applies a global size multiplier for easy overall size adjustment.
These effects combine to create more realistic and visually interesting firework trails, with larger, brighter heads tapering off towards the tail.
float rand_size = rand(@id);
rand_size = chramp('randomize_size', rand_size);
@pscale = rand_size;
@pscale *= chramp('size_over_life', @agen);
f@relAge = fit(@age, @min, @max, 0, 1);
float bump = chramp('bump_trail_head', @relAge);
@pscale *= bump;
float pscale_global_mult = chf('pscale_global_multiplier');
@pscale *= pscale_global_mult;
For more realistic results, the value of the bump at the trail head should be animated over the firework’s lifetime.
Wrangle 04: Trim by trail id
This wrangle focuses on creating variation in trail length:
- It uses the trail ID to generate a random factor for each trail. This factor is used to adjust the apparent age of particles in the trail.
- Particles that exceed a certain age threshold are removed.
The result is that different trails in the firework will have varying lengths, adding complexity and natural randomness to the overall firework shape. This helps avoid a uniform, artificial look, making the firework display more dynamic and realistic.
Together, these wrangles contribute significantly to the organic, varied appearance of the firework, creating a more convincing and visually appealing effect.
f@old = fit01(rand(@trail_id), chf('trim_low_random_values'), chf('trim_high_random_values'));
@agen /= @old;
if (@agen>1) removepoint(0, @ptnum);
Conclusion
The VEX wrangles described here represent one way to enhance a basic particle simulation for creating more detailed firework effects. Each wrangle focuses on a specific aspect of the firework’s appearance, from color and sparkle effects to trail shaping and length variation.
This approach has been useful in my production work, but it’s important to remember that the needs of each shot can vary greatly. Houdini’s flexibility allows for many different techniques, and I encourage exploration to find the method that best suits your specific project requirements.