25 Comments

  1. Nigel say:

    Hi,

    Great tutorial!
    Only question is, is it possible to set up dynamically?

    Example: i spawn units they all need to clear the fog instead of the 3 defined ones (RTS).

    Im not good with shaders but is it possible to foreach a variable in a shader ? So we dont need to hardcode the available players in the game.

    • admin say:

      Hi. As I know Unity has not supported passing arrays to shaders yet, so you need to have some amount of slots in shader for your player or have several shaders with different slot num. But you can turn slots off dynamically, for example, by setting player position (aperture position) somwhere outside the map.

      This shader, as I’ve said in tuto, has a limitation of player number. If you has a lot of players with fog of war you may have performance problems, In this case you need to think about non shader solution or multypass rendering.

      • Nigel say:

        Thanks for your quick reply!

        I will look around for other solutions, but have learned some about shaders thanks to your tutorial!

  2. Ben say:

    Hey, awesome tutorial, works great, but I do have one question.

    Instead of 3 players, I have 5.

    I don’t know shaders very well at all, so this is pretty much an intro to them for myself.

    I figured out how to set everything up to support 5 players, however in order for the shader to show 5 units, I need to modify line 57 to look something like this:

    ” float alpha = (1.0 – (baseColor.a + powerForPos(_Player1_Pos, IN.location) + powerForPos(_Player2_Pos, IN.location) + powerForPos(_Player3_Pos, IN.location) + powerForPos(_Player4_Pos, IN.location) + powerForPos(_Player5_Pos, IN.location)));

    I then get an error saying “Arithmetic instruction limit of 64 exceeded.

    I’ve checked the forums and they said “change to Target 3.0 or fix your math”.

    So, being a novice, is there a way to make this math work as is, or will I need to change to a Target 3.0 shader? If I need to change, what changes would I need to make to the shader? I tried adding the Target 3.0, the fragment frag, and vertex vert as Unity documentation suggested, but I just got another long list of errors saying my syntax is off.

    Sorry for the long question. Again, awesome tutorial, and if you have the time to respond to this, that’d be amazing. Thanks :)

  3. Gabriel say:

    Awesome tutorial. I want to make a RTS. I just want to have 5 units per player on the map. I created 5 “players” for that. The problem I am facing is that I want each unit to have a different FogRadius. Tried to achieve that using material.SetFloat in the Fog of War Player script:
    if (Physics.Raycast (rayToPlayerPos, out hit, 1000, layermask)) {
    FogOfWarPlane.GetComponent ().material.SetFloat (“_FogRadius”, radius);
    FogOfWarPlane.GetComponent ().material.SetVector (“_Player” + Number.ToString () + “_Pos”, hit.point);

    }

    I tried the above with 3 units. However, the radius is the same for all of them. May I ask you for assistance on how I could do the aformentioned? Thanks in advance 😀

    • admin say:

      Looks like you have one _FogRadius varible for the all players. You should have five _FogRadius variables for eatch players like _FogRadius1, _FogRadius2, _FogRadius3 etc

      • Gabriel say:

        Hi thanks for your reply.

        Yea I only had one.
        Just made these modifications:

        _FogRadius1 (“_FogRadius1”, Float) = 1.0
        _FogRadius2 (“_FogRadius2”, Float) = 1.0
        _FogRadius3 (“_FogRadius3”, Float) = 1.0

        float alpha = (1.0 – (baseColor.a + powerForPos(_Player1_Pos, IN.location, _FogRadius1) + powerForPos(_Player2_Pos, IN.location, _FogRadius2) + powerForPos(_Player3_Pos, IN.location, _FogRadius3)));

        And added a new parameter for the function powerForPos:
        float powerForPos(float4 pos, float2 nearVertex, float FogRadius)

        However, I am getting the following warning and error:
        Shader warning in ‘Custom/FogOfWar’: Program ‘SurfShaderInternalFunc’, implicit cast from “float4” to “float2” at line 51

        Line 51 -> outData.uv_MainTex = vertexData.texcoord;

        Shader error in ‘Custom/FogOfWar’: Program ‘SurfShaderInternalFunc’, too many parameters in function call at line 58

        Line 58 -> float alpha = (1.0 – (baseColor.a + powerForPos(_Player1_Pos, IN.location, _FogRadius1) + powerForPos(_Player2_Pos, IN.location, _FogRadius2) + powerForPos(_Player3_Pos, IN.location, _FogRadius3)));

        The problem seems to be the function since it started working when I removed the parameter I added and changed _FogRadius to _FogRadius1. The problem should be related to how shaders work because I can’t see why it says too many parameters when there are 3 in the function declaration.

        I also noticed that the visionRadius of my player is “smaller” than the _FogRadius because of the distance to the camera. What I mean is that since the Fog is closer, the circle looks bigger than the detection radius of my units. May I ask how can I calculate the _FogRadius so that it fits the detection range?

        Thanks in advance, you’ve been a great help.

        • admin say:

          May be you have problem with input variables limitation.

          Could you give a full shader code? It is hard to understand where is the problem.

          • Gabriel say:

            Sure, thanks for helping :)

            // FogOfWar shader
            // Copyright (C) 2013 Sergey Taraban
            //
            // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
            // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
            // THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
            //

            Shader “Custom/FogOfWar” {
            Properties {
            _Color (“Main Color”, Color) = (1,1,1,1)
            _MainTex (“Base (RGB) Trans (A)”, 2D) = “white” {}
            _FogRadius1 (“_FogRadius1”, Float) = 1.0
            _FogRadius2 (“_FogRadius2”, Float) = 1.0
            _FogRadius3 (“_FogRadius3”, Float) = 1.0
            _FogMaxRadius(“FogMaxRadius”, Float) = 0.5
            _Player1_Pos (“_Player1_Pos”, Vector) = (0,0,0,1)
            _Player2_Pos (“_Player2_Pos”, Vector) = (0,0,0,1)
            _Player3_Pos (“_Player3_Pos”, Vector) = (0,0,0,1)
            }

            SubShader {
            Tags {“Queue”=”Transparent” “IgnoreProjector”=”True” “RenderType”=”Transparent”}
            LOD 200
            Blend SrcAlpha OneMinusSrcAlpha
            Cull Off

            CGPROGRAM
            #pragma surface surf Lambert vertex:vert

            sampler2D _MainTex;
            fixed4 _Color;
            float _FogRadius1;
            float _FogRadius2;
            float _FogRadius3;
            float _FogMaxRadius;
            float4 _Player1_Pos;
            float4 _Player2_Pos;
            float4 _Player3_Pos;

            struct Input {
            float2 uv_MainTex;
            float2 location;
            };

            float powerForPos(float4 pos, float2 nearVertex);

            void vert(inout appdata_full vertexData, out Input outData) {
            float4 pos = mul(UNITY_MATRIX_MVP, vertexData.vertex);
            float4 posWorld = mul(_Object2World, vertexData.vertex);
            outData.uv_MainTex = vertexData.texcoord;
            outData.location = posWorld.xz;
            }

            void surf (Input IN, inout SurfaceOutput o) {
            fixed4 baseColor = tex2D(_MainTex, IN.uv_MainTex) * _Color;

            float alpha = (1.0 – (baseColor.a + powerForPos(_Player1_Pos, IN.location, _FogRadius1) + powerForPos(_Player2_Pos, IN.location, _FogRadius2) + powerForPos(_Player3_Pos, IN.location, _FogRadius3)));

            o.Albedo = baseColor.rgb;
            o.Alpha = alpha;
            }

            //return 0 if (pos – nearVertex) > _FogRadius
            float powerForPos(float4 pos, float2 nearVertex, float _FogRadius) {
            float atten = clamp(_FogRadius – length(pos.xz – nearVertex.xy), 0.0, _FogRadius);

            return (1.0/_FogMaxRadius)*atten/_FogRadius;
            }

            ENDCG
            }

            Fallback “Transparent/VertexLit”
            }

        • admin say:

          Gabriel, I’ve found the problem in your shader. Your forgot to change powerForPos function definition. You change only realisation

          you have to replace
          float powerForPos(float4 pos, float2 nearVertex);

          to

          float powerForPos(float4 pos, float2 nearVertex, float _FogRadius);

          you need to learn some basics of programming in C/C++ :)

          • Gabriel say:

            LOL omg I feel so dumb because I hadn’t noticed there was a function declaration in the middle of the code until you pointed it out xD

            Thanks a lot and sorry for all the trouble :)

  4. matt say:

    Hi, this is an awesome tutorial, I am really enjoying playing around with this fog of war effect.

    I’m having an issue when I am running this shader on an iOS device. While everything works perfectly in the Unity player, as soon as I run on iOS (iPhone 5s) I get an error “WARNING: Shader Unsupported: ‘Hidden/TerrainEngine/Details/BillboardWavingDoublePass’ – Pass ” shader state not supported”

    I don’t suppose you might have any ideas why the Apple device is being difficult?

    That said this is an awesome tutorial and I have learnt a lot from it, regardless of my inability to debug my own game

  5. Luca say:

    hello Sergey,
    your tutorial is amazing, thanks for sharing.

    I have a simple question to ask you.

    I adapted it to fit my 2d game and it works as far as the map is revealed for a circle under the plane.

    But I cannot see sprites laying on the map. the map and the plane lay on the xy plane and I can see the sprite only if i lift it on the z axis to reach the area between the camera and the plane. As it lays below the plane it disappears.

    Any idea about this?

    • admin say:

      Hi Luca
      Try to check drawing order of 2D camera and for of war camera. May be other parameters of the camera are wrong.
      Also try to replace fog of war shader by simple regular transparent shader and check sprite disappearing.

      • admin say:

        It is just demo game
        Some guys wrote me they use it in his games
        But after update to Unity 5 you may get some problems

  6. Elaine say:

    Hi Sergey,

    Thank you so much for this tutorial! I’ve been using your fog of war in my game for several months now and it has been working great, but I just upgraded to Unity 5 and something seems to have broken, although I don’t have any errors in the console. I can see that the render texture is working correctly and there is a solid gray circle where the mask is, but it’s not cutting through the black anymore to show my scene. I know this is a free tutorial you’ve put together and I completely understand if you don’t have time to look at a solution, but any direction on where to troubleshoot would be helpful!

    Thanks!

    • admin say:

      Actually I’ve move my flat to another country and I have no time to support all of this stuff(
      I even have no normal computer now

  7. Debon say:

    Uhm…I have a problem :)
    I already finished the shader thing it looks amazing but
    I dont know why the spotlight thing doesn’t follow my player/character..
    do you think the problem is coming from the FogOfWarPlayer.cs?
    or the fogofwar.shader itself?

    I’m confused in the FogOfWarPlayer.cs
    because I tried to rewrite the other codes like Vector3 to Vector2, Ray to Ray2D, RaycastHit to RaycastHIt2D, Physics to Physics2D and the 1000 to different numbers like 1000000 or 1.5f and also the Camera.mainCamera.blahblah to Camera.main.WorldToScreenPoint ahahahaha
    sorry again for the trouble I wish I can send some printscreen to show it to you and the P.S. of the game so that you can help me immediately. :(
    Please help me

  8. Lucas say:

    Hi ,
    Thank you so much for this tutorial!
    But…uhm…Im a novice at shader…and Unity. so I do have a problem with my work even if I do exactly what you did in the video. The problem is that there is no aperture on the FogOfWarPlane in my work. Its just completely black.

    I completely understand if you don’t have time to reply, but any direction on where to troubleshoot would be helpful!

    Thanks again.

Write a comment