Surface intersection

I've made this article out of my twitter thread

Intersection of sphere with intersaction of gyroid and sphere

Hey! This is a tutorial thread on how to find the intersection of two or more surfaces (not volumes) to make complicated #SDF shapes you can use for #raymarching.

  1. Let's start with a basic raymarching setup
#define SPHERE length(p)-1.
#define SDF(p) SPHERE
vec3 p; float d=0.,i,e=1.; for(;i++<99.&&e>.01; p=d*normalize(vec3((FC.xy-.5*r)/r.y,1))+ vec3(0,0,-5), p*=rotate3D(t,vec3(.3,1,0)), d+=e=.5*SDF(p)); o+=100./i/i;

You don't need to understand the bottom line, let's just focus on the line starting with

#define SDF(p) …

It defines the shape to render. Here's a sphere:

#define SPHERE length(p)-1.
#define SDF(p) SPHERE

  1. And here's an SDF for a plane Z (it's parallel to X- and Y-axis)
#define PLANE_Z -p.z
#define SDF(p) PLANE_Z

  1. To find the intersection of these two surfaces we just do
#define SDF(p) length(vec2(PLANE_Z, SPHERE))

And BOOM!💥 The circle is here!

The thing is that length of two SDFs is close to zero only if both SDFs are close to zero.

  1. We can inflate this surface by subtracting a small value from the SDF:
#define SDF(p) length(vec2(PLANE_Z, SPHERE))-.2

Please, pay attention to terminal -.2 in the formula.

  1. Can you make a short break to think about how to make a cylinder using this trick?

  1. Great, you did it! It's just an intersection of two planes inflated by subtracting a small value:
#define SDF(p) length(vec2(PLANE_X, PLANE_Z))-1.2

They often shorten this to just length(p.xz)-1.2 which is effectively the same.

  1. Let's intersect cylinders! It will result in two crossing circles
#define CYLINDER_Y length(vec2(PLANE_X, PLANE_Z))-1.2
#define CYLINDER_X length(vec2(PLANE_Y, PLANE_Z))-1.2
#define SDF(p) length(vec2(CYLINDER_Y, CYLINDER_X))-.1

  1. The crazy stuff begins! Beware gyroid
#define GYROID dot(sin(p*9.),cos(p.zxy*9.))*.1
#define SDF(p) GYROID

It is not easy to understand its shape because gyroid is borderless and we are inside

  1. To understand its shape better we have to intersect it with some other primitive. Why not a sphere?
#define SDF(p) length(vec2(SPHERE, GYROID))-.02

You can learn more about gyroids on

  1. You want to intersect intersections? No problem! We can use our weird shape from twit #7 for that:
#define CROSS_RINGS length(vec2(CYLINDER_Y, CYLINDER_X))-.2
#define SDF(p) length(vec2(CROSS_RINGS, GYROID))-.01

  1. You can intersect more than two surfaces at once! Use vec3 or vec4 for that:
#define SDF(p) length(vec3(CYLINDER_Y, CYLINDER_X, SPHERE))-.1

  1. Aaaaannndddd… the regular sphere SDF is a shortcut of the very same formula!
#define SDF(p) length(vec3(PLANE_X, PLANE_Y, PLANE_Z))-.9

#define SDF(p) length(

#define SDF(p) length(p)-.9

I was shocked to learn about it! 🤯

  1. That's it! Try playing with the code, interesting patterns can suddenly appear

It's my first tutorial thread. I would be grateful if you could share your thoughts on the subject, ask questions or brag about the SDFs you discover.