Blog

Syndicate content
don't panicpetrockethttp://www.blogger.com/profile/10147348345426496177noreply@blogger.comBlogger36125
Updated: 12 min 33 sec ago

Spacescape - Now With Billboards

Wed, 02/17/2010 - 23:37
spacescape image with billboard sprites
(click to enlarge)

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"

(click images to enlarge)
planet with generated skybox

planet with generated skybox 2

As usual, I uploaded these images and more to the My First Planet gallery.

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
right
left
left
top
top
bottom
bottom
front
front
back
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):
outside skybox layer sphere

Introducting Spacescape! A Space Skybox Creator.

Tue, 02/16/2010 - 00:59
Spacescape Alpha

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.

For making the haze I create an inverted unit sphere and use a glsl shader on it that implements fbm and ridged fbm noise using Perlin's improved noise (not simplex noise). Lintfordpickle at britonia-game.com has a good explanation with code samples about how fbm and ridged fbm noise work

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.

New YouTube Channel For Planet Dev Videos

Sat, 02/06/2010 - 15:17
I started the petrocket YouTube channel and am posting dev videos there for now. I like Vimeo, but YouTube now allows HD videos and I think it has a larger developer audience.

Here's another quick video I uploaded to test the HD quality. Sorry for the jerky camera movement.

Simple Flexibile Atmosphere Shaders

Sun, 01/24/2010 - 23:10


Uploaded a video of the effect


First, why no posting since September? Well, in October my wife went into pre-term labor so she was on bed rest and that meant I had to become a mom till our son was born late November. Then in early December it was holiday madness and new baby madness!

Slowly, after the holidays I started work on the planet again. I've mostly been converting it to an Ogre Plugin and refactoring it. I'll do a separate blog post about the architecture of the plugin later I hope, but for now this post is about my work in NVidia FX Composer 2.5 working on some flexible atmosphere shaders.

If you don't know, my earlier shaders were based entirely off Sean O'Neil's free atmosphere shaders. Now, Sean does things the right way, which is why his work looks so good! His shaders represent the atmosphere of the earth very accurately. The one thing that prevented me from cutting and pasting them into my project was they rely on your atmosphere radius being a certain ratio to the surface radius (an earth sized ratio). My atmosphere's are much exaggerated so it didn't really work and I was kind of lost in all the math.

Side note:If you're ever struggling with this stuff I highly recommend you contact him because he's very kind and helpful.

So I started work on a shader that isn't mathematically correct, it just uses a look up table for the blend colors based on 2 things:
- dot product between the camera and the light
- dot products between the two sphere intersections of a ray from the camera to the vertex being drawn and the light.


Here's the 32x16 look up table for the atmosphere shell.



On the horizontal axis values on the left are used when the point on the atmosphere is pointing away from the sun and values on the right are used when the point on the atmosphere is pointing toward the sun. The vertical axis values are for blending between points near the surface of the planet (bottom) and points at the edge of the atmosphere (top).

So here is a side view of the planet that shows the gradient well.



To calculate the color to use on the horizontal axis I use this:

float StretchAmount = 0.5;
ln = dot(lightDir, farVertexPosition);
lnn = dot(lightDir, nearVertexPosition);
lc = dot(lightDir, cameraPosition);

ln = max(0,ln + StretchAmount);
lnn = max(0,lnn + StretchAmount);

uv.x = saturate(ln + (lnn * lc)) * saturate(lc + 1.0 + StretchAmount);


So when the camera is between the planet and the sun ln will be 0 and lnn will be 1 and lc will be 1 so you'll get uv.x = 1 (the blue color of the atmosphere). When the camera is on the back side of the planet ln will be 1, lnn will be 0 so uv.x would be 1.0 (the blueish color of the atmosphere) from the back too except the saturate(lc + 1.0 + StretchAmount) bit scales the value based on lc, which would be -1, so -1 plus 1 + stretch amount = 0.5, so uv.x ends up being 0.5 and you end up seeing the redish colour.

The StretchAmount is used to determine where the sunset should begin.

I also multiple the color by the height so it fades out as the atmosphere gets thinner, and also multiply by another amount so values at the back of the sphere fade out. This value is defined by:

float StretchAmt2 = 0.5;

float ln2 = max(0,ln + StretchAmt + StretchAmt2);
float lnn2 = max(0,lnn + StretchAmt + StretchAmt2 );
float alpha = saturate(ln2 + (lnn2 * lc));

float finalAlpha = height * alpha;


I wanted to have the alpha fade out after the point at which the sunset starts and this allows for that. Notice it is basically identical to the uv.x calculation it just offsets the ln and lnn values so that I can control when to start fading out the atmosphere. If StretchAmt2 is 0 then the atmosphere will be faded out by the horizon, a value of 0.5 is what is used in the pictures and it lets the atmosphere fade out about a quarter way around the back of the planet.



The surface shader uses a smaller 32x2 gradient map.


The top row corresponds to the atmosphere color and the bottom row corresponds to the sun color. Horizontal values correspond to the dot product between the surface position and the sun position.

Currently the pixel shader color output comes from this:

outColor = (diffuse * sunColor) + (atmosphereColor * min(AtmosphereTransparency,attenuation)) * sunColor;


The AtmosphereTransparency is how transparent I want the atmosphere to be, and presently I'm using 0.4 based on personal preference.

Lastly, the attenuation factor is based on the distance from the camera to the vertex being drawn and the code to calculate it is this:

float vd = min(AtmosphereHeight,VisibilityDistance);
outAttenuation = saturate((cameraToVertexDistance - VisibilityDistance)/ (AtmosphereHeight + vd));


VisibilityDistance is the minimum visibility distance so you can adjust it for personal taste. A large visibility distance will give the atmosphere a very thin impression and a small visibility distance would be a very dense atmosphere.

Here's a boring picture from the surface:


Next step is to put these shaders into Ogre and see how they look. Until then, don't forget to read the NVidia GPU Guide and ATI GPU Guides every night before you go to bed.