Mike Turitzin

@miketuritzin.bsky.social

Building a game/engine based on signed distance fields ~ Past: rendering lead @figma.com, indie VR dev, founder @ Workflowy, search backend @ Google, Quake modder miketuritzin.com

Just implemented instant flipping between the current and previous shaders (PSOs) after a hot-reload. This is really simple to implement - just hold onto the previous PSOs after hot-reload, and then add a shortcut to flip between new and old, which is instant! 1/

Followed my own advice to do the simplest/dumbest implementation, and just (finally) got shader hot-reloading working. Rather than watching files for changes, tracking dependencies between them, etc., I just implemented a ctrl+R shortcut that reloads ALL shader pipelines ... 1/

At long last, SDF material textures are supported in my engine! I've decided to go for a textural and slightly hand-painted look. Currently using color and normal maps, might consider roughness as well. 1/

Another useful property of convex shapes: A "convex combination" of the vertices of a convex shape (vertex weights that are non-negative and sum to 1) yields a point inside the shape. Barycentric coordinates of triangles are a specific example of this.

Mike Turitzin@miketuritzin.bsky.social · 3mo ago

Convex shapes (specifically polyhedra) come up constantly in games and graphics. A few useful properties: - A convex polyhedron is the convex hull of its vertices. - One can also be defined as the intersection of half-spaces defined by a set of planes (one per face). 1/

Taking advantage of Jolt Physics's ability to "cook" its internal binary format to speed up startup times in Debug builds a ton. It was taking a long time to generate SDF collision mesh chunks on startup for Debug builds in particular. I'd prefer not to have to cache this data,

I'm surprised at how often following the thought experiment of "what is the simplest and dumbest way I could solve this problem" saves a ton of work. AI-assisted coding discourages thinking this way, but I think that can be a trap, as code is still a liability.

A cool thing about handling materials via palettes in this way is that you need only "pay for what you use" in terms of material complexity. So in the common case of a brick that uses only 1 material, no material weights need be cached at all! [cont]

Mike Turitzin@miketuritzin.bsky.social · 4w ago

I'm close to finishing a major rework of how materials are baked in my engine. Rather than baking material properties directly, I now store a material palette per brick and bake blend weights. This means that material property blending is "deferred" to render-time, ... 1/

Just used De Morgan's law to merge ANDs and ORs of multiple bit-flags into a single atomic-OR. a & b == ~(~a | ~b) So NOT the bits you want to AND, then atomic-OR, then NOT the result. The OR'd bits obviously work with no changes. (Could also do this with atomic-AND.)

The constant focus on "productivity" (and "output") lately is driving me a little insane. What's the end result you're trying to achieve? (and why is that worthwhile?) What results show you're getting there more quickly?

I'm close to finishing a major rework of how materials are baked in my engine. Rather than baking material properties directly, I now store a material palette per brick and bake blend weights. This means that material property blending is "deferred" to render-time, ... 1/

I've seen significant differences in shader execution times several times recently from just reordering code blocks (this is obviously non-dependent code). This is on NVIDIA hardware. Interesting to see, I suspect it has to do with hiding read latency with ALU work, but would ..

Something that just clicked for me - In the same way that dividing by distance-to-origin (L2 norm) projects a point onto the unit circle/sphere: Dividing by L1 norm projects onto the unit diamond/octahedron Dividing by L-infinity norm projects onto the unit square/cube cont.

my #1 grizzly beard protip for (game) dev is: if you have a bug that you dont understand the cause of immediately, dont try to fix it; add & iterate visualization / inspection tools until the cause is plain to see. the accumulation of 'observability' in your system's state will pay off many times

Just got a major SDF ray-marching perf improvement based on a simple tweak: increase the minimum step size above the epsilon required to stop marching. This seems to work really well with my setup. Doesn't have the downside of visibly "bloating" silhouette edges (which ... 1/

Because ray-marching SDF bricks is so comparatively expensive, with two-pass occlusion culling I'm generally rendering frames faster the more other stuff I add. (Disoccluded bricks are drawn in magenta.)

Kind of obvious when you think about it, but it was cool to realize that I don't need to record position history to draw artillery trails, as the same closed-form trajectory equation can be used to "rewind time" for each shot to generate its trail positions.

I'm not using it every day depending on what I'm doing, but man, hot-reload of C++ (using Live++) is a life-saver for gameplay iteration. I remember back when I was building my VR app, I would not only have to close/compile/run but also often take the headset off and on. Oof.

If you graph the representable floating point values on the 2D plane, you get something that looks like clipmaps/cascades. Therefore floating point representations are LODs for real numbers🤔 (also shows why floating point for absolute positions is bad)

Bild