Game Development Community

Day and Night Cycles in TGEA

by Matt Vitelli · 04/03/2008 (10:28 am) · 54 comments

Download Code File

First thing's first, this resource was written for TGEA 1.7 beta 2. Beta 1 has a problem initializing new shaders to the skybox class. Extract the engine files into the engine/source/terrain folder. Do a fresh recompile and then get ready to add some new code.

Copy SkyP.hlsl and SkyV.hlsl into your game/shaders folder.

Once you've recompiled, add the following code to your scriptsAndAssets/client/scripts/shaders.cs file:

new ShaderData( SkyShader )
{
   DXVertexShaderFile 	= "shaders/skyV.hlsl";
   DXPixelShaderFile 	= "shaders/skyP.hlsl";
   pixVersion = 2.0;
};

Next, copy scriptsAndAssets/server/scripts/DayNight.cs into the corresponding folder. Open game.cs and ender the following code below the other execs:

exec("./dayNight.cs");

Now, very important:

Two extra material lists must be added to your sky object. If they are not, your mission WILL NOT load up.

In your mission file, edit the sky object so that the material lists look like:
materialList = "scriptsAndAssets/data/skies/Skies/sky_day.dml";
sunsetList = "scriptsAndAssets/data/skies/Skies/sky_sunset.dml";
nightList = "scriptsAndAssets/data/skies/Skies/sky_night.dml";

Basically, materialList controls the mid-day sky, sunsetList controls the sunset sky, and nightList controls the night-time sky. Depending on your sun object's elevation, the sky's coloring will change based on the skyboxes.

Now that all is in place, you can use the DayNight function. The DayNight function uses a schedule to manipulate a sun object for a user-inputed duration of time. The function modifies the sun's azimuth and elevation. The change in elevation is statically set to add one or subtract one. The lower the change, the subtler the effect. Ideally, the change in azimuth should be twice as much as the change in elevation. (Because the total amount of elevation you can move is 180 and the total amount of azimuth you can move is 360 before going back to the point of origin.) Your sun's base elevation and azimuth should also keep this into account. To keep things simple, I set both of mine to zero so that when the function is called, it increases/decreases them at the same rate.

So, in the mission editor name your sun something along the lines of "GreatSun" or "MySun" and then call the dayNight function like this:

DayNight(GreatSun,50);

Where 50 is the time in milliseconds before the next sun update. I hope this resource is helpful to people. Really, a lot of interesting effects can be done with this. It is well-suited to handle an Oblivion-type of simulation using a persistent world. Since the time of day is locked to the sun's elevation, it's easy to save and adjust.
#21
09/13/2008 (7:38 am)
As indicated, this is currently broken 1.7.1. But I have found a fix that got it working again for me.

void Sky::renderSkyBox(..)
   .
   .
   .

                  PrimBuild::texCoord2f(texCoords[3].x,    texCoords[3].y);
                  PrimBuild::vertex3f(  renderPoints[3].x, renderPoints[3].y, renderPoints[3].z); 
               PrimBuild::end();
   .
   .
   .
               PrimBuild::vertex3f(mPoints[index+(3*val)].x, mPoints[index+(3*val)].y, mPoints[index+(3*val)].z);
            PrimBuild::end();
   .
   .
   .
}

Change to

void Sky::renderSkyBox(..)
   .
   .
   .

                  PrimBuild::texCoord2f(texCoords[3].x,    texCoords[3].y);
                  PrimBuild::vertex3f(  renderPoints[3].x, renderPoints[3].y, renderPoints[3].z); 
               PrimBuild::end([b]false[/b]);
   .
   .
   .
               PrimBuild::vertex3f(mPoints[index+(3*val)].x, mPoints[index+(3*val)].y, mPoints[index+(3*val)].z);
            PrimBuild::end([b]false[/b]);
   .
   .
   .
}

Edit: Also comment out the two GFX->setupGenericShaders( GFXDevice::GSModColorTexture );
Basicaly whats happening is the shaders are being turned off for rendering. Making these changes will turn them back on.
#22
09/24/2008 (1:29 am)
Matthew White:

Change
ShaderData *sd;
if(!Sim::findObject("SkyShader", sd))
{
   Con::errorf("no shader 'SkyShader' present!");
   return;
}
GFX->setShader(sd->shader);

To:
ShaderData *sd;
if(!Sim::findObject("SkyShader", sd) || !sd->getShader())
{
   Con::errorf("no shader 'SkyShader' present!");
   return;
}
GFX->setShader(sd->getShader());
#23
03/10/2009 (4:25 am)
Can anyone make this work on 1.8.1?
#24
03/17/2009 (2:19 pm)
Matt,

I implemented everything that was in the file. The one problem that I have is the DayNight(GreatSun,50); where does that go in the mission file. My other question is, is there a way to speed it up to test that it's working properly.

Thanks
#25
03/17/2009 (4:22 pm)
That needs to be called after your Sun object is created. I called mine in game.cs when the server started up, but you could call it at the very end of your mission file. To make it go faster, you could either increase the value that it increases/decreases from in dayNight.cs or you could call DayNight(GreatSun,50); at a lower value (ie DayNight(GreatSun,10))
#26
03/17/2009 (5:37 pm)
Here is my mission file

//--- OBJECT WRITE BEGIN ---
new SimGroup(MissionGroup) {
canSaveDynamicFields = "1";
Enabled = "1";
cdTrack = "2";
CTF_scoreLimit = "5";
musicTrack = "lush";

new ScriptObject(MissionInfo) {
canSaveDynamicFields = "1";
Enabled = "1";
desc0 = "UNDER CONSTRUCTION.";
descLines = "2";
name = "Infernal Solace";
};
new MissionArea(MissionAreaObject) {
canSaveDynamicFields = "1";
Enabled = "1";
Area = "-360 -648 720 1296";
flightCeiling = "300";
flightCeilingRange = "20";
bounce = "50";
locked = "true";
};
new Sky(GlobalSky) {
canSaveDynamicFields = "1";
Enabled = "1";
position = "0 0 0";
rotation = "1 0 0 0";
scale = "1 1 1";
materialList = "scriptsAndAssets/data/skies/sky_skybox.dml";
sunsetList = "scriptsAndAssets/data/skies/overcast/sky_overcast.dml";
nightList = "scriptsAndAssets/data/skies/storm/sky_storm.dml";
cloudHeightPer[0] = "0.349971";
cloudHeightPer[1] = "0.3";
cloudHeightPer[2] = "0.199973";
cloudSpeed1 = "0.0005";
cloudSpeed2 = "0.001";
cloudSpeed3 = "0.0003";
visibleDistance = "100000";
fogDistance = "100000";
fogColor = "0.6 0.6 0.7 1";
fogStorm1 = "0";
fogStorm2 = "0";
fogStorm3 = "0";
fogVolume1 = "0 0 0";
fogVolume2 = "0 0 0";
fogVolume3 = "0 0 0";
windVelocity = "1 1 0";
SkySolidColor = "0.113 0.148 0.215 0";
useSkyTextures = "1";
renderBottomTexture = "0";
noRenderBans = "0";
renderBanOffsetHeight = "10";
skyGlow = "1";
skyGlowColor = "0.356863 0.039216 0.376471 0";
windEffectPrecipitation = "1";
};
new sgSun(GreatSun) {
canSaveDynamicFields = "1";
Enabled = "1";
azimuth = "0";
elevation = "35";
color = "1 1 0.8 1";
ambient = "0.4 0.4 0.5 1";
castsShadows = "1";
useBloom = "1";
useToneMapping = "1";
useDynamicRangeLighting = "1";
DRLHighDynamicRange = "1";
DRLTarget = "0.8";
DRLMax = "1";
DRLMin = "0.5";
DRLMultiplier = "1.4";
bloomCutOff = "1.5";
bloomAmount = "1.2";
bloomSeedAmount = "0.5";
direction = "0 0.954268 -0.298953";
position = "0 0 0";
rotation = "1 0 0 0";
scale = "1 1 1";

};

//--- OBJECT WRITE END ---
#27
03/17/2009 (5:38 pm)
Here is my game.cs file where I put the DayNight()

function startGame()
{
if ($Game::Running) {
error("startGame: End the game first!");
return;
}

// Inform the client we're starting up
for( %clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++ ) {
%cl = ClientGroup.getObject( %clientIndex );
commandToClient(%cl, 'GameStart');

// Other client specific setup..
%cl.score = 0;
}

// Start the game timer
if ($Game::Duration)
$Game::Schedule = schedule($Game::Duration * 1000, 0, "onGameDurationEnd" );
$Game::Running = true;
// Start DayNight cycle
DayNight(GreatSun,3);
}

I lowered it to 3 to see if anything was happening.

I am not getting any type of cycling or changing from day to night.

I really need to get this working correctly. If you could help me I would really appreciate it.
#28
03/18/2009 (3:50 pm)
When you manually change the sun's elevation, does your sky change?
#29
03/18/2009 (4:17 pm)
I will try changing the elevation and get back to you as soon as possible.
#30
03/18/2009 (4:34 pm)
The shadows on my character are rotating around every second like it is in the code that I changed but nothing else is happening. The sky isn't changing nor is there shadows coming along the landscape.

Thanks again for all your help
#31
03/18/2009 (5:01 pm)
Ok. Changing the elevation is the first obvious way to tell. A value of 3 is pretty damn fast, even 50's pretty fast. This code doesn't handle shadows along the landscape, just textures on the sky. If you're using TGEA 1.7 or later, you'll need to make the change that Simon Duggan made above.
#32
03/18/2009 (8:45 pm)
I put the false in both statements and still nothing. The sun is cycling perfectly because the shadow around my character is rotating but still no changing of the sky boxes.
#33
03/19/2009 (10:51 pm)
Alright, I got something to happen now I just need to figure out how to polish it. Now I can see 5 sides to the skybox that are all different colors and they don't change. Has anyone had this problem? Can anyone help?
#34
03/19/2009 (11:29 pm)
Robert, have you checked your console to see if there are any errors? Did you make sure you added the Sky Shader? I've had no issues implementing this into 1.7 apart from the PrimBuild::end(false) change. (Not sure about 1.8, I don't use it.)
#35
03/19/2009 (11:31 pm)
Sweet, I finally got it to work. Thanks for your help Matt.
#36
03/19/2009 (11:32 pm)
I forgot to comment out the GFX-> and now it works great.
#37
03/29/2009 (9:07 pm)
Anyone got this working with TGEA 1.8.1 and can share the required changes? I have tried everything listed above and I only see a moving sun.
#38
06/16/2009 (5:01 am)
does anybody know why my sun would be moving but skyboxes not updating?
i added the false part in:
PrimBuild::texCoord2f(texCoords[3].x,    texCoords[3].y);  
                  PrimBuild::vertex3f(  renderPoints[3].x, renderPoints[3].y, renderPoints[3].z);   
                  PrimBuild::end(false);
and at the other part also.

and here is my mission file:
new Sky(GlobalSky) {
      position = "-1088 -928 0";
      rotation = "1 0 0 0";
      scale = "1 1 1";
      materialList = "scriptsAndAssets/data/skies/sky_skybox.dml";
      sunsetList = "scriptsAndAssests/data/skies/sky_storm.dml";
      nightList = "scriptsAndAssests/data/skies/afx_darksky.dml"; 
      cloudHeightPer[0] = "0.7";
      cloudHeightPer[1] = "0.3";
      cloudHeightPer[2] = "0.199973";
      cloudSpeed1 = "0.002";
      cloudSpeed2 = "0.001";
      cloudSpeed3 = "0.003";
      visibleDistance = "800";
      fogDistance = "500";
      fogColor = "0.4 0.4 0.4 1.0";
      fogStorm1 = false;
      fogStorm2 = true;
      fogStorm3 = false;
      fogVolume1 = "100 0 169.5";
      fogVolume2 = "150 170 250";
      fogVolume3 = "0 0 0";
      windVelocity = "0.2 0.2 0";
      windEffectPrecipitation = true;
      SkySolidColor = "0.64 0.148 0.215 0";
      useSkyTextures = true;
      renderBottomTexture = false;
      noRenderBans = false;
      skyGlow = false;
      locked = "true";
   };
   new Sun(GreatSun) {
      azimuth = "45";
      elevation = "35";
      color = "1.0 0.97 0.86 1.0";
      ambient = "0.18 0.18 0.2 1.0";
      castsShadows = true;
   };

Please help i am making a role playing game and this is a pretty big part of the process :)
#39
06/16/2009 (8:08 am)
Hi Bryce,

The sun is treated as a special light source in the code, which means you must use the sgSun rather than the regular sun class. (Not sure about T3D, but in TGEA sgSun is marked as a sgLight, while the regular sun isn't.) If you replace your sun in the mission with this, it should work:

new sgSun(GreatSun) {  
       azimuth = "45";  
       elevation = "35";  
       color = "1.0 0.97 0.86 1.0";  
       ambient = "0.18 0.18 0.2 1.0";  
       castsShadows = true;
       useBloom = "0";
       useToneMapping = "0";
       useDynamicRangeLighting = "0";
       DRLHighDynamicRange = "0";
       DRLTarget = "0.8";
       DRLMax = "1";
       DRLMin = "0.5";
       DRLMultiplier = "1.4";
       bloomCutOff = "1.5";
       bloomAmount = "1.2";
       bloomSeedAmount = "0.5";
    };
#40
06/16/2009 (2:22 pm)
Hi Matt,

I changed the sun but it still doesn't change the sky box :(

I am using tgea 1.7.1 with afx as well if that makes a difference, but i did make the code changes required to ge it working.