XNA SpriteFont有多种颜色?

时间:2011-09-02 20:50:48

标签: xna drawstring

有没有办法绘制带有多个彩色水平区域的文字? 作为一个例子,我想绘制文本“Hello”,下半部分为红色,上部为绿色。要使用的文本必须是动态的。 使用普通纹理,我只使用Draw方法并传递一个子矩形以绘制不同颜色的纹理部分,但是对于文本?

4 个答案:

答案 0 :(得分:1)

最好的方法可能涉及自定义着色器。但是,您也应该能够使用剪刀矩形。

  1. 通常以浅色(绿色)
  2. 绘制文本
  3. 设置ScissorRectangle,只允许在文本的下半部分进行绘制
  4. 使用底色(红色)正常绘制文本。应该修剪上半部分,以便绿色文本保留在那里。
  5. 为了澄清,您的文本应该在同一时间绘制。

答案 1 :(得分:1)

我会用'Crappy Coding Guy'建议的自定义效果来做这个,它需要一些数据发送到效果,下面的代码是你需要逐个像素的HLSL淡化字符串的颜色在Color1和Color2之间。您可以通过从中减去.5并使用于lerp的值乘以10来使其变为纯色变换。

float4x4 Projection;
float4 Color1, Color2;
float FontHeight;
float2 Location;

Texture2D FontTexture;
sampler TextureSampler = sampler_state { texture = <FontTexture> ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = clamp; AddressV = clamp;};

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float2 Texture : TEXCOORD0;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float2 Texture : TEXCOORD0;
    float2 OriginalPosition : TEXCOORD1;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;

    output.OriginalPosition = input.Position;
    output.Texture = input.Texture;
    output.Position = mul(input.Position, Projection);

    return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    float4 fontColor = lerp (Color1, Color2,  (1.0 / FontHeight) * (input.OriginalPosition.y - Location.y));
    return tex2D(TextureSampler, input.Texture)*  fontColor;
}

technique Technique1
{
    pass Pass1
    {
        VertexShader = compile vs_2_0 VertexShaderFunction();
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}

和C#一起使用它。 (显然你不必每帧都设置效果的所有参数,我只是不想发布太多的方法,如果你需要完整的例子我很乐意通过电子邮件发送给你)

protected override void Draw(GameTime gameTime)
{
   GraphicsDevice.Clear(Color.CornflowerBlue);
   fontEffect.Parameters["Projection"].SetValue(Matrix.CreateOrthographicOffCenter(0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 0, 1));
   fontEffect.Parameters["Color1"].SetValue(Color.Red.ToVector4());
   fontEffect.Parameters["Color2"].SetValue(Color.Blue.ToVector4());
   fontEffect.Parameters["FontHeight"].SetValue(font.LineSpacing);
   FieldInfo fontTexture = typeof(SpriteFont).GetField("textureValue", BindingFlags.NonPublic | BindingFlags.Instance);
   fontEffect.Parameters["FontTexture"].SetValue((Texture2D)fontTexture.GetValue(font));            
   fontEffect.CurrentTechnique.Passes[0].Apply(); 

   spriteBatch.Begin( SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, DepthStencilState.Default, RasterizerState.CullNone, fontEffect);            
   spriteBatch.DrawString(font, "abcdefghijklmnopqrstuvxyz", new Vector2(10, 100), Color.White);
   spriteBatch.End();

   base.Draw(gameTime);
}

编辑:您可能会注意到我必须从精灵字体中获取纹理,这是一个非常烦人的私有字段!如果有人知道更好的方法,请告诉我们!

答案 2 :(得分:1)

我知道这是一个老问题,但是这个tool将允许您创建具有各种效果的自定义位图字体,如阴影,浮雕,发光。它将为您生成字体纹理,然后您可以编辑并添加多种颜色或其他后处理效果。在XNA中使用它只需添加到您的Content项目,并将ContentProcessor设置为“Sprite Font Texture”。然后,您可以像加载普通的精灵字体一样在游戏中加载它。

答案 3 :(得分:0)

如果你想要更多的控制,你可以使用两种不同的spritefont纹理。使用位图字体制作器获取您的初始spritefont:http://create.msdn.com/en-US/education/catalog/utility/bitmap_font_maker。如果需要,修改纹理以使其看起来很漂亮(投影等)。制作字体纹理的副本,并用透明的洋红色覆盖文本的上半部分。然后你将文本绘制两次,第二次使用修改后的字体和不同的颜色。这种方法的优点是你的上半部分和下半部分不需要用直线描绘,也就是说上半部分可能是粘在顶部等上面。