Day and Night Cycles in TGEA
by Matt Vitelli · 04/03/2008 (10:28 am) · 57 comments
For the files: www.box.com/s/4cd4c05f5ef7b5e079c4 or shoot me an email if they're unavailable.
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:
Next, copy scriptsAndAssets/server/scripts/DayNight.cs into the corresponding folder. Open game.cs and ender the following code below the other execs:
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:
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:
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.
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.
#2
04/03/2008 (5:12 pm)
Hi Matt, I haven't tested this over a server, but I could see how that could pose a problem. Perhaps a better way would be to have a client-side variable that gets updated by the server. Seeing as only the sun's elevation is used to determine the sky's color, you could just update that variable and send it to the clients.
#3
I was just suggesting more deterministic approach to updating the sun position and sky based on initial seed values maintained by the server for those who might need it.
For example, instead of calling %sun.apply() on the sun object every 50 milliseconds the sun's information would be constantly updated on the server, and when a client connects a command would be sent that would tell the client the current position to set the sun as well as the update frequency, and then the client would be responsible for running its own schedule for continuing to update the appearance of the sky and sun from there.
04/03/2008 (5:24 pm)
Matt, my main concern was with updating every client several times a second with sun positionining data. For example every 50 milliseconds is sending out updates to every client on the server 20 times per second. That may be acceptable for some people in which case its not a problem.I was just suggesting more deterministic approach to updating the sun position and sky based on initial seed values maintained by the server for those who might need it.
For example, instead of calling %sun.apply() on the sun object every 50 milliseconds the sun's information would be constantly updated on the server, and when a client connects a command would be sent that would tell the client the current position to set the sun as well as the update frequency, and then the client would be responsible for running its own schedule for continuing to update the appearance of the sky and sun from there.
#4
sounds cool matt.
04/03/2008 (7:36 pm)
why on earth wouldn't you update it that often? I would think that you could do it client side and just have it run a check ever 60 seconds or so to maintain sync. I mean honestly how fast you gonna have it change from day to night.sounds cool matt.
#5
I added a couple of fxSunlights to this to see the sun and it actually does a zigzag in the sky then goes down. The shadows are changing too as they should be but not in the correct manner of course.
Additionally, the ambient lighting doesn't seem to update. Sure the shadows move, but the overall lighting of the sun is still there.
04/15/2008 (10:58 pm)
Well I managed to get this into 1.03 and it sems to work, mostly. The Skybox shaders work perfectly. I added a couple of fxSunlights to this to see the sun and it actually does a zigzag in the sky then goes down. The shadows are changing too as they should be but not in the correct manner of course.
Additionally, the ambient lighting doesn't seem to update. Sure the shadows move, but the overall lighting of the sun is still there.
#6
04/23/2008 (8:23 am)
yeah something like this will never work realistically as long as there are baked in shadows on the level. this is precisely why there are none in the newer engines like Crysis. all shadows are dynamic. Still it is a cool effort
#7
04/27/2008 (4:04 am)
@James: It should be noted that most MMORPGs for example still use baked shadows for terrain and buildings. They have shadows, but if you watch them as the day progresses you will see they are in the same location in the middle of the night as they would be at any time of day. So it depends on the genre.
#8
04/27/2008 (8:23 am)
This is true. Still, dynamic shadows greatly enhance the realism of the scene. Because of this, I'm working on a dynamic lightmap enhancement for TGEA. Currently I have working with a premade dts, but I'm working on getting it into Legacy Terrain.
#9
05/29/2008 (8:07 am)
Matt you rock! :-)
#10
My implementation works client side, however the server tracks the position of the sun (modified Celestial object) and sends an update to all clients every minute via a scripted trigger. Given that you have a day that lasts for longer than 20 minutes, the effect of the sun slightly fudging it's position on the client to correct it's "true" server position is virtually unnoticable even when looking for it.
We used this method as a framework for updating all dynamic environmental effects that require synchronization across all clients. One packet sent to all clients every minute that controls all environmental variables: wind speed and direction, cloud cover %, time of day, precipitation type and density, etc. Since all clients are updated with the same information on the exact same interval, the variance between clients is little more than that of normal server latency.
For what it's worth.... you'd be better served mashing DX10 into the TGEA graphics pipeline... utilize DX10's dynamic shadow mapping and gain all the other goodies in one fell swoop. I'm never a fan of reinventing the wheel when there's a much better wheel already out there.
06/03/2008 (6:17 pm)
Just some food for thought as to how to make day/night client/server capable and cheap...My implementation works client side, however the server tracks the position of the sun (modified Celestial object) and sends an update to all clients every minute via a scripted trigger. Given that you have a day that lasts for longer than 20 minutes, the effect of the sun slightly fudging it's position on the client to correct it's "true" server position is virtually unnoticable even when looking for it.
We used this method as a framework for updating all dynamic environmental effects that require synchronization across all clients. One packet sent to all clients every minute that controls all environmental variables: wind speed and direction, cloud cover %, time of day, precipitation type and density, etc. Since all clients are updated with the same information on the exact same interval, the variance between clients is little more than that of normal server latency.
For what it's worth.... you'd be better served mashing DX10 into the TGEA graphics pipeline... utilize DX10's dynamic shadow mapping and gain all the other goodies in one fell swoop. I'm never a fan of reinventing the wheel when there's a much better wheel already out there.
#11
06/04/2008 (7:58 am)
I could not agree more. But direct X 10 or any type of cutting edge graphics seems to fall on deaf ears around here.
#12
06/04/2008 (1:13 pm)
DirectX 10 just doesn't seem worth it to me. For starters, I don't have the hardware to work on a directX10 renderer and I doubt that the majority of consumers do either. I agree with you that DirectX 10 support would be nice and probably speed certain aspects of development up, however most of what DirectX 10 accomplishes can be done in DirectX 9 with some small work-arounds. What would really be great would be an implementation of the Rayleigh and Mie Scattering equations into the TGEA sky system. I've been working on and off on such a system, and I believe it would greatly enhance the amount of realism in TGEA's environments.
#13
GFX->setTextureStageColorOp(1, GFXTOPModulate);
to
GFX->setTextureStageColorOp(1, GFXTOPDisable);
This is using the TGEA MMO Kit so there could be something else causing this, but this seemed to resolve the issue and the sun is showing properly up.
I am also tieing some shading into the atlas terrain based on the sun being up or down and trying to sync that all back up with the game clock for the kit.
06/07/2008 (1:03 pm)
Just a note, I had to change this line in 1.03 otherwise it was overwriting the display of the Sun.GFX->setTextureStageColorOp(1, GFXTOPModulate);
to
GFX->setTextureStageColorOp(1, GFXTOPDisable);
This is using the TGEA MMO Kit so there could be something else causing this, but this seemed to resolve the issue and the sun is showing properly up.
I am also tieing some shading into the atlas terrain based on the sun being up or down and trying to sync that all back up with the game clock for the kit.
#14
Compiling...
sky.cpp
x:\torque\tgea_1_7_1\engine\source\terrain\sky.cpp(1005) : error C2248: 'ShaderData::shader' : cannot access private member declared in class 'ShaderData'
x:\torque\tgea_1_7_1\engine\source\materials\shaderdata.h(39) : see declaration of 'ShaderData::shader'
x:\torque\tgea_1_7_1\engine\source\materials\shaderdata.h(19) : see declaration of 'ShaderData'
Any thoughts on this?
07/08/2008 (6:14 pm)
GettingCompiling...
sky.cpp
x:\torque\tgea_1_7_1\engine\source\terrain\sky.cpp(1005) : error C2248: 'ShaderData::shader' : cannot access private member declared in class 'ShaderData'
x:\torque\tgea_1_7_1\engine\source\materials\shaderdata.h(39) : see declaration of 'ShaderData::shader'
x:\torque\tgea_1_7_1\engine\source\materials\shaderdata.h(19) : see declaration of 'ShaderData'
Any thoughts on this?
#15
07/08/2008 (6:56 pm)
Disregard, made a slight change to the engine in 1.7.1 in shader.h, setting the declaration to public.
#16
What happens is now the build is error free, the console brings no errors or warnings, but the system simply doesn't work.
The skybox looks like a solid cube, and the colours are static; not at all the effect you intended, I imagine.
Is there something I'm missing, or doing incorrectly?
MMW
07/09/2008 (8:09 am)
Nah, I am definitely still getting errors in 1.7.1.What happens is now the build is error free, the console brings no errors or warnings, but the system simply doesn't work.
The skybox looks like a solid cube, and the colours are static; not at all the effect you intended, I imagine.
Is there something I'm missing, or doing incorrectly?
MMW
#17
07/09/2008 (3:12 pm)
I've had this problem as well in the newer versions. I'm working on a fix.
#18
Where exactly does one place the "DayNight(GreatSun,50)" call to start the effect running? I was able to compile in the two sky files, make the changes to the script files as instructed, and clone and rename the skybox in "Skies", but I cannot seem to get the effect to start up correctly (i.e., the dawn is not coming up like thunder).
07/26/2008 (12:30 am)
A question, please:Where exactly does one place the "DayNight(GreatSun,50)" call to start the effect running? I was able to compile in the two sky files, make the changes to the script files as instructed, and clone and rename the skybox in "Skies", but I cannot seem to get the effect to start up correctly (i.e., the dawn is not coming up like thunder).
#19
08/22/2008 (9:33 am)
one stupid question, the skies, i mean the .dml i dont have it, and in the .zip they dont exist :(
#20
08/22/2008 (9:58 am)
Just wondering if the fix available for 1.7.1 now? 
Torque 3D Owner Matt Kronyak
RealmSource LLC
If that's the case, it seems like it would save some bandwidth in a client / server setting to have other variables on the sun object on the server side that are adjusted by the schedule, and when a client connects send a "StartDayNight" command that specifies the current values as well as the conditions for the local simulation and then running a local DayNight function on the client. To improve this further another idea would be to only compute the current sun settings on the server on a client connection event (or some other condition) based on the difference in time from the last and current triggering time divided by the duration value.
Also, does changing the sun properties on the server affect the mission data that is ghosted to the client, thereby requiring mission lighting to be re-computed on connection? In that case constantly modifying the sun would almost always require new clients that are connecting to re-light the mission.