2011-09-02 126 views
0

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

回答

1

最好的方法可能会涉及自定义着色器。但是,你应该也可以用剪刀矩形做它。

  1. 在你上面的颜色通常绘制文本(绿色)
  2. 建立一个ScissorRectangle,允许对文本
  3. 的下半部分只绘制正常绘制的文本,用您的底部颜色(红) 。上半部分应该被裁剪,所以绿色文字应该保留在那里。

为了澄清,你的文本应该在同一个地方绘制两次。

0

如果你想要更多的控制,你可以使用两个不同的spritefont纹理。使用位图字体制作工具来获取您的初始精灵字体:http://create.msdn.com/en-US/education/catalog/utility/bitmap_font_maker。如果需要,修改你的纹理,使其看起来不错(投影等)。制作字体纹理的副本,并用透明洋红色覆盖文本的上半部分。然后你画两次你的文字,第二次用修改过的字体和不同的颜色。这种方法的优点是,你的上半部分和下半部分不需要用直线划定,也许上半部分可能是咕噜咕噜咕噜的顶部等。

1

我会用自定义效果正如'Crappy Coding Guy'所建议的那样,它需要一些数据发送到效果,下面的代码是HLSL,您需要逐像素地淡化Color1和Color2之间字符串的颜色。你可以把它一个坚实的颜色变化的数值减去1.5到饱和乘以用于线​​性插值的值由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); 
} 

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

1

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