đ week 10, day 3 - zoomy RC car, Zoom fatigue, and my blood feud with all things JS
creative coding 10am-12pm
Kevan, Rodrigo, and I made an RC car in p5.js, my favorite creative coding frenemy.
(the p5 sketch itself is performant; itâs actually the gif itself that is laggy)
While I was staring at the canvas, poised to implement the vector calculations for positional offset from the colliding corner to the center of the object body, Kevan had the very excellent idea to simply flip the velocity sign upon collision so that the car bounced off the wall. This has glitches in certain scenarios, such as when you manage to sneak the car out of bounds quickly so that it gets âstuckâ in the wall, but makes it extremely fun to zoom and bounce around the arena.
my blood feud with p5.js
Never take magic for granted in the programming world. Code framework sorcery is a sword with no handle, will demand a hidden price you were not ready to pay, will bite you every time, etc. My least favorite part of bringing a p5 sketch out of the editor environment (i.e. deploying it on my personal website) is finding all the p5 global variables by trial and error and fixing the namespacing.
coordinate systems
I perpetually forget about the counterintuitiveness of p5âs coordinate systems and inevitably re-derive them EVERY TIME.
- Positive y points down, which is different from classroom math but pretty par for the course in HTML canvases and on computer screens in general. Fine.
- In polar, it gets weird.
θ=0
points up. Positiveθ
goes clockwise. This is-Ď/2
off and the opposite direction from classroom math polar coordinates.
rectangle drawing mode
p5âs default rectangle-drawing mode starts from the upper-left corner. This is fine until you want to move them around, do collision detection on a rotated shape, or add any kind of complexity or additional dongles onto a base shape.
We suffered with the default rectMode(CORNERS)
for a while. Near the end of our session I refactored things over to work with rectMode(CENTER)
and all the math got subtly a little easier to think about.
bonus: js blood feud
I very reasonably mistyped this.width
as this.w
and this.height
as this.h
very early on, and it stalled us out for half an hour as we stared in puzzlement at the very bizarre results coming out of our extremely plausible-looking math, because, of course, Javascript interpolated and gave us no catastrophic indicators that I was accidentally passing undefined values into expressions. WTF JS đ¤
Once I realized this and fixed it, the trigonometry for finding the corners of the car suddenly worked and I screamed.
rust raytracer pairing w/ Rodrigo 12:30-1:45pm
Rodrigo recently started âRaytracing in One Weekendâ (over a weekend no less) and got a raytraced sphere, and Iâve been wanting to pair with him to find out more about his setup!
stack
- GLSL: Shader language. Runs math on the GPU and decides what color each pixel should be. Good for vector math.
- Vulkan: An extremely low-level cross-platform 3D graphics API frequently used for video games. Modern analogue to OpenGL, but lower-level. Can be used for both desktop and mobile graphics, multithread friendly.
- Rust: We could say a lot about Rust but the important points here are that itâs a performant type-safe language and thereâs a tutorial for Rust-Vulkan interop.
Basically, all the vector math and actual ray tracing happens in GLSL.
Vulkan manages the hairy low-level communication between different parts of your computer that you may be used to thinking of as a seamless whole, such as the window display, the GPU, the buffers and memory, etc. It will pass compiled GLSL bytecode through a graphics pipeline that communicates with the graphics card, and manage representations of âimagesâ that are waiting to be rendered on the screen. This would be significantly less painful in OpenGL, but Vulkan gives you an extreme level of control that is useful for demanding modern applications.
Rust is used here to execute Vulkan API calls, but there are various other languages you could also have used to write your executable, if you want.
GLSL debugging time!
Bounced the idea of setting up data interop between GLSL and Rust to enable interactivity, vs. just working on shader stuff within GLSL. The Rust-side code was dense with Vulkan API calls and fully incomprehensible to me, having not used Vulkan before, so we looked at the GLSL.
Since spheres were the only 3d primitives currently implemented, we tried setting a really big sphere with its surface just below the main sphere, to pretend to be the âfloorâ of the scene. Interestingly (I donât have screenshots, so this will be hard to imagine), the big âfloorâ sphere showed up on both the top and bottom of the main sphere, so that the scene looked like an old-school Cylon eye.
Why would this happen? We came up with several hypotheses and seemed to debunk all of them. GLSL is notoriously hard to debug because you have no way to introspect your program state other than by literally drawing things on the screen.
- Wrapping? Is a modulus used anywhere? (debunked)
- Ray reflection across the X-axis? Is it possible the ray direction is being flipped or miscalculated? (debunked; even if the axes had gotten flipped, there was no apparent math that would cause the ray to register a second hit on the other side of the axis from the true hit.)
- Hardcoding error in ray intersection detection? (probably debunked) I saw a
closest_t
float set with the intention to be âreally bigâ so that it could be used in comparison tests to see if the ray had hit something nearby. But it wasnât actually that big, so the big sphere could have eclipsed it. But the bug wasnât there; even when we actually set it to be really big (1e10
), it didnât change anything.
At some point I tapped out because my brain was getting GLSL-fried and Zoom-fatigued, but it was fun pairing and bouncing ideas around!
personal interest/background blurb
I wrote an OpenGL/C++ raytracer in 6.837 in college, but it was about 13 years ago and I was severely sleep deprived and spending 50+ hrs/week doing other labs and psets, so I only remember some of the theory and could not write a raytracer on the spot if you asked me to. This is something I think it would be nice to brush up on.
In recent years, I have only done a little bit of GLSL in web-based environments where I didnât have to set up from scratch, such as The Book of Shadersâ online editor. For my creative coding shader exercises such as langmap, I yoinked a GLSL-JS example setup from somewhere so that I wouldnât have to muddle through the setup on my own, although getting the user event data to interop was still an Experience.
Zoom fatigue / decompression 1:45-3pm
I was getting pretty severe Zoom fatigue after 3+ hours pairing over Zoom. I miss when people were down to use gather.town during deep pandemic (although I miss literally nothing else about deep pandemic).