Projects that
escalated.

None of these were planned. Something small bugged me, it turned out to be interesting, and then it was 3 a.m. and I was reading a forum thread from 2014 about refractive index.

Close-up of a green glass cube numbered 4 between red and blue cubes. Its edges are rounded and the black numerals are inlaid in the faces.
The rounded edges come from the SDF, not a beveled mesh. The numerals are inlaid black enamel.
Five glass cubes numbered 2 to 32 on a gray shelf, with light refracting through each one and their reflections on the shelf.
Refraction, reflections and shadows, all ray traced on the phone, every frame.
iOS · Shipping October

I gave a puzzle game
real ray tracing.

A drop-and-merge game where the pieces are glass, with refraction computed per pixel on the iPhone’s ray tracing hardware. Light bends through each cube, picks up its color on the way through (Beer–Lambert absorption), and lands on the shelf as a colored shadow.

The cubes aren’t meshes. Each one is a signed distance field, and the ray marches along it to find the true rounded surface. So the edges are mathematically round instead of faceted, and the code knows exactly how far light traveled inside the glass.

At the edges and corners, a six-wavelength spectral fan splits the light into visible prism fire. Only there, because that’s the only place real glass does it.

For a while the cubes looked like they had square corners, which is not great on a game whose whole bit is realistic glass. I went after the geometry twice. Didn’t fix it either time. So I built a debug mode that paints every bounce of every ray its own color, and the edges came back perfectly round. The geometry had been fine the whole time. Right at the edge of a cube, glass basically turns into a mirror, and there was nothing off to the side for it to reflect, so the rims went black. And a black outline looks exactly like a hard corner. The fix was hiding a couple of studio lights just out of frame, which is the same trick product photographers use to give glass clean edges.

Renderer
Metal, hardware RT
Target
120 Hz locked
Requires
A17 Pro or newer
Fallback
Full SceneKit path
Metal / MSLHardware ray tracing SDF raymarchingMetalFX SceneKitSwiftUI
macOS · 227 commits in 16 days

A photograph you can
look around.

Take a flat photo and get back a gaussian splat, a 3D scene made of millions of soft colored blobs. Then put it on a Looking Glass holographic screen, where it has real depth you can lean side to side and look into.

The display needs 66 views of the scene at once, rendered into one 4092×4092 “quilt” that its lenticular lens fans out across your eyes. I measured the whole path end to end at 270 fps, about 3.7 ms a frame, roughly four and a half times faster than it needs to be. That’s fast enough to drag the scene around live instead of pre-rendering it.

Most of the real work was measuring. I built an offscreen renderer that runs the display’s own lenticular shader and hands back the exact pixels the glass would show, so I could see bugs without pointing a camera at the hardware.

The Looking Glass SDK kept rejecting what I rendered, with an error about pixel formats. So I tried five different formats, and all five failed the exact same way, which is when I stopped believing the error message. The SDK needs to create that texture itself, because it quietly shares it with the display behind the scenes. Same format, it just had to come from the SDK instead of from me, and everything worked. I only found that by measuring every combination I could think of, 10 draws across 6 setups, until the pattern showed up.

Views/frame
66
Measured
270 fps
Quilt
4092 × 4092
Own code
~16,000 lines
MetalGaussian splatting Looking GlassSwift Photogrammetry
Raspberry Pi · Running on the wall

A wall panel that feels
like an appliance.

A touchscreen mounted on the wall that controls the music in the house. I wanted it to feel like a $400 product you’d buy at a store, not a hobby project running in a browser.

It’s a 5.5″ AMOLED panel turned sideways, run by a Raspberry Pi 5 that boots straight into the app so you never see a desktop. The main colors get pulled out of the album art and drive a WebGL background of seven drifting, breathing clouds that change with whatever’s playing.

It talks to the speakers over the local network, so it keeps working when the internet doesn’t. It grabs the next track’s artwork and colors before you hit skip, so the transition never stalls.

I lost two whole days to a deploy that swore it worked. The code lives in iCloud Drive, and iCloud likes to keep files as empty placeholders until something actually opens them. So my sync tool copied the placeholders, reported bytes transferred like everything was fine, and put every single file on the Pi at zero bytes. Nothing on my end said anything was wrong. The fix was making iCloud download everything before packing it up.

Panel
5.5″ AMOLED
Control
Local UPnP
Frontend
Svelte 5 + WebGL2
Boot
Straight to kiosk
Raspberry Pi 5TypeScript Svelte 5WebGL2 Sonos UPnPsystemd
Swift + Python · Negative result

I built a model to beat
Vegas. It lost.

I play in a college football confidence pool. You rank ten games by confidence, and each pick you get right scores that many points. I’ve won it twice. The obvious next step was replacing my spreadsheet with a real model.

So I built one: a leakage-aware training set of 6,398 games across nine seasons, walk-forward backtested. Then I added the stuff that’s supposed to give you an edge, like rest days, travel distance, time-zone changes and rankings.

The edge features added −0.02 points a week. Just ranking games by the betting line beat both models outright, 44.07 points a week against 43.55. Feature importance made the reason pretty clear: the closing line already prices everything in, because thousands of people with money on it got there first.

I could have shipped it as “AI that beats Vegas.” But I’d literally built the thing that proved that false, and shipping it anyway would’ve been a lie with a nice icon on it. So I rebuilt the app around what’s actually true: the market ranking is provably the best one available, and the app’s job is to automate it, calibrate it properly, and be a really good native app while it does.

This is the one I’m proudest of. I set out to beat Vegas and I didn’t, and I’d rather publish that than squint at a result until it looks like a win. The calibration work still paid off: refitting the win-probability curve on all 6,398 games showed the old one was measurably overconfident. Just not the improvement I went looking for.

Training set
6,398 games
Market
44.07 pts/wk
Best model
43.57 pts/wk
Verdict
Market wins
Swift / SwiftUIPython scikit-learnOn-device LLM WeatherKitSwift Charts
Plasticity render of both wind pods mounted on either side of the Moza R12 wheelbase.
Fabrication · Ongoing

It didn’t stop
at a seat.

The sim isn’t really a racing game. It’s modeling tire temperature, grip and downforce in real time, and it hands all of that back out as live telemetry. So the car already knows your left front is about to let go. This project is about getting that onto your body before you’d ever read it on a screen.

Five haptic transducers, each in its own spot: engine and gearshifts through the seat, lockup in the foot that’s causing it, curbs in the shoulder on that side. Two wind pods with Bell–Mehta nozzles. A harness that tightens across your chest when you brake. And since the cockpit has no extrusion to bolt anything to, I had to design and print every single mount from scratch.

Wheelbase
Moza R12 V2
Display
Vision Pro / CloudXR
Haptics
5 channels
Structural
ASA

Read the full build

Also on the bench

Smaller, still
overdone.

The smart home

Automations run locally wherever possible, so nothing important depends on someone else’s cloud staying up, or their company staying in business. The test: does it still work with the internet unplugged?

Printed things

Replacement parts for stuff the manufacturer gave up on, brackets for things that were never meant to be mounted, and plenty of objects that didn’t need to exist. Some end up in the shop.

The home lab

Self-hosted where it makes sense, networked right, and documented well enough that future me, troubleshooting it at midnight two years from now, has something to go on.

Building something
similar?

I do the research part for other people too: a full parts list, in the right order, with the mistakes already taken out.

Project planning Ask me about a build