How to detect in a shader, if two objects are close

Hi,

I'd like to write a shader effect, where a transparent wall "glows" locally when a ball comes near it. By "glow" I mean simply make the transparent wall locally opaque. In my current implementation that wall doesn't glow correctly. In a script attached to the wall I pass the ball position to the wall-shader:

renderer.material.SetVector("_BallPos", Vector4(pinball.transform.position.x, 
 pinball.transform.position.y, pinball.transform.position.z, 1));

So far I've written this shader code:

Shader "PinballShaders/BoundaryGlowShader"
{
    Properties 
    {
        _Color ("Main Color", Color) = (0.1, 0.3, 0.7, 0.25)
        _BallPos("Pinball position", Vector) = (0,0,0,1)
        //Max dist indicates the size of the effect when 
        //pinball comes near the wall
        _MaxDist("Maximum distance", Float) = 2.0
        _MainTex ("Base (RGBA)", 2D) = "white" {}
    }
    SubShader 
    {
        //Blend One One 
        Blend SrcAlpha OneMinusSrcAlpha

        Tags {Queue = Transparent}
        Cull Off

        Pass
        {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"

uniform float4 _Color;
uniform float4 _BallPos;
uniform float _MaxDist;
uniform sampler2D _MainTex;

struct v2f {
    float4 pos : POSITION;
    float4 color : COLOR0;
    float4 fragPos : COLOR1;
};

v2f vert (appdata_base v)
{
    v2f o;
    o.pos = mul (glstate.matrix.mvp, v.vertex);
    //Store the fragment position relative to eye coordinate system.
    //Is this interpolated between vertex and fragment shader?
    o.fragPos = o.pos;
    o.color = _Color;
    return o;
}

half4 frag (v2f i) : COLOR
{
    float4 outColor = i.color;
    float distance = length(_BallPos - i.fragPos.rgba);
    //the nearer the ball to pixel's 3d coordinate, the more opaque it should be
    outColor.a =  max(1 - distance / _MaxDist, 0.0);

    return outColor;
}
ENDCG

        }
    } 
    FallBack "VertexLit"
}

Any idea what's wrong with my code? Isn't fragPos interpolated across the triangle?

Looks like your checking the distance in the pixel shader, after coordinates have already been transformed into eye / screen space.

You need to convert the point into the wall’s local co-ordinate system, and then do the distance calculation in the vertext shader instead.

Convert the position of the ball into local space before sending to the shader:

Vector4 localPoint = transform.InverseTransformPoint(pinball.transform.position);
localPoint.Scale(transform.localScale);
localPoint.w = 1;
renderer.material.SetVector("_BallPos", localPoint);

And the shader changes:

v2f vert (appdata_base v)
{
    v2f o;
    // Check distance here.

    float dist = distance(_BallPos, v.vertex);
    float safety = step(0.001 , maxDistance);
    o.color = _Color;
    o.color.a = safety *  (1 - clamp(dist, 0, maxDistance)/maxDistance);
    o.pos = mul (glstate.matrix.mvp, v.vertex);
    //Store the fragment position relative to eye coordinate system.
    //Is this interpolated between vertex and fragment shader?
    o.fragPos = o.pos;
    return o;
}

half4 frag (v2f i) : COLOR
{
    float4 outColor = i.color;
    return outColor;
}

Thanks to Horsman. I changed a bit of his code, so that it works fine even for objects of arbitrary triangulation:

struct v2f {
    float4 pos : POSITION;
    float4 color : COLOR0;
    //position of the wall fragment in eye coordinates
    float4 fragPos : TEXCOORD1;
    //position of the pinball in eye coordinates
    float4 ballPos : TEXCOORD2;
};

v2f vert (appdata_base v)
{
    v2f o;
    o.color = _Color;
    o.pos = mul (glstate.matrix.mvp, v.vertex);

    o.fragPos = mul (glstate.matrix.modelview[0], v.vertex);
    o.ballPos = mul (glstate.matrix.modelview[0], _BallPos);

    return o;
}

half4 frag (v2f i) : COLOR
{
    float4 outColor = i.color;

    // Check distance here.
    float dist = distance(i.ballPos, i.fragPos);
    float safety = step(0.001 , _MaxDist);
    outColor.a = safety *  (1 - clamp(dist, 0, _MaxDist)/_MaxDist);

    return outColor;
}

Performance would be better, if the ball position in eye coordinates would not be computed in the vertex shader (=matrix multiplication for each vertex) but in a Unity script (=only one matrix multiplication).