Exploring and attempting to recreate Noita’s “Falling-Sand” Simulation from scratch using C and OpenGL.
Be sure to like and subscribe, you cool people. That way I can continue to make more vids
like this.
NOTE: There’s a typo @2:07. I wrote “bytes” when it should be “bits” for the gs_vec2, color_t, and b32 member variables for the particle struct. So the overall size should be *drastically* different (only 24 bytes in total). Sorry for the confusion!
00:00 – Introduction
00:33 – Gunslinger
00:58 – Research/Resources
01:13 – Cellular Automata
01:52 – Sand Algorithm
03:15 – Water
05:25 – Wood/Walls
05:53 – Fire
06:32 – Gunpowder/Salt/Lava/Oil/Acid
07:37 – Polish/UI/Drag-Drop Images
08:56 – Final Sand Sim Presentation / Exploding Pictures
Project source:
Gunslinger:
Discord:
Get Noita:
Get Powder Toy:
Music:
Blue Dot Sessions – Lakdeside Path:
Resources Used:
Nolla Games GDC:
Noita Gameplay Showcase –
Noita Technical Explanation –
Game Of Life:
Game Of LIfe:
Stuff To Read:
Special Thanks:
Guilherme Teres from Uniday Studio:
Everyone in my Discord channel. Thanks for hanging around and being awesome.
Nguồn: https://openworldleague.org/
Xem thêm bài viết khác: https://openworldleague.org/category/game
Edit:
Wall of Text Warning
– At 02:07, the size of the b32, gs_vec2, and color_t member variables should only be represented as "bits", not "bytes". Therefore the overall size is not the grossly exaggerated amount shown here, but 24 bytes. Thanks to @Nyzcere for pointing that out! There's always a mistake you miss!
– I've gotten a concern about the memory storage for the particle data. Something else I'm regretting not going into more detail. To clarify, the texture size is not the screen's full resolution in this implementation. It's 629 x 424 for a total of ~266.7k particles. Total memory storage for this buffer is therefore ~6.4MB. I think that's acceptable for a small game world like this. The size of this particle data can definitely be lowered though! If you pack the life time and color information into 4 bytes (24 bits for the life and 8 bits for a color lookup index into a shared table), you could drastically reduce the size. However, the goal of the vid was to show off a concept and demonstrate an implementation – not to achieve extreme efficiency.
– It's also been requested to explain a bit more about how the rendering occurs, since that seems to be a large concern for people who might attempt something like this.
For the particles' updates, they really are that simple, naive and brute force. It seems odd, but the resolution of my world shown is roughly 260k particles, and it easily hits a 16ms frame time. However as you scale the world, this won't cut it. So you have some options. You could split it up into sizeable chunks, say 512×512 (like Noita does), and then partition those chunks into active/inactive buckets and only update the active particles. To further speed this up, you could multi-thread the simulation.
Now, here's the catch: Noita and my simulations are both single-buffered and run on the CPU. So that means multi-threading is…challenging. You have to be careful at the boundaries of your chunks, since there's a large chance you'll have a lot of data-races at boundary walls.
Noita handles this by splitting its update frame into 4 sections – it creates groups of chunks to update in a "checker like" pattern, so it maintains a large separation area between chunks. This works well enough in practice so that a particle has a large enough area it can travel in a single frame between neighboring chunks without having to worry about getting accessed twice in different threads.
You could also move the entire sim to the GPU, but that's a different beast altogether. 🙂
The rendering is done in a single draw call. I keep a 2d array of 32-bit rgba color data which maps directly to the pixel data. There is also a GPU texture that has the exact same dimensions as this CPU texture. As I update pixels, I change the color data as well.
Then, when I'm done with the sim in the frame, I push the entire color buffer and copy its data into the GPU texture. Therefore rendering the scene is just a single draw call to present the buffer to screen. I also have 3 other calls for post processing.
All in all, the entire scene is rendered in 5 calls:
– one to render the simulation to an offscreen target
– three for post processing (bright filter, bloom, and composite)
– one for final presentation to back buffer
– Salt isn't less dense than water, I misspoke. But, it looks cool. That's what matters, right?
– @championchap brought up a point that I sneakily didn't address in the video (I'm starting to realize that I need to address everything much more fully than I did). The "simple" sand falling algorithm works great as a base, and adding forces, like gravity and velocity, do work to add some variation for a more "realistic" behavior set. However, if the velocity fails to move the particle in any way, the simulation falls back to this simple algorithm and it can look "out of place" with how uniformly it falls. Think about it – we specifically tell the sand to follow those rules in a fall through pattern – look down, then look down and left, then down and right. What you can do to force some variation is to alternate how to iterate through the columns of your data. Easiest way I've found is to add a frame counter and then on even frames, you iterate left-to-right. For odd frames, right-to-left. This adds enough variation to that falling pattern that it greatly helps out with this issue of unwanted uniformity.
– Also, thanks for all the kind words and motivation, everyone. Subscribe and be on the lookout for the next one. I've already started working on it 😀
Very well done
As dani would say: "Epic!"
What a great video. Brilliant for people (like me) looking to get into this area of graphics programming. Great job!
Holy shit, Is this channel even real?
Really nice video, high quality too, I was impressed with the animations, thanks John!
Learned a lot from the video. Thank you
Great video! Your explanations make everything understandable, and I love it! Subbed
Great.
Amazing piece of work <3. Did you code your own "code demonstrator" or are you using a motion design tool to show how the code is executing + matrix animation ? (At 02:10 for example)
Great video, thanks for your work
I actually wondered about the mechanics behind noita's particle simulation and how to produce the same effects in c++ OpenGL / Vulkan. This channel is perfect for me since I am planning to convert 3d rendered frames to video using ffmpeg and something like that. But I am really stupid around tinkering with graphics APIs. Anyway great work! you got yourself a new sub
does this run on 1 core?
The editing, pacing, and illustrations in this video are absolutely top notch.
after watching the devs video, it seems like you made liquids much more complicated. Still a great video!
Best 10 minutes spent on youtube ever. I would love for you to do a step by step tutorial of this in c++ or something !
This channel's videos are really well made. I'm surprised you only have 2.1k subs. You now have 2.101k 🙂
Very interresting experiment Mr. Jackson, thank you for the share!
This video doesn't feel like it's made by 2k ytber. I expect you to grow quickly. You can help your odds by uploading more frequently, but maybe this can only be a side thing for you.
Regarding 5:10 I'm trying to understand where that happens in the code. I'm a novice but I don't see it in update_sand for example, just that it checks the calculated end position. Any pointers? Anyway, keep up the good work! This video and the source code is my Bible right now so much appreciated.
hello sir really a great video but telling frankly i dont know anything about opengl but i want to learn the complete opengl from basic to advance and i thing you are the best person who can guide me. so sir can you please tell me what are the requirement of learning opengl (currently i am learning c is it useful in learning opengl)?? please sir help me out please .
Do you think it's possible to do this with JavaScript?
Thanks.
Great video! Is this simulation able to simulate communicating vessels or hydrostatic pressure where water will try to keep an even level with all of the connected water particles?
cool vid & nice editing skills 😀 long time ago this 8 KiB executable used to sim snow in a similar fashion (those were the days!) https://www.youtube.com/watch?v=qPOoU44GU50
this is amazing!
How would you do the evaporating glyphs from Noita when you get an ability?
What about making this in 3d with voxels ?
Nice project. Could you please, create a release on the Github repository (ex: binaries) for people who don't have VS 2015 installed ?
Found you through a recent game jam instant sub.
incredible video
I am seeing sometimes your fps drops below 60. Is it possible to write this whole code gpu accelerated ?
rad video! will be rewatching and checking out the code when i have some more time. thanks for sharing!
This was so amazing and inspiring at the same time. Immediate sub.
I love this series, thank you for making videos.
Thanks for this, yes a series would be awesome – really enjoyed the explanation.
How does your computer not crash when simulating all the tiny cells? Are you using some sort of optimization? If so which one
Very Epic Video!
Very nice video 👍, subbed
holy flip. with all these if monsters, how are you pulling so many fps is beyond me. great job at creating your engine sir
I've read every one of those articles you showed on the screen, and this video helped me actually understand it. Thank you.
EDIT: Please make a series on your open source game library, I'd love to build somethingg similar to this for school reasons.
I really want to make a isometric game but I'm just beginner with hope 🙂 no programming language experience from past, what is your advice for a beginner and I want a video about it if you mind ^-^
I also wonder, what is the situation of your isometric game engine, it will release soon ?
I don't even know english well but I understand what's going on :3 thanks master
This is one of those videos that could last days and I would still be sad when it ended
wow 1 dislike vs 1k like 🙂