Rendering Nebulae
New Nebulae
Recently I began replacing the old particle-based nebula standin with proper volumetric nebula shaders. The nebulae need to be many and varied, and so I want to procedurally generate them like the rest of the universe. After being introduced to some awesome volumetric nebula examples on ShaderToy, I thought I'd too have a play around with ray-tracing a noise field to create procedural nebulae. The end result looks something like this :
Ray Tracing a Noise Field
The general algorithm for rendering a volumetric noise field:
- for each pixel on the screen, cast a ray from far to near (or near to far based on your needs)
- at each step, accumulate density by looking up procedural noise functions - in this case, a fractal brownian motion function.
- return the accumulated density, to be manipulated for the final pixel colour.
This is a very basic implementation of volumetric ray-tracing, and runs very slow for the output quality. Optimising the shader to get the best quality from the least amount of integration steps is thus paramount. Importance-based sampling, multi-resolution techniques, adaptive integrations all help enormously to speed up these brute-force integrations into a real-time technique suitable for games.
Turn a Field of Blobs into a Nebula
Ray tracing a noise field produces a fairly bland looking set of 3D blobs - it's fantastic to now have a fully 3D effect to fly in and around, but for beautiful nebulae we want both blobiness and wispiness, and the basic noise field has no wispiness.
Domain warping is a standard procgen technique especially suited for generating folds or wisps, whereby instead of sampling the noise at the exact coordinates given, you modify the coordinates for each lookup. For the nebula shader, at each step in the ray we lookup another noise function to generate a small change-in-direction of the ray, and continue the march through the noise field but with each step accumulating a bit of a direction variation. So each path from the far pixel depth to the eye involves tracing some squiggly curve through the noise field. Tweaking this "random walk" gives some nice little wisps and swirls as you can see here:
The variation during the raymarch ended up needing to be very subtle, or the noise field quickly degenerates from a lovely blobby or wispy and cohesive image into a torrid mess. Below is an example of too-much-crazy generated from heavy-handed domain warping:
Here was another tweaked version, this time getting close to the desired effect, but still breaking up somewhat:
Colours
I tried various procedural colourations of the noise field, but none of them produced the interestingly haunting and beautiful colours seen in astrophotography. There needs to be some way to output a colour given the 1-D normalised density value produced from the integration through the noise field. As yet I haven't found the colouring solution I want, but I have created a good prototype using a 1-D hand-drawn colour gradient. I found some NASA photos of nebulae and sampled colours from it, producing the following 1D texture. The density value is simply used as the x-coordinate when looking the texture map. In the end, I'll need to procedually generate these gradients too.
Future Improvements
I need to procedurally generate the colours, but what will be really cool is including light scattering effects in the nebula shader, similar to how the atmosphere shading works. So instead of just generating a density value, the ray-march will also generate a colour value - dense gas will extinguish colour behind it, but also in-scatter other colours and light. Any suns within the nebula will generate their own light along the rays' march, lighting the nebulae from within.
Gameplay
I want the nebulae to be volumetric not just for asthetic reasons and to fit in with the freedom of exploration throughout the galaxy, but also to provide further gameplay aspects. I'm thinking something along the lines of nebulae with internal electrical storms that jam communications and radars - and potentially dealing damage to ships within - perhaps providing a (somewhat risky) clever way to escape an otherwise overwhelming foe.
Another gameplay aspect I want to explore is (natural or otherwise) supernovae, producing an animated expanding nebula or dust or gas cloud. This fits in with an aspect of the backstory I am writing at the moment.
Recently I began replacing the old particle-based nebula standin with proper volumetric nebula shaders. The nebulae need to be many and varied, and so I want to procedurally generate them like the rest of the universe. After being introduced to some awesome volumetric nebula examples on ShaderToy, I thought I'd too have a play around with ray-tracing a noise field to create procedural nebulae. The end result looks something like this :
Ray Tracing a Noise Field
The general algorithm for rendering a volumetric noise field:
- for each pixel on the screen, cast a ray from far to near (or near to far based on your needs)
- at each step, accumulate density by looking up procedural noise functions - in this case, a fractal brownian motion function.
- return the accumulated density, to be manipulated for the final pixel colour.
This is a very basic implementation of volumetric ray-tracing, and runs very slow for the output quality. Optimising the shader to get the best quality from the least amount of integration steps is thus paramount. Importance-based sampling, multi-resolution techniques, adaptive integrations all help enormously to speed up these brute-force integrations into a real-time technique suitable for games.
Turn a Field of Blobs into a Nebula
Ray tracing a noise field produces a fairly bland looking set of 3D blobs - it's fantastic to now have a fully 3D effect to fly in and around, but for beautiful nebulae we want both blobiness and wispiness, and the basic noise field has no wispiness.
Domain warping is a standard procgen technique especially suited for generating folds or wisps, whereby instead of sampling the noise at the exact coordinates given, you modify the coordinates for each lookup. For the nebula shader, at each step in the ray we lookup another noise function to generate a small change-in-direction of the ray, and continue the march through the noise field but with each step accumulating a bit of a direction variation. So each path from the far pixel depth to the eye involves tracing some squiggly curve through the noise field. Tweaking this "random walk" gives some nice little wisps and swirls as you can see here:
The variation during the raymarch ended up needing to be very subtle, or the noise field quickly degenerates from a lovely blobby or wispy and cohesive image into a torrid mess. Below is an example of too-much-crazy generated from heavy-handed domain warping:
Here was another tweaked version, this time getting close to the desired effect, but still breaking up somewhat:
Colours
I tried various procedural colourations of the noise field, but none of them produced the interestingly haunting and beautiful colours seen in astrophotography. There needs to be some way to output a colour given the 1-D normalised density value produced from the integration through the noise field. As yet I haven't found the colouring solution I want, but I have created a good prototype using a 1-D hand-drawn colour gradient. I found some NASA photos of nebulae and sampled colours from it, producing the following 1D texture. The density value is simply used as the x-coordinate when looking the texture map. In the end, I'll need to procedually generate these gradients too.
Future Improvements
I need to procedurally generate the colours, but what will be really cool is including light scattering effects in the nebula shader, similar to how the atmosphere shading works. So instead of just generating a density value, the ray-march will also generate a colour value - dense gas will extinguish colour behind it, but also in-scatter other colours and light. Any suns within the nebula will generate their own light along the rays' march, lighting the nebulae from within.
Gameplay
I want the nebulae to be volumetric not just for asthetic reasons and to fit in with the freedom of exploration throughout the galaxy, but also to provide further gameplay aspects. I'm thinking something along the lines of nebulae with internal electrical storms that jam communications and radars - and potentially dealing damage to ships within - perhaps providing a (somewhat risky) clever way to escape an otherwise overwhelming foe.
Another gameplay aspect I want to explore is (natural or otherwise) supernovae, producing an animated expanding nebula or dust or gas cloud. This fits in with an aspect of the backstory I am writing at the moment.
Reminds me of morrowind. Game itself looked kinda chunky. But sky was beautiful . Exept this time they are generated on the fly and won't look compressed.
ReplyDeleteAhh Morrowind, probably my favourite of the series simply because the world was just whacky! And the weather effects were gorgeous, for example in the desert areas when a dust storm rolled in.
DeleteRegarding the look of Pegwars, right now I'm running on art assets that are up to 15 years old, and I'm not going to put much effort into them as I am not an artist, and the game is still evolving rapidly. The artwork you see here apart from being 'programmer art' are what I consider 'technical prototypes', they have the right number of polys, nodes, metadata etc but only as an eventual guide to artists.
The scale of the game is still a bit out, I've done work in the last year to reduce the spaceships and cockpits down to realistic size, then I am working up from there to change buildings and planets to fit to scale. The planets themselves are too small in general. This is exactly the kind of reason why I don't want to employ artists too soon, otherwise their awesome art and attention to detail is wasted if I need to make relatively large changes later on. But I think I'm getting reasonably close to locking these details down.
The eventual plan is to raise some money to build and polish the content - I know some excellent artists from the games industry that I'd love to work with again. If that doesn't eventuate, I might strip everything back to basics and go for a deliberate low-poly look. I quite like the look of early polygonal games such as the amazing game Epic (https://www.mobygames.com/game/amiga/epic/screenshots) or the new Battlezone (https://www.mobygames.com/game/battlezone____)
What will be the realistic size? Looking at Star citezen and Elite:dangerous for example. In both games ships look believable, yet star citizen ships are tiny in comparison.
DeleteIn graphics i would also prefer polygonal look. Going back to elite II. Game looked really bad on dos with all the ugly pixelated textures, i liked plain look of amiga version. Now with opengl rendering you can truly appreciate absence of pixels and clean vibrant visuals
hello there, still checking your blog regularly. How it goes?
ReplyDeleteHello! Slowly, as usual. I've been putting volumetric clouds in, but at the moment they are a little slow as they are unoptimised and use a lot of GPU fill rate. But it is cool flying through them. Also I've been working on shipyard loadout interface, allowing you to position new ship systems where you want. I added a new procedural planet type that looks like gas giants.
DeleteI uploaded a short gameplay video from a few months ago : https://youtu.be/xFTpYYuYljk It's pretty rough but should give an idea of how the game plays
Will we get another update for new year?
ReplyDelete