Radio Bubbles Postmortem


Radio Bubbles design was informed by its aesthetic. While discussing a bunch of possible options of what to do for the theme — rituals, Ash was playing around with shaders and sent me (Brin) some pics of shaders that we both really liked.

These lines reminded me of radio reach maps. We started talking about making something with radios. Coming to the actual theme, rituals, I wanted to make something that would make you want to return to it every day.

Original picture Ash sent me

Radio reach map radio reach maps

The idea of a slow social media, one that limits you in how much you can post is nothing new. Twitter would be the most popular (and least effective form of it), limiting you to 255 characters. Something like slowly allows you to send messages but they take physical time to “arrive” at the destination, encouraging thoughtful and long discussion.

Radio Bubbles is a mix of this. It allows you to send a message once per day, hopefully encouraging you to come back. But that message is small, lowering the barrier and hopefully making it more open to offhand comments. Requiring to send a message before being able to see other ones is also a way of inviting the player to “just put something in there” to be able to see the messages. This creates something like a bucket of comments where one swims on top, every so often.

Let’s end it on the note of frequency. Both in the randomly assigned number to each player and the frequency of messages. Your MHz is something that is not unique to you, which I think is wonderful, because in real life you could also have multiple people broadcasting over the same frequency at different times. And well, Radio Bubbles are all about async communication.

Lastly, frequency of messages. I thought at first that it would be send 1, get 1. But that’s stupid, we need a reason to look at Ashe’s nice shaders.

Visual tricks

The game actually runs in a regular window. To achieve the effect that you see a number of simple tricks was used:

  • make the window just big enough to contain everything it needs in order to not obstruct mouse input for other applications
  • set the window to be always on top
  • make it borderless
  • make the default environment color transparent
  • allow per pixel transparency
  • enable per pixel transparency
  • tell the entire node tree to enable per pixel transparency.

(seriously, why does Godot have so many options that all need to be turned on to enable a single thing??)

After that is done you have an empty and invisible something on your screen that can render things inside of it and accept inputs. Good for virtual pets and such


The blob that shows the procedural art and has moving edges is just the noise shader from SnakeAcid(read how it’s made here), but inverted this time, and instead of rendering noise it renders a viewport texture of a viewport that has all the procedural art inside of it.

The procedural art that grows and morphs over time was created using a number of shaders, textures and particles. I myself don’t really comprehend how it works but i will try to explain it.

  • it starts with a perlin noise layer to give the starting visuals with the white lines something to render

  • then add a particle emitter. In 200 seconds it creates 300 particles of various sizes and colors, slowly moving in random directions while still orbiting the centre. They appear and disappear slowly and gently to preserve continuity. The particle renderer uses a blurry circle texture (also the gif is significantly sped up for convenience)

  • because the lines tend to be jagged and sharp the image is blurred using textureLod, we mix a lower lod with a higher lod so that small details are still present while the edges of individual particles merge.

  • after that a shader independently checks the red, green and blue channels, it creates bands of black and white color that alternate and move up the gradient over time. A formula is used to offset them over time and create multiple bands, it looks like this and results in this

  • each pixel looks at the results of the previous step for its 8 neighbours. If any of them are a different color from the pixel itself - it adds the color it was checking for to the output color. (this additive approach results in white when all colors are equal, and combinations of them when two lines intersect)

  • the raw unedited value of the pixel is checked, if it is very dark or very bright - a small transformation is applied to the value and the result is cut off using a bayer matrix.(visible in illustration above)
  • after that a color wrangler with the same setup as in SnakeAcid is applied to make colors pretty

the patterns you see are bigger than in the game because they render based on screen UVs and recording large res gifs is a pain. Also the neon green is the placeholder color for the transparent bits (godot can’t display transparency in-editor).

P.S. There’s like 8 floating point variables in this shader that can be changed at runtime while keeping the movement of the images continuous, they are not touched in engine because it was hard to animate them in an compelling way while running out of time.

The “””“Server”””””

The whole messaging system runs off google spreadsheets. We’re using HTTP Requests to send data via a google form. The google form is converted is feeding the data to a google spreadsheet. There is a GScript inside of the google spreadsheet that is converting the spreadsheet into a json that is hosted on googles servers. We end the whole cycle by pulling that JSON into the engine with a HTTP request.

It’s extremely janky but it works. We will write a tutorial at a later point on how to do replicate it in godot/any engine with http request.

Get Radio Bubble

Download NowName your own price


Log in with to leave a comment.


Any plans to open source?


<3 very poggy


google spreadsheets LOL thats very very clever!

Great! I was fascinated by this work and wanted to know more about it. This is valuable material :)

ooh fancy