Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Simple weather simulation

Discussion in 'World Building' started by protopop, Dec 9, 2019.

  1. protopop

    protopop

    Joined:
    May 19, 2009
    Posts:
    1,557
    I’m writing a very simple weather simulation and I’m wondering if anyone has any suggestions.

    What I have is basically 2 variables

    1) Temperature
    2) Humidity

    Amount of clouds in sky = percent humidity (100% humidity is cloud covered, 0% is clear sky)
    Humidity increases automatically over time (this simulated evaporation)
    Humidity = chance of rain/snow - at 100% it is guaranteed to rain/snow
    Amount of humidity at time of rain/snow indicates how strong the rainfall/snowfall will be
    Rainfall/snowfall reduces humidity
    Temperature below 0 + precipitation is snow
    Temperature above 0 + precipitation is rain
    Temperature is lower at higher altitudes and further north (it’s an open world game)

    I know there are a million factors in real weather but I want something very abstracted and simple and extensible. I think this will give a nice systemic feel that is somewhat natural.

    Do you have any suggestions or feedback about this? I appreciate any help.
     
    henners999 and JoeStrout like this.
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    If it's an open-world game, do you have just two variables for the whole world? Or do you divide the world into chunks somehow, and simulate them for each chunk? The latter would be an interesting enhancement. You could define some simple prevailing wind direction, and have humidity move from chunk to chunk in that direction.

    Also, the % chance of precipitation should be a function of humidity _and_ temperature. Higher where it's cold. This will produce more frequent, gentler rains/snow in colder chunks, and less frequent but more intense rains where it's warm.

    Combined with the prevailing winds, this would also tend to give you different weather on each side of a mountain range. The upwind side will be wet, as humid air coming in from the plains goes up, cools down, and drops its moisture. And on the down-wind side, it will be quite dry. (This is exactly the situation in the Rocky Mountains where I lived for many years; the western side is green and lush, while the eastern side is very dry.)
     
    protopop likes this.
  3. protopop

    protopop

    Joined:
    May 19, 2009
    Posts:
    1,557
    Thank you:)

    Its two variables for the whole world. They only differences I had planned, at least for now, are:

    Temperature gets colder in the north and warmer in the south
    Temperature gets colder at higher altitudes

    There are enough mountains and valleys that this can have an effect, and the world is 16kmx16km so there is enough north south movement to feel a difference between north and south.

    I like the idea of dividing the world into chunks, and what you mention about the mountains. The problem here is I am struggling to make the computer recognize landmasses and divid land based on that. The terrain is procedurally generated so I cannot hand place anything, and while I can have it recognize man made objects, its hard to "recognize" landscape features. So for now I don't think that's possible.

    But you do make me think I could divide the land mathematically into different climate zones in addition to the north/south high/low to add more flavour. Thats something I can do and I think its a good idea. I can procedurally assign various differences to each sector. I think for now for simplicity Im going to create these "climate zones" just as divided up land, and not based too much on geography and wind yet, partly because its easier, and partly because of that landscape recognition issue.

    My favorite part is what you said about temperature and humidity working together - do you mean:

    Chance of precipitation is higher where its cold (maybe humidity x 2 in colder area,so a 50% chance of snowing with 25% humidity in the cold)
    Chance of Precipitation is = humidity where warmer.(so a 25% chance of precipitation with 25% humidity in the warm)

    That would nicely mimic how warm air can hold more humidity. I like that a lot and its going right into my list:) I like anytime the very simple math still approximates somewhat the real world.


    Weather Model

    1) Temperature
    2) Humidity

    • Amount of clouds in sky = percent humidity (100% humidity is cloud covered, 0% is clear sky)
    • Humidity increases automatically over time (this simulated evaporation)
    • Humidity = chance of rain/snow - at 100% it is guaranteed to rain/snow
    • Amount of humidity at time of rain/snow indicates how strong the rainfall/snowfall will be
    • Rainfall/snowfall reduces humidity
    • Temperature below 0 + precipitation is snow
    • Temperature above 0 + precipitation is rain
    • Temperature is lower at higher altitudes and further north (it’s an open world game)
    • Chance of precipitation is higher where its cold (maybe humidity x 2 in colder area,so a 50% chance of snowing with 25% humidity in the cold)
    • Chance of Precipitation is = humidity where warmer.(so a 25% chance of precipitation with 25% humidity in the warm)
     
    JoeStrout likes this.
  4. neoshaman

    neoshaman

    Joined:
    Feb 11, 2011
    Posts:
    6,492
    MY take:
    A. Have 2 low freq noise encompassing the whole terrain, each coding either moisture or temperature. Make them scroll randomly and slowly.
    B. have a global gradient in the direction of cold/warm region
    C. have cloud noise
    D. have a low frequency flowmap noise, for wind direction

    The the procedure is,
    For each unit of your world or whatever you organize the weather metric:
    1. combine landscape altitude, with temperature and the global gradient to get the combined temperature map
    2. create a derivative (slope) map of the landscape
    3. Dot product the slope map direction with the wind direction, ignore anything above 0 (ie slope and wind goes in same direction), take the absolute of the result. You will know where cloud should accumulate (get stuck on mountain), modulate with altitude as you please (ie cut out below cloud level)
    4. combine the cloud accumulation map with the cloud noise (boost cloud) and the moisture map (boost cloud), modulate as you see fit with temperature.
     
    protopop likes this.
  5. protopop

    protopop

    Joined:
    May 19, 2009
    Posts:
    1,557
    Thank you, I like a lot of the implications in this.

    I like what you said about the ow frequency noise. I actually just learned to generate and read Perlin noise and I wa going tuba the weather changes on scrolling through that.

    But now I feel like its more natural to just have the humidity increase over time, and precipitate when it saturates, yielding snow or rain depending on the temperature.

    I think though that there is something to the low frequency noise yo mention, like maybe using it as an adjunct to oily the weather In unpredictable ways?

    Also the global gradient is being implemented. I have a basic colder the more north or warmer the more south. Its just a latitude check.

    From what I am reading about, and based on what you said, wind direction is a another major component of the weather. I think I have to leave it out for the moment because it would involve big additions to my cloud system, which are also procedurally generated but right now just have a wind direction in one direction. But I could see using a low frequency Mao to alter that in an update - its great food for thought.

    I don't know what a dot product is so I am lost after that, although a moisture map is something I've heard of In a lot of weather simulations.

    I think this kind fo reveals what will be missing most I my first simulator is a posture map and how that changes based on the geography. Im going to keep working on my geography recognizer and maybe this can make it into my weather round two.

    BTW this is where the weather system is going

    wild.JPG
     
  6. neoshaman

    neoshaman

    Joined:
    Feb 11, 2011
    Posts:
    6,492
    Moisture is basically humidity.

    Yeah I simulate that with the low frequency, so it does increase over time locally (by scrolling), somehow, when the noise gradient rise and fall in that point, it's low frequency so that the surface covered is big enough. INstead of scrolling you can sample a slice of a 3D noise, but since you are not well verse in custom perlin, and it seem unity's is 2D, scrolling is the best approximation, by combining multiple layer here, you could have more complex pattern too.

    Basically what the various map does is increasing the likelihood of that, based on circumstance (the boost). Such as more rain in altitude, more rain in a mountain side, etc ... you can add as many layer and stuff you want, for example have a map where certain part are always raining (for mood) OR mopre likely to rain by having more humidity, like forest or tropical forest map, have more region where it's less likely to rain like desert, industrial landscape, etc ....

    For example the wind map is a way to have more cloud in that aggregate around mountain peak, so that it rain more on one side than another. You can just use the altitude to do the same (which I do so that only high altitude create cloud), but it won't have a side, top will always have a cloud halo.

    I use a separate cloud layer to have visual, basically the humidity low frequency dictate where cloud density are, but the cloud tell you where the actual cloud are, and only the cloud can rain. But it's a humidity map too, it rain when cloud are dense enough.
    ------------------------------more explanation------------------------------------------------------
    The derivative is simply doing a pass that sample the 8 neighbors of a points and compute the direction of the slope (just create vector to each point from the center, then average them, flat part will have a 0 length vector).

    Dotproduct is function in
    https://docs.unity3d.com/ScriptReference/Vector3.Dot.html
    or
    https://docs.unity3d.com/ScriptReference/Vector2.Dot.html

    It takes two vectors (that you should normalized) and return a single number that tells you how much in the same direction they are (1 if they are in the same direction, 0 is they are perpendicular, -1 if opposite, and all in between)
    https://docs.unity3d.com/ScriptReference/Vector2-normalized.html

    We are looking for wind, of a certain altitude that goes against the slope, so we need negative number, we discard the positive (if positive then 0) and we take the absolute value (abs(result)) to turn that into a data in 0-1 range to mix with other data and noise.

    Wind map are basically just two noise, one encoding the X basis, and the other the Y, you take bothe value as input for a vector, then normalized it. You can scroll the two noise independently to have random wind pattern.
     
    henners999 and protopop like this.
  7. protopop

    protopop

    Joined:
    May 19, 2009
    Posts:
    1,557
    that KINDA goes over my head, but part of it makes sense. I already acmes a low res version of the Heightmap - I turn it into an 8x8 pixel image - and I don't think its too much of. stretch to turn this into a 64 tile kind of flow map with each tile having a vector, or do the same with a 4x4 or even 2x2 version. Thanks for the detailed explanation:)
     
  8. Roman_Keivan

    Roman_Keivan

    Joined:
    May 31, 2019
    Posts:
    21
    Hi @neoshaman I would like to implement this but my knowledge is not sufficient, I have studied perlin noise, to a basic level. I would be very grateful for help in the implementation of similar systems. at the level of pseudocode and concept

    Im use this method to generate perlin frequency:
    Code (CSharp):
    1. public float OctavePerlin(float x, float y, int octaves, float persistence)
    2.         {
    3.             float total = 0;
    4.             float frequency = 1;
    5.             float amplitude = 1;
    6.             float maxValue = 0;  // Used for normalizing result to 0.0 - 1.0
    7.             for (int i = 0; i < octaves; i++)
    8.             {
    9.                 total += Mathf.PerlinNoise(x * frequency, y * frequency) * amplitude;
    10.  
    11.                 maxValue += amplitude;
    12.  
    13.                 amplitude *= persistence;
    14.                 frequency *= 2;
    15.             }
    16.  
    17.             return total / maxValue;
    18.         }