Professional Documents
Culture Documents
Cloud Cover
Cloud Cover
Cloud Cover
The Cloud Cover program was written for the Educated Programming Contest
(now since closed down), on the subject of clouds. Against stiff competition from
various marshmallows and cottonwool, we (Matt and I) won. It was written in two
weeks flat, and coincided with our second year Maths revision, which may explain
how come we managed to fail so many exams. We were supposed to win £25, but
It's never turned up. Never mind.
I coded the realtime Perlin Noise to generate the clouds, and all the rest of
the graphics stuff, and Matt designed the overall program, and wrote the all
important inner loop which actually makes the clouds as good as they are.
Quite a few people have expressed an interest in the program, and asked
Requires DOS4GW how it was done. I promised to write an article on the subject, so here it is.
I intend to be a little vague in this article. This is for a couple of reasons, but mainly because I don't want
anyone to feel they have to follow our program exactly. The way we did it was just one possible way of many (and
not an especially good way at that). I would much rather people experimented themselves, rather than
just blatently copied our algorithms. So I shall go as far as telling you why we made each step, and how it was
based on real clouds, but probably won't give a lot of pseudocode.
General Information
We thought a good deal about what screen mode to render the clouds in, eventually coming to the
decision that an 8-bit mode would be very restrictive, and not really do the clouds justice. We settled,
eventually, for a truecolour (24-bit) mode, rather than Hicolour (16-bits). Firstly it would look better, and
secondly it would be easier/faster to program.
Not being a wizard, and being unable to communicate with the VESA 1.5 BIOS from within the 32-bit .EXE,
I initially had some trouble getting the program to autodetect the graphics card. Eventually I gave up, and
http://freespace.virgin.net/hugo.elias/models/m_clouds.htm (1 of 12) [25/10/2010 20:39:31]
Cloud Cover
decided to place the burden on the user. The trouble is this. Truecolour modes come in two flavours, 24-bit or
32-bit, but it's up to the graphics card which it supplies you with. It's possible to query the number of bits per
pixel, but I was having serious trouble calling the Real Mode VESA functions. In the end, we had to write two
inner loops, one to render to a 24-bit screen, and one to render to a 32-bit screen, and let the user
choose whichever one doesn't look like nonsense.
As I said before, this program was written in just two weeks, so it's a bit of a mess, and many things
could have been done a lot better. Everything is software rendered, and little attempt was made to optimise it.
It uses a good deal of look up tables, so the more cache you've got, the faster it'll run. However, I expect that
it would be possible to speed it up a great deal with 3D graphics hardware. It should even be possible to make
a version that allows you to look around freely. Anyway, I'll leave that up to you, and get on with the article.
About Cloudscapes
The first thing you should do if you're going to simulate clouds is to rush outside and look at some
real clouds. Make as many observations about the clouds as you can. However, if you're anything like me,
you're probably reading this at night, so I'll tell you some things about clouds.
All of these things happen in a real life cloudscape, and lots more besides. The more things we can
simulate, the more realistic our clouds will look.
Creating Clouds
If you have not already, I suggest you read the article on Perlin Noise.
Perlin Noise is great for creating cloudy type things, and can produce very realistic results. However, it is
far too slow to be used for a realtime graphics application like this, and a faster alternative must be found.
In the end, we settled for comopsition of four octaves of animated noise at various frequencies
and amplitudes.
Each octave (four in total) was calculated seperately, and they were all added together to create a
cloud texture. A sheet of noise was handled like this:
Smooth
Create an array of noise Resample it up.
it
It doesn't look a great deal like the cloud cover in the program yet, but it's getting
there. Importantly, observation number 5 (above) has not been satisfied. This entire
texture contains cloud to some extent. What we really want is areas of cloud, and areas of
totally empty sky.
function CloudExpCurve(v)
c = v - CloudCover
if c < 0 then c=0
c
CloudDensity = 255 - ((CloudSharpness ) *
255)
return CloudDensity
end function
Values of CloudCover between 0 and 255 give total cloud cover and empty sky respecitvely.
CloudSharpness controls how fuzzy or sharp the clouds are. Lower values give sharper,
denser clouds, and values closer to 1.0 give fuzzier, thinner clouds. Do not use values any
greater than 1.0.
You should agree that these look a lot more like clouds than the previous image.
So, we shall take our little square of clouds, and lay it over a sphere to represent the curvature
of the earth.
The camera is then positioned, not in the centre of the sphere, as this is not realistic. We live on
the surface of the earth, not in the centre. So, put the camera somewhere near the top of the sphere,
and point it at the clouds. Sorry that the diagram doesn't really show the correct position of the
camera, but it would have been too cluttered.
Colouring it in nicely
Right, now that the clouds are in place, they're going to need to be coloured like clouds. You might
be tempted to colour the sky blue, and the clouds white, and leave it at that. You're more than welcome, but
it would look lame.
Firstly, we'll render the backdrop to the clouds. The sky directly overhead is blue, but if you look into
the distance, you will see that it becomes a pale blue / grey.
Blue Sky
To do this, we needed the know the distance to the cloud dome at each pixel.
Knowing this information, we kind of bodged together an algorithm to produce a blue/
grey gradient across the sky. I'm sure you can figure out something similar, so I
won't go into detail here.
Since the light from the sun scatters in the atmosphere, you get a bright glow
around it. We modeled this glow with an exponential function. See there it is again.
Also, a constant value was added to light up the atmosphere to make the atmosphere
calculations work correctly.
This was stored as a 320x150x8bit texture map to be used later to make the
clouds glow near the sun.
In the pseudocode at the end of this page, I shall refer to this as the Glow
map.
Now, the blue sky and the glow were combined to create a bright glowing
atmosphere.
Since the camera never moved, this was stored as a 320x150x24bit texture
map.
In the pseudocode at the end of this page, I shall refer to this as the BlueSky
map.
Lens Flare
Lastly, a lens flare texture was created. You can use any lens flare map you
like. This one was created in much the same way as the glow map, but six lines were
added as well. The lines are the width of the sun, and fade off exponentially.
In the pseudocode at the end of this page, I shall refer to this as the
LensFlare map.
There are a couple of things going on every frame. Firstly, the cloud map must be animated. Then the
blue sky, sun glow, cloud map, and lens flare are all combined to create the final image.
If you read and understood my very brief explanation of how the clouds were created, then it is a
simple task to animate them. All you need to do it to animate the original noise maps.
You will remember that there are basically 4 noise maps. The ones we used were 32x32 pixels
each. Animating them is simply a matter of interpolating them from one noise map to another.
p2 = time
p1 = 1 - time
end loop
Any finally, you will have to actually take all this information (BlueSky, Glow, Lensflare and Clouds),
and combine them into an image. Now, we took a look at the original code, and we can't figure out what some of
it does, so we haven't included it here, for the sake of simplicity. This fragment of pseudocode will probably
not produce nice clouds straight off, so don't write to me complaining. It's only really meant as a guide to how
we achieved it, to point you in the right direction. You may have to do a lot of fiddling around and rearranging,
and lots of optimising. Basically, don't copy out this code. read it, try and figure out vaguely what's going on,
and write your own version from scratch.
function HazeExpCurve(d)
p = d2 / c
return Hazynessp
end function
Now, use the exposure function, since values of Red, Green and Blue may be quite
high
Red = ExposureFunction(Red)
Green = ExposureFunction(Green)
Blue = ExposureFunction(Blue)
end loop
References
LIGHT (in C++) ! : http://math1.uibk.ac.at/~werner/light/
Kim Pallister has written an article, based on this one, explaining some methods of using
hardware acceleration to speed up the rendering of clouds. However, I get the feeling that hardware acceleration
is not appropriate for all aspects of these clouds. I think that, until graphics cards get more advanced, or allow
you to program your own routines, some of this will still have to be done in software.
Ken Perlin's course notes from the GDCHardCore gamers workshop, San Francisco, Dec 9, 1999.
Return to the Good Looking Textured Light Sourced Bouncy Fun Smart and Stretchy Page.