I love looking up at the night sky—and in real life, the stars are these tiny bright pinpricks staring back. In many games though, they tend to be flat and blurry. I’ve made a lot of space scenes in my time, and this sort of limitation is always a pet peeve of mine.
The challenge: how do I make the stars look sharp and twinkle back at you in a game?
It’s all about understanding the magic behind the scenes.
The best answer I’ve seen lately was a pixel art game (Steredenn), which keeps a relatively low resolution pixel art look but then puts some stars at single pixels in 1080 resolution. This gives them that nice sharp look. Unfortunately, I’m not making a pixel art game.
For Curved Space, I wanted to be able to use a polar mapped sphere for my background—lets me do some other interesting things with galaxy effects, etc. So then, the question is how to make this skybox look decent?
I started with some stock footage stars from the Milky Way. Nothing fancy, and could potentially have been synthetically generated. Mapped to a sphere though, it’s a little bit fuzzy:
It doesn’t look terrible in a thumbnail, but when this is your whole sky its soft and blurry—even at already fairly high resolution!
If the high resolution isn’t enough, then we need ultra high resolution. I found footage that was > 8192 pixels wide, which officially made it the highest resolution asset in any project I’ve worked on. I stripped it down to greyscale and stored it as a single A8 channel. Yes this is a lot of memory, but at least it’s only using 1/4 as much compared to full color. It’s also a little nicer and more consistent than DXT given the sharpness we’re looking for.
It’s a bit crisper, but honestly didn’t help too much… it’s still pretty blurry. And grey.
Next do _not_ generate mipmaps, which leaves the stars with a subtle twinkle effect and sharpness. It also saves memory.
You can see the crisp per pixel stars!
I pushed the intensity of the stars with an exponent and scale, putting them well into HDR and letting my bloom give them an extra push. The exponent also allows me to get the ‘density’ of stars closer to what I’m looking for aesthetically:
Nice sharp stars but still grey.
Finally, I blended in a low resolution color map for that Milky Way / NASA photo feel. Not necessarily realistic, but it ‘feels’ right.
Final result, with a hint of color in the background and a hint of tinting in the stars themselves.
End result: single pixel (or close to single pixel) sharp pin-prick stars with a bit of bloom where appropriate… and some handy sliders to control exponents.
Looks really sharp at full resolution, especially on a higher res screen.
Now, the one downside is that if it’s not a skybox / not locked to the camera, it does twinkle a bit as the camera moves—but I’d actually consider that a positive in this case. Normally I’d be horrified to avoid mipmapping on such a texture based asset, but in this case I think it just works.
It’s made with ShaderForge for the Standard renderer, but the concept should apply to ShaderGraph and URP/HDRP as needed.
UPDATE (June 7th, 2020): Our friend Ian tried Andrew’s skybox suggestion for his game Novaforge. We’ve included Ian’s thoughts below.
Previous version of the skybox in NovaForge.
Thanks for the suggestion, I’m very happy with how it turned out! It really highlighted how muddy my old skyboxes were.
When writing a shader to implement your approach, I added a few embellishments. The first was to layer in the old skyboxes as a background element, lightly enough that it doesn’t distract from the new stars and galactic plane, but still able to add a little more texture to the darker parts of the sky.
New version of skybox in NovaForge after implementing suggestions.
My second addition was to add a nebula/cloud mask to add detail and structure to the soft glow of the galactic plane, and to create that mask I pulled out the nebula from a creative commons panorama of the night sky. The clouds of our galactic core are a striking visual in nature, and since Novaforge is meant to take place at near-Earth stars I wanted to capture some of that familiar sky.