Environment transparency in a radius

I'm trying to work on a isometric view in a game. As you can imagine this brings its own sort of problems when it comes to things disappearing behind walls and out of view.

Is there any fairly simple way of making the environment "in front of" the player character be partially transparent in a radius around the player?

Example Image Only part of the wall should be transparent, not all of it, say a radius 3 times the size of the player.

Send the position of the character to the shader for the walls, and set their alpha based on distance from that radius. Then, alpha blend.

It's probably possible to do all the necessary detection of "in front of" in shaders, but with an isometric game, it's likely that you can do better, easily. I'll let someone else chime in about ideas of how to do that. I only have to offer a method that makes things invisible, blended, or opaque, based on distance, so you're working with a Terminator time-machine style globe.

This is not an optimized method (I'd recommend using square distance and caching more variables for real use), and it just uses a texture, no lighting or anything, but it can give you the idea. Also, I think it only works on Mac/iOS/Android. Sorry, I don't know how to write in Cg at this point. You could try taking it to the forum and asking for a conversion, if you need it.

Shader "Partially Invisible Wall" {

Properties {
    _InvisibleRange ("Fully Invisible Range", Float) = 0
    _OpaqueDistance ("Opaque Distance", Float) = 1
    _MainTex ("Texture", 2D) = ""
}

SubShader {
    Tags {Queue=Transparent}
    Blend SrcAlpha OneMinusSrcAlpha
    Pass {
        GLSLPROGRAM
        varying vec3 position;
        varying vec2 uv;

        #ifdef VERTEX
        void main () {
            gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
            position = gl_Vertex.xyz;
            uv = gl_MultiTexCoord0.xy;
        }
        #endif

        #ifdef FRAGMENT
        uniform sampler2D _MainTex;
        uniform vec3 playerPosition;
        uniform float _InvisibleRange, _OpaqueDistance;
        void main () {
            float distance = distance(position, playerPosition);
            gl_FragColor = vec4(texture2D(_MainTex, uv).rgb,
                    (distance - _InvisibleRange) / (_OpaqueDistance - _InvisibleRange));
        }
        #endif
        ENDGLSL
    }
}

}

You'd have to get the player's local position over to the shader, which you could do with this (although again, this is made to be a simple demonstration, and it could be optimized):

void Update () {
    renderer.material.SetVector("playerPosition", 
        transform.InverseTransformDirection(player.position - transform.position));
}

If you are using first person view, just set the min distance to 3 meters. :-)

It might require some clever sorting, but you could draw a sphere to the depth buffer only before the wall (and anything else in front) is drawn. That way when the wall is drawn the pixels that would have been inside the sphere will be discarded.