问题
So I've been looking across the web to find an answer to this question, but I seem to be missing something.
I've got a little project going that dynamically creates 3D terrain in XNA 4.0, but I want be able to draw a circle (or any other shape for that matter, but let's first go with a circle) on the terrain. Now I've read some things about 'projective texturing' but I'll admit I'm at a complete loss when it comes to shader-language.
The idea is that I can (dynamically) create a basic shape, say a circle with a 2 'units' diameter, then draw that on the terrain to function as an indicator where the cursor is. (I am able to get the cursor position on the 3D terrain.)
Would anyone know how to do this, is it required to use shaders for this? Any help on the matter is apreciated!
Thanks in advance!
回答1:
You can use a shader ...
you pass as parameter to the terrain shader, the 3D world position of your cursor, and a radius... to define a sphere,
the trick is pass the vertex world position from the vertex shader to the pixel shader, and in the pixel shader you only have to tint the output color if the pixel is being drawed, is inside the sphere.
EDIT: I have found an old shader done by myself... with two types of selection circle and box, 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;
}
}
来源:https://stackoverflow.com/questions/8000164/how-to-draw-a-circle-on-3d-terrain-in-xna