Game Development Community

dev|Pro Game Development Curriculum

Volumetric 3D Clouds (Art Files Included)

by Bryce · 07/06/2007 (5:33 pm) · 9 comments

Download Code File

First, create a blank code file called clouds.cs in your game's server/scripts directory. Paste the following into your file. I'll wait.

$cloudCount = 20; // Number of clouds in the sky in the Mission Area
$cloudDensity = 20/20; // How dense the billboards in the clouds are
$PuffMin = 0.4; // The Minimum scale of the billboards from my original model
$PuffMax = 2.6; // The maximum scale of the billboards from my original model
$PuffDist = 18; // Max distance the boards should be from the center. Increasing makes bigger clouds
$CloudAltitude = 225; // Altitude of Clouds
    // You should also increase $PuffMax and $PuffMin if you increase $PuffDist. Looks better.

new SimSet(CloudGroup);

function MakeBoards(%pos)
{
   for (%i = 0; %i < 6; %i++)
   {
      %a = getRandom(5);
      %b = getRandom(5);
      %c = getRandom(5);
      %vec = "0 0 0";
      %sub = getRandom(0,1);
      if (%sub $= 1)
         %vec = VectorSub(%pos, %a SPC %b SPC %c);
      else
         %vec = VectorAdd(%pos, %a SPC %b SPC %c);
      %boardPos = %vec;
      %sizeScale = getRandom($PuffMin,$PuffMax);
      %size = %sizeScale SPC %sizeScale SPC %sizeScale;
      %shape = "cloud" @ getRandom(1,2);
      %board = new TSStatic() {
         canSaveDynamicFields = "1";
         position = %vec;
         rotation = "1 0 0 0";
         scale = "1 1 1";
         shapeName = "~/data/shapes/clouds/" @ %shape @ ".dts";
         receiveSunLight = "1";
         receiveLMLighting = "0";//
         useAdaptiveSelfIllumination = "1";//
         useCustomAmbientLighting = "0";
         customAmbientSelfIllumination = "0";
         customAmbientLighting = "0 0 0 1";
         useLightingOcclusion = "0";//
      };
      %board.setScale(%size);
      MissionCleanup.add(%board);
      CloudGroup.add(%board);
   }
}
function MakePuffs(%pos)
{
   for (%i = 0; %i < ($cloudDensity * 20); %i++)
   {
      %a = getRandom($PuffDist);
      %b = getRandom($PuffDist);
      %c = getRandom($PuffDist/4); // Divide by four here so that the vertical offsets aren't too extreme
      %vec = "0 0 0";
      %sub = getRandom(1);
      if (%sub $= 1)
         %vec = VectorSub(%pos, %a SPC %b SPC %c);
      else
         %vec = VectorAdd(%pos, %a SPC %b SPC %c);
      MakeBoards(%vec);
   }
}
function BuildClouds()
{
   %W = getWord(MissionArea.area,2);
   %H = getWord(MissionArea.area,3);
   %west = getWord(MissionArea.area,0);
   %south = getWord(MissionArea.area,1);
   for (%i = 0; %i < $cloudCount; %i++)
   {
      %x = getRandom(%W) + %west;
      %y = getRandom(%H) + %south;
      %pos = %x SPC %y SPC $CloudAltitude;
      MakePuffs(%pos);
   }
}

Done? Now, open server/scripts/game.cs and add the following at the bottom of that big block of exec(""); statements:
exec("./clouds.cs");

Now, copy the four files included with the resource. don't paste them yet; Create a new folder in your data/shapes directory called clouds. Paste the four files inside this folder.

To spawn the clouds, open the console with the tilde (') key in-game. Enter in BuildClouds(); and give it a few minutes. Look up! Clouds! You can adjust the shapes and numbers with the six global variables at the top of the clouds.cs file.

Flaws:
1. They don't cast shadows on the terrain.
2. They can't move.
3. The billboards will show a faint outline when viewed from a distance.
4. They take a few minutes to complete drawing. Torque can't instantly load and render a massive amount of polygons, their textures, and their alpha channels.
5. It may take a hit on your framerate. Reduce $CloudCount to maybe 10 and $CloudDensity to 11/20. It won't look as realistic and there won't be as many clouds in your mission area, but you should be able to keep your precious frames!

How it Works:
Let's look at those functions going from the bottom up. All this may get confusing; bear with me if you actually care about what's going on. BuildClouds() uses a for loop which works with $CloudCount to create, by default, 20 points for clouds to spawn. When a point is made, it's handed off to MakePuffs().
The only visible things in these clouds are the billboards. The puffs are not the billboards. Positions for "puffs" are chosen within a random radius of the cloud position that BuildClouds() chose. Using a puff system makes more random shapes and figures out of the clouds. When a puff position is made, it's sent off to MakeBoards().
MakeBoards() creates 6 billboards with our clouds texture within a radius of the Puff position. Now all this gets repeated for all the clouds, all the puffs, and all the billboards.

WARNING!!!!! DO NOT SAVE YOUR MISSION FILE WHILE CLOUDS ARE IN THE AIR UNLESS YOU WANT TEN MINUTE LOAD TIMES!!!!!! If you need to save something, enter CloudGroup.delete() in the console, and the clouds will be all gone in a few seconds. Then save. BuildClouds() is something that should be called upon mission creation in your scripts, or whenever you think is necessary.

Happy Cloud-ing!

#1
07/07/2007 (6:12 am)
Huh. Found out that you cannot change the scale with the variable. Sorry about that, I'll see if I can find a way to fix that or provide new billboards.
#2
07/09/2007 (12:55 am)
I know this is in script, but you can always just use the Foilage Replicator and have some minor changes for it not to stick it on the ground, but have it in the air. This should be much faster than "few minutes".

I have an updated fxShapeReplicator resource that shows you how.
#3
07/09/2007 (1:57 pm)
Scale issue has been fixed.
@James: Yes, that would probably be way more efficient. This is for us demos out there :-)
#4
07/13/2007 (1:23 pm)
Thanks for this resource Bryce. I have a question though. My mission is outside of the mission area and I was wondering if there was a way to make it spread everywhere. Maybe it could be done like the precipitation where there is a box around the player where the precipitation is spawned.
#5
07/14/2007 (3:30 am)
Adam, you just answered your own question. Have you actually though of using the precipitation? It is very flexible and have many uses (Not only Weather)

This is done client side though. So I dont think everyone will se the same effects.
#6
08/20/2007 (1:08 pm)
Okay, scale issue has not been fixed. Anyone know how to scale billboards? I'm not seeing any effect.
#7
08/20/2007 (6:12 pm)
Maybe image pixel size?
#8
08/21/2007 (7:13 am)
@Adam: That wouldn't work for this purpose. In the code, it is try to add the billboards at randomly selected sizes by setting the scale. I've even tried doing that in the world editor by getting into one of the clouds I made, No change when I scale it.
#9
08/10/2008 (10:14 pm)
Looks good, have to try.