Polar Coordinates
Thinking in angles and distances
So far, we have worked exclusively in Cartesian coordinates: x and y values that describe horizontal and vertical position. This system is intuitive for rectangles, grids, and straight lines. But some shapes are awkward to describe this way. Try drawing a circle in Cartesian coordinates, and you end up with square roots and implicit equations. Try describing a spiral, and the math becomes tangled.
There is another way to think about position in 2D space. Instead of asking "how far right and how far up?", we can ask "how far from the center, and in which direction?" This is the essence of polar coordinates.
From Cartesian to Polar
Every point in 2D space can be described by two numbers: its radius (distance from the origin) and its angle (direction from the positive x-axis). We call these r and theta.
Interactive: Explore Cartesian vs Polar
Drag the point to explore polar coordinates
The conversion between coordinate systems is straightforward. Given a point at Cartesian coordinates (x, y):
- Radius:
r = length(vec2(x, y))or equivalentlysqrt(x*x + y*y) - Angle:
theta = atan(y, x)
In GLSL, we can write this conversion as:
vec2 toPolar(vec2 p) {
return vec2(length(p), atan(p.y, p.x));
}The atan function with two arguments gives us the angle in radians, ranging from -PI to +PI. This is often called atan2 in other languages. The angle is measured counterclockwise from the positive x-axis.
Understanding the Angle
The angle returned by atan(y, x) spans from -PI (pointing left) through 0 (pointing right) to +PI (also pointing left, but approached from above). This range can be inconvenient. Often we want values normalized to 0-1 for easier manipulation.
To normalize the angle:
float angle = atan(p.y, p.x);
float normalized = (angle + 3.14159) / 6.28318;Adding PI shifts the range from [-PI, PI] to [0, 2PI]. Dividing by 2PI maps it to [0, 1]. Now the angle sweeps smoothly from 0 to 1 as you rotate around the center.
Radial Patterns
The power of polar coordinates becomes apparent when you start using radius and angle to drive visual properties. The simplest example: a radial gradient.
Polar Gradients
Brightness decreases with distance from center
When brightness depends on radius alone, you get concentric circles. When it depends on angle alone, you get radiating lines. Combining both opens up infinite possibilities.
vec2 centered = uv * 2.0 - 1.0;
float r = length(centered);
float angle = atan(centered.y, centered.x);
float radialGradient = 1.0 - r;
float angularGradient = (angle + 3.14159) / 6.28318;Spirals
Spirals emerge naturally when you combine angle and radius in a single expression. The key insight: a spiral is what happens when the "zero crossing" of a pattern depends on both how far out you are and what direction you are facing.
float spiral = fract(angle / 6.28318 + r * tightness);Interactive: Spiral Generator
Spirals emerge from combining angle and radius
The fract function wraps values to the 0-1 range, creating repeating bands. Adding the radius term makes these bands twist outward. Multiplying the angle determines how many spiral arms appear. Multiplying the radius controls how tightly the spiral winds.
Star Shapes
Stars are perhaps the most elegant demonstration of polar thinking. A star is simply a shape where the radius varies with angle in a repeating pattern.
float star(vec2 p, float points, float inner, float outer) {
float angle = atan(p.y, p.x);
float segment = 6.28318 / points;
float a = mod(angle + segment * 0.5, segment) - segment * 0.5;
float r = mix(outer, inner, abs(a) / (segment * 0.5));
return length(p) - r;
}Interactive: Star Generator
Star shapes come from modulating radius by angle
The magic happens in the mod operation. By taking the angle modulo the segment size, we repeat the same pattern for each point of the star. The mix interpolates between the outer and inner radii based on how far through each segment we are.
A Gallery of Polar Patterns
Once you internalize polar thinking, patterns that seemed complex become simple. Concentric rings, radiating rays, polar checkerboards, flower petals: all emerge from basic operations on radius and angle.
Pattern Gallery
Each of these patterns uses the same fundamental approach: convert to polar coordinates, then apply familiar operations (sine waves, step functions, modular arithmetic) to the radius and angle values.
Animation in Polar Space
Polar coordinates shine for animation. Subtracting time from the angle creates rotation. Subtracting time from the radius creates expansion or contraction. Combining both creates mesmerizing spiral motion.
float spiral = sin(angle * 5.0 + r * 10.0 - u_time * 2.0);
float pulse = sin(r * 8.0 - u_time * 3.0);Animated Polar Pattern
Animating polar patterns by subtracting time from angle and radius terms
The pattern seems to flow outward because we subtract time from terms that include radius. If we added time instead, it would flow inward. Adjusting the coefficients changes the speed and character of the motion.
When to Think in Polar
Polar coordinates are not always the right choice. For rectangular UI elements, grids, or text rendering, Cartesian coordinates remain more natural. But when your pattern has rotational symmetry, when it radiates from a center, or when you want circular motion, polar thinking often leads to simpler code.
The mental shift takes practice. Instead of thinking "move right and up," think "rotate and expand." Instead of "horizontal stripe," think "ring at a certain radius." The more you work with polar coordinates, the more intuitive this perspective becomes.
Key Takeaways
- Polar coordinates describe position as radius (distance from center) and angle (direction)
- Convert using
length(p)for radius andatan(p.y, p.x)for angle - The angle ranges from -PI to PI; normalize to 0-1 with
(angle + PI) / (2*PI) - Spirals combine angle and radius:
fract(angle + r * tightness) - Stars modulate radius by angle using
modto create repeating segments - Subtracting time from angle or radius terms creates rotation or expansion
- Use polar coordinates when patterns have radial symmetry or circular motion