Value Generators
Value generators are a core concept in three.quarks that provide flexible ways to generate and modify values over time or based on other parameters. They are used throughout the particle system to control particle properties such as size, color, rotation, emission rate, and more.
Overview
Value generators allow you to define how values change rather than using fixed values. This approach enables dynamic and more natural-looking particle effects. For example, instead of using a constant size for particles, you can make them grow or shrink over their lifetime.
Types of Value Generators
three.quarks provides several types of value generators to suit different needs:
Basic Value Generators
These generators produce simple numeric values:
ConstantValue
import { ConstantValue } from "three.quarks";
// Creates a value generator that always returns 5
const constant = new ConstantValue(5);
The ConstantValue
generator returns the same value every time. It’s useful when you want a fixed property.
IntervalValue
import { IntervalValue } from "three.quarks";
// Creates a value generator that returns a random value between 1 and 10
const interval = new IntervalValue(1, 10);
The IntervalValue
generator returns a random value within a specified range. The value is determined once when the particle is created and remains constant for that particle’s lifetime.
Function-based Value Generators
These generators produce values that can change over time or based on a parameter:
PiecewiseBezier
import { PiecewiseBezier, Bezier } from "three.quarks";
// Creates a Bezier curve from 0 to 1
const bezier = new Bezier(0, 0.33, 0.66, 1);
// Creates a piecewise bezier function starting at time 0
const piecewise = new PiecewiseBezier([[bezier, 0]]);
The PiecewiseBezier
generator uses Bezier curves to interpolate values smoothly. It’s particularly useful for creating easing functions or natural motion curves.
Color Generators
These generators are specific to producing color values:
ConstantColor
import { ConstantColor } from "three.quarks";
import { Vector4 } from "three";
// Creates a color generator that always returns red (RGBA)
const red = new ConstantColor(new Vector4(1, 0, 0, 1));
The ConstantColor
generator returns a constant color value.
ColorRange
import { ColorRange } from "three.quarks";
import { Vector4 } from "three";
// Creates a color generator that returns a random color between red and blue
const colorRange = new ColorRange(
new Vector4(1, 0, 0, 1), // Red
new Vector4(0, 0, 1, 1), // Blue
);
The ColorRange
generator returns a random color within a specified range. Like IntervalValue
, the color is determined once for each particle.
RandomColor
import { RandomColor } from "three.quarks";
import { Vector4 } from "three";
// Creates a color generator that returns a different random color between red and blue each time
const randomColor = new RandomColor(
new Vector4(1, 0, 0, 1), // Red
new Vector4(0, 0, 1, 1), // Blue
);
Unlike ColorRange
, the RandomColor
generator produces a new random color each time it’s called.
Gradient
import { Gradient } from "three.quarks";
import { Vector3 } from "three";
// Creates a gradient from black to white
const gradient = new Gradient(
[
[new Vector3(0, 0, 0), 0], // Black at position 0
[new Vector3(1, 1, 1), 1], // White at position 1
],
[
[1, 0], // Alpha 1 at position 0
[1, 1], // Alpha 1 at position 1
],
);
The Gradient
generator interpolates colors based on a parameter (usually time). It’s excellent for smooth color transitions over a particle’s lifetime.
RandomColorBetweenGradient
import { RandomColorBetweenGradient, Gradient } from "three.quarks";
// Create two gradients
const gradient1 = new Gradient(/* ... */);
const gradient2 = new Gradient(/* ... */);
// Create a random color between the two gradients
const randomGradient = new RandomColorBetweenGradient(gradient1, gradient2);
This generator creates random colors between two gradients, allowing for more varied color transitions.
Rotation Generators
These generators are specific to producing rotation values:
AxisAngleGenerator
import { AxisAngleGenerator, ConstantValue } from "three.quarks";
import { Vector3 } from "three";
// Creates a rotation around the Y axis with a constant speed
const rotation = new AxisAngleGenerator(
new Vector3(0, 1, 0), // Y axis
new ConstantValue(1), // 1 radian per second
);
The AxisAngleGenerator
rotates particles around a specified axis by a given angle.
EulerGenerator
import { EulerGenerator, ConstantValue } from "three.quarks";
// Creates a rotation that changes in all three axes
const rotation = new EulerGenerator(
new ConstantValue(0.1), // X rotation
new ConstantValue(0.2), // Y rotation
new ConstantValue(0.3), // Z rotation
);
The EulerGenerator
applies rotation using Euler angles, which is useful for more complex rotations.
RandomQuatGenerator
import { RandomQuatGenerator } from "three.quarks";
// Creates random rotations
const random = new RandomQuatGenerator();
The RandomQuatGenerator
generates random rotations, which is useful for creating varied orientations.
Vector Generators
These generators are specific to producing 3D vector values:
Vector3Function
import { Vector3Function, ConstantValue } from "three.quarks";
// Creates a vector that grows in all dimensions
const vectorFunc = new Vector3Function(
new ConstantValue(1), // X component
new ConstantValue(2), // Y component
new ConstantValue(3), // Z component
);
The Vector3Function
generator creates 3D vectors based on separate functions for each component.
Using Value Generators in Particle Systems
Value generators are used throughout the particle system configuration to control various properties:
import {
ParticleSystem,
ConstantValue,
PiecewiseBezier,
Gradient,
SphereEmitter,
ColorOverLife,
SizeOverLife,
} from "three.quarks";
import { Vector3, Vector4 } from "three";
// Create a particle system
const system = new ParticleSystem({
// Use a constant value for particle lifetime
startLife: new ConstantValue(2),
// Use a constant value for initial speed
startSpeed: new ConstantValue(5),
// Use a sphere emitter
shape: new SphereEmitter(),
// Add behaviors that use function generators
behaviors: [
// Size changes over particle lifetime using a bezier curve
new SizeOverLife(new PiecewiseBezier(/* ... */)),
// Color changes over particle lifetime using a gradient
new ColorOverLife(new Gradient(/* ... */)),
],
});
Creating Custom Value Generators
You can create custom value generators by implementing the appropriate interface:
import { ValueGenerator, GeneratorMemory, FunctionJSON } from "three.quarks";
// Create a custom value generator
class CustomValueGenerator implements ValueGenerator {
type: "value" = "value";
constructor(private parameter: number) {}
startGen(memory: GeneratorMemory): void {
// Initialize if needed
}
genValue(memory: GeneratorMemory): number {
// Generate and return a value
return Math.sin((this.parameter * Date.now()) / 1000);
}
toJSON(): FunctionJSON {
return {
type: "CustomValueGenerator",
parameter: this.parameter,
};
}
clone(): ValueGenerator {
return new CustomValueGenerator(this.parameter);
}
}
Performance Considerations
When using value generators, keep these performance tips in mind:
ConstantValue
is the most efficient generator as it doesn’t need to compute anything.- Complex generators like
PiecewiseBezier
are more CPU-intensive, so use them sparingly with large numbers of particles. - Consider using
startGen()
to pre-compute values for particles when possible.
Examples
Size that grows and then shrinks
import { PiecewiseBezier, Bezier, SizeOverLife } from "three.quarks";
// Create a bezier curve that rises and falls
const curve = new Bezier(0, 1, 1, 0);
const sizeChange = new PiecewiseBezier([[curve, 0]]);
// Add it to a behavior
const behavior = new SizeOverLife(sizeChange);
Color that transitions from red to blue over lifetime
import { Gradient, ColorOverLife } from "three.quarks";
import { Vector3 } from "three";
// Create a gradient from red to blue
const colorChange = new Gradient(
[
[new Vector3(1, 0, 0), 0], // Red at start
[new Vector3(0, 0, 1), 1], // Blue at end
],
[
[1, 0], // Full opacity at start
[0, 1], // Fade out at end
],
);
// Add it to a behavior
const behavior = new ColorOverLife(colorChange);
Random rotation speed around y-axis
import {
AxisAngleGenerator,
IntervalValue,
RotationOverLife,
} from "three.quarks";
import { Vector3 } from "three";
// Create a rotation with random speed between 1 and 3 radians per second
const rotation = new AxisAngleGenerator(
new Vector3(0, 1, 0),
new IntervalValue(1, 3),
);
// Add it to a behavior
const behavior = new RotationOverLife(rotation);
Conclusion
Value generators are a powerful feature of three.quarks that allow for flexible and dynamic particle effects. By combining different generators and behaviors, you can create complex and visually appealing effects that would be difficult to achieve with static values.
Next Steps
Now that you understand value generators, here are some recommended next steps:
-
Explore Behaviors: Learn more about Behaviors to understand how to apply value generators to different particle properties.
-
Optimize Performance: Review the Optimization Techniques guide to ensure your particle systems run efficiently.
-
Study Examples: Look at the Examples section to see value generators in action in complete particle systems.
-
Advanced Integration: Integrate your particle systems with other Three.js features like physics simulations or scene transitions.