Summary

Lava Lamp is a minimally interactive lava lamp simulation. Enjoy the atmosphere.

The lava requires time to heat up before it will move, so when you first start the game, wait 10 or so seconds.

You may press left click to attract lava to your mouse, press right click to spawn a small ball of lava.

Performance is rather poor right now. Appealing visuals and physics were my first priority.

Technology

Lava Lamp source code may be found here: https://github.com/chrisspieler/sbox-lava-lamp

The lava consists of spheres that rise or fall depending on their temperature. Each sphere is subtly attracted to every other sphere in a manner similar to gravity, resulting in pleasant "clumping" and "tumbling" motions. Turbulence caused by convection is faked with simple curl noise - there's no fluid simulation here.

A shader is used to render all lava spheres to a single screenspace quad. For each pixel on the screen, ray marching is used to sample a signed distance function for the "scene". This scene SDF is the union of every sphere SDF in the scene, joined via a SmoothMin function that grants every sphere a melted appearance characteristic of metaballs.

The distance returned by the SDF determines whether a sphere is in front of the camera at that pixel. If, so a surface normal is calculated using additional samples from nearby positions on the surface of the metaball. This normal is eventually used when shading the pixel.

If the final sample taken for the current pixel is more distant than the depth buffer value for that pixel, the current pixel gets discarded. Finally, once we know for sure that this pixel won't be discard for whatever reason, it gets shaded via ShadingModelStandard. The calculated material for that pixel includes the normal obtained earlier, low roughness, zero metalness, and an emission color that is a darker version of the albedo color.

Console Commands

  • metaball_world_debug
    • 0 - Disable
    • 1 - Show simulation bounds and mouseover info as well as render and collision radii for each metaball
  • metaball_vis
    • 0 - Disable
    • 1 - Slow metaballs are blue, fast ones are red
    • 2 - Cold metaballs are blue, hot ones are red