Notes
How Vitrola is made
Rendering a 1979 Technics SL-Q3 offline in Cycles, one light group at a time, and mixing the light live in Metal by the time of day.
Matheus Fidelis, São Paulo
Vitrola is a Mac wallpaper: a Technics SL-Q3 on a desk by a window in São Paulo. When Spotify or Music plays, the platter spins up, the arm drops onto the record and the cover on the stand changes to the album you're playing. The light follows your clock. I wanted it to look like a photograph and cost close to nothing to leave running all day. Most of the decisions below come from holding both of those at once.
The turntable
I modeled the SL-Q3 in Blender from the service manual and a folder of reference photos: a body of 430 × 130 × 375 mm with the lid, a 312 mm platter with its strobe dots, an S-shaped arm with 230 mm effective length. Each modeling round was rendered from the same angles as the reference photos and compared side by side, and the three largest differences got fixed before the next round. The parts that move (platter, arm, cue lever, lid) are separate objects with their origins on the real pivots, because the app has to know exactly where they rotate. Wear came last: dust in the mat grooves, swirl marks on the platter rim, the start/stop print rubbed off where a thumb kept pressing it.
Rendering light instead of pictures
Nothing is rendered in 3D on your Mac. Each framing (wide, medium, close and top) is rendered in Cycles at 3456 × 2234, the native resolution of a 16″ MacBook Pro, but not as a finished image. The scene's light is split into light groups: sun, sky, desk lamp, fill and the city lights outside. Each group is rendered on its own, in white, at intensity 1. The sun gets one plate per position (morning, midday, afternoon) and the view through the window gets one per time of day. Light adds linearly, so the sum of every plate at weight 1 is the full render.

Sun (afternoon)

Sky

Fill

Desk lamp

City lights

Window view (afternoon)
The mixing happens on the GPU, in Metal. A preset (morning, day, afternoon, night) is a set of RGB weights per group plus exposure, vignette and grain. The clock is a list of keyframes, like 07:30 morning and 17:15 afternoon, and between two of them the weights are interpolated with a smoothstep. Since everything is linear before tone mapping, each preset can be pre-mixed into a single texture, and at any time of day the shader blends the two neighbors. Then it applies the vignette, a grain that is fixed per pixel, and the tone map.

07:30

12:00

17:30

21:00
The renders use AgX in Blender, so the shader needs the same curve, or the app and the Blender previews disagree. What shipped is an AgX approximation calibrated against pairs of linear EXR and Blender's own PNG output for the same frame: contrast +0.04, an offset of +0.009 in log space and an output gamma of 1.18. The average error is about 3/255.
One trap: the plates are half-float OpenEXR, decoded by ImageIO. It opens ZIP and PIZ compression fine, but with DWAA or DWAB it returns zero images and no error. Everything ships as ZIP.
Your album on a cardboard sleeve
In the plates, the standing cover and the record label are pure white. The app knows the four projected corners of each, so it maps the album art onto them with a homography and multiplies it by the light. Anything in front, like a monstera leaf, is already cut out of the mask. The label works the same way inside a circle, with an angular blur while it spins.

In the plate

In the app
The cover also throws light. I render the area around it once with a white sleeve and once with a black one, and the difference is the light the cover bounces onto the desk. The app adds that difference tinted by the art's average color, so an orange album warms the wood a little. The pile on the desk shows the album you played before this one.
The record is drawn live too, lit with a diffuse and a specular pass from Cycles. The groove pitch is fixed, as on a real cut, so each band is as wide as its song is long and a short side leaves a wide run-out. The players only report the track that is playing, so the app remembers the durations it has seen for each album and estimates the rest. The Music library gives the full list locally, and an optional setting looks it up in Apple's public catalog.
Platter and arm
The SL-Q3 is a quartz-locked direct drive, and it gets to speed fast. The platter angle is computed in closed form from the clock instead of being added up every frame. Each play or pause starts an exponential approach to the target speed, with a time constant of 0.16 s going up (locked at 33⅓ in about 0.7 s) and 0.22 s for the brake. The angle is the exact integral of that, so a dropped frame never makes the record drift.
The arm is drawn from sprites rendered at 29 angles, at most 1.5° apart, with its shadow and its reflection on the lid. The app crossfades the two nearest sprites and corrects the rest of the angle, and the lift from the cue, with a homography built from the camera matrix. Motion uses critically damped springs: about 0.45 s to lift, around a second to swing over, and a slow landing. If you skip a track in the middle of a move, the arm carries on from where it is. Once down, the needle follows the song's progress across the band.
Rain
Every 15 minutes the app asks Open-Meteo for the current weather at the city in the window, São Paulo by default. If it's raining there, drops run down the glass and refract the view behind them, limited to a mask of the visible glass. With the lid open, the drops you see through the acrylic are dimmed by its measured transmission.
Leaving it on
A wallpaper runs for hours, so the main job is to not draw. Frames come from a CADisplayLink at 30 fps that only runs while something moves: the platter, the arm, a cover crossfade, rain, the steam from the coffee. It stops when the desktop is covered, the screen is locked or the displays sleep. macOS keeps reporting the desktop window as visible behind a maximized app, because of the strip under the menu bar, so the app also checks whether the animated area itself is covered. On Apple Silicon that comes to about 3% CPU while a record plays and 0% when windows cover it.
Shipping 1.3 GB of light
The plates for the four framings add up to about 1.3 GB, which is too much for an installer. The DMG is about 11 MB. The app then downloads only the framing you choose, in packages of up to about 300 MB that are verified with SHA-256 and resume if the connection drops. The license server is a Cloudflare Worker, and the packages sit in R2.
If you want to ask about any of this, write to matheus@onezi.com.br.