Combining Procedural Shapes: Building Complex Graphics in GLSL
One of the biggest advantages of procedural graphics is that simple shapes can be combined to create much more complicated ones.
Instead of drawing an image, we build it one piece at a time.
Think of it like building with LEGO bricks.
One brick is simple.
A handful of bricks can become a house, a car, or even an entire city.
Procedural shaders work in exactly the same way.
Today we'll learn how to combine circles, rings, and gradients to build more complex graphics.
Every Shape Is Just a Number
When we created a circle, the result wasn't actually a shape.
It was a number.
float circle = 1.0 - step(0.25, distance(vUv, vec2(0.5)));
Pixels inside the circle received the value 1.0.
Pixels outside received 0.0.
Those numbers can be added, subtracted, or multiplied just like any other values.
That simple idea allows us to build almost anything.
Combining Two Circles
Let's place two circles next to each other.
float circleA = 1.0 - step(
0.18,
distance(vUv, vec2(0.35, 0.5))
);
float circleB = 1.0 - step(
0.18,
distance(vUv, vec2(0.65, 0.5))
);
Each one is created independently.
Now let's combine them.
float shape = circleA + circleB;
Both circles appear together.
Instead of drawing one object, we've created two.
Understanding Addition
Adding procedural shapes is similar to placing stickers on top of each other.
If either shape exists, the final result also exists.
Addition creates a union of shapes.
This is one of the most common techniques in procedural graphics.
Subtracting Shapes
What happens if we subtract one shape from another?
float shape = circleA - circleB;
Where the second circle overlaps the first, part of the shape disappears.
This technique is useful for cutting holes, creating crescents, and designing more interesting silhouettes.
Multiplying Shapes
Multiplication behaves differently.
float shape = circleA * circleB;
Only the overlapping area remains visible.
Everything else disappears.
This creates an intersection between the two shapes.
A Complete Example
#ifdef GL_ES
precision mediump float;
#endif
varying vec2 vUv;
void main(){
float circleA = 1.0 - step(
0.18,
distance(vUv, vec2(0.40, 0.5))
);
float circleB = 1.0 - step(
0.18,
distance(vUv, vec2(0.60, 0.5))
);
float shape = circleA + circleB;
gl_FragColor = vec4(vec3(shape), 1.0);
}
Although each circle is simple, together they begin to form more interesting graphics.
Creating a Capsule Shape
Move the circles closer together.
vec2(0.45, 0.5)
vec2(0.55, 0.5)
Now they overlap.
Instead of looking like two separate circles, they begin to resemble a capsule.
This simple trick appears in many procedural user interface elements.
Combining Rings
The same technique works with rings.
float ringA = outerA - innerA;
float ringB = outerB - innerB;
float shape = ringA + ringB;
Now two outlined circles appear together.
This can become a radar display or a futuristic interface.
Mixing Glows
Earlier we created glowing circles.
Now combine them.
float glow = glowA + glowB;
The light naturally blends where the two glows overlap.
Many lighting effects begin with exactly this idea.
Animating Individual Shapes
Nothing says every shape must move the same way.
vec2 centerA = vec2(
0.35 + sin(uTime) * 0.10,
0.5
);
vec2 centerB = vec2(
0.65,
0.5 + cos(uTime) * 0.10
);
Each circle now moves independently.
By combining animated shapes, much richer effects become possible.
Where Is This Technique Used?
Combining procedural shapes is one of the foundations of shader programming.
It appears in
- User interface elements
- Game icons
- Particle systems
- Loading indicators
- Procedural logos
- Radar displays
- Health bars
- Target markers
- HUD graphics
- Motion graphics
Many complex designs begin with only circles, rectangles, and gradients.
Try These Experiments
Create two circles.
circleA + circleB
Subtract one circle.
circleA - circleB
Show only the overlap.
circleA * circleB
Animate one circle.
sin(uTime)
Animate both circles independently.
sin(uTime)
cos(uTime)
Try changing their positions, sizes, and colours.
You'll be surprised how many unique designs you can create.
A Small Challenge
Can you create these effects?
- A pair of overlapping circles.
- A capsule shape.
- A glowing Venn diagram.
- A moving radar interface.
- A simple procedural logo made from circles.
Remember that every effect starts with a few simple building blocks.
What We Learned
Today we discovered that procedural shapes can be combined using ordinary mathematical operations.
Adding shapes creates unions.
Subtracting shapes cuts holes.
Multiplying shapes keeps only overlapping regions.
These techniques allow simple primitives to grow into much more complicated graphics.
Leave Combining Procedural Shapes: Building Complex Graphics in GLSL to:
Read more #editing posts
Best Posts From hey2d
We have not curated any of hey2d's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.
More Posts From hey2d
- Fragment Shaders Made Simple: What gl-FragColor Does
- Understanding gl-Position: My First Real Vertex Shader
- Creating Procedural Galaxies and Nebulas in GLSL
- Creating a Procedural Night Sky and Stars in GLSL
- Creating Procedural Clouds in GLSL
- Adding Reflections and Highlights to Procedural Water in GLSL
- Creating Procedural Water in GLSL
- Creating Procedural Smoke in GLSL
- Creating Procedural Fire in GLSL
- Creating Procedural Wood Grain in GLSL
- Creating a Procedural Marble Texture in GLSL
- Domain Warping in GLSL: Distorting Noise to Create Organic Worlds
- Fractal Brownian Motion in GLSL: Building Rich Procedural Noise
- Understanding Gradient Noise in GLSL
- Creating Smooth Value Noise in GLSL
- Creating Random Values in GLSL: The Building Blocks of Procedural Graphics
- Combining Translation, Rotation, and Scaling in GLSL
- Scaling Shapes in GLSL: Making Procedural Graphics Grow and Shrink
- Rotating Shapes in GLSL: Understanding Coordinate Rotation
- Moving Shapes in GLSL: Understanding Coordinate Translation