Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Android friendly fog-of-war-like shader/system

Discussion in 'Android' started by Skotrap7, Apr 27, 2022.

  1. Skotrap7

    Skotrap7

    Joined:
    May 24, 2018
    Posts:
    124
    Hi, the title of the post may be misleading, but I couldn't think of the right words to use, so here is my situation:

    I am working on a top-down isometric game on Android in URP. We have several levels that are indoor areas, that are currently using a black skybox for the background areas. However, this shows the outer walls of the rooms, and we would like the outer areas of the scene to just be all solid black.

    I've been trying a fog-of-war type of thing, following this post. This isn't URP friendly, so I've been trying to convert the shader to shader graph, but still can't get it to work. I probably don't understand everything about how this is supposed to work to make the right changes. I've also tried following this tutorial and trying to adapt it to be URP friendly with no luck. Again, I may not fully understand what is going on here.

    Currently, I've been reading this which is using render features and seems the most promising, but it doesn't have the behavior I am looking for.

    If anyone can help either fill the gaps of my understanding or provide better references/tutorials on making something like this I would greatly appreciate it.

    Here are some images to hopefully better describe what we want. Also, the idea of using a fog-of-war for unexplored areas of the map is cool, but not necessary. Mostly we just want to obscure the outdoors geometry.

    A part of our scene that shows the outdoors geometry:
    upload_2022-4-27_8-49-52.png

    And we'd like this fog-of-war like shader thingy to make it look like this:
    upload_2022-4-27_8-52-11.png

    Initially I was thinking to just place planes all around, but the geometry and corners involved in several areas would require quite a lot of planes of various sizes to obscure everything.

    Again, fog-of-war-area-revealing feature is nice to have, but not required, and any assistance is very appreciated.

    Current state of things:
    • Another camera, orthographic projection, in center of map high above looking straight down with a black plane over the entire map and "showing" only the indoor areas using one of the linked methods above.
    Thanks in advance.

    EDIT:
    A reasonably priced asset from the asset store would be an acceptable option, assuming it supports URP and works on Android (and hopefully iOS eventually).
     
  2. Skotrap7

    Skotrap7

    Joined:
    May 24, 2018
    Posts:
    124
    For the last several days I've been trying to write a custom render feature to accomplish this. I've been looking at the built in RenderObjects. I now have a plane over my entire level and the objects beneath the plane render through it (though they are slightly tinted for some reason I don't yet understand), but otherwise it looks basically like the skybox version. I'm still trying to figure out a way to block everything outside the bounds of the objects beneath it.

    My guess as to what is going on with what I have is that I've basically created a depth test and rendered everything that is further away from the camera than this plane, but the exterior sides still render because they are still hit by the depth test.

    If anyone has any other thoughts on how I could/should approach this further, I would appreciate the insight.
     
  3. Skotrap7

    Skotrap7

    Joined:
    May 24, 2018
    Posts:
    124
    Well, I may be posting this in the wrong forum, but I've made some progress. I'm going to post my progress here and maybe add another post in another forum linking back here.

    I feel like I'm about 90% there now, so here we go:

    First, some initial setup:
    1. Add a Layer, I named mine Fog of War.
    2. Add a plane in your scene and scale it up to cover the entire area you want to be hidden and set its layer to the new layer (Fog of War). This plane will be our fog, it is going to hide everything in the outdoor area of my level.
    3. Add an additional renderer asset. I just duplicated the ForwardRenderer asset already in my project in my /Settings. I named it Fog Mask Renderer. This renderer is going to be what we use to indicate the areas that should be hidden/visible in our "fog" plane.
    4. In the new renderer asset uncheck the new layer (Fog of War) from the Opaque Layer Mask in the filtering section. At this point what I've done so far, is to create a renderer that will NOT render anything on the Fog of War layer. This will let the renderer see through our fog plane and render any opaque objects it does see. upload_2022-5-3_12-6-47.png
    5. Create a new Render Texture in the project and set it to 1024x1024 and RGBA32. I named mine Fog Mask Texture
    6. Add a new Camera to the scene:
      • Move it to approximately the center of the level
      • Translate it up in the y direction some to get it out of the way
      • Set it to Orthographic projection and adjust the size property to fit the entire level in its view
      • In the Rendering settings, set the Renderer to the new renderer (Fog Mask Renderer)
      • Uncheck "Render Shadows"
      • In Environment set Background Type to solid color and Background to white
      • In Output set the Output Texture to the new Render Texture (Fog Mask Texture)
      • Delete the Audio Source Listener component upload_2022-5-3_12-7-34.png
      • This new camera is now going to be writing to the render texture a completely white texture and everything that is NOT on the Fog of War layer will be draw on that texture normally. This is important for the next step.
    7. Create a new unlit shader graph shader (I called mine Fog of War) with a Texture property.
    8. Create a new material using this new shader (Also called Fog of War) and assign this new material to that fog plane we created in step 2. In the material's texture property, drag/drop that render texture we created from step 5
    9. The shader implementation is pretty basic. Add a Sample Texture 2D node and sample the texture. Next, add a compare node, color node (set to completely white) and compare the sampled texture to that color node. Now add a branch node with true = 1 and false = 0 (default) and set the output of that node to the Alpha channel. Last step, on the output node set the color to whatever the fog color you want. I just made mine black. upload_2022-5-3_12-9-42.png
    10. Final step, adjust your fog plane height to wherever you'd like the fog to cut off from the level.

     

    Attached Files:

  4. Skotrap7

    Skotrap7

    Joined:
    May 24, 2018
    Posts:
    124
    Final result:
    upload_2022-5-3_12-13-51.png

    It works, but it is not as good as I wanted it to be. I'm not sure exactly how to move forward from here, but I am at least making some progress. I hope someone has some insights that can help me.
     
unityunity