So, what have i been doing since the last update ?
Main thing: experimentation. Testing new colors, new algorithms, new variations of existing algorithms, to get a good feeling of what's possible or not.
Technically, i switched from rendering particles to rendering point sprites. Took a day or so to code in ( especially as i had to keep the interface clean to be generic enough for a future DirectX implementation, if needed ). But i'm very happy with the results, especially the memory saving. Think about it: all my clouds are one million points. With particles ( orientated towards the camera in a vertex shader ), it required 32 bytes per vertex, 4 vertices per particle, and 6 indices per particle. That's 1,000,000 * 32 * 4 = 128 MB for the vertex buffers and 1,000,000 * 6 * 4 = 24 MB for the index buffers, so a total of 152 MB of video memory to render my nebulaes.
Now, with point sprites, i only need 1,000,000 * 16 = 16 MB for the vertex buffer, and no index buffer. 16 to 152 is a saving of 9.5 times less video memory ! ( and of course, that's 9.5 times less bandwidth for filling this data by the CPU ). The problem with point sprites is that i had to switch to a rendering that has a constant max point size ( while before, points of the clouds could be of variable sizes if needed ) and that i can only use one texture.
Fortunately, i found a good trade-off: i render the "large features" ( variable point sizes ) with normal billboarding ( where i can control the size and the texture coordinates in a vertex shader ), and the "small features" ( constant point sizes, around 95% of the cloud ) with point sprites. So there's no loss of quality at all. Performance also improved a lot, and i'm now getting from 15 to 60 fps depending on where the camera is located in the nebulae ( don't forget it's fully volumetric ! ).
I optimized the points generation loop by pre-allocating a memory buffer and removing some temp variables, and also optimized the cos/sin calls as David mentionned in my previous journal entry. The net gain is around x3.4 faster than before.
I've added some code to deform the cloud point with some Perlin noise, to give a "turbulence" effect so that "straight lines" generated by strange attractors appear a bit more natural. Of course, as everything in the algorithm, the amount / type of distortion can be randomly generated to have more variety.
On my "todo" list, i still have to:
- test a multi-pass color accumulation algorithm, to avoid the loss of color precision at very low transparencies
- use negative blending for some features like bok globules. Why negative blending ? Because i don't want to have to sort 1 million particles due to alpha blending :)
- experiment 3D IFS ( another equation for generating the cloud points )
- add "main stars" to the nebulae and light it based on the color and distance between each point and these stars.
- i've also been considering rendering particles with normal mapping, but i'll probably drop that since i believe it'll look "good enough" without it :)
The following screenshot is a cloud point ( yes, it is made of one million points ! ). I thought the result was looking very mathematical, and the code is dead simple. Bonus points for anybody who can guess how it was generated :)
The next two images are a nebulae deformed with Perlin noise and rendered from 2 different viewpoints: