Oliver Franzke
@p1xelcoder.bsky.social
I'm making colored pixels for Double Fine Productions. Lead Programmer of Broken Age. Also worked on Keeper and the remastered versions of Grim, DotT, FT and Monkey Island.
You can see this nicely in this closeup. Notice how the number and orientation of the edges changes on the left side as both meshes are merged.
November 11, 2025 at 7:15 PM
You can see this nicely in this closeup. Notice how the number and orientation of the edges changes on the left side as both meshes are merged.
I wanted to clarify what I mean by fixed vs. dynamic topology. In game graphics meshes can normally be not merged smoothly because the edges and connectivity is static and holes can't be closed or created. Dynamic topology recomputes the connectivity when needed.
November 11, 2025 at 7:14 PM
I wanted to clarify what I mean by fixed vs. dynamic topology. In game graphics meshes can normally be not merged smoothly because the edges and connectivity is static and holes can't be closed or created. Dynamic topology recomputes the connectivity when needed.
For the implicit surface? This is done using the distance field gradient.
November 10, 2025 at 8:51 PM
For the implicit surface? This is done using the distance field gradient.
Normal polygonal meshes have a fixed topology. Roughly speaking this means the number of holes in an object can't change. Also the (explicit) surface of two meshes can't be blended smoothly into one. This is no problem for distance field morphs with implicit surfaces.
November 10, 2025 at 8:03 PM
Normal polygonal meshes have a fixed topology. Roughly speaking this means the number of holes in an object can't change. Also the (explicit) surface of two meshes can't be blended smoothly into one. This is no problem for distance field morphs with implicit surfaces.
Bonus post to end the week: If you are a graphics programmer do yourself a favor and get a MIDI board. It makes the work way more tactile and fun. Full props to Matt and @aaronmjacobs.com for getting me on the MIDI train. :)
November 7, 2025 at 10:43 PM
Bonus post to end the week: If you are a graphics programmer do yourself a favor and get a MIDI board. It makes the work way more tactile and fun. Full props to Matt and @aaronmjacobs.com for getting me on the MIDI train. :)
The morphs in Keeper use distance fields as an (implicit) surface representation, which makes it possible to control the distance at which the surface should lie. In other words, it’s easy to deflate or inflate objects, and meshes become easily ‘moldable’.
November 7, 2025 at 6:40 PM
The morphs in Keeper use distance fields as an (implicit) surface representation, which makes it possible to control the distance at which the surface should lie. In other words, it’s easy to deflate or inflate objects, and meshes become easily ‘moldable’.
So what is a "distance-field"? It refers to a function that tells you, for every point in space, how far away the closest surface is and—by extension—in which direction it lies.
November 6, 2025 at 6:54 PM
So what is a "distance-field"? It refers to a function that tells you, for every point in space, how far away the closest surface is and—by extension—in which direction it lies.
The experiments with surflets and voxels yielded some cool results, but it became quite obvious that distance fields were the way to go to represent the surface of morph objects (as I alluded to previously). This allowed us to implement some visually neat effects like this twist transition.
November 5, 2025 at 4:41 PM
The experiments with surflets and voxels yielded some cool results, but it became quite obvious that distance fields were the way to go to represent the surface of morph objects (as I alluded to previously). This allowed us to implement some visually neat effects like this twist transition.
Every cool graphics feature begins with a doodle… well at least for me.
November 5, 2025 at 3:10 PM
Every cool graphics feature begins with a doodle… well at least for me.
This illustrates the full process of capturing the "Essence" of a mesh to be used in a morph. The distance field is retrieved and then the mesh is projected onto the cube-shaped "screen" in order to pack its surface properties into two cubemaps.
November 4, 2025 at 6:12 PM
This illustrates the full process of capturing the "Essence" of a mesh to be used in a morph. The distance field is retrieved and then the mesh is projected onto the cube-shaped "screen" in order to pack its surface properties into two cubemaps.
Is might cat obsessed with isosceles right triangles?
November 4, 2025 at 2:59 PM
Is might cat obsessed with isosceles right triangles?
In order to use a mesh in a morph it has to be converted first, which is done by projecting its properties (base color, normal, roughness, AO) onto a cube. The results are then packed into two cubemaps. These maps in combination with the associated distance-field comprise the "Essence" of the mesh.
November 3, 2025 at 10:25 PM
In order to use a mesh in a morph it has to be converted first, which is done by projecting its properties (base color, normal, roughness, AO) onto a cube. The results are then packed into two cubemaps. These maps in combination with the associated distance-field comprise the "Essence" of the mesh.
I'll talk more about morphs next week, but here is a prototype called "fractal guts" which didn't make it into the game. It's perfect for Halloween though!
October 31, 2025 at 7:12 PM
I'll talk more about morphs next week, but here is a prototype called "fractal guts" which didn't make it into the game. It's perfect for Halloween though!
Ha! I totally forgot that we did one more morph experiment using space filling spheres (thanks OpenVDB!). I was planning to compute a correspondence set, so that the spheres of the different shapes can move from one to another, but we moved on to another approach. Still looks pretty cool though. :)
October 30, 2025 at 4:26 PM
Ha! I totally forgot that we did one more morph experiment using space filling spheres (thanks OpenVDB!). I was planning to compute a correspondence set, so that the spheres of the different shapes can move from one to another, but we moved on to another approach. Still looks pretty cool though. :)
Between surflet and voxel morphs the former was more promising. Here is a look behind the cube-shaped curtain... Each object is represented by a cube-quad to obj-surface mapping, which then makes it straight forward to move the associated surflet between the surface locations and blend properties.
October 29, 2025 at 5:55 PM
Between surflet and voxel morphs the former was more promising. Here is a look behind the cube-shaped curtain... Each object is represented by a cube-quad to obj-surface mapping, which then makes it straight forward to move the associated surflet between the surface locations and blend properties.
Another experiment we tried was to use (axis and surface aligned) voxels rather than surflets. The obvious benefit is that there are no holes the surface, but the voxelized look didn't fit Keeper and it was expensive to render due to the voxel density needed to make this work.
October 28, 2025 at 4:06 PM
Another experiment we tried was to use (axis and surface aligned) voxels rather than surflets. The obvious benefit is that there are no holes the surface, but the voxelized look didn't fit Keeper and it was expensive to render due to the voxel density needed to make this work.
You can see the trajectory of the surflets even better in this example. I actually was pretty happy with the results back then because this method handles differences in surface topology very well.
October 27, 2025 at 7:30 PM
You can see the trajectory of the surflets even better in this example. I actually was pretty happy with the results back then because this method handles differences in surface topology very well.
In order to get to the morphs we have in Keeper now I first experimented with different approaches. Here is one of the early tests in which "surflets" are used to transform from one to another mesh. I still love the "wiggly paths" during the transition.
October 27, 2025 at 7:26 PM
In order to get to the morphs we have in Keeper now I first experimented with different approaches. Here is one of the early tests in which "surflets" are used to transform from one to another mesh. I still love the "wiggly paths" during the transition.
Another visual effect @leepetty.bsky.social, Jeremy Mitchell and I talked about a lot for Keeper was the Mandelbulb fractal. It didn't make it into the game in it's "pure" form, but the experiments I did were fun. :)
October 25, 2025 at 8:00 PM
Another visual effect @leepetty.bsky.social, Jeremy Mitchell and I talked about a lot for Keeper was the Mandelbulb fractal. It didn't make it into the game in it's "pure" form, but the experiments I did were fun. :)
In case you are wondering what is involved to make a game like Keeper… here is some (but by no means all) the hardware I used.
October 24, 2025 at 3:59 PM
In case you are wondering what is involved to make a game like Keeper… here is some (but by no means all) the hardware I used.
A short story told through passport photos…
October 24, 2025 at 11:17 AM
A short story told through passport photos…
I wrote a neat morph system for Keeper and hopefully I can share a bit more about it in the future. This particular morph was an experiment using symmetry that didn't make it into the game in the end.
October 23, 2025 at 9:23 PM
I wrote a neat morph system for Keeper and hopefully I can share a bit more about it in the future. This particular morph was an experiment using symmetry that didn't make it into the game in the end.
You know that the release is nigh once the NVIDIA driver update mentions your game... :o
October 14, 2025 at 6:12 PM
You know that the release is nigh once the NVIDIA driver update mentions your game... :o
I used the best kept secret of professional game development again today... duct tape! Yep. Taping down a controller button is a great way to spam a feature for "soak testing".
September 19, 2025 at 11:45 AM
I used the best kept secret of professional game development again today... duct tape! Yep. Taping down a controller button is a great way to spam a feature for "soak testing".
It's _that_ part of the project.
September 18, 2025 at 6:14 PM
It's _that_ part of the project.