Cool toy! As an avid snow enjoyer, I would like to point out that wind and snow interact in all kinds of interesting ways, and it would be super cool to see some of those captured in future iterations of a toy like that.
One of those is that snow doesn't necessarily get packed onto the wind-exposed side; those features tend to stay bare. The lee side is where the snow will accumulate, but with that too depends on the features. Tall / steep / abrupt features will tend to generate areas with no snow at all directly behind them. Gentle downwind slopes will accumulate massive snow drifts. This all of course depends on the quality of the snow itself, roughly related to the air temperature at the time of precipitation but not solely that.
A quick little tweak to add to the control panel could be "stickiness" - how much the snow pours vs sticks to itself. Cheap one and would give the toy some behavioural variation.
Even though coding was agent-assisted (not fully vibed though), putting it together took two weeks something to get where it is and to see it working on all mobile. I also have 15+ years of precious experience with JS, but zero with webgl.
Every year during snow season I try to make it faster/more flakes. After this year though in chrome, I think it'd be whiteout conditions ;-) (it'll auto-scale to try to match your system performance. Best effects in a clean browser with not too much else running/open at the same time)
Very nice! I made a version of this effect for a little NYE thing years ago [0] (source here [1]). I first saw this effect in Iguana's Blastersound BBS intro [2]. I always thought that intro looked slick!
Neat to see and it takes me back years when I needed to make a similar effect for a Christmas greeting for Canon in Flash. It needed to be able to run in Flash and on sluggish office computers of the time (16 years ago - 2010).
I eventually settled on a pooled particle system with three bitmaps:
Display bitmap - the visible output
Collision bitmap - a grayscale heightmap tracking accumulated snow
Snow sprite - the particle graphic with soft/transparent edges
When a particle hit the collision bitmap (simple pixel check), I stamped its graphic onto both the display bitmap and added it to the collision bitmap. Using grayscale for collision meant soft-edged sprites contributed proportionally to the heightmap, preventing the soft/transparent edges from causing unrealistic fast accumulation. Using stamping meant that we did not have to keep all the collided particles in memory and so the user could spam away snow particles with their mouse to their hearts content (few 100's at a time).
Edit: even more fun to see all the different ways to solve the same 'problem'. From simple to quite complex!
Seeing this really makes it hit home how rarely you find this sort of joy in tech anymore. This reminds me of when computers still seemed fun and I wanted to learn more about them
I did something similar[0] in JS on a Christmas eve eve a while back - needs to run via a server now as Web Workers cannot be loaded from file:// anymore.
As a bc skiier though, an actual snow simulator, on real topos, with wind/rate/quality/temp/sun sliders would be useful for the study of snowpack formation and avalanche conditions.
Oh, that's something I also did in QBasic ages ago. I since lost the source code, but it basically worked by querying the screen from bottom to top, finding snow pixels (white) and moving them down, unless there was an obstacle. The initial snow on the ground (and the snowman) were using a different color that was almost white so it wouldn't detect as snow. It worked fairly well in 320×200 at the time.
I've tried the same approach in Turbo Pascal with BGI in the hopes of having a faster language and higher resolution available. It turned out to be quite a bit slower, likely because drawing and querying pixels was a bit more involved when using an adapter layer like BGI.
A few weeks ago I tried rewriting all that in TypeScript for fun and also trying to integrate it as an easter-egg with our graph drawing library (which renders with SVG) and first had to figure out how to efficiently support arbitrary obstacles that are initially SVG as well as a potentially changing viewport of the whole scene. I got sidetracked and didn't finish it, but proper collision handling was so easy back then (just look at the pixel color), but now with vector graphics and reading pixels being a very slow operation in many cases, it was surprisingly complicated.
I never did the collision physics, but I used to love making graphical demos with "falling sand"-type simulations.
One of the first was "rain" [1] by semi-randomly walking blue pixels down the screen and not clearing the buffer. But then the screen would go all blue, so I made them pop up to the top and do the same walk but as black pixels. It came out as a rain-on-the-window effect:
Eventually, I started just using one pixel and moving it really fast to render scenes. This is basically what raster rending does anyway, but instead of doing every pixel, the random walk will only hit a subset of pixels every frame and will make a really cool scratchy effect.
It's how I learned lower level programming. TempleOS is a lot of fun but the community around it is very 4chan/kiwifarms. I never jived with that.
During the pandemic I was showing my buddies the game I'd made in TempleOS on Discord, and after a bit the conversation moved on and I was just playing idly, and my character died. The screen went black and error text showed up. My buddy interrupted the conversation with "wait, does the game just segfault when you die!?".
"Of course not. The game didn't segfault, the operating system did." The bug lasted for months and would just kill the entire OS every time you died. It was a lot of fun.
I loved Christmas Lemmings so much back in the day! The snowfall visualization and the little Santa lemming clearing it. I made a much less impressive snowfall demo a while back based on that (minus the clearing lemming, because I always wanted to watch the snow pile up). https://anderegg.ca/projects/flake/
I haven't looked at the code, but I suspect that those flakes have hit another snowflake and are now considered "fallen" snow. And for fallen snow there's probably an optimization that only x% of particles are updated every step
I wrote a similar snow app a couple of years ago in Logitech Modula-2 for DOS. I used an array to hold the flake data. If a flake stopped when it hit another flake, it would go again on the next round because the flake it hit would also keep going.
The nostalgia is real. Reminds me of the 'Falling Sand' game era.
For anyone trying to scale this in JS: the bottleneck usually isn't the rendering, but the object overhead/GC.
If you switch from an object-per-flake model to a single flat Float32Array for positions/velocities (Data-Oriented Design), you can typically push 10x more particles before hitting the frame budget. Keeping the memory layout cache-friendly makes a massive difference even in a high-level managed environment like V8.
The real bottleneck is doing it on the CPU, if you switch to WebGPU you can simulate millions of particles simultaneously in just few milliseconds per frame.
The game that impresses me with its performance is Noita, they managed to balance an "every pixel is simulated" physics engine and have it run quite well.
If you take it to the max (rate, speed) with 0 melt, let it fill up, then turn melt to the max - you get reverse snow falling up.
That's not snow falling up. The pixels moving up are blue. It's more like the air is being pushed out like bubbles from the pressure of the snow.
Inverse even. It’s certainly amusing!
Evaporation?
Cool toy! As an avid snow enjoyer, I would like to point out that wind and snow interact in all kinds of interesting ways, and it would be super cool to see some of those captured in future iterations of a toy like that.
One of those is that snow doesn't necessarily get packed onto the wind-exposed side; those features tend to stay bare. The lee side is where the snow will accumulate, but with that too depends on the features. Tall / steep / abrupt features will tend to generate areas with no snow at all directly behind them. Gentle downwind slopes will accumulate massive snow drifts. This all of course depends on the quality of the snow itself, roughly related to the air temperature at the time of precipitation but not solely that.
A quick little tweak to add to the control panel could be "stickiness" - how much the snow pours vs sticks to itself. Cheap one and would give the toy some behavioural variation.
Here’s my take with some dither and vector fields.
http://nouveauxhivers.dub4powder.xyz/
an invitation for event I promoted recently.
Press ? for some stats on desktop.
Even though coding was agent-assisted (not fully vibed though), putting it together took two weeks something to get where it is and to see it working on all mobile. I also have 15+ years of precious experience with JS, but zero with webgl.
Impressive graphics! But the music loop is even better in my ears :-)
That's amazing! I'm going to need to up my game next year.
Here's my variant on the same toy idea, using a CA, generated trees, and a few other tricks.
https://vps.kimbruning.nl/snow/2025/snow_singlecore_scalable...
Every year during snow season I try to make it faster/more flakes. After this year though in chrome, I think it'd be whiteout conditions ;-) (it'll auto-scale to try to match your system performance. Best effects in a clean browser with not too much else running/open at the same time)
The snowflakes are all flocking together! Can you have a murmuration of snowflakes?
Very nice! I made a version of this effect for a little NYE thing years ago [0] (source here [1]). I first saw this effect in Iguana's Blastersound BBS intro [2]. I always thought that intro looked slick!
[0] https://www.horsedrawngames.com/nye
[1] https://bitbucket.org/izzo/hdgnye
[2] https://youtu.be/qPOoU44GU50
I always loved that intro too [0] :-) I implemented the effect in Pascal back then.
FYI, you can download the source code [1].
[0] https://news.ycombinator.com/item?id=31311461 [1] http://ftp.lanet.lv/ftp/mirror/x2ftp/msdos/programming/iguan...
Very pretty!
Neat to see and it takes me back years when I needed to make a similar effect for a Christmas greeting for Canon in Flash. It needed to be able to run in Flash and on sluggish office computers of the time (16 years ago - 2010). I eventually settled on a pooled particle system with three bitmaps:
Display bitmap - the visible output Collision bitmap - a grayscale heightmap tracking accumulated snow Snow sprite - the particle graphic with soft/transparent edges
When a particle hit the collision bitmap (simple pixel check), I stamped its graphic onto both the display bitmap and added it to the collision bitmap. Using grayscale for collision meant soft-edged sprites contributed proportionally to the heightmap, preventing the soft/transparent edges from causing unrealistic fast accumulation. Using stamping meant that we did not have to keep all the collided particles in memory and so the user could spam away snow particles with their mouse to their hearts content (few 100's at a time).
Edit: even more fun to see all the different ways to solve the same 'problem'. From simple to quite complex!
Love it :)
I also rate the author's slogan: "make things, not too much, mostly crap". A reference to Michael Pollan's "eat food, not too much, mostly veg".
Seeing this really makes it hit home how rarely you find this sort of joy in tech anymore. This reminds me of when computers still seemed fun and I wanted to learn more about them
Love everything about this. The idea of just do something because it's enjoyable for yourself, the retro style, the toyish-aspect...
I did something similar[0] in JS on a Christmas eve eve a while back - needs to run via a server now as Web Workers cannot be loaded from file:// anymore.
python3 -m http.server 8080
[0] https://github.com/benperiton/SnowCam
This is a toy, and fun.
As a bc skiier though, an actual snow simulator, on real topos, with wind/rate/quality/temp/sun sliders would be useful for the study of snowpack formation and avalanche conditions.
Oh, that's something I also did in QBasic ages ago. I since lost the source code, but it basically worked by querying the screen from bottom to top, finding snow pixels (white) and moving them down, unless there was an obstacle. The initial snow on the ground (and the snowman) were using a different color that was almost white so it wouldn't detect as snow. It worked fairly well in 320×200 at the time.
I've tried the same approach in Turbo Pascal with BGI in the hopes of having a faster language and higher resolution available. It turned out to be quite a bit slower, likely because drawing and querying pixels was a bit more involved when using an adapter layer like BGI.
A few weeks ago I tried rewriting all that in TypeScript for fun and also trying to integrate it as an easter-egg with our graph drawing library (which renders with SVG) and first had to figure out how to efficiently support arbitrary obstacles that are initially SVG as well as a potentially changing viewport of the whole scene. I got sidetracked and didn't finish it, but proper collision handling was so easy back then (just look at the pixel color), but now with vector graphics and reading pixels being a very slow operation in many cases, it was surprisingly complicated.
I never did the collision physics, but I used to love making graphical demos with "falling sand"-type simulations.
One of the first was "rain" [1] by semi-randomly walking blue pixels down the screen and not clearing the buffer. But then the screen would go all blue, so I made them pop up to the top and do the same walk but as black pixels. It came out as a rain-on-the-window effect:
https://x.com/Rendello_/status/1231426590380318729
Eventually, I started just using one pixel and moving it really fast to render scenes. This is basically what raster rending does anyway, but instead of doing every pixel, the random walk will only hit a subset of pixels every frame and will make a really cool scratchy effect.
In PICO-8: https://x.com/Rendello_/status/1258243668626063361
In TempleOS: https://www.youtube.com/watch?v=W-wpUcDFZaI
Porting it to TempleOS sounds like a fun journey
It's how I learned lower level programming. TempleOS is a lot of fun but the community around it is very 4chan/kiwifarms. I never jived with that.
During the pandemic I was showing my buddies the game I'd made in TempleOS on Discord, and after a bit the conversation moved on and I was just playing idly, and my character died. The screen went black and error text showed up. My buddy interrupted the conversation with "wait, does the game just segfault when you die!?".
"Of course not. The game didn't segfault, the operating system did." The bug lasted for months and would just kill the entire OS every time you died. It was a lot of fun.
Brilliant!
Did anyone else ramp up all the settings to try and fill the screen with snow?
I saw a cool "bubbling" effect. Some of the air gaps by the trees would bubble up as the snow pilled on.
I'm learning about shadertoy so immediately went here:
https://www.shadertoy.com/view/tfKfRw
But no snow piling up which is nice!
I feel like playing lemmings now!
I loved Christmas Lemmings so much back in the day! The snowfall visualization and the little Santa lemming clearing it. I made a much less impressive snowfall demo a while back based on that (minus the clearing lemming, because I always wanted to watch the snow pile up). https://anderegg.ca/projects/flake/
Why do some snowflakes stop in mid-air?
I haven't looked at the code, but I suspect that those flakes have hit another snowflake and are now considered "fallen" snow. And for fallen snow there's probably an optimization that only x% of particles are updated every step
I wrote a similar snow app a couple of years ago in Logitech Modula-2 for DOS. I used an array to hold the flake data. If a flake stopped when it hit another flake, it would go again on the next round because the flake it hit would also keep going.
Harkens back to https://boredhumans.com/falling_sand.php
I liked this! Very fun to play with when ignoring meetings.
I used to spend hours in The Powder Toy as a teen (it's also how I learned about Conway's GoL):
https://powdertoy.co.uk/
Now I also play Noita, which also has the same powder-based physics:
https://store.steampowered.com/app/881100/Noita/
I had to check if the author was Alphapapa
This is fun to see :) thanks!
Powder toy deserves a mention here
Addictive
The nostalgia is real. Reminds me of the 'Falling Sand' game era.
For anyone trying to scale this in JS: the bottleneck usually isn't the rendering, but the object overhead/GC.
If you switch from an object-per-flake model to a single flat Float32Array for positions/velocities (Data-Oriented Design), you can typically push 10x more particles before hitting the frame budget. Keeping the memory layout cache-friendly makes a massive difference even in a high-level managed environment like V8.
The real bottleneck is doing it on the CPU, if you switch to WebGPU you can simulate millions of particles simultaneously in just few milliseconds per frame.
The game that impresses me with its performance is Noita, they managed to balance an "every pixel is simulated" physics engine and have it run quite well.