Volumetric fog?

Blitz3D Forums/Blitz3D Programming/Volumetric fog?

Strider Centaur(Posted 2004) [#1]
So here I am working on this Underwater Demo, when I hit my first road block in blitz, traveling near the speed of light. I want to make the sea have that all so cool looking hazy feel using fog. However, Blitz does not seem to support this directly ( witch I always took for granted in OpenGL with Gui and Glut I guess.

Anyway, Ive created a simple Fake fog system useing 10 spheres at 10% opacity. Its fast on my system and looks good enough, not as smooth on the transitions between layes as Id like but does do well for water type affects, I imagine it would work for ground fog too. The desire to not directly manipulate each entities color based on distance was my main reason for making this.

	pfog1 = CreateSphere(8,p\pivot)
	pfog2 = CreateSphere(8,p\pivot)
	pfog3 = CreateSphere(8,p\pivot)
	pfog4 = CreateSphere(8,p\pivot)
	pfog5 = CreateSphere(8,p\pivot)
	pfog6 = CreateSphere(8,p\pivot)
	pfog7 = CreateSphere(8,p\pivot)
	pfog8 = CreateSphere(8,p\pivot)
	pfog9 = CreateSphere(8,p\pivot)
	pfog10 = CreateSphere(8,p\pivot)


	FlipMesh pfog1
	FlipMesh pfog2
	FlipMesh pfog3
	FlipMesh pfog4
	FlipMesh pfog5
	FlipMesh pfog6
	FlipMesh pfog7
	FlipMesh pfog8
	FlipMesh pfog9
	FlipMesh pfog10
	pfogtex = LoadTexture ("textures\fog.bmp")
	EntityTexture pfog1, pfogtex
	EntityTexture pfog2, pfogtex
	EntityTexture pfog3, pfogtex
	EntityTexture pfog4, pfogtex
	EntityTexture pfog5, pfogtex
	EntityTexture pfog6, pfogtex
	EntityTexture pfog7, pfogtex
	EntityTexture pfog8, pfogtex
	EntityTexture pfog9, pfogtex
	EntityTexture pfog10, pfogtex

	; since the alphas tend to add up we try to keep them change at each dispance the same
	; finally reaching opaque at the tenth box
	EntityAlpha pfog1,.10
	EntityAlpha pfog2,.10
	EntityAlpha pfog3,.10
	EntityAlpha pfog4,.10
	EntityAlpha pfog5,.10
	EntityAlpha pfog6,.10
	EntityAlpha pfog7,.10
	EntityAlpha pfog8,.10
	EntityAlpha pfog9,.10
	EntityAlpha pfog10,.10
; scale the spheres to cover the range we need
	ScaleEntity pfog1,15,1,1
	ScaleEntity pfog2,15,5,5
	ScaleEntity pfog3,15,10,10
	ScaleEntity pfog4,15,15,15
	ScaleEntity pfog5,20,20,20
	ScaleEntity pfog6,25,25,25
	ScaleEntity pfog7,30,30,30
	ScaleEntity pfog8,35,35,35
	ScaleEntity pfog9,45,45,45
	ScaleEntity pfog10,55,55,55
	



The fog texture is just a 256x256 BMP file of solid dark blue.

Yea I know I could have used a type or array, but this is so simple I don't see anyone having trouble with it.

I started with boxes to try and keep poly count down, but it looked bad, so I switched to spheres. If you dont want eveything shaded by the first sphere either rescale it or just do away with it.

Also, to get varios effects of fogging its all about the scaling, I susgest in most cases that you keep the Y scale much tighter between layers than I do here.

A full demo will be uploaded soon.


Strider Centaur(Posted 2004) [#2]
Heres the hole thing so far, just comment out the texture loads or supply your own.


; The Aquatic Demo, a demo to experiment with underwater effects.
;
; Would like to grow this into a mer based game, in this demo the goals are:
;
; 1) Creat a pleasing underwater experiance in sight, sound and movement
; 2) Support multiple player access to allow it to be shared
; 3) incorperate the 3D tile system based using a 2D tile system to layout the sea floor
; 4) for comparison, try alternate terrain builds using other tool.
; 5) experement heavily with strong lighting affects and LOD in relation to intensity and fog.
; 6) create models and animation sequances that match the movement to produce a smooth integrated feel.
; 7) Get pats on the back from my Blitz Pals.  Uhh, huh, thats it yea.  LOL
;
;

; Keeping it simple
; Where possible I will beg barrow and umm barrow as mutch from other peoples work ( with their permisions ) as possible
; I will also use the refinement process for development, that is, first get it all working, then make it look good and
; optimize as needed.


; Step 1  the Player type needed for the Network thingy
Type pdata
	Field playerID		; The NetID of this player
	Field name$			; the Name of this player shown over head.
	Field x#			; Now if Blitz supported Vectors this would be so much easier
	Field y#			; these are movement variable not positional ones
	Field z#
	Field wx#			; world postion These on the otherhand, are postional variables
	Field wy#			
	Field wz#
	Field yaw#			; ya know this 3D world stuff is gona really take some experimenting to get these right
	Field pitch#
	Field roll#
	Field speed# 		; yea see, its like this, things underwater do not instantly start and stop like in most FPSs.
	Field accell#		; so we need to know how fast things can speed up
	Field decell#		; and slow down
	Field mesh			; give you one guess what goes here, if you guess the mesh Entity handle, you'd be right.
	Field pivot			; used for movemement
End Type

Type timer
	Field timerID
	Field tdelay
	Field lasttime
	Field mode			; 0 off, 1 + number of times to triger, -1 allways on.
	Field triggered		; 1+ = number of times triggered, should be cleared to 0 when tested. max value will never exceed 32000
End Type 
; So Im going to make some assumptions on screen size and modes here, I like windowed
; but if you one of those full screen types, go ahead, change it.
; Why globals, Well sure I can get this info from inside blitz, but to set the data this is how I like to do it.
; no constants this time, its nice to be able to define defaults that can be changed.  :)
Global viewwidth = 800
Global viewheight = 600
Global viewmode = 2
Global viewcolors = 32


;Never sure if this is needed or not, but I do it anyway
Global ppivot
Global pcammera
Global pfog1
Global pfog2
Global pfog3
Global pfogtex
Global plight1
Global plight2
Global surfacedownplane
Global surfaceupplane
Global seafloorplane
Global surfacedowntex
Global surfaceuptex
Global seafloortex

;Timers?  We don't need no stinking timers!  Well maybe just a few
;

					
Global fratetimer   ; this will hold the frame rate timer handel
Global frdelay = 1000/60	; this is sort of 60FPS  adjust to taste

Global gamestatus	; used to track the return status codes from functions

; Main Loops should be very clean, no uneeded logic, no variables that are not predefined above
; easy and clean.
;============= MAIN GAME LOOP =================
gamestatus = Init_Game()		; make a non-stop timer for FPS and game controle
If gamestatus = 1 Then RuntimeError ("Could not INITIALIZE GRAPHICSMODE")
If gamestatus = 2 Then RuntimeError ("PDATA type does not exist, not created")

Init_World("demo")				; Load the game world sceen data, we make the basice in init_game, this loads
								; models for details in terrain and sturctures.
fratetimer = Init_Timer( frdelay, -1 )
While Not KeyHit(1)
	If TimerCheck(fratetimer) Then 
		InputUpdate()
		;NetHandler()
		CollisionHandler()
		MovementUpdate()
		RenderUpdate()
		;NetUpdate()
	EndIf
	;AIUpdate()
Wend

End

;=============  END MAIN GAME LOOP ============



; you will find Im function crazy, I think a game or any code should have a main section of almost purely function
; calls and the main game loop and thats it.

; Setup all the pre demo stuff and screen modes
Function Init_Game%()
	AppTitle " The Merfolk Demo "
	If Not GfxMode3DExists(viewwidth, viewheight, viewcolors) Then Return (1)
	Graphics3D viewwidth, viewheight, viewcolors, viewmode
	SetBuffer BackBuffer()
	
	;creat the first pdata so we can load up the player info
	p.pdata = New pdata
	If p = Null Then Return (2)

	; ok lets set up the player pivot parent and camera ( going FP here )
	p\pivot = CreatePivot ()
	pcammera = CreateCamera(p\pivot) 
	
	;light?  Yea the spot light its so handing to see things.
	; but Blitz is do kind to give us a default one we simply need to change the color
	; nice semi-dark blue for now
	CameraFogMode pcammera,1
	CameraFogColor pcammera, 0,0,100
	CameraFogRange pcammera, 1,55			; about 100 meters
	
	; Now we all know that the cammera fog is not Volumetric so we will emmulate this with a few large boxes.
	; how this works is they are centered on us, and we flip them so we can see the texture on them from the inside.
	; we then set the alpha levels from low to high as they radiate out from us.  We use 10 such bozes with a .10 alpha
	; each, the first box in placed right in front of the cammera, so everything is shaded 10% by that one, the others
	; stretch out from there till 100% opacity is reached at max range.  We can increase viewing range by simple
	; decreasing the alpha as needed.  Above water is would be reasonable to all layers to 0 opacity, or for those fogy
	; surfuce days, the first 3 or so to 0 and the rest to propper levels for the fog desired.
	;pfog1 = CreateCube(p\pivot)
	;pfog2 = CreateCube(p\pivot)
	;pfog3 = CreateCube(p\pivot)
	;pfog4 = CreateCube(p\pivot)
	;pfog5 = CreateCube(p\pivot)
	;pfog6 = CreateCube(p\pivot)
	;pfog7 = CreateCube(p\pivot)
	;pfog8 = CreateCube(p\pivot)
	;pfog9 = CreateCube(p\pivot)
	;pfog10 = CreateCube(p\pivot)
	
	pfog1 = CreateSphere(8,p\pivot)
	pfog2 = CreateSphere(8,p\pivot)
	pfog3 = CreateSphere(8,p\pivot)
	pfog4 = CreateSphere(8,p\pivot)
	pfog5 = CreateSphere(8,p\pivot)
	pfog6 = CreateSphere(8,p\pivot)
	pfog7 = CreateSphere(8,p\pivot)
	pfog8 = CreateSphere(8,p\pivot)
	pfog9 = CreateSphere(8,p\pivot)
	pfog10 = CreateSphere(8,p\pivot)


	FlipMesh pfog1
	FlipMesh pfog2
	FlipMesh pfog3
	FlipMesh pfog4
	FlipMesh pfog5
	FlipMesh pfog6
	FlipMesh pfog7
	FlipMesh pfog8
	FlipMesh pfog9
	FlipMesh pfog10
	pfogtex = LoadTexture ("textures\fog.bmp")
	EntityTexture pfog1, pfogtex
	EntityTexture pfog2, pfogtex
	EntityTexture pfog3, pfogtex
	EntityTexture pfog4, pfogtex
	EntityTexture pfog5, pfogtex
	EntityTexture pfog6, pfogtex
	EntityTexture pfog7, pfogtex
	EntityTexture pfog8, pfogtex
	EntityTexture pfog9, pfogtex
	EntityTexture pfog10, pfogtex

	; since the alphas tend to add up we try to keep them change at each dispance the same
	; finally reaching opaque at the tenth box
	EntityAlpha pfog1,.10
	EntityAlpha pfog2,.10
	EntityAlpha pfog3,.10
	EntityAlpha pfog4,.10
	EntityAlpha pfog5,.10
	EntityAlpha pfog6,.10
	EntityAlpha pfog7,.10
	EntityAlpha pfog8,.10
	EntityAlpha pfog9,.10
	EntityAlpha pfog10,.10

	; scale the boxes to cover the range we need
	ScaleEntity pfog1,15,1,1
	ScaleEntity pfog2,15,5,5
	ScaleEntity pfog3,15,10,10
	ScaleEntity pfog4,15,15,15
	ScaleEntity pfog5,20,20,20
	ScaleEntity pfog6,25,25,25
	ScaleEntity pfog7,30,30,30
	ScaleEntity pfog8,35,35,35
	ScaleEntity pfog9,45,45,45
	ScaleEntity pfog10,55,55,55
	
	
	; more light out there in front of us for that cool distant glow feel
	; Thats right our water will be a magical happy glowing kind of place
	; not very realistic but hey we are merfolk, we can do this kind of stuff.  :)
	plight1 = CreateLight(2,p\pivot)
	LightColor plight1, 0,100,100
	LightRange plight1, 150
	PositionEntity plight1, 0,20,200
	
	; and some more light, placed at point of view
	plight2 = CreateLight(3,p\pivot)
	LightColor plight2, 0,50,50
	LightRange plight2, 200.0
	
	; Ok we need the Sea, well 3 planes, yea we will make a sky orb and use it when you get close to surface
	; The top plane is the furface of the water as seen from above the water, hey we want to jump out of water too.
	; this one is less transparant than the one from looking up.
	surfacedownplane = CreatePlane()
	PositionEntity surfacedownplane, 0,0.01, 0 ; minor adjustment over plane below it.
	surfacedowntex = LoadTexture("textures\water.bmp")
	EntityAlpha surfacedownplane,.75
	EntityTexture surfacedownplane, surfacedowntex
	
	; The next one down is the bottom a mostly transparant( hey isn't that translucent? ) plane that we can see the
	; sky throuh.  Also know that Fog is turned off when we are less than 100 meters from the surface, well in reality
	; the closer we get the further the max range of the fog raises so its still there, when we are very need the surface
	; it will extend well beyond the skysphere and thus appear non-present.  Ahh, you ask what about if you look down while 
	; near the surface?  Well silly, since your location in the sphere is very near the upper side of it, the fog will 
	; still be blocking the extreams of the toward the hurizon and bellow the surface, Genius I know, but as a friend 
	; said, why not just use a 5 sided sky box centered on the character and placed above the water? To witch I said, "umm".
	;surfaceupplane = CreatePlane()
	;PositionEntity surfaceupplane, 0,0,0
	;surfaceuptex = LoadTexture("texture\water.bmp")  ; in future will be using 2 sepereate texture for up/down
	;EntityAlpha surfaceupplane, .30
	;FlipMesh surfaceupplane
	; of coarse we cant flip planes, what was I thinking, no big deal will simply make a surface mesh, that way I can 
	; animate it with waves and stuff anyway.  So there.
	
	; Finally the sea floor, yea, its a big flat sea with a sandy texture, dont like it?  Me either so will be adding
	; stuff down there real soon.
	seafloorplane = CreatePlane()
	PositionEntity seafloorplane, 0, -300, 0
	seafloortex = LoadTexture("textures\seafloor.bmp")
	EntityTexture seafloorplane, seafloortex
	
	;initialize the skybox, using my friend idea, see also move_skybox 
	;init_skybox()
	
	;Set the starting info
	; sence we don't have spawn points in our wourld yet we get the good ole 0,250,0
	p\wx# = 0.0
	p\wy# = -299.0	;we starting out at close to 300 meters down, hows that For working under preasure?  
	p\wz# = 0.0
	p\yaw# = 0.0
	
	
	;p\mesh = LoadAnimMesh("merperson1.3ds", ppivot);  Hey when I have a model I get to uncomment this.  :)
	
	
	; position the player in starting location.
	PositionEntity p\pivot, p\wx, p\wy, p\wz
	;PositionEntity pcammera, p\wx, p\wy, p\wz
	;PositionEntity pfog1, p\wx, p\wy, p\wz
	;PositionEntity pfog2, p\wx, p\wy, p\wz
	;PositionEntity pfog3, p\wx, p\wy, p\wz
	;PositionEntity pfog4, p\wx, p\wy, p\wz
	;PositionEntity pfog5, p\wx, p\wy, p\wz
	;PositionEntity pfog6, p\wx, p\wy, p\wz
	;PositionEntity pfog7, p\wx, p\wy, p\wz
	;PositionEntity pfog8, p\wx, p\wy, p\wz
	;PositionEntity pfog9, p\wx, p\wy, p\wz
	;PositionEntity pfog10, p\wx, p\wy, p\wz

	
	Return (0) ; if not true our function was completed without a problem
End Function
	
;setup collisions
Function Init_Collisions()

End Function

; Handle collisions	
Function CollisionHandler()
	
End Function

; get input from player
Function InputUpdate()
	p.pdata = First pdata
	p\yaw# = 0	; lets make sure we only move if a key is down 
	p\pitch# = 0;
	p\roll# = 0;
	p\z# = 0;
	p\y# = 0;
	p\x# = 0;
	If KeyDown( 203 ) Then
		p\yaw#=+1
		If seq <> jump Then
			new_seq = idle
		End If
		moving=True
	EndIf
	If KeyDown( 205 )  Then 
		p\yaw#=-1
		If seq <> jump Then
			new_seq = idle
		End If
		moving=True
	EndIf 
	If KeyDown( 208 ) Then 
		p\z#=-0.4
		If seq <> jump Then
			new_seq = walk
		End If
		moving=True
	EndIf
	If KeyDown( 200 ) Then
	  	p\z#=+0.4
		If seq <> jump Then
			new_seq = walk
		End If
		moving=True
	EndIf 
	If KeyDown( 57 ) Then
		p\y# =+0.4
	EndIf

End Function


; Basicly set up BlitzPlay the totally awesome network lib for Blitz.  Woot BP rocks
; Mode is either Host 0 or client 1
; port is the port to listen/connect on
; players is the max number of players
; ServerIP is the IP address of the game server(host) defaults to localhost at 128.0.0.1
; return status codes 0 if all went ok.
Function Network_Init%( mode%, port, players%, ServerIP$ = "128.0.0.1" )


	Return (0)
End Function

; update the network, basicly sends network data and recieves it from network
; while I use BlitzPlay for this, I use my own wrappers so the netcode 
; stays independant of the game, incase I want to use something else later.
; returns 0 if all went as planed or errorcode otherwise.
Function NetUpdate%()

	Return (0)
End Function

;The heart of the network portion of the demo/game
; This function handles all incomming messages and sorts/stores/posts the data to the right variables used
; by other functions like ChatUpdate, MovementUpdate and so forth.
Function NetHandler%()

	Return (0)
End Function

; Called after input and NetHandler this function updates all movable objects in the world space
; basicly cycles through the pdata's and other similar types and adjust there postion to speed ratio
; based on the timer datas for each object. This will position all players in the game/demo
Function MovementUpdate()
	For p.pdata = Each pdata
		TurnEntity p\pivot, p\pitch#, p\yaw#, p\roll#
		MoveEntity p\pivot, p\x#, p\y#, p\z#
		p\wx# = EntityX(p\pivot)
		p\wy# = EntityY(p\pivot)
		p\wz# = EntityZ(p\pivot)
	Next	
End Function

; This function calles all the updateworld and render functions, also handles the HUD information
Function RenderUpdate()
	UpdateWorld
	RenderWorld
	Draw2DHUD()
	Flip
End Function


;Create a new timer useing the Delay provided
; the mode is -1 non-stop, 1+ count down timer, 0 stopped( usually cause countdown has happened )
; use countdown for cases where you want effects to last for a specific time but dont need to keep
; updating the effect after that.  powerup durations for example durations for example.
; return the timer id from the timer type created	
Function Init_Timer%(timeDelay%, mode ="-1")
	utimer = 0
	For t.timer = Each timer
		If t <> Null Then 
			tiemid = t\timerID
			If timerid > utimer Then utimer = timerid   ; lets get the highest timer ID so far 
		End If
	Next
	utimer = utimer + 1; lets make this ID one greater than the highest ID so far and thus unique
	t.timer = New timer
		t\timerID = utimer
		t\tdelay = timeDelay
		t\lasttime = MilliSecs ()
		t\triggered = 0
	
	Return t\timerID
End Function

;Checks the a given timer( by ID ) to see if it has triggered, clearmode 0 (default) will clear the timer if trigger and
; if so return the number of times it triggerd since last check. Setting the clearmode to none zero will 
; simply return the timer triggered data and not clear it, regardless of if it triggered or not.
; the default is to clear the trigger data if triggered.
Function TimerCheck%(timerID%, clearmode = 0)
	For t.timer = Each timer
		If tiemrID% = t\timerID Then
			If t\triggered Then
				ttemp = t\triggered
				If clearmode = 0 Then t\triggered = 0
				t\lasttime = MilliSecs()
				Return (ttemp)
			End If
		End If
	Next
	Return (-101)		;Invalid trigerID
End Function

; loop through all timers and update there triggered stats
Function TimerUpdate()
	For t.timer = Each timer
		If t\mode > -1 Then									; is it non-stop or other?
			If t\lasttime + t\tdelay > MilliSecs() Then    ; did the time expire?
				t\triggered = t\triggered + 1				; yep, so increment triggered
				t\lasttime = MilliSecs()					; reset timer.
				If t\mode > 1 Then 					; its a count down timer amd it hasnt counted down yet?
					t\mode = t\mode -1				; yep, so count down
					If t\mode < 0 Then t\mode = 0   ; prevent it from any chance of crossing over into a non-stop timer
				End If
			End If
		Else 												; so its a non-stop timer
			If t\lasttime + t\tdelay > MilliSecs() Then    ; did the time expire?
				t\triggered = t\triggered + 1				; yep, so increment triggered
				t\lasttime = MilliSecs()					; reset timer.
			End If
		End If
	Next		
End Function

; TimerResetMode lets you change the mode or count of a timer, so that for instance you can restart a stopped
; countdown timer.  It does no other testing, so if you should use TimerCheck before a reset if you are interested
; in the timer status before the reset.
Function TimerResetMode( id%, modecount% )
	For t.timer = Each timer
		If id = t\timerID Then 
			t\mode = modecount
			Return
		End If
	Next
End Function

; Reset the delay setting of a timer, used for fine tuning a timer at run time, like when else silly?
; ID is the timer ID and tdelay is the delay for the timer.  It does no other timer opperation, see also TimerResetMode	
Function TimerResetDelay( id% , tdelay% )
	For t.timer = Each timer
		If id = t\timerID Then
			t\tdelay = tdelay
			Return
		EndIf
	Next
End Function


; this handles the zone specific data for this area of the world, it loads all models and terrains
; repositions player to the propper zone entry point in relations to players present zone settings
; sets all lighting and rendering options and updates the network to let other players know that this 
; player has left one zone and entered the one specified, including the new players starting location.
; of coarse in the Demo there is only one zone, but I figured what they heck, better to plan ahead.
; The data read comes from the zone file, named __zonename__.zon.  These files are located in the zones directory
; there format???? well to be done still.  But probably very INI in format.
Function Init_World( zone$ )
	zonefile$ = "zones\"+ zone$ +".zon"
	
	; this is just a referance cube set out there in the sea
	cube = CreateCube ()
	ScaleEntity cube ,5,5,5
	PositionEntity cube,0,-295,20
	cube1 = CreateCube()
	ScaleEntity cube1, 3,3,3
	PositionEntity cube1, 3,-250,30
	
End Function


; draws some debugging data to screen.  Will be using surfaces in 3D later, but for now this will do.
; called by RenderUpdate
Function draw2DHUD()
	linenum = 0		
	For p.pdata = Each pdata
		linenum = linenume+1
		Text 10,10+(FontHeight()*linenum),"Player: "+p\name+" at location: x:"+p\wx# +" y:"+p\wy# +"z:"+p\wz#
	Next
End Function


As for spelling, me? never happens.


N(Posted 2004) [#3]
I like your commenting style. Come work for me and become a millionaire.


Strider Centaur(Posted 2004) [#4]
I love comments, I beleive its as important to explain to yourself the concepts as well as the usage. Makes it so much easier to come back too later. :)

Hmm well as I read over it, I can see where maybe a little spelling might help here and there, but the code works. Yep it does.


Dreamora(Posted 2004) [#5]
just a small sidenote:
witch I always took for granted in OpenGL with Gui and Glut I guess


Blitz3D uses DirectX7 not OpenGL


Strider Centaur(Posted 2004) [#6]
Really? lol

I knew that, but OpenGL had these capabilities years before DirectX even existed. Thats why I was suprised to see it missing in the 7th version of a API that is itself the 2nd API from Microsoft targeted at graphics for windows. :/

Im fairly sure most modern graphics cards( ie. those since like 97 ) can do this in hardware now. Just the API seems to be lacking anyway to access it. Well when BMax hits and the 3D module is ready all this will be mudy water under the bridge.

Normally I would have done the Apply a Alpha Mask to the zBuffer thing, but didn't see any clear or easy way to do this. That is, that would have been as fast as the technique above. Granted it would look alot smoother, but all that bit handeling would be SO SLOOOOOOOW.


Strider Centaur(Posted 2004) [#7]
Made several updates to this, a newer version is in the code archives here. Working on turning the fog into a more controlable function for easy inclusion in other projects.

Will end up with the ability to alter the fog in real time.
goals:
-Allow for color change on the fly
-Easy range control ( one function to set min and max range )
-Layer control to set how many layers and at what opacity for each layer
-SkySphere switching to turn a given layer into a skysphere with entityorder set and sky texture applied.
-Seperate texturing option for each layer
-Use types to contol layers
-single command to initialize a simple fog system
-Function call to manipulate all aspects of the fog.