Search Unity

Shadow mapping at different heights?

Discussion in 'General Graphics' started by Nicolas-Liatti, Jun 15, 2016.

  1. Nicolas-Liatti

    Nicolas-Liatti

    Joined:
    Jun 19, 2013
    Posts:
    89
    Hi,

    I'm working on implementing a shadow mapping solution, which I'm using as a "line of sight". I basically use the same technic as shadow mapping to display what the enemy sees.
    So far, this works great.

    Now, I would like to represent what the enemy would see for a specific height: for example, if an object makes a height of 1, display where it would be visible from the enemy.

    I tried to do this by modifying the shadow maps algorithm, by rendering the world position with + 1:

    Code (CSharp):
    1. half4 FragOrtho (VertexOut i) : COLOR
    2.         {
    3.             float4 positionWorld = OrthoGraphicDepthToWorldPosition(i);
    4.               float visible = 0.0;
    5.  
    6.               positionWorld.y += 1.0;
    7.               visible += CalculateVisibility(positionWorld);
    8.             return GenerateMask(visible);
    9.         }
    My problem is that it's "bleeding" on other objects, and I don't know how I can fix this.

    Here is the code which is computing the visibility:

    Code (CSharp):
    1. float CalculateVisibility(float4 pixelWorldPos)
    2.         {
    3.             // Calculate distance to source in range[0 - far plane]
    4.             float sourceDistance = distance(pixelWorldPos.xyz, _SourceInfo.xyz);
    5.  
    6.             // Convert world space to LOS cam depth texture UV's
    7.             float4 sourcePos = mul(_SourceWorldProj, pixelWorldPos);
    8.  
    9.  
    10.             float3 sourceNDC = sourcePos.xyz / sourcePos.w;
    11.  
    12.             // Clip pixels outside of source
    13.             clip(max(min(sourcePos.w, 1 - abs(sourceNDC.x)), _Settings.w - 0.5));
    14.  
    15.             // Convert from NDC to UV
    16.             float2 sourceUV = sourceNDC.xy;
    17.             sourceUV *= 0.5f;
    18.             sourceUV += 0.5f;
    19.  
    20.             // VSM
    21.             float2 moments = tex2D(_SourceDepthTex, sourceUV).rg;
    22.             //moments.y = moments.y - 1;
    23.  
    24.             float visible = ChebyshevUpperBound(moments, sourceDistance, _Settings.z);
    25.  
    26.             // Handle vertical out of bound pixels
    27.             visible += _Flags.x * _Flags.y * (1 - step(abs(sourceNDC.y), 1.0));
    28.             visible = saturate(visible);
    29.  
    30.             // Ignore pixels behind source
    31.             visible *= step(-sourcePos.w, 0);
    32.  
    33.             // Calculate fading
    34.             float edgeFade = CalculateFade(abs(sourceNDC.x), _Settings.y);
    35.             float distanceFade = CalculateFade(sourceDistance / _SourceInfo.w, _Settings.x);
    36.  
    37.             // Apply fading
    38.             visible *= distanceFade;
    39.             visible *= edgeFade;
    40.  
    41.             return visible;
    42.         }
    I think I would need to modify something there to take into account the +1 on the world pos, but I can't find where...
    Any idea for someone good at maths? :)

    Here is my current result, as you can see the back of the wall shouldn't be green:
     
  2. theANMATOR2b

    theANMATOR2b

    Joined:
    Jul 12, 2014
    Posts:
    7,790
    So this is way above my knowledge base as an artist although I know the logic for shadow maps. So Ill give this a shot
    Not sure about the height thing, but for the bleeding - couldnt the polygon normals be read on the surface detected. If the normal of the polygon is facing the shadow caster, and the shader is opaque the shadow map ends at that polygon - does not travel further in that direction.
     
  3. Nicolas-Liatti

    Nicolas-Liatti

    Joined:
    Jun 19, 2013
    Posts:
    89
    That could be a solution yes. but I think there's a mistake in my equation, because when I don't add the "height", the visible pixels are right and it does not bleed.