Как нарисовать круг на 3D-ландшафте в XNA?

Поэтому я просматривал Интернет, чтобы найти ответ на этот вопрос, но, похоже, я что-то упускаю.

У меня есть небольшой проект, который динамически создает 3D-территорию в XNA 4.0, но я хочу иметь возможность рисовать круг (или любую другую форму, если на то пошло, но давайте сначала начнем с круга) на местности. Теперь я читал кое-что о «проективном текстурировании», но я признаю, что я в полной растерянности, когда дело доходит до языка шейдеров.

Идея состоит в том, что я могу (динамически) создать базовую форму, скажем, круг диаметром 2 «единицы», а затем нарисовать его на местности, чтобы он служил индикатором, где находится курсор. (Я могу получить положение курсора на трехмерной местности.)

Кто-нибудь знает, как это сделать, нужно ли для этого использовать шейдеры? Любая помощь по этому вопросу приветствуется!

Заранее спасибо!


person Strike    schedule 03.11.2011    source источник


Ответы (1)


Вы можете использовать шейдер...

вы передаете в качестве параметра шейдеру ландшафта положение вашего курсора в 3D-мире и радиус... для определения сферы,

хитрость заключается в том, чтобы передать мировую позицию вершины из вершинного шейдера в пиксельный шейдер, а в пиксельном шейдере вам нужно подкрасить выходной цвет только в том случае, если пиксель рисуется внутри сферы.

РЕДАКТИРОВАТЬ: я нашел старый шейдер, сделанный мной... с двумя типами круга выбора и прямоугольника, вот он:

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;       
    }
} 
person Blau    schedule 03.11.2011
comment
Так мне нужно установить параметр в шейдере на вектор3 курсора? Или есть другой способ передать его шейдеру? - person Strike; 06.11.2011
comment
вы можете передать его как часть вершины, но это не имеет смысла, потому что у вас есть только один курсор, и это было бы пустой тратой времени. - person Blau; 06.11.2011
comment
Я добавил шейдер, который сделал некоторое время назад. - person Blau; 06.11.2011
comment
Это было действительно очень полезно. Я также не слышал о функциях расстояния и лерпа в HLSL, так что это открыло мне глаза. - person Strike; 06.11.2011