XNA SpriteFont с несколькими цветами? - PullRequest
0 голосов
/ 03 сентября 2011

Есть ли способ нарисовать текст с несколькими цветными горизонтальными областями?В качестве примера я хочу нарисовать текст «Hello» с нижней половиной красным и верхней зеленой.Текст для использования должен быть динамическим.С обычной текстурой я бы просто использовал метод Draw и передал бы прямоугольник, чтобы нарисовать части текстуры другим цветом, но для текста?

Ответы [ 4 ]

1 голос
/ 26 октября 2012

Я знаю, что это старый вопрос, но этот инструмент позволит вам создавать пользовательские шрифты Bit Map со всеми видами эффектов, такими как тени, тиснение, свечение. Он создаст для вас текстуру шрифта, которую вы затем сможете редактировать и добавлять несколько цветов или другие эффекты последующей обработки. Использование его в XNA - это всего лишь вопрос добавления в ваш проект Content и установки ContentProcessor на «Sprite Font Texture». Затем вы можете загрузить его в свою игру так же, как и обычный шрифт спрайта.

1 голос
/ 16 сентября 2011

Я бы сделал это с пользовательским эффектом, предложенным '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);
}

Редактировать: Вы, вероятно, заметите, что мне пришлось извлечь текстуру из шрифта спрайта, это приватное поле, которое довольно раздражает! Если кто-нибудь знает лучший способ получить это, пожалуйста, сообщите!

1 голос
/ 03 сентября 2011

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

  1. Нарисуйте текст обычным цветом (зеленый)
  2. Установите ScissorRectangle , который позволяет рисовать только в нижней половине текста
  3. Нарисуйте текст как обычно, используя нижний цвет (красный). Верхняя половина должна быть обрезана, чтобы зеленый текст оставался там.

Для пояснения, ваш текст должен быть нарисован в одном и том же месте оба раза.

0 голосов
/ 05 сентября 2011

Если вы хотите больше контроля, вы можете использовать две разные текстуры spritefont. Используйте средство создания растровых шрифтов, чтобы получить начальный spritefont: http://create.msdn.com/en-US/education/catalog/utility/bitmap_font_maker. При желании измените текстуру, чтобы она выглядела хорошо (тень и т. Д.). Сделайте копию текстуры шрифта и замените верхнюю половину текста прозрачным пурпурным цветом. Затем вы рисуете текст дважды, второй раз с измененными шрифтами и другим цветом. Преимущество этого метода заключается в том, что верхняя и нижняя половина не должны быть очерчены прямой линией, т. Е., Возможно, верхняя половина может быть излишне капающей через верх и т. Д.

...