Oct 30 2022: 3D on an ESP32

Related project pages

A quick hack, to turn 2D into 3D

Also with 3D anaglyph!

Also with 3D anaglyph!

The first 3D on the MCH2022 badge

3D on the MCH2022 badge

After recently uncovering some Red/Cyan 3D anaglyph glasses, I decided it would be a cool idea to make a small demo of "Anaglyph 3D", a technique using one color per eye, filtered by the Red/Cyan 3D anaglyph glasses (Red left eye, Cyan right eye).

So I set off to make the effect, starting with simple 3D drawing. It is mostly the same as 2D, with the exception of the extra dimension and an extra step.

3D math is deceptively simple

3D has extra steps

3D has extra steps

Everything starts with the graphics stack getting a command (e.g. draw a rectangle of a certain size). The size and position of this shape is usually relative, so it needs to transformed into a set of absolute positions. For 2D, this would be perfect to draw right away, but for 3D, it's not so easy. 3D needs to be projected first. I'll get to how that works in a bit. Assuming projection is done, the next step is rasterisation. Rasterisation is the process of turning a shape defined by it's outline into a series of dots on a grid. In simpler terms; To rasterise is to produce the pixels you see based on the shape.

Projecting 3D into 2D

Projecting 3D into 2D

The reason for 3D having the extra step is because of how our eyes work. Our eyes see farther away objects as smaller than close objects; the light covers a smaller portion of the eye.
Let's take a look at the diagram first. The horizontal blue line here represents the axis 𝑧 = 0, and the vertical represents 𝑥 = 0. The red dot represents the original point in 3D space, and the green dot represents the projected point in 2D space to calculate.
You can see that 𝑧projected = 0. Now look at the triangles in the diagram. The bigger triangle is in reality a scaled up version of the smaller. The relative scale 𝑠 of the smaller triangle can be calculated using 𝑠 = 𝑓 ÷ (𝑧original + 𝑓). This is always a fraction because a number 𝑠 > 1 would mean that the projected triangle is bigger (which we'll assume it isn't). The final 𝑥projected can simply be found by multiplying 𝑥original by 𝑠.
Finally, we're left with this formula: 𝑥projected = 𝑥original ⋅ 𝑓 ÷ (𝑧original + 𝑓)
This can be applied to the 𝑦 as well coordinate by simply substituting 𝑥 for 𝑦.

Picture time!

Monkey with global lighting coming from the top right

A demonstration with Suzanne, a built-in model from Blender

Suzanne rendered in realtime

Suzanne in 3D anaglyph

Like the blog?

If you'd like to receive an email when I make a blog post, you can fill out the form below.