Archive for November, 2008

Atmospheric Scattering

As you may have noticed this will be the first entry of two.  I have implemented Sean O’Neils atmospheric Scattering as described in GPU Gems 2, and in the next few articles I hope to outline how I went about implementing it.

Sean O’Neils implementation is split into several parts, these are GroundFromAtmosphere, AtmosphereFromAtmosphere and SpaceFromAtmosphere as well as GroundFromSpace, AtmosphereFromSpace and SpaceFromSpace.

You can read Sean’s article on GPU Gems2 on the NVidia wesite, where they also provide full source code (although the source is for OpenGL and GLSL).

I’ve actually had quite a bit of trouble implementing this, partially because the variables and input constants are so ‘fiddly’, and also because of the maths involved, but I’m quite pleased with the results.

I would definately recommend setting up the variables so they can be changed at run-time.  Another thing to note is that the radius of the atmosphere has to be 102.5% times larger than the radius of the planet (m_fRadius * 1.025f).

I have found looking around various forums that everybody seems to NEED to use different settings in order to get the scattering working correctly, which seems a bit odd to me.  So, for your convience, here are the scattering settings which I am currently sending to the effect files:

m_fWavelengths = new float[3];

m_fWavelengths[0] = 0.640f;     // 640 nm for red
m_fWavelengths[1] = 0.560f;     // 560 nm for green
m_fWavelengths[2] = 0.455f;     // 455 nm for blue
m_fWavelengths[0] = (float)Math.Pow(m_fWavelengths[0], 4.0f);
m_fWavelengths[1] = (float)Math.Pow(m_fWavelengths[1], 4.0f);
m_fWavelengths[2] = (float)Math.Pow(m_fWavelengths[2], 4.0f);

// Rayleigh scattering constant
m_fKr = 0.0025f;
m_fKr4PI = m_fKr * 4 * (float)Math.PI;

// Mie scattering constant
m_fKm = 0.0010f;
m_fKm4PI = m_fKm * 4 * (float)Math.PI;

m_fSunBrightness = 16.0f; // Set the brightness of the sun.

m_fScaleDepth = 0.25f;

m_fg = -0.8f;

Hopefully after reading the article on GPU Gems, the above variables will be self explanatory (yeah right!).

I’ve yet to find something that looks good from both Space and from within the atmosphere (currently when within the atmosphere either the sky is too dark or the ground is :s),   I think this problem may be related to my heightmap information, but I’ll have to look further into it.  but at least playing with the variables is quite fun; and produces some interesting atmospheres.



Noise Part I

Noise is useful for many things, from texture generation for natural objects to heightmap generation.  This small article will explain how I use a psuedo-random  noise function to generate the planet heightmaps.

First, let me just outline what noise is and the different applications it can be used for.  Let’s consider the following:
5 + a = x.

Looking at the simple equation, you can see that we can control the output ‘x’ by supplying a specific variable ‘a’.  What’s even better is that even if you reset the computer, as long as the variable ‘a’ stays the same, you will always get the same output.  Now this may seem like a huge oversimplification, but that is effectively what Pseudorandom numbers’ are.  As long as we keep the seed the same ( our ‘a’ variable ), the outcome will always be the same.  This has many uses, especially if you are trying to create textures that are ‘natural’ looking, such as fire, clouds, wood, marble, and for me, terrain heightmaps.  This is great for planets, because I don’t need to save any heightmap information at all, as it is now all generated on the fly.
Perlin Noise

There are many different kinds of noise that can be used, with the most common probably being Perlin Noise.

The perlin noise function should return a value within the [-1,1] range.  When you pass in variables in small increments, then the results should also have only small changes.  If you pass in random values to the noise function, then you will get seemingly random values as output.

Perlin noise also works best if you take ‘samples’ of noise (called octaves) and modify the output by the amplitude (which decreases per octave of noise).  This works like follows:

float lfResult = 0;

float lfPersistance = 0.8f;
for(int i = 0; i < octaves; i++)
float freq = i * 2;
float amplitude = lfPersistence * i;
lfResult += PerlinNoise(xyz * freq) * amplitude;

You can see here that the result will be sampled and refined the desired number of times.

Here is a link to Ken Perlin’s original improved noise function, which can be easily converted to c#.

In the second part of the Noise articles I will show you have to use perlin noise to generate heightmaps using 3d coordinates, as well as the actual code 🙂

You can Read Noise Part II here,

Leave a comment