• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Fog Fading System

Level 13
Joined
May 24, 2005
Messages
609
Hello,

this is a small system, that adds smoothly fading fog to your map.

There are two versions:

v2.0:
- function based (change_fog function: changes to a new fog data within specified duration and given smoothness)
- more flexible than 1.3
- requires Vexorian's TimerUtils (included)

v1.3:
- this adds an automatic day/night cycle changing fog
- very easy to use, you just have to copy one trigger to your map and change the constant values to your needs
- if this is all you need, you can go with 1.3, else you should better use 2.0



JASS:
library FFS initializer Init requires TimerUtils
   
    // fog structure
    struct fog
        string name
        real start
        real end
        real density
        real red
        real green
        real blue
    endstruct
    
    globals       
        private constant integer FOG_STYLE = 0  // 0 = linear, 1 & 2 are expon. functions
        
        // These variables store the current values of the actual active fog
        private real fog_start = 0
        private real fog_end = 9999
        private real fog_density = 0
        private real fog_red = -1
        private real fog_green = -1
        private real fog_blue = -1
        
        // variables used for calculations
        private integer fog_fade_ticks
        private real fog_fade_amount_start
        private real fog_fade_amount_end
        private real fog_fade_amount_density
        private real fog_fade_amount_red   
        private real fog_fade_amount_green
        private real fog_fade_amount_blue
        
    endglobals
    
private function FFS_Change_Fog_Callback takes nothing returns nothing
    local timer t = GetExpiredTimer() 
    
    call SetTimerData(t, GetTimerData(t) - 1 ) 
    
    set fog_start   = fog_start   - fog_fade_amount_start
    set fog_end     = fog_end     - fog_fade_amount_end
    set fog_density = fog_density - fog_fade_amount_density
    set fog_red     = fog_red     - fog_fade_amount_red
    set fog_green   = fog_green   - fog_fade_amount_green
    set fog_blue    = fog_blue    - fog_fade_amount_blue
    
    call SetTerrainFogEx(FOG_STYLE, fog_start, fog_end, fog_density, fog_red, fog_green, fog_blue)

    if GetTimerData(t) <= 0 then
        call ReleaseTimer(t)
    endif

    // Below is a debug display that shows raw values each update tick
    // call DisplayTextToPlayer(GetLocalPlayer(),0,0, "FOG - start: "+R2S(fog_start)+", end: "+R2S(fog_end)+", dens: "+R2S(fog_density)+", R: "+R2S(fog_red)+", G: "+R2S(fog_green)+", B: "+R2S(fog_blue))
    
    set t = null
endfunction

function FFS_Change_Fog takes fog NewFog, real fading_duration, real period returns nothing
    local timer t
    
    // If no fog active, get color values
    if fog_red == -1 and fog_green == -1 and fog_blue == -1 then
        set fog_red = NewFog.red
        set fog_green = NewFog.green
        set fog_blue = NewFog.blue
    endif  

    // if duration 0 or less: instant change
    if fading_duration <= 0 then
        set fog_start   = NewFog.start  // Though, we need to update the variables
        set fog_end     = NewFog.end              
        set fog_density = NewFog.density
        set fog_red     = NewFog.red
        set fog_green   = NewFog.green
        set fog_blue    = NewFog.blue 
        
        call SetTerrainFogEx(FOG_STYLE, fog_start, fog_end, fog_density, fog_red, fog_green, fog_blue)
    else    
        set fog_fade_ticks = R2I( fading_duration / period )
        
        set t = NewTimer()
        call SetTimerData(t, fog_fade_ticks) 
          
        // Calculate the color amounts to be faded every tick
        set fog_fade_amount_start   = ( fog_start   - NewFog.start   ) / fog_fade_ticks
        set fog_fade_amount_end     = ( fog_end     - NewFog.end     ) / fog_fade_ticks
        set fog_fade_amount_density = ( fog_density - NewFog.density ) / fog_fade_ticks
        set fog_fade_amount_red     = ( fog_red     - NewFog.red     ) / fog_fade_ticks
        set fog_fade_amount_green   = ( fog_green   - NewFog.green   ) / fog_fade_ticks
        set fog_fade_amount_blue    = ( fog_blue    - NewFog.blue    ) / fog_fade_ticks
        
        call TimerStart(t, period, true, function FFS_Change_Fog_Callback)
    endif
    
    set t = null
endfunction

private function Start takes nothing returns nothing
    // This also might be a good place to create an initial fog
endfunction


//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterTimerEvent(t, 0.01, false)
    call TriggerAddAction(t, function Start)
endfunction

endlibrary

JASS:
library FFS initializer Init

    globals
        // I recommend tu use 1.0 here for final maps
        private constant real TIME_OF_DAY_SPEED = 10.0 // 10 makes a good timelapse for testing 
        
        private constant real SECONDS_PER_HOUR = 20.0 // Only change this, if you also change it in the game constants!
        private constant real START_TIME = 6   // Time at game start
        
        private constant integer FOG_STYLE = 0  // 0 = linear, 1 & 2 are expon. functions
        
        // Fog #1: noon time, 12 p.m.
        private constant real NOON_FOG_START = 1000 // Start distance of fog
        private constant real NOON_FOG_END   = 2500 // End distance of fog
        private constant real NOON_DENSITY = 1.0 // Fog density
        // Color values
        private constant real NOON_RED    = .9
        private constant real NOON_GREEN  = .7
        private constant real NOON_BLUE   = .4
        
        // Fog #2: night time, 24 p.m.
        private constant real NIGHT_FOG_START = 800 // Start distance of fog
        private constant real NIGHT_FOG_END   = 2000 // End distance of fog
        private constant real NIGHT_DENSITY = 1.0 // Fog density
        // Color values
        private constant real NIGHT_RED   = .6
        private constant real NIGHT_GREEN = .3
        private constant real NIGHT_BLUE  = 1.0
        
        // ============================================================
        // Don't touch the code below unless you know what you're doing
        // ============================================================
        
        // variables used by the system
        private real fog_density
        private real fog_start
        private real fog_end
        private real fog_red
        private real fog_green
        private real fog_blue
        private real fog_fade_ticks
        private real fog_fade_amount_start
        private real fog_fade_amount_end
        private real fog_fade_amount_density
        private real fog_fade_amount_red   
        private real fog_fade_amount_green
        private real fog_fade_amount_blue
        private real time_dif
    endglobals

private function Start takes nothing returns nothing
    // Time of day speed
    call SetTimeOfDayScale(TIME_OF_DAY_SPEED)

    // Set Starting Time
    call SetFloatGameState(GAME_STATE_TIME_OF_DAY, START_TIME )
    
    // Fading is processed every second
    // and we got 12 hours to fade between 2 fog colors
    set fog_fade_ticks = ( 12 * SECONDS_PER_HOUR ) / TIME_OF_DAY_SPEED
    
    // Density amounts to be faded every second
    set fog_fade_amount_start = ( NIGHT_FOG_START - NOON_FOG_START ) / fog_fade_ticks
    set fog_fade_amount_end = ( NIGHT_FOG_END - NOON_FOG_END ) / fog_fade_ticks
    set fog_fade_amount_density = ( NIGHT_DENSITY - NOON_DENSITY ) / fog_fade_ticks
    
    // Color amounts to be faded every second
    set fog_fade_amount_red = ( NIGHT_RED - NOON_RED ) / fog_fade_ticks
    set fog_fade_amount_green = ( NIGHT_GREEN - NOON_GREEN ) / fog_fade_ticks
    set fog_fade_amount_blue = ( NIGHT_BLUE - NOON_BLUE ) / fog_fade_ticks
    
    // Calculate Fog Color for starting time
    // between noon and midnight
    if START_TIME > 12 and START_TIME <= 24 then
        set time_dif = ( ( START_TIME - 12 ) * SECONDS_PER_HOUR ) / TIME_OF_DAY_SPEED
        set fog_start = NOON_FOG_START + fog_fade_amount_start * time_dif
        set fog_end = NOON_FOG_END + fog_fade_amount_end * time_dif

        set fog_density = NOON_DENSITY + fog_fade_amount_density * time_dif
        set fog_red = NOON_RED + fog_fade_amount_red * time_dif
        set fog_green = NOON_GREEN + fog_fade_amount_green * time_dif
        set fog_blue = NOON_BLUE + fog_fade_amount_blue * time_dif
    // after midnight, before noon
    else
        set time_dif = ( START_TIME * SECONDS_PER_HOUR ) / TIME_OF_DAY_SPEED
        set fog_start = NIGHT_FOG_START - fog_fade_amount_start * time_dif
        set fog_end = NIGHT_FOG_END - fog_fade_amount_end * time_dif
        set fog_density = NIGHT_DENSITY - fog_fade_amount_density * time_dif
        set fog_red = NIGHT_RED - fog_fade_amount_red * time_dif
        set fog_green = NIGHT_GREEN - fog_fade_amount_green * time_dif
        set fog_blue = NIGHT_BLUE - fog_fade_amount_blue * time_dif
    endif
    
    call SetTerrainFogEx(FOG_STYLE, fog_start, fog_red, fog_density, fog_red, fog_green, fog_blue)
    
endfunction

private function Timer takes nothing returns nothing
    local real time = GetFloatGameState(GAME_STATE_TIME_OF_DAY)
    
    // between noon and midnight
    if time > 12 and time <= 24 then
        set fog_start = fog_start + fog_fade_amount_start
        set fog_end = fog_end + fog_fade_amount_end
        set fog_density = fog_density + fog_fade_amount_density
        
        set fog_red = fog_red + fog_fade_amount_red
        set fog_green = fog_green + fog_fade_amount_green
        set fog_blue = fog_blue + fog_fade_amount_blue
    // after midnight, before noon
    else
        set fog_start = fog_start - fog_fade_amount_start
        set fog_end = fog_end - fog_fade_amount_end
        set fog_density = fog_density - fog_fade_amount_density
        
        set fog_red = fog_red - fog_fade_amount_red
        set fog_green = fog_green - fog_fade_amount_green
        set fog_blue = fog_blue - fog_fade_amount_blue
    endif
    
    // Apply fog values
    call SetTerrainFogEx(FOG_STYLE, fog_start, fog_end, fog_density, fog_red, fog_green, fog_blue)
    
    // Below is a debug display that shows raw values each update tick
    // call DisplayTextToPlayer(GetLocalPlayer(),0,0, "FOG - start: "+R2S(fog_start)+", end: "+R2S(fog_end)+", dens: "+R2S(fog_density)+", R: "+R2S(fog_red)+", G: "+R2S(fog_green)+", B: "+R2S(fog_blue))
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    local trigger t2 = CreateTrigger()
    call TriggerRegisterTimerEvent(t, 0.01, false)
    call TriggerAddAction(t, function Start)
    call TriggerRegisterTimerEvent(t2, 1, true)
    call TriggerAddAction(t2, function Timer)
endfunction

endlibrary
I hope, it might be useful for some people.
 

Attachments

  • fog_system.jpg
    fog_system.jpg
    17.2 KB · Views: 182
  • Fog_Fading_System_20.w3x
    27.8 KB · Views: 58
  • Fog_Fading_System_13.w3x
    20.7 KB · Views: 43
Last edited:
Level 13
Joined
May 24, 2005
Messages
609
Sure, code added.

I've set up a new version (2.0) that is function based and uses structs.

It provides a Change_Fog function, that changes to a new Fog within a specified duration and a given smoothness.

There is an idea in my mind having different fog layers. So that you could have an environmental basic fog and change different multiinstanceable fogs just as you like that fade in and out while keeping the basic environmental fog alive. Unfortunately, this seems to be a bit more complicated and I'm not even sure if it's worth the time or someone would really make use of it. Just imagine 12 players manipulating the map's fog with their spells.. a disco level maybe..

Anyway, I think the current version should be useful for a lot of purposes, as it is.

I've also kept the older 1.3, because for some people, the basic automatic day/night fog might be all they need and it's easier to use.
 
Last edited:
Top