You can use a shader ...
you pass as a parameter the landscape shader, the three-dimensional position of your cursor and the radius ... to determine the sphere,
the trick transfers the vertex world point from the vertex shader to the pixel shader and in the pixel shader you only need to paint over the output color, if the pixel is selected, it is inside the sphere.
EDIT: I found an old shader made by me ... with two types of selection circle and window, here you are:
uniform float4x4 xWorldViewProjection; uniform float3 xCursorPos; uniform float xCursorRadio; uniform float4 xLightColor = float4(0.8, 0.8, 0.8,1); uniform float4 xAmbientFactor = 0.4f; uniform float3 xCamPos; uniform int xCursorType=0; // 0: Circle 1: Box void VS_Basico( in float4 inPos : POSITION, in float3 inNormal : NORMAL0, in float4 inColor : COLOR0, out float4 outPos: POSITION, out float3 outNormal:TEXCOORD1, out float3 outPos2 : TEXCOORD0, out float4 outColor: COLOR0 ) { outPos = mul (inPos, xWorldViewProjection); outNormal = inNormal; outPos2 = inPos.xyz; outColor = inColor; } float4 PS_CursorPerPixelCircular ( in float4 inColor : COLOR, in float3 inPos:TEXCOORD0 ) : COLOR { float f = distance(inPos, xCursorPos); float4 outColor = inColor; if (f<xCursorRadio) { outColor=lerp(float4(0,1,1,1), inColor, 0.4) ; } return outColor; } float4 PS_CursorPerPixelCuadrado ( in float4 inColor : COLOR, in float3 inPos:TEXCOORD0 ) : COLOR { float3 size = float3(xCursorRadio,xCursorRadio,xCursorRadio); float3 minSize = xCursorPos - size; float3 maxSize = xCursorPos + size; float4 outColor = inColor; if (inPos.x>=minSize.x && inPos.x<=maxSize.x && inPos.y>=minSize.y && inPos.y<=maxSize.y && inPos.z>=minSize.z && inPos.z<=maxSize.z ) { outColor=lerp(float4(0,1,1,1), inColor, 0.4) ; } return outColor; } void PS_Basico( in float4 inColor : COLOR0, in float3 inPos:TEXCOORD0, in float3 inNormal:TEXCOORD1, out float4 outColor: COLOR0 ) { float3 xLightPos = float3(40, 40, 0); float3 LightDir = normalize(inPos - xLightPos); float3 reflectionVector = reflect(LightDir, inNormal); float3 eyeVector = inPos - xCamPos; float specular = dot(normalize(reflectionVector), normalize(eyeVector)); specular = pow(specular, 256); float difusse_factor = -dot(normalize(inNormal), LightDir); if (difusse_factor<0) difusse_factor = 0; float4 col = inColor * xAmbientFactor + inColor * difusse_factor * xLightColor; if (xCursorType ==0) { col = PS_CursorPerPixelCircular(col, inPos); } else { col = PS_CursorPerPixelCuadrado(col, inPos); } col.a = 1; col.rgb += specular; /* col.xyz = col.xyz * (inPos.y+1) / 2; col.y = 2*col.x; col.z = 2*col.x; */ outColor = col; //outColor = float4(inNormal, 1); } //------------------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------- //--- TECNIQUES ----------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------------- technique ColoredWired { pass Pass0 { VertexShader = compile vs_2_0 VS_Basico(); PixelShader = compile ps_2_0 PS_Basico(); FILLMODE = WIREFRAME; } } technique ColoredSolid { pass Pass0 { VertexShader = compile vs_2_0 VS_Basico(); PixelShader = compile ps_2_0 PS_Basico(); FILLMODE = SOLID; } }