This project is a masterclass in leveraging low-level GPU primitives to achieve organic complexity without the bloat of modern frameworks. It elegantly demonstrates that true performance is found in mathematical precision rather than brute-force computation.
Deep Dive
Prerequisite Knowledge
- No data available.
Where to go next
- No data available.
Deep Dive
How I Simulated 100,000 Cells At 60 FPS
Added:I'm making a game where you start with a single living cell and grow it to build bigger microorganisms. It's going to be a short incremental game with some light automation elements, but it's not an idle game, so you'll have to keep actively playing to make progress, kind of like in Factorio or Satisfactory, but much shorter. Let me give you a quick tour of my custom engine. First, we've got these nice dynamic organic cells that deform based on their speed and direction.
I added a cool squishy looking mitosis animation when cells split.
Behind the scenes, this is all powered by my own custom physics engine to make sure the cells don't overlap as they collide and divide. I also added this ray traced parallax background with tiny specks of dust flying around. This gives the whole scene a feeling of depth, making it feel more like a liquid that the cells are swimming around in. And did I mention that this runs entirely in the browser and scales up to 100,000 cells at 60 fps, even on a slow laptop?
Oh, and one more thing. You might be wondering, in an incremental game, don't you often have much bigger numbers?
Isn't 100,000 cells a bit small? You're right. We need to go bigger. Much bigger. That's why I added an infinite zoom mechanic. And each cell is its own little micro universe. This is also persistent. So at the end of the game, the first cell you ever started with and grew into billions of other cells will still be there. I'll show you how I got this working using nothing but raw WebGL and vanilla JavaScript. No engine, no dependencies, just a plain HTML file dragged and dropped into the browser.
In this video, I'll focus entirely on how I rendered these squishy organic cells at a stable 60fps. And you don't even need any prior knowledge in graphics programming to follow along. If this video gets enough interest, I'll show off the other features in the future. So, please consider subscribing, or even better, go and try the full tech demo by clicking the link in the description below. If you enter your email there, I'll send you a promo code for a super secret in-game item once the game releases. You also get access to a GitHub repo with the full source code for this tech demo. I've even created simplified versions at various stages of the video so you can easily follow along. Now, let's get started. So, to get this demo working, I had to overcome six main challenges. The first one was honestly just to find a basic approach that would work with this many simultaneous cells. Normally, when you want to draw soft and squishy things, you'd use a soft body physics engine.
These essentially work by modeling the organism using many points and connecting them with springs. The problem is that this would be way too slow for simulating a 100,000 cells. So, we have to use some other trickery to make it faster. What if we just draw a single circle? Then we can add some clever distortion to make it look more organic and make this run super fast on the GPU. So, that's our first proper challenge, drawing circles directly on the GPU. Unfortunately, it turns out GPUs are pretty dumb devices. They really can only do one thing well. Draw triangles. Lots of them and really fast.
Now, while we could draw a circle with just triangles, it's kind of slow. Also, to make it look nice at the edges, we have to use a lot of triangles. So, we'll do it in a different way. We'll piece together two triangles to draw a square and then use some math to cut out the circle from the middle. This works in two steps. First, we use JavaScript to send some coordinates for the four points to the GPU. This defines the area to draw in. In the second step, the GPU asks us for each pixel that's within this area, what's the color of this pixel at this coordinate? Any pixel that's within the circle gets drawn purple, whereas any pixel outside the area will stay transparent. This whole process happens for many pixels in parallel, and it's one of the reasons why GPUs are so fast.
The way this works in practice is that the GPU calls this function many times, once for each pixel. So if we set a red color here, every pixel within our drawing area will be drawn red. This piece of code here runs directly on the GPU and it's called the pixel shader or fragment shader. The code here is written in GLSL, a language specifically designed for GPUs. Now, as I said before, in the fragment shader, we can also get the coordinate for each pixel.
This allows us to set a different color depending on where our pixel is. For example, like this, we can turn all pixels whose x coordinate is greater than zero to green and all other pixels to blue.
Now, to draw a circle, we just need to define a center point and a radius.
Then, for each pixel, we calculate the distance from the center. And if this distance is shorter than the radius, the pixel is within the circle and gets colored purple. All other pixels are outside and remain transparent. And there we have it. A nice circle drawn very fast on the GPU. Now for our next challenge, how do we get such a nice glow effect and stroke on our circle?
For the inner glow, we can use a technique called interpolation. We define two colors and transition from one to the other as we get closer to the edge of the circle. We can make this look even nicer by adding an exponential fall-off function. Basically, instead of changing the colors at the same rate everywhere, we change them much faster near the edges, which gives us this nice inner glow effect. For the outer glow, we can use a very similar technique.
Though in this case, we don't interpolate between two colors, but instead we reduce the transparency the farther away we get from the center of the circle. We can also use a smoothing function here to make this look even nicer. Finally, we can simply draw the stroke on top. We can do this by checking if the pixel's position is close enough to the radius of the circle. If it is, we override the color with our stroke color. This is a bit of a simplification. In reality, we also use a bit of interpolation here between the stroke color and the underlying circle color. This is to prevent rendering artifacts at the edges of the stroke. So, basically, we've implemented some simple anti-aliasing. Let's also update the background color to something a bit nicer. Our next big challenge is to make this look less like a pure mathematical circle and more like a wobbly organic looking cell. Now remember for each pixel we use the radius of the circle to check whether or not it's within the circle. So obviously if we increase the radius the circle grows. If we reduce it it shrinks again.
But what if we increase the radius only for a certain segment of our circle? For example for each pixel we can calculate this angle. And if it is within a certain range, we increase the radius.
Instead of using an if statement, we can apply this trick to the entire circle and use a smooth function to modify the radius based on the angle. For example, a sign function. We can then adjust the amplitude and frequency of our sign function to get a nice uniform curve.
The amplitude defines the height of the curve and the frequency, how many ripples we have.
We can even animate the curve by adding the current time of the simulation to the angle. This still doesn't look very organic though. But there's a really neat trick we can use. Instead of a single sine wave, we just add multiple of them at different frequencies, amplitudes, and speeds.
This creates positive and negative interference and results in a very organic randomlook wobble. It's also really fast to calculate on the GPU since we're just using a dot product to add the influences together. I think this is starting to look pretty cool, but it leads us to our next big challenge. When we add movement to our cell, it doesn't really look like a living being. It looks more like a blob that just floats around. Instead, we want it to squash and stretch organically according to the direction it's moving in. First, how do we actually add movement to all of this? We need to define a velocity vector that is calculated in JavaScript. Remember to draw our circle, we had to tell the GPU which area to draw in by giving it four points. To add movement on each frame of the simulation, we simply move those four points a little bit along the velocity vector. Now, let's reset our cell and set the velocity to zero. Let's also temporarily disable the wobbling we just implemented. To show how the stretching of the cell works, I'll add an overlay in a different color so we can more easily see how the circle is modified based on its velocity. If we pause our simulation here, we can see that we need to stretch the original circle in the direction of the velocity vector while simultaneously squashing it in the direction perpendicular to the velocity vector. Now, how do we actually do that? We use a technique called domain warping. Remember, the GPU works by giving us a coordinate for a pixel and then asks us what color that pixel is. Let's say we're drawing this pixel right here. With our previous code, without domain warping, the fragment shader gets the coordinate of the pixel and checks if it's within the radius of the circle. As you can see, this pixel is clearly outside the circle. So, it's drawn transparent. Now, with our new technique, domain warping, we use the velocity vector to move the coordinates slightly. We then use this warped coordinate for checking the distance and evaluating it further. This means that even though we're drawing this pixel right here, we're actually evaluating the color of this pixel over here, the warped position happens to lie on the stroke of the circle. So when filling in the color of the actual pixel at the fragment position, the stroke color is used.
Now, what about this pixel here? Since it's perpendicular to the velocity vector, we adjust the warped coordinate outwards and we're actually using the color of this pixel here. If we apply this logic to all pixels, we get this nicel looking result. This technique is called domain warping because we're essentially squishing or warping the entire coordinate system of our pixels before drawing. We can now reenable our old code that makes the cell wobble to combine both effects. The actual code for this is actually surprisingly short.
It's just a bit of vector math and dot products.
There's one last big challenge to overcome for our organic cell. Adding a nice interior texture to make it look like a living organism. To do this, we first use the GPU to draw a grayscale image containing random noise. Because generating this image is comparatively slow, we do this in a pre-processing step when the simulation starts. We then map the texture onto our circle. Then with some clever color mixing, we can merge the texture with the old background colors of the cell. Looks pretty cool to me, but it's still a bit flat. We can very easily add a subtle lens distortion effect by simply shifting the texture coordinates slightly when reading the texture. The cool thing is because we've been using the warped fragment coordinates from our previous step, the texture will now ooze along with the cell as it moves. We don't even have to add any extra code for this. One more thing we can do to make this look even better is to move the texture slightly based on the velocity of our cell. For example, when the cell moves to the right, we move the texture in the opposite direction. It's subtle, but this gives us a nice oozing effect. Since we've generated the texture to be tileable, the GPU will just repeat it as it moves.
And there we have it, our beautiful organic cell. Now, of course, there's a lot more we have to do to render 100,000 of these. I'll show you more pieces of the engine in future videos. Don't forget to secure your promo code for the super secret in-game item in the link down below. You can find this final code sample and all prior steps in the private GitHub. And I'll release more code as I make more videos on this. Once I release the final game, there will be a bundle to buy the final source code for the whole game with a commercial license that allows you to use it for your own games. It'll also include some other goodies like the full game design document at various stages of development and early prototypes, but that's a ways down the road. In the meantime, let me know in the comments which of the engine features you'd like to see next. Have a great day and thanks for watching filmatics.
Related Videos

TOP 15 Data compression Interview Questions and Answers 2019 Part-2 | Data compression | Wisdom jobs
wisdomjobs
281 views•2019-06-28

CTS 158: 802.11w Management Frame Protection
ClearToSend
4K views•2019-02-04

NDSS 2019 Send Hardest Problems My Way: Probabilistic Path Prioritization for Hybrid Fuzzing
NDSSSymposium
496 views•2019-04-02

How realistic is Cities: Skylines?
CityBeautiful
159K views•2019-02-14

GUIs & TUIs: Choosing a User Interface for Your Python Project | Real Python Podcast
realpython
2K views•2025-04-04

The OSI Model - Explained by Example
hnasr
225K views•2019-05-12

Cloud Computing - Introduction
elithecomputerguy
98K views•2019-10-07

From Traveler's Dilemma to Dynamic Routing | Demystifying Networking
IITBombayJuly
5K views•2019-08-04
Trending

WOW! Judge TURNS THE TABLES on Trump in His OWN $10B LAWSUIT!!!
MeidasTouch
197K views•2026-07-23

Playstation NO DISC/NO BUY Fight Is Over...
DavidJaffeGames
4K views•2026-07-23

Steam and Xbox Just Dropped The Hammer On PlayStation
OhNoItsAlexx
9K views•2026-07-23

Americans Confused in Australia for 17 Minutes Straight
IWrocker
17K views•2026-07-23