# Day and Night Cycles and Skybox Blending

I've been working on adding day/night cycles and random weather to my project using the Neoaxis engine. The day/night cycles itself is pretty simple, just rotating the "sun" light around the Y axis.

dayLength = 120; // How many real seconds to a game day
degreesPerSecond = 360f / dayLength;
sunY = 180f;  // Start on the horizon (6am)
currentHour = 6;
hourChange = 0;


Then on Tick for the sun

degreesPerTick = degreesPerSecond * Entity.TickDelta;

if(sunY >= 360f) {
sunY = 0f;
} else {
sunY += degreesPerTick;
}

hourChange += degPerTick;
if(hourChange >= 15f) {
currentHour++;
if(currentHour > 24) {
currentHour = 1f;
prevHour = 0f;
}
hourChange = 0f;
}

sun.Rotation = new Angles(0, sunY, 0).ToQuat();


So, that got the sun moving nicely through the sky lighting up things as expected and calculating the hours based on each hour moving 15 degrees through the rotation.

I then started looking at how to implement the changes to the color of the skybox in order to have the nice orange skys during sunrise/sunset, blue as the day progresses and to black at night. Getting the color to change was easy but for some reason I can't seem to work out how to make the color lerp progress properly.

// Skybox changes
if( (currentHour >= 20 && currentHour <= 24) || (currentHour >= 0 && currentHour <= 4) ) {

Engine.MapSystem.SkyBox.Instance.Color = skyNightColor;

} else if( currentHour >= 4 && currentHour < 7) {

Engine.MapSystem.SkyBox.Instance.Color = skyMorningColor;

} else if( currentHour >= 7 && currentHour < 10 ) {

Engine.MapSystem.SkyBox.Instance.Color = skyDayColor;

} else if( currentHour >= 10 && currentHour < 15 ) {

Engine.MapSystem.SkyBox.Instance.Color = skyDayColor;

} else if( currentHour >= 15 && currentHour < 18) {

Engine.MapSystem.SkyBox.Instance.Color = skyEveningColor;

} else if( currentHour >= 18 && currentHour < 20) {

Engine.MapSystem.SkyBox.Instance.Color = skyNightColor;

}


What I am a little stuck on at the moment is how to work out the lerpAmount for each of the relevant places. I guess I need to somehow look at the start rotation of the lerp (e.g. 180) and the end position (e.g. 210) and then work out how to represent the current position as a value between 0 and 1 to use as the lerp value.

Is that the appropriate way to achieve what I am looking to do?

Sure, you can do that. For instance, if you want the color to change from skyNightColor at 4:00 to skyMorningColor at 7:00, you could write some code like

if (currentHour >= 4 && currentHour < 7)
color = lerp(skyNightColor, skyMorningColor, (currentHour - 4) / (7 - 4));


The expression (currentHour - 4) / (7 - 4) remaps currentHour linearly to zero at 4:00 and one at 7:00.

This assumes that currentHour is a float variable that varies continuously from 4 to 7 as time goes on. Right now you have it as an integer variable that changes discretely, but it'll probably be more useful as a float. (You can always cast it to an int if you need the integer hour.) Or you can also write the lerps in terms of sunY, if you prefer.

One enhancement you may want to do, depending on how fast time can run in your game, is replace the linear interpolation by cubic splines. If time runs slowly, it probably won't be noticable, but if time runs quickly (e.g. hours pass in a few seconds) then the sudden shift from one lerp to another can be noticable. Cubic splines such as Catmull-Rom splines will smooth this out. The spline control points would be the RGB values for your colors.

• Thanks Nathan. I changed my code to calculate the hours as a float as suggested and implemented your solution. Working great. Thanks. I will be reading up about the Catmull-Rom splines out of interest but I plan to run time pretty slowly in my game so the lerp will probably be just fine for my needs at the moment. – Tim Jan 21 '14 at 5:01