[TUTORIAL] Fog Of War

well i register the actor but is not working:((
I dont know where i could made a mistake could u upload your project so i can see where i made the mistake?

Well…there are quite a few steps here, so I guess it’s not that easy to make it work. Some checkpoint would be:

  1. If you’re using a template project, delete the PostProcessVolume in the scene.
  2. Make sure your Blueprint is based upon FogOfWarManager and that it contains an unbounded post process volume.
  3. I’ve uploaded the material and material parameter collection and linked to it in a post above. Make sure that the Material Parameters are named correctly and have the exact same values as in the screenshot above.

I’m a bit relucatant to upload the whole project because it has changed quite a bit since I wrote the FOW-stuff and there’s a lot of functionality obscuring the core functionality of the tutorial. On the other hand, I could probably implement it in a clean project though it would take a few hours. So try really, really hard to make it work replicating it exactly as outlined in the tutorial and if it still doesn’t work I could probably upload a clean project in a few days. And if you have any specific questions feel free to ask.

Ty man i got it working now the problem was with the post process.Well thanks again and good luck with your project.

Brilliant! Good luck with your project too. Btw. if you experience an occasional crash while exiting the game you could add an extra check to the method void AFogOfWarWorker::UpdateFowTexture()



...
...
for (auto Itr(Manager->FowActors.CreateIterator()); Itr; Itr++) {

//ADD THIS
   if(StopTaskCounter.GetValue() != 0) {
     return;
   }

Until now i didnt had any crashes so if i do i will add that.Thanks

hey, i was trying to follow ur method, and to see how it works, but i got this as my screen. pretty sure this is not what it is supposed to be. im new in textures and materials, so any ideas as to why this is happening?

Link to the project if needed
https://drive.google.com/file/d/0BwN8c-GkqURWNXJKRGtxajk5bXc/view?usp=sharing

Hunter of Dragons (great profession),

you’re quite right, it’s not supposed to look like that :slight_smile: My guess is that there is something wrong with the material instance of the FOW-material, and that the texture parameters FOWTexture and/or LastFOWTexture haven’t been correctly set. Did you download and use the materials I posted in post #12? They should work. If that doesn’t solve the issue, I will look at your project later today though I’m stuck at work ATM.

Yah, i used the materials you posted in #12. The FOW_Mat refused to show up in the editor though. The PP_FOW_MAT, FOW_MAT_Insntance, and FOWParameters did.

p.s - updated link in case the previous one doesnt work :- [)

Hunter of Dragons!

I’ve looked at you project and there were a few things missing:

  1. A default texture for PP_FOW_Mat’s FOWTexture and LastFowTexture parameter. I just use a simple black 32x32 texture in my project (they will get updated anyways). I think that’s why your screengrab uses some sort of tile-texture, it’s probably some default texture from the engine.
  2. The FOW_Mat_Instance material must have PP_Fow_Mat as its parent. Set both of the Texture Parameter Values to a plain white texture.
  3. In your LevelInfo-blueprint construction script where you create the dynamic material instance, the parent material must be set to FOW_Mat_Instance.
  4. To make the FOW render correctly the LevelInfo-instance in the game world should have coordinates of 0,0,0.

I think that’s it, at least it seems to be working for me now. I’ve uploaded a modified version of your project here: . If it’s allright with you I’ll just leave it there and other people may download it as a starting point. If you don’t want it up however, I’ll take it down at your request. Also, out of curiosity, my Visual Studio didn’t like your project so I couldn’t open it properly, but where do you call the RegisterFowActor(AActor* Actor)-method in FogOfWarManager?

Was calling it in BeginPlay, getting the player by GetWorld()->GetFirstPlayerController()->GetControlledPawn(). and no, i dont have any problem, its good to have guides around !! :slight_smile: . Once i followed your steps, my project started working as well. Thanks :smiley: . A Side question. Which part of the c++ code deals with the previously seen areas being grey when out of line of sight??

Hooray, it’s working!
If you don’t mind I’ll move the sample project linkt to the main post and credit you.

The code dealing with previously discovered areas putting it in a “shroud of darkness” are the sections below in FogOfWarWorker.cpp. The first section is used if you’ve enabled blurring (via a checkbox in your LevelInfo-object), and the second section is without blurring. If you don’t want “shroud of darkness”, just remove the elses. If you find the value too dark or too light, just change the integers. Changing them towards 255 makes the shroud of darkness lighter and towards zero makes it darker.



//If this is a previously discovered position that we're not currently looking at, put it into a "shroud of darkness".							
else {
      sum += (Manager->blurKernel* * 100);
}					
...
...
else {
     Manager->TextureData[x + y * signedSize] = FColor((uint8)100, (uint8)100, (uint8)100, 255);
}


yah i kind of figured that out just now while going through the code !! xD . Thank you so much. Also, if i want the sight radius to be high, i just need to increase the sight rangevalue higher right? should that be passed from the registered actors? And also, since the level we are working on is HUGE. and its not showing properly in that level, what else does it need to be changed? I changed the samples per meter, but the visible area is going ahead of my pawn, and my pawn is going into the darker area as a result

Yes, to increase the “global” sight value just increase the SightRange-value. If you want individual sight ranges you will have to modify the FogOfWarWorkerThread a little bit. Something like this should work:

  1. Create a new parameter in AYourCharacter for sight range.
  2. Move the line int sightTexels = Manager->SightRange * Manager->SamplesPerMeter; into the loop just beneath it.
  3. Try casting the *Itr to AYourCharacter
  4. If the cast succeeds, replace Manager->SightRange with the sight range parameter from your character.

Hey, thanks. I managed to achieve what i wanted by having the position of my levelinfo bp correspond to the playercharacter, and it works fine now. Also, any hidden things were also casting the dark areas, which i did not want, so i changed the trace channel in code to my custom trace channel.
What i wanted to ask is, TIs this process FPS dependent? In the example project, it had 120 fps, and the fog was pretty reactive. But in the project we are working on, it does not have that high an fps, and the response time for the fog drops quite a bit. Any way to speed that up?

The solution isn’t directly depending on the FPS, but the thread calculating the FOW is bound by CPU. Thus if your CPU is heavily taxed, the FOW-thread will be slower. If you have long sight ranges and/or many characters calculating line of sight the solution is not optimized and will probably perform poorly. This is commented in FogOfWarWorker.cpp:



//CONSIDER: This is NOT the most efficient way to do conditional unfogging. With long view distances and/or a lot of actors affecting the FOW-data
						//it would be preferrable to not trace against all the boundary points and internal texels/positions of the circle, but create and cache "rasterizations" of
						//viewing circles (using Bresenham's midpoint circle algorithm) for the needed sightranges, shift the circles to the actor's location
						//and just trace against the boundaries. 
						//We would then use Manager->GetWorld()->LineTraceSingle() and find the first collision texel. Having found the nearest collision
						//for every ray we would unveil all the points between the collision and origo using Bresenham's Line-drawing algorithm.
						//However, the tracing doesn't seem like it takes much time at all (~0.02ms with four actors tracing circles of 18 texels each),
						//it's the blurring that chews CPU..


This is perfectly doable, though may require a little bit of work. I would, however, do some time measuring up front to see if the line of sight(LOS)-calculations really require that much cpu-time. I would also investigate if the fancy, new EQS system could be used.

The thread is spawned with a “below normal”-priority in FogOfWarWorker.cpp Changing the line:



Thread = FRunnableThread::Create(this, TEXT("AFogOfWarWorker"), 0U, TPri_BelowNormal);


to



Thread = FRunnableThread::Create(this, TEXT("AFogOfWarWorker"), 0U, TPri_AboveNormal);


will make the thread manager prioritize the FOW-thread over other threads.

I’ve also put in a little “breathing space” for the thread to allow for other processes to utilize the CPU in FogOfWarWorker here:



		Manager->fowUpdateTime = Manager->GetWorld()->TimeSince(time);
			}
		}
		FPlatformProcess::Sleep(0.1f);


You could reduce the Sleep to e.g. 0.001f to speed up the process by ~100 ms.

Also, the blending time between the last and the current FOW-texture is set to be quite snappy. Having a longer blending time could make the FOW-blending appear smoother. You can change this in the LevelInfo-blueprint graph in the section “Set blending factors between FOW-textures” by reducing the multiplicand of DeltaSeconds. Ideally the blend time should be equal to the time a full update cycle of the FogOfWarWorker. To achieve this you could use e.g. the mean of the last five update times as your target blending time and derive your blending factor from that.

Hope that’ll get you startet :slight_smile:

Cheers,

yah, i had changed the sleep already, that made it go a bit faster. The last thing i want to ask is, WHen an area has not been discovered at all, it is currently pitch black, and when it has been seen once, or “unveiled”, it applies the transperency. How do i change the initial parameter so that the undiscovered areas also show some sort of transparency, instead of being pitch black?

Edit:- So i just added a else after the " if (currentlyInSight.Contains(FVector2D(x + shiftedIndex, y))) " , and there i set the transparency to a higher value. But then, the regions previously seen but not in line of sight went pitch black, even though i had disabled the shroud of darkness. So In order to handle transparency of the three states, i need to explicitly define the transparency? Or is there a way to set the default transparency to something?

Hi,

Sorry about the late reply. You can set the default brightness in FogOfWarManager.cpp by altering the following code lines:



TextureData.Init(FColor(0, 0, 0, 255), arraySize);
LastFrameTextureData.Init(FColor(0, 0, 0, 255), arraySize);


Increase the zero values towards 255 to change from pitch black to fully transparent (no fog).

That does not work though. I changed that, but my undiscovered areas are still pitch black. that like only changes the areas in the “Shroud of darkness effect”

Edit:- okay, since then, i fixed the stuff, and the game packages, but it crashes on opening the packaged game saying render thread exception. I tried packaging the example build that we had put up, that does the exact same thing. Packages, but the packaged game crashes on launch.

Hi,
For some reason the FOW is running in the editor and everything is black. Could you shed some light as to why this could be?

Hey nice work, but I am having trouble getting it to run. I am new to C++ so this might be a noob mistake. I just want to implement it in the top down template and see if I can modify it to fit my project. First, when I created the project I need to include the header file of the FogOfWarWorker in the FogOfWarWorker.cpp since otherwise it gives me an error at the top. When I try to compile after this Manager->GetWorld() gives me an error that says “Error: pointer to incomplete class type not allowed”. The only thing different in my code is the project name I also didn’t start this as a c++ project but as a blueprint project, would that even make a difference? If I ever get to implement part of this you would get the credit of course :slight_smile: