Version 0.5 of Spacescape has been released - Download it!
If you were waiting for Spacescape to run on OSX, your wait is over! Not only is it over, Spacescape got some requested features that are really cool.
v0.5 FEATURE LIST
Support for OSX
HDR mode for working in high dynamic range and exporting 32bit per channel .exr or .dds skybox images. Also allows for using HDR billboards (.exr)
Import billboard data file to manually specify billboard positions, brightness, distance and colour
More export options! Export now adds support for UNREAL (3d cube map with correct rotations and .dds output), UNITY (correct naming), SOURCE (correct naming and .tga output)
Debug box option for those trying to determine the orientation of the exported skybox faces for importing into a different engine
Converted billboard file field to support a browse button so you can choose any file on your computer instead of having to put them in the media/materials/textures folder
About this HDR thing..
You can thank the good folks at NVidia Demos for financing the addition for a recent demo they released! You can see part of the Spacescape generated HDR starfield with actual star values, positions, brightness values, colours and some generated nebulas around 6:54.
It's really cool, but for most games you'll probably stick with non-HDR because you just don't need the extra data. HDR skyboxes are cool when you want to accurately adjust the exposure in your game for, say, a daytime scene when the stars are not visible because the atmosphere is so bright, and then as night comes and the atmosphere is no longer bright the stars become visible. Keep in mind a few things:
Use HDR billboards in .exr format or the outlines of your billboard stars will get too blown out as you adjust the exposure. Some sample .exr billboards are included in the app or you can make your own in Gimp or Photoshop.
Use the new HDR Power field to push most of your stars into the background if you are using randomly generated star positions, otherwise use a data file.
If you use a data file to specify star data, the input is a csv file that requires an X, Y, Z, ABSMAG, and DISTANCE. All these values are based on actual star data and there is a sample data.csv file with a few constellations in it in the Files section of project. You can also find a massive star database at http://www.astronexus.com/hyg
Use HDR Multiplier to make background stars and nebulas really faint and near stars bright
A good range for HDR brightness values is between 0 and 10, even though the colour values for stars is from 0 to 255, when in HDR mode those numbers are actually converted to the 0 to 1 range then the HDR power function is applied and the result is multiplied by the HDR multiplier.
There's lots left to do
And that's an understatement. Spacescape is nothing like the final tool I want it to be. I want to implement a simple mode for non-wizards, and a skybox library - a way to share skyboxes from within the app amongst many other things. I'd also like improve the way layer masks work and possibly add terrain and planets!
Kickstarter?
To add all the features I want would take a lot of time. I was only able to add in these recent features because Nvidia was able to help pay for those hours. So I'm considering putting up a kickstarter or indiegogo project to get the other features funded. Maybe nobody will notice? On the other hand, Spacescape has been downloaded 41,000 times since I posted it in 2010.
I've gone and made the atmosphere shader more complex, sorry. The basic idea is still pretty straight forward, but I added mie scattering to the pixel shader and added extra code to fix issues with the atmosphere being too transparent when near the surface of the planet (stars were showing through).
Also, I worked on pre-calculated/static shadow maps for the terrain and used those with the grass and trees. JohnJ created Paged Geometry, which is built for 2d heightmaps, but I semi-adapted it so that each face of the planet cube has its' own paged geometry instance. Here's a video of that:
Note: the atmosphere shader in this video is the old atmosphere shader so the atmosphere is still too transparent on the sunny side of the planet
It has issues like, the billboard trees don't display right when viewed top down and they don't fade out based on height like they should. Also there is an abrupt transition from one paged geometry instance to the next when you cross over from one cube planet face to another. I may just have to roll my own simplified version.
And now, here is the NVIDIA FX Composer shader for the current atmosphere shader I'm using:
// this is the sun position/direction float4 gLamp0DirPos : POSITION < // or direction, if W==0 string Object = "Light0"; string UIName = "Lamp 0 Position/Direction"; string Space = (LIGHT_COORDS); > = {10.0f,10.0f,10.0f,1.0};
// this is for setting where the horizon should fall on the sphere float StretchAmt < string UIName = "Stretch Amount"; string UIWidget = "Slider"; float UIMin = 0.0; float UIMax = 1.0; float UIStep = 0.01; > = {0.25f};
// get distance to atmosphere horizon - use max(0,...) because we can go into the atmosphere altitude = max(0,camHeight - AtmosphereRadius); horizonDist = sqrt((altitude*altitude) + (2.0 * AtmosphereRadius * altitude));
// without this, the shift between inside and outside atmosphere is jarring float tweakAmount = 0.1; float minDot = max(tweakAmount,horizonDist / camHeight);
// scale minDot from 0 to -1 as we enter the atmosphere float minDot2 = ((camHeight - SurfaceRadius) * (1.0 / (AtmosphereRadius - SurfaceRadius))) - (1.0 - tweakAmount); minDot = min(minDot, minDot2);
// get dot product of the vertex we're looking out float posDot = dot(camToPos / farDist,-camPos.xyz / camHeight) - minDot;
// calculate the height from surface in range 0..1 float height = posDot * (1.0 / (maxDot - minDot));
// push the horizon back based on artistic taste ln = max(0,ln + StretchAmt); lnn = max(0,lnn + StretchAmt);
// the front color is the sum of the near and far normals float brightness = saturate(ln + (lnn * lc));
// use "saturate(lc + 1.0 + StretchAmt)" to make more of the sunset side color be used when behind the planet oUV.x = brightness * saturate(lc + 1.0 + StretchAmt); oUV.y = height;
// as the camera gets lower in the atmosphere artificially increase the height // so that the alpha value gets raised and multiply the increase amount // by the dot product of the light and the vertex normal so that // vertices closer to the sun are less transparent than vertices far from the sun. height -= min(0.0,minDot2 + (ln * minDot2)); oAlpha = height * brightness;
// normalised camera to position ray oCamToPos = -rayDir;
// use exponential falloff because mie color is in high dynamic range // boost diffuse color near horizon because it gets desaturated by falloff return 1.0 - exp((diffuseColor * (1.0 + uv.y) + mieColor) * -fExposure); }
Possible Improvements - pre-calculate camera height, camera height squared and other such variables. you should notice that a lot of the vertex shader code would be the same for every vertex including calculating horizon distance, camera and light only based calculations and parts of the sphere intersection calculations. - simplify mie scattering equation and remove hdr - when the camera is inside the atmosphere we no longer need to calculate the atmosphere closest intersection so the program should switch to a simpler version of the shader once inside.
Known Issues - transition from outer atmosphere to inner atmosphere is not smooth. I suspect this is due to my atmosphere being an un-realistic size so I had to add a tweak amount so that the transition point is actually a bit inside the atmosphere at a point where only the inside of the sphere is visible to the camera. At the point where the camera is the same height as the atmosphere, it can still see the outside of the atmosphere shell. - when on the surface of the planet looking back at the horizon it looks more like a painted shell than a spherical haze - when you get really close to the edge of the atmosphere on the side facing the sun there is an artifact that appears that I haven't fixed yet. - there are banding issues in the sky gradient when on the side of the planet facing the sun that I haven't solved yet and I think they're related to the color choices in my gradient, but I'm not sure.
If you have any suggestions, improvements or bug fixes please let me know in the comments!
Just a minor update - I've added billboard sprites to the mix where as before I was just using point sprites. I also added an extra line to the noise shader like this: noiseSum = pow(noiseSum / powerAmount);
This allows me to control the slope of the noise gradient so it is more steep or more gradual, which is something I needed for masks.
The image above really taxes my system (3-4 fps). It has 12 layers: one ridged noise mask for the brightest stars, then another for the middle level of stars and then two more ridged noise haze layers and the rest are mixes of billboard and point stars.
For kicks I threw the generated skybox into the planet app and it's definitely a bit over the top and low-res/blurry. Still it is "fun"
I re-implemented writeToFile() in the plugin so I can save to files. I also added a writeToMaterial() function to the plugin so I can preview the skybox in ogre.
One thing I've noticed is that the resolution of skybox really affects the brightness of small stars. When I save a 2048x2048 skybox out the single pixel point stars are crisp, but get lost when imported into a program with a low screen resolution. So you kinda have to take that into account when making the skyboxes. It might look great at the resolution on your monitor, but not at the resolution on someone else's monitor. This is where the writeToMaterial() function will be useful so you can preview the skybox at different resolutions to see if it works OK at low resolutions.
I might mess with the mipmap generation for lower levels so that stars don't loose their brightness as quickly when the high resolution image is scaled down.
Here's a sample generated skybox (click for 1024x1024 version - open in new window): right left top bottom front back
And here's a funny little screenshot of what a skybox layered sphere looks like from the outside (not the same as the one above):
Spacescape is a tool that uses Ogre to create / generate space scene skyboxes. The way it works is a camera sits inside a number of user defined layers / shells. Each layer can be a bunch of point sprites ( for stars), or a noise field (for nebulas/haze etc.) You can define how many stars you want and the color based on distance. In the screenshots I'm posting there are 7 layers. 3 of the layers are regular blue/white stars, 1 is a few red stars, 2 layers are ridged fbm noise of different colours and the 3rd layer is regular fbm noise used as a mask to make stars cluster by darkening regions of space.
This has been a really fun tool to make and I still have a lot left to do like the GUI. At present it reads in xml config files or you can use the plugin api to manipulate the skybox via code. Did I mention this will be an Ogre plugin too? I plan on releasing the plugin and tool as soon as I get a GUI and finish refactoring the save to file code.
How it works
Making a bunch of point sprites is easy. I use an Ogre::ManualObject for that with pointSprites enabled on the material.
To create the skyboxes I just create a camera with FOV set to 90degrees and render to texture the six images of the skybox. I have it set up to render to texture the mipmap levels too, so if a user wants to save a dds file with mipmaps they can, or they can just save out the six individual images. With the Ogre plugin it will also be possible to not save out the file but just tell the plugin to create a skybox with a given config file and use it in your own application.
Here's some more images (click to enlarge - you'll need to in order to see the stars better):
A note about dithering: I've had a tough time figuring out what to do about gradient banding with dark colors in the space backgrounds. Without some kind of dithering or noise the gradient is very obvious. You can see the banding clearly in all the videos and screenshots I've posted prior to this post. The skybox I was using before was generated with blender and spiced up in photoshop, but there was no dithering on the haze so it's really ugly. To get around this with Spacescape, I provide the option to dither a noise layer by a controllable amount and this seems to make the banding issue go away.
The plan is to use this plugin in MyFirstPlanet to let users design their own space skyboxes easily too.
Hopefully, I'll have a demo and some source code posted in the next week or so.