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/
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
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/
A couple shots from the video I posted yesterday, as the low video (re)encoding bitrate completely nuked most of the texture detail
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/
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.
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/
9/10 Reddit users agree - barycentric coordinates are useful. Thanks AI!
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]
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/
A laser to fire while defending the base. Surely no inappropriate pictures will be drawn using this laser. Surely.
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 NPR Tiny Desk concert we have been waiting for www.youtube.com/watch?v=e81L...
Napalm Death: Tiny Desk Concert
YouTube video by NPR Music
youtube.com
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 ..
Trying out a couple new 3D->1D hash functions for my terrain generation RNG, inspired by this paper: jcgt.org/published/00... The possibility of losing my now-fondly-familiar default seed terrain makes me a bit sad though 🥲
jcgt.org
2026 Advances in Real-Time Rendering in Games course line up is here - check it out! advances.realtimerendering.com
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.
The depth and thoroughness of @bgolus.bsky.social articles, when you are blessed with one relevant to what you're currently doing. (In this case, using normal maps with triplanar texture mapping.) bgolus.medium.com/normal-mappi...
Normal Mapping for a Triplanar Shader
Triplanar mapping is a great solution for dealing with texturing on complex geometry that is difficult or impossible to use traditional UVs…
bgolus.medium.com
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)
Dawn/Chrome now supports WebGPU "immediates" (aka. push constants). Curious of the perf impact vs. per-draw uniform buffer bindings via dynamic offsets. (Haven't used push constants in other APIs.) Bindless would/will also make this a lot more useful. developer.chrome.com/blog/new-in-...
What's New in WebGPU (Chrome 149-150) | Blog | Chrome for Developers
Immediates and stricter validation for transient attachments.
developer.chrome.com
This is a clever use of 32-bit atomics for depth+color rasterization output that I hadn't thought of. (I hadn't read the FreePipe paper; this summary is from @m-schuetz.bsky.social's recent CuRast paper: github.com/m-schuetz/Cu... )
Really love this project and article - a handmade early-mid-90s-ish FPS. The procedural pixel art "gibbing" and particle effects are pretty cool, among other stuff staniks.github.io/articles/cat...
Catlantean 3D - Making Graphics Like It's 1993
A deep dive into the asset creation pipeline for Catlantean 3D.
staniks.github.io