I knew I wanted to write about the Moon right around the time I was finishing the "Airfoil" article because it's been a while since I focused on space. Having covered "Earth and Sun" awhile ago, it was finally time to tackle the Moon itself.
The Moon felt like a great topic. It was conceptually much simpler than the more heavily physics-oriented articles on Airfoil and Bicycle. This subject wouldn't require any complicated simulations to show the Moon's motion. I was also hoping that it could be a shorter article than the last few pieces that kept increasing in length.
To explore the viability of this topic, I ordered some books in early March. Coincidentally, around that time I also watched SmarterEveryDay's video encouraging people to witness the total solar eclipse on April 8th, 2024. I'll be forever grateful to Destin, the YouTube channel's creator, for making that video, because it convinced me to visit Dallas to see the totality – it was absolutely mesmerizing. I've seen partial solar eclipses before, but the totality was unquestionably the best natural phenomenon I've ever seen.
All that sealed the deal on writing about the Moon, and after working on some initial rendering and simulation prototypes, I "officially" begun writing the piece in late May.
It took me a while to figure out which aspects of the Moon I should write about. Having prototyped a reasonably realistic rendering of the Moon, I knew I wanted to cover some of the visual aspects of that body, and the last chapter dedicated to opposition surge was actually the first part that I finished writing.
I also knew I wanted to begin the article with some elementary gravitational simulations. Those are pretty easy to make, but despite their simplicity, the sandbox-y nature makes them very interactive and visceral, which helps to explain all the effects leading to orbital motion.
However, with these two endpoints in place, I struggled to find a reasonable flow of the topics in the middle of the article. Originally, I wanted to focus on the details of orbital motion in even finer detail. I tried to do some kind of "let's build the Moon's orbit step by step" tutorial, but that proved to be a dead end. I realized that no one would want to manually tweak some of these abstract parameters to make them fit the real orbit, especially if that real orbit keeps changing with all the Sun's perturbations.
The epiphany arrived when I came up with the idea of explaining how the Moon's orbital motion affects observers on Earth. After all, this is the only way most of us will ever experience the Moon, so focusing more on what we see, and why we see it struck me as the most natural way to present the topics. It was a huge relief to unlock this direction, especially since it immediately led the way to all the "here's how the sky looks from Earth" demonstrations – I think these really reward self-directed experimentation.
The rest was just filling in the gaps. For example, writing about tides and spin-orbit locking required some background on fine-grained gravitational simulations, but interludes like these quite naturally split the more orbit-heavy discussions of the Moon's motion.
I was a little hesitant to delay the introduction of sunlight until almost two-thirds of the way into the article. It feels like we get to the good stuff like lunar phases and eclipses pretty late in the game, and as a result the article feels unusually tail-end heavy. However, I do think that separating out the motions of the Moon from the visuals of the Moon was the right choice. At the end of the day, all the sunlight-related effects are merely a consequence of the Moon's position in space.
The Moon is a grayish body embedded in the black background of space, so I wanted the accent colors used in the text and demonstrations to be a bit more eye-popping. I settled on a more vibrant, neon-like color scheme that I think works well in some places and slightly worse in others.
As usual, I created a single Sketch document where I tested different design ideas, often on top of screenshots taken from the in-progress article. You can see this messy canvas below:

I haven't recently used any photographs in my articles, but the two pictures of the lunar surface were just unbeatable to show what I was describing. I also really wanted to put the earthrise picture somewhere in the piece. I'm glad it fits so well in the black-to-white transition and the end of the article.
The rest of the design visuals came straight from the real world. For example, the color of the sky is just a computer simulation of the scattering that happens in the atmosphere. The stars are just real positions of around 9000 of the brightest stars seen from the Earth. In cases like this, it's very liberating to just copy nature without having to come up with custom designs.
While most of the graphics in the article are pretty simple, some components required a lot of dedicated work.
Rendering of the Moon was a major rabbit hole that I fell into. Correctly rendering the Moon's colors requires specification of 5 different parameters. These parameters not only vary per location, but they also change values for different light wavelengths.
While maps of these parameters are available and well described, they're also missing the Moon's polar region, because very little sunlight actually reaches those areas. For these reasons, a fully physically correct rendering of the Moon wasn't really feasible, so I had to settle for a simplified model, in which I crudely estimate the baseline parameters based on the modified textures from NASA's CGI Moon Kit.
That gave me the correct shading of the Moon, but to render the geometry and shadows of the craters I used the relaxed cone stepping method where the height-map of the Moon's surface gets ray marched to directly evaluate the elevation or shadow at a given location. The color and height-map are then mapped using octahedron environment maps to minimize the uneven mapping in the polar regions that happens in the more traditional equirectangular projection arrive at these deformed textures:

When it comes to Earth, this was the third time that I've rendered it on my site. Although I simulated the colors of the sunlit atmosphere, the clouds are once again just a single fixed texture. I had some grand visions of simulating their motions like I did for fluids in the "Airfoil" article, but I realized that this would be yet another time sink with minimal visual reward. As time flies, the Earth keeps spinning, which obscures any motion of the clouds, especially with the motion blur I applied to the rotating surface.
When I started working on the simulations of the orbital motions, I originally wanted to just use some classic analytical formulas from Astronomical Algorithms, but the ultimate source of truth these days seem to be the NASA JPL models that I've referenced in the article.
The resulting datasets from these calculations are freely available, and with the help of Greg Miller's blog post, I was able to parse the data files and convert them to the format I needed. The full ephemeris for the motions of even just the Moon and the Earth-Moon barycenter was pretty large. Since we aren't trying to land on the Moon using my article, I removed some of the unnecessary higher precision terms, and by reducing the range of supported time-frames to only the next 100 years, I was able to fit all the data I needed in 1 MB of storage.
Interestingly enough, the positions expressed in these NASA ephemeris files are relative to the barycenter of the entire Solar System, which means that in this reference frame, the Sun itself also meanders around. I originally thought I could ignore the Sun's motion, but, without accounting for that movement, the simulated eclipses on Earth wouldn't happen at the right time and place.
With this solid foundation in place, all the orbital simulations became very easy, as I just needed to query this small database for the positions and velocities of the Moon, the Earth, and the Sun at any desired time.
In comparison, the simulations where the reader can create and smash planetary blobs were much harder to make. For close interactions of the bodies, I employed smoothed-particle hydrodynamics in which a fluid or a solid is simulated with particles that can interact with each other through forces. In the blog, I used some simplified interaction models that are dedicated for simulation of solids, but more complicated models can fairly accurately represent other properties like temperature or damage state of real bodies.
The gravitational interactions between the bodies were also non-trivial. A full-featured simulation requires calculating the gravitational attraction of each particle with all the other particles, or an n² relation. This very quickly becomes computationally unfeasible.
To make this work, I wrote a simple version of the Barnes–Hut algorithm where the space is divided into regions. Conceptually, this allows a group of distant particles to be aggregated into a single body that can be used to cheaply express distant gravitational interactions.
These simulations ended up working fine for the planetary collisions, but I also really wanted to simulate how impact craters are created. I ported to JavaScript some parts of an SPH simulation library that I found and I eventually got some things going, as you can see in the animated GIF below:

Unfortunately, these simulations were quite finicky and pretty slow, so after sinking many hours into trying to fine-tune them, I eventually completely abandoned that idea.
I also implemented SPH simulations using WebGL, and I got reasonably far in the process:

Given constrained nature of WebGL, I had to use ancient GPU programming techniques by abusing textures and stencil buffers to get correct binning of particles. You can see the slices of the 3D world packed into a 2D texture in the debug dump in the background of this animation. I ended up abandoning this approach, because it was pretty hard to work with, and doing n-body gravitational simulations this way would be even more challenging.
So how did the hopes of a "shorter article" pan out? At over 16000 words, this is my longest article yet. I'm really not sure how this happened. I think I just severely underestimated what it would take to describe all the topics I wanted to present. While I was making the article, I also chased a few simulation dead ends that contributed to the long time it took to complete it all.
While I wish I could have finished this article much earlier, I don't regret the extra effort spent on making it. I'm very happy with how the piece turned out.
Bartosz Ciechanowski
2025-01-02 01:32:51 +0000 UTCBartosz Ciechanowski
2025-01-02 01:27:28 +0000 UTCKevin Henry
2024-12-29 06:07:55 +0000 UTCSascha von Meier
2024-12-23 16:03:16 +0000 UTCAwesomeLemon
2024-12-22 17:08:24 +0000 UTC