Nobody is going to teach you how to program shaders in a forum post
Don't mind whipping one up though:
bool CreateCutoutEffect(sf::Shader& InShader, float InRadius, float InSharpness)
{
// Vertex shader.
const char* Vs = R"(
varying vec2 v_Position;
void main()
{
v_Position = (gl_ModelViewMatrix * gl_Vertex).xy;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
})";
// Fragment shader.
const char* Fs = R"(
uniform sampler2D u_Texture;
uniform float u_Radius;
uniform float u_Sharpness;
uniform vec2 u_Origin;
varying vec2 v_Position;
void main()
{
vec2 To = v_Position - u_Origin;
float Percent = dot(To, To) / (u_Radius * u_Radius);
float Modulation = smoothstep(u_Sharpness, 1.0, Percent);
vec4 Color = texture2D(u_Texture, gl_TexCoord[0].st);
gl_FragColor = vec4(Color.rgb, Color.a * Modulation);
})";
bool Result = InShader.loadFromMemory(Vs, Fs);
if (Result)
{
InShader.setParameter("u_Texture", sf::Shader::CurrentTexture);
InShader.setParameter("u_Radius", InRadius);
InShader.setParameter("u_Sharpness", InSharpness);
}
return Result;
}
Only thing you have to do is update the view-space uniform u_Origin whenever your player moves (e.g. shader.setParameter("u_Origin", PlayerPosition). Being in view space means that you'll need to transform the parameter (i.e. PlayerPosition) by the render target's view. The sharpness parameter is in the range [0.0, 1.0] and defines how sharply the circle fades out at the edge.
Doing it with a RenderTexture would be equally simple. You'd just need to clear the render texture with an alpha of 0, render all the to-be-faded elements, then, with alpha blending turned off, render something that has an alpha of (for example) 0 over the area you want faded out, and finally render said RenderTexture over the screen.
EDIT: Totally forgot the whole .NET thing. It should be pretty much identical though.