Semi-transparante tekst weergeven
samenvatting
Laat de tekst semi-transparant lijken.
Werkomgeving
Voorwaarden
Ondersteunde XNA-versies |
|
Ondersteunde platforms |
|
Windows vereist Vertex Shader-versie | 2.0 |
Windows Vereiste Pixel Shader-versie | 2.0 |
Werkomgeving
perron |
|
stof
Door een dekking van 0,0~1,0 toe te passen op de kleurstructuur die is opgegeven door de methode SpriteBatch.DrawString, kunt u de tekst in semi-transparantie tekenen. De meeste kleuren die al zijn gedefinieerd in de eigenschappen van de kleurstructuur zijn niet ingesteld op ondoorzichtig, dus ze kunnen semi-transparant worden gemaakt door dekking toe te passen.
// 半透明の文字(75%)
this.spriteBatch.DrawString(this.font,
"Draw transparent text. (75%)",
new Vector2(50.0f, 100.0f), Color.White * 0.75f);
Color
bouwer
Stel de kleur in. Er is ook een 0.0~1.0 float constructor.
r | byte | Specificeer de rode kleur van 0~255. |
g | byte | Geef de groene kleur op als 0~255. |
b | byte | Specificeer de blauwe kleur van 0~255. |
een | byte | Specificeer de dekking (alfacomponent) van 0~255. |
Trouwens, de methode voor het specificeren van de doorschijnende kleur van sprites is veranderd sinds XNA Framework 4.0, en om een formaat zoals "new Color(255, 255, 255, 192)
" te specificeren dat wordt gebruikt in XNA Framewrok 3.1 en eerder, moet je de mengstatus van SpriteBatch specificeren met "BlendState.NonPremultiplyplied".
// スプライトの描画準備
this.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
// 半透明の文字(75%)
this.spriteBatch.DrawString(this.font,
"Draw transparent text. (75%)",
new Vector2(50.0f, 100.0f), new Color(255, 255, 255, 192));
Aangezien de formule voor het berekenen van de uitvoerkleur echter is gewijzigd, wordt de rand van het teken in een donkere toestand weergegeven.
Over de uitvoerkleur
In de vorige tips hebben we twee overvloeipatronen gebruikt om tekst als voorbeeld weer te geven. Aan de andere kant werd zoals verwacht prachtige doorschijnende tekst weergegeven. Aan de andere kant werden de randen van de tekst donkerder gemaakt. Dit komt omdat de formule voor het uitvoeren van de kleur verschilt afhankelijk van de gebruikte mengtoestand.
Stel de parameters van de expressie in op
- resultaat : Uiteindelijke uitvoerkleur
- bron : De kleur van de textuur die u probeert te tekenen
- bestemming : De achtergrondkleur van de bestemming
- RGBA: Componenten van respectievelijk R (rood), G (groen), B (blauw) en A (alfa (dekking))
En zoals gedefinieerd, is de berekeningsformule voor de twee mengtoestanden als volgt.
- BlendState.AlphaBlend (standaard null) (vermenigvuldigde alfa)
- resultaat = source.rgb + destination.rgb * (1 - source.a) // source.rgb is echter al alfa-toegepast
- BlendState.NonPremultiplyplied (geïnterpoleerde alfa)
- resultaat = bron.rgb * bron.a + bestemming.rgb * (1 - bron.a)
In feite, als u het met deze formule vindt, zal de waarde van het resultaat in beide gevallen hetzelfde zijn. Als u echter bilineaire filtering gebruikt, worden de bovenstaande berekeningen uitgevoerd na kleurinterpolatie met aangrenzende pixels in de pixelshader, zodat het uiteindelijke uitvoerresultaat anders zal zijn.
Ik zou graag wat berekeningen willen doen omwille van het. Als de kleur van de tekst wit is (Color.White), is elke kleurcomponent van de pixel waarin de tekst wordt weergegeven (r:255, g:255, b:255, a:255). Pixels die geen tekst weergeven zijn (r:0, g:0, b:0, a:0). Als we de tekst semi-transparant maken op 50% en deze interpoleren met de tussenliggende waarde van deze twee pixels (d.w.z. de rand van het teken), hoe veranderen de bovenstaande twee vergelijkingen dan het resultaat?
Trouwens, de achtergrondkleur is (r:0, g:0, b:255, a:255). (Berekeningen worden uitgevoerd op witte tekst en blauwe achtergrond)
Interpolatie met BlendState.AlphaBlend (vermenigvuldigde alfa)
Aangezien alfa vooraf op elk element van de tekstkleur wordt toegepast, wordt de tekstkleur gehalveerd met 255 (r:128, g:128, b:128, a:128) (Kleur.Wit * 0.5f"). Pixels waarop geen tekst wordt weergegeven, worden gelaten zoals ze zijn (r:0, g:0, b:0, a:0).
Aangezien de bilineaire filterformule wordt uitgevoerd voordat de overvloeitoestand de achtergrondkleur berekent, is de kleur van de rand van de tekst (r:64, g:64, b:64, a:64), wat een tussenliggende waarde is tussen (r:128, g:128, b:128, a:128) en (r:0, g:0, b:0, a:0).
Hier is de uitdrukking
- resultaat = source.rgb + destination.rgb * (1 - source.a)
Als u het toepast op:
- resultaat = (r:64, g:64, b:64) + (r:0, g:0, b:255) * (1 - 0,25) // 0,25 geeft aan dat a:64 25% van a:255 is
En de uiteindelijke samengestelde kleur met de achtergrondkleur is (R:64, G:64, B:255).
Interpolatie met BlendState.NonPremultiplyplied (geïnterpoleerde alfa)
De kleur van de tekst is wit (r:255, g:255, b:255), en alleen de alfa is gehalveerd om het semi-transparant te maken, dus de waarde van de pixel waarin het teken wordt weergegeven is (r:255, g:255, b:255, a:128) (nieuwe kleur (255, 255, 255, 128)). Pixels die geen tekst weergeven, blijven hetzelfde (r:0, g:0, b:0, a:0).
Aangezien de bilineaire filterformule wordt uitgevoerd voordat de overvloeitoestand de achtergrondkleur berekent, is de kleur van de rand van de tekst (r:128, g:128, b:128, b:128, a:64), wat een tussenliggende waarde is tussen (r:0, g:0, b:0, a:0).
Hier is de uitdrukking
- resultaat = bron.rgb * bron.a + bestemming.rgb * (1 - bron.a)
Als u het toepast op:
- resultaat = (r:128, g:128, b:128) * 0,25 + (r:0, g:0, b:255) * (1 - 0,25)
En de uiteindelijke samengestelde kleur met de achtergrondkleur is (R:32, G:32, B:224).
overweging
Aangezien de achtergrondkleur (r:0, g:0, b:255) is, zorgt interpolatie met BlendState.AlphaBlend (r:64, g:64, b:255) ervoor dat de transparante kleur van de tekst mooi wordt uitgedrukt zonder het pigment van de achtergrondkleur te verliezen. In het geval van interpolatie met BlendState.NonPremultiplyplied (r:32, g:32, b:224) is de blauwe component echter donkerder dan de achtergrondkleur, zodat de randen van de tekst (natuurlijk) donkerder lijken te zijn.
Rood, Groen is donkerder dan BlendState.AlphaBlend.)
Deze standaard vermenigvuldigde alfa van het XNA Framework 4.0 wordt in detail beschreven in de blog "Hinikeni XNA", dus als je meer wilt weten, raadpleeg dan de onderstaande link. Daar wordt het beschreven als een voorbeeld van het tekenen van een rood element tegen een witte achtergrond.
Alle codes
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
#if WINDOWS_PHONE
using Microsoft.Xna.Framework.Input.Touch;
#endif
namespace TransparentText
{
<summary>
ゲームメインクラス
</summary>
public class GameMain : Microsoft.Xna.Framework.Game
{
<summary>
グラフィックデバイス管理クラス
</summary>
private GraphicsDeviceManager graphics = null;
<summary>
スプライトのバッチ化クラス
</summary>
private SpriteBatch spriteBatch = null;
<summary>
スプライトでテキストを描画するためのフォント
</summary>
private SpriteFont font = null;
<summary>
GameMain コンストラクタ
</summary>
public GameMain()
{
// グラフィックデバイス管理クラスの作成
this.graphics = new GraphicsDeviceManager(this);
// ゲームコンテンツのルートディレクトリを設定
this.Content.RootDirectory = "Content";
#if WINDOWS_PHONE
// Windows Phone のデフォルトのフレームレートは 30 FPS
this.TargetElapsedTime = TimeSpan.FromTicks(333333);
// バックバッファサイズの設定
this.graphics.PreferredBackBufferWidth = 480;
this.graphics.PreferredBackBufferHeight = 800;
// フルスクリーン表示
this.graphics.IsFullScreen = true;
#endif
}
<summary>
ゲームが始まる前の初期化処理を行うメソッド
グラフィック以外のデータの読み込み、コンポーネントの初期化を行う
</summary>
protected override void Initialize()
{
// TODO: ここに初期化ロジックを書いてください
// コンポーネントの初期化などを行います
base.Initialize();
}
<summary>
ゲームが始まるときに一回だけ呼ばれ
すべてのゲームコンテンツを読み込みます
</summary>
protected override void LoadContent()
{
// テクスチャーを描画するためのスプライトバッチクラスを作成します
this.spriteBatch = new SpriteBatch(this.GraphicsDevice);
// フォントをコンテンツパイプラインから読み込む
this.font = this.Content.Load<SpriteFont>("Font");
}
<summary>
ゲームが終了するときに一回だけ呼ばれ
すべてのゲームコンテンツをアンロードします
</summary>
protected override void UnloadContent()
{
// TODO: ContentManager で管理されていないコンテンツを
// ここでアンロードしてください
}
<summary>
描画以外のデータ更新等の処理を行うメソッド
主に入力処理、衝突判定などの物理計算、オーディオの再生など
</summary>
<param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
protected override void Update(GameTime gameTime)
{
// Xbox 360 コントローラ、Windows Phone の BACK ボタンを押したときに
// ゲームを終了させます
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
{
this.Exit();
}
// TODO: ここに更新処理を記述してください
// 登録された GameComponent を更新する
base.Update(gameTime);
}
<summary>
描画処理を行うメソッド
</summary>
<param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
protected override void Draw(GameTime gameTime)
{
// 画面を指定した色でクリアします
this.GraphicsDevice.Clear(Color.CornflowerBlue);
// スプライトの描画準備
this.spriteBatch.Begin();
// 通常の文字
this.spriteBatch.DrawString(this.font,
"Draw normal text.",
new Vector2(50.0f, 50.0f), Color.White);
// 半透明の文字(75%)
this.spriteBatch.DrawString(this.font,
"Draw transparent text. (75%)",
new Vector2(50.0f, 100.0f), Color.White * 0.75f);
// 半透明の文字(50%)
this.spriteBatch.DrawString(this.font,
"Draw transparent text. (50%)",
new Vector2(50.0f, 150.0f), Color.White * 0.5f);
// 半透明の文字(25%)
this.spriteBatch.DrawString(this.font,
"Draw transparent text. (25%)",
new Vector2(50.0f, 200.0f), Color.White * 0.25f);
// スプライトの一括描画
this.spriteBatch.End();
// 登録された DrawableGameComponent を描画する
base.Draw(gameTime);
}
}
}