How do I achieve a ”Fog of War” – Shader or Texture?

Hey guys, :slight_smile:

I’m going to implement a “fog of war” system to my realtime-strategy game. Luckily, there are already topics about that. But every one used another method and I can’t really get, how they wanted to do it. :smiley:



These are the best looking topics I found:

Drawing a texture above the terrain: http://hub.jmonkeyengine.org/groups/general-2/forum/topic/fog-of-war-1

Using a shader: http://hub.jmonkeyengine.org/groups/effects/forum/topic/three-dimensional-fog-of-war-and-field-of-view/



I think, drawing a texture should be more easy than writing an own fog-shader - But of course, a 3-dimensional fog-of-war would be extremely nice. Unfortunately, I don’t know much about shaders and all the tutorials I found didn’t help.

So, any ideas (or link to guides :D) would help me a lot since I really, really need this feature in my game.



Yours,

destro



EDIT: Detecting which object is visible and which isn’t, is not the problem - It’s just how to display the fog-of-war in the not-visible-areas.

i never used one, but with my limited knowledge on it, i wonder if a stencil buffer could help here, and just draw what ever should be visible

3-dimensional fog-of-war?



what about 3D texture ? you could even use terrain heightmap to build one i think.

My problem is how to draw the dark parts on the terrain - Can I access the alphamap for this?

I never painted textures to the terrain from my code (I always read them directly from an image alphamap), so my questions might be silly. :smiley:



Or would it be better to first draw everything dark and then draw the visible areas over the dark ground?



EDIT: I think, I’ve got it - I found this topic: http://hub.jmonkeyengine.org/groups/graphics/forum/topic/newbie-question-on-how-to-draw-a-custom-texture

By using the terrain material I can add an additional texture that I can modify - An “overlay” texture. :slight_smile: (black and transparent at some places)

Hm, seems that I faced the next problem. :slight_smile:

How do I achieve a transparent texture on the terrain? I’ve tried setting the BlendMode to Alpha or even with white parts, but it seems that the Common/MatDefs/Terrain/TerrainLighting.j3md is totally ignoring the alpha value I’ve set to the texture for each pixel.



Any ideas? Maybe I can access the alphamap and change there, how “transparent” the texture is painted over the old one.



EDIT: I think, just changing the alphamap’s values should work too - Then I’ll just use a “black” texture that is painted semi-transparent.

I’ll keep you up-to-date, how this is working (Because I think, other people might face this problem, too). :slight_smile:

Transparency has other effects too (such as needing placing in the transparent bucket, etc). Best to avoid it unless you really need it.

Thanks for all the answers, the alphamap-manipulating and adding a black texture did the trick. :slight_smile:



This is the result (far from being perfect, but it’s a beginning - Things like a better smoothing and so on are just tweaking):



2 Likes

The image you posted looks really great, I could use this in my project. But I can’t figure out what you actually did there. What did you mean with “By using the terrain material I can add an additional texture that I can modify”? The Terrain Material has the alphamap and 3 Textures. How did you get this black texture in there? And how exactly did you manipulate the alphamap? I read the post of this link and I understand the posted code, but how would you use it?
My understanding of the alphamap is that you define by using RGB colors where which texture is rendered. So how do you manipulate the alphamap to achieve a transparency effect?
Maybe you could post some code snippets in here :slight_smile:

I wonder what your fog of war really do. It does not hide 3D objects, do it?
If I understand well, you “remove” the texture of non-visited areas by painting a back overlay over it.

Please correct me if I’m wrong, but not hiding the enemy units in a big problem in any RTS.

Hiding enemy units can be handled separately though and generally the entire unit is either visible or not, whereas the terrain model is partially visible.

I would suggest using a separate mesh that is above everything else, in case you decide to swap out some major component at some point (terrain for example. plus it’s a single update as apposed to trying to take case of your trees next.

Thoughts on producing a nice effect:
Use two seperate tilable fog images, start with a black color,
Overlay the first (darker fog) and animate movement slowly,
Overlay the second (lighter fog) animate slightly faster.

Use mix() to produce the final fragColor

You offset the FoW mesh by the camera angle to ensure it is showing the area you want properly and it will produce a great looking effect.

@Wasserleiche
You undestand the alphamap thing correct - The thing is: The image contains 4 colors, not 3: Red, Green, Blue and Alpha. :wink:
This 4th channel is where I specify how strong the black texture painted.

@yang71

I wonder what your fog of war really do. It does not hide 3D objects, do it? If I understand well, you "remove" the texture of non-visited areas by painting a back overlay over it.

Please correct me if I’m wrong, but not hiding the enemy units in a big problem in any RTS.

@zarch said: Hiding enemy units can be handled separately though and generally the entire unit is either visible or not, whereas the terrain model is partially visible.
zarch already posted my answer. :D The culling of enemies is handled seperately, this was no problem at all.

Although I’ve had an interesting thought - you could define a simple texture (probably at fairly low resolution, 256*256 should be plenty even for a pretty large map) and set a value in it for 0->1 for the level of fog of war at that point.

A custom shader used on all models including landscape could map world x,z to a u,v point in the fog of war texture. Each pixel could then be drawn fading to black (or whatever) based on the fog level (the non-fogged portion would then be drawn as per the standard shader) and the results would be both units and terrain emerging naturally and gradually from the fog of war.

This would be awesome :slight_smile: Unfortunately, I don’t know how to program shaders, definitely something I planned to do the last years, but… yeah… too lazy. :smiley:
If another person could do this, this would be a very cool feature.

Any insight on how you cull your 3D units based on the FoW ?
I’m really interested in that also!

Well, detection if a unit is visible or not is very simple: Check all units owned by the player and see, if the specified enemy unit is in their “visible range”.
If none of your units can see the enemy unit, it should be invisible (Otherwise, it should be visible).

My server calculates those booleans, whenever a unit moves and if the visibility of an object changes for a specific player, then the server sends an update to the according player. :slight_smile:

Hope, that helps.

@destroflyer said: @Wasserleiche You undestand the alphamap thing correct - The thing is: The image contains 4 colors, not 3: Red, Green, Blue and Alpha. ;) This 4th channel is where I specify how strong the black texture painted. .

But what black texture do you mean? Which one of the 3 possible terrain textures do you use? Or what do you mean by “overlaying a black texture”? I really don’t get how you are doing this.

Ouch. That’s going to scale pretty poorly as its a classic n^2 approach.

Be better to create a texture (just needs 1 8 bit channel per pixel per player) representing the map. Colour pixels by how well you can see them - easiest is probably just to update the map around moving units by setting it all to black then using a brush to paint in the visible area for each units (ImagePainter using blend mode lightenOnly or additive (depending on how you wanted units to reinforce each other’s vision) could do that for you).

Then each enemy just does a simple check against the nearest pixel on the map and is visible if value is > the configured threshold. By tweaking the threshold different units could even have different levels of visibility meaning they are seen sooner or later.

This means you have two order n (write to map once per friendly, read from map once per hostile) operations rather than one n squared.

You also only need to update visibility map a couple of times per second and if you got smart about where objects are moving you can only update the “dirty” areas.

Oh…depending on expected number of units and what other utility you can get from it this may qualify as premature optimisation (which is bad). If you only ever have 10 units on screen you are probably fine, however for something larger you need a more sophisticated approach.

Thanks a lot. I found how to make invisible some object… Setting the Culling to always do the trick.