I recently wrote a blog post about how I was learning to make video games in the Unity game engine. In that post, I built a simple space scene, and added some basic game mechanics. After writing that post, I wanted to try something a little flashier by building a dramatic version of the Sun to sit at the centre of the scene. This project let me dive into the depths of particle simulation in Unity. At first, the simulation was done entirely on the CPU. Later, I discovered the Unity Visual Effect Graph and the incredible performance a GPU is capable of.
My first attempt involved adding a sphere to my scene and wrapping it with an equirectangular projection of the surface of the Sun, just like I'd done with Mars in my previous post. The results were underwhelming. The solar surface is alive and radiating energy, but my sphere looked like a giant tangerine floating through space.
To make things feel a bit more lively, I created a densely packed particle system in Unity, and then created a custom texture using Photoshop using an image of smoke. I created this texture by finding an image of a boat on fire, cropping out a section of the smoke, and adding alpha values to each pixel based on how dark it was, essentially converting darkness into transparency. Here's how it looked with ~1000 particles fading in and out on the surface of the sphere.
The surface of the Sun now has motion, which certainly makes things more interesting than they were before. Unfortunately, that's still not very interesting, and things look a little bit off. I soon realised that the texture I created wasn't actually transparent. Areas of thin smoke weren't rendering with transparency, they were rendering completely opaquely!
The fix took hours to find, with the majority of the time trying to work out how to convert darker pixels to transparency in my image. Working with alpha channels in Photoshop is not intuitive for beginners! After fixing the alpha channels in my image, and figuring out how to import a transparent texture into Unity, here's what things looked like:
Much better! The next thing I tried was to add the corona. The corona is the outer layer of the sun's atmosphere, and it's much dimmer than the surface of the sun. So, I added another layer of particles, but made them dimmer and more orange in colour.
I was really happy with this, but I wanted to take things further. The Sun pictured above contains approximately 1200 particles, all of which are simulated on the CPU. Recently, I'd been reading about the Visual Effect Graph, an upcoming feature in Unity which allows you to simulate particles entirely on the GPU. It turns out the GPU is very good at this task. This project was a great excuse to dive into the VFX Graph and see what it was capable of.
To kick things off, I created a sphere containing hundreds of thousands of particles. Then I started increasing the numbers, eventually simulating 2,000,000 particles at once:
Despite having a huge number of particles rendering on my screen, I was able to fly around the scene and maintain a constant 200 FPS. In order to bring my FPS down to a steady 60, here's what it took (note that the FPS looks lower because my GIF recording software is capped at 15 FPS):
That's an explosion of 14 million individual particles being simulated in real-time.
I wanted to make use of the power of the VFX Graph in order to bring my Sun to life.
I created a spherical volume of particles, and configured the graph in order to have new particle instances spawn on the surface of the sphere. To do this, I created a vector of random numbers, then normalised it so that it had a length of 1. This vector represents a random point on the unit sphere. The sphere representing the Sun in my scene has a radius of 42. To get a random point on this surface, I multiplied the vector representing the random point on the unit sphere by 42. The final result is a random point on the surface of the Sun.
With the ability to spawn miniature particle systems on the surface of my sphere, my next task was to introduce some chaos. I wanted them to look like they belonged on the surface of a star.
The "turbulence" node of the Unity VFX Graph gave me an effect I was happy enough with, and one that I think is beautiful in isolation.
At this point I had constructed a giant hollow sphere of particles, which I hoped wouldn't look out of place when I wrapped them around the Sun I made earlier. I placed the Sun inside this particle ball, then added a script to make the whole thing rotate.
At this point I was happy enough with where I was at, but I realised the motion of particles on and around the Sun were really effective at drawing focus to it. To further draw attention to the Sun, and make things more dramatic, I added a stream of particles which spawn on the surface of the Sun, and travel outwards before fading away.
To finish things off I wanted to add some solar prominence, so I fired up Photoshop and painted another texture. This time I just painted it manually rather than basing it off of a real image. I spawned 50 instances of it such that it wrapped around the Sun, and added so slight variation to the scale of the particles as they spawn. The particles spawn at a random rotation, and slowly rotate around the Sun.
The final result isn't the most realistic, but it's certainly quite dramatic, and I'm pretty happy with it overall.
If I were to continue working on it, I would likely replace the surface of the sun with a shader rather than repeatedly spawning smoke particles, and try to make it appear to "glow" more than it currently does using lighting rather than particles.
Thanks for reading!