True Cone of Sight? Commandos

Hi everyone!

I would like to know if anyone ever tried to simulate FOV (from Commandos game, picture below) in Unity to work with different height variations. I discovered that this is really hard task to accomplish. I tried Projectors, raycasting and all other methods found on internet but it was always not what i was looking for.

alt text

Projectors can be a good solution, but:

1. I need shader which allow me to render cone texture only on top faces of other objects (Picture below represents bad projector)

44574-problem1.jpg

2. Projector should not draw texture through walls, buildings etc. I know i can use layers to block rendering the cone on the second wall, but depends to enemy position it’s important to render cone on all objects.

44575-problem2.jpg

Can anyone give me an idea or solution how can i achieve this type of FOV rendering?

Thanks!

What is the code for the shader you are using for the projector? This is actually not very hard to accomplish in shader code. If you could post the code of the shader, I could help you more exactly, but…

What you want to do is add a check to see how “vertical” a surface is, and not alter the color if it is too vertical. Here is some psuedo shader code to demonstrate this:

// assuming Y is up
half3 up = half3(0,1,0);
if(dot(normal, up) == 1) {
    // this is a flat floor surface, adjust color
}

That is just a general idea. Odds are it will never be exactly 1 (or might be 0, I forget what the value of a dot product of two matching directions is), so you will need to test for a range.

General idea though is to run a test on the dot product of the normal of the vertex against the world up normal.

EDIT:

I see. ok, first we need to get the normal data:

make a new struct:

struct appdata {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
}

modify the existing struct:

struct v2f {
    float4 uvShadow : TEXCOORD0;
    float4 uvFalloff : TEXCOORD1;
    float4 pos : SV_POSITION;
    float3 norm : NORMAL;
};

Now to modify our vertex function:

v2f vert (appdata i)
{
    v2f o;
    o.pos = mul (UNITY_MATRIX_MVP, i.vertex);
    o.uvShadow = mul (_Projector, i.vertex);
    o.uvFalloff = mul (_ProjectorClip, i.vertex);
    o.normal = i.normal;
    return o;
}

Now our fragment function should have a normal to work with. Now try doing this:

fixed4 frag (v2f i) : SV_Target
{
    fixed4 texS = tex2Dproj (_ShadowTex, UNITY_PROJ_COORD(i.uvShadow));
    texS.a = 1.0-texS.a;
    fixed4 texF = tex2Dproj (_FalloffTex, UNITY_PROJ_COORD(i.uvFalloff));

    fixed4 res;
    // assume Y is up
    if(dot(i.normal, float3(0,1,0)) >= 0.9) {
        res = lerp(fixed4(1,1,1,0), texS, texF.a);
    } else {
        res = texS;
    }

    return res;
}

For the if statement, you may need to play with that 0.9 value. It is going to be a value between -1 and 1; but I forget what the value will be when the normal and the up vector are the same (or close to it).

This is by no means a complete solution (or maybe it is? I did not test it), but it should help to point you in the right direction. The main points to take are this:

  1. You need to get normal information to your frag function
  2. you need to compare the dot product of the normal to the world up vector to figure out how vertical a face is.

I am also unsure what texS and texF contain at this point of the shader. I’m assuming texS is the shaded texture BEFORE the projection is applied, but I could be wrong.

This link should help a bit as well, as it explains inputs to vertex/fragment shaders:

Hi @JacobDzwinel,

Did you manage to make it work as expected? I’m facing the same problem…

Thanks!

To everyone wondering how I finally achieved nice effect of true cone of sight, I found this

I hope this will help you :slight_smile:

If you are looking for rendering projector texture on top of the objects you should definetly check rageingnonsense post below. He led me to write a good shader that actually works. You can check final results in the picture i posted in comment.

Thanks!

@JacobDzwinel,
now can you do it?

Hey guys.

anyone manage to found a solution for this problem ?

I have been searching and trying different methods for months and things starting to get really frustrating.

So please if anyone knows a solution just share it.

Thanks.