Visualizza testo semitrasparente
sommario
Fai in modo che il testo appaia semitrasparente.
Ambiente operativo
Prerequisiti
Versioni XNA supportate |
|
Piattaforme supportate |
|
Versione Vertex Shader richiesta da Windows | 2.0 |
Versione Pixel Shader richiesta da Windows | 2.0 |
Ambiente operativo
piattaforma |
|
sostanza
Applicando un'opacità di 0,0~1,0 alla struttura Color specificata dal metodo SpriteBatch.DrawString, è possibile disegnare il testo in semitrasparenza. La maggior parte dei colori già definiti nelle proprietà della struttura Colore non sono impostati su opachi, quindi possono essere resi semitrasparenti applicando l'opacità.
// 半透明の文字(75%)
this.spriteBatch.DrawString(this.font,
"Draw transparent text. (75%)",
new Vector2(50.0f, 100.0f), Color.White * 0.75f);
Color
costruttore
Imposta il colore. C'è anche un costruttore float 0.0~1.0.
r | byte | Specificare il colore rosso da 0~255. |
g | byte | Specificare il colore verde come 0~255. |
b | byte | Specificare il colore blu da 0~255. |
un | byte | Specificare l'opacità (componente alfa) da 0~255. |
A proposito, il metodo per specificare il colore traslucido degli sprite è cambiato rispetto a XNA Framework 4.0 e per specificare un formato come "new Color(255, 255, 255, 192)
" utilizzato in XNA Framewrok 3.1 e versioni precedenti, è necessario specificare lo stato di fusione di SpriteBatch con "BlendState.NonPremultiplied".
// スプライトの描画準備
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));
Tuttavia, poiché la formula per il calcolo del colore di output è stata modificata, il bordo del carattere verrà visualizzato in uno stato scuro.
Informazioni sul colore di output
Nei suggerimenti precedenti, abbiamo utilizzato due modelli di fusione per visualizzare il testo come esempio. D'altra parte, il bel testo traslucido è stato visualizzato come previsto. D'altra parte, i bordi del testo erano scuriti. Ciò è dovuto al fatto che la formula per l'output del colore varia a seconda dello stato di fusione utilizzato.
Impostare i parametri dell'espressione su
- risultato : Colore di output finale
- fonte : Il colore della texture che stai cercando di disegnare
- destinazione : Il colore di sfondo della destinazione
- RGBA: componenti di R (rosso), G (verde), B (blu) e A (alfa (opacità)) rispettivamente
E come definito, la formula di calcolo per i due stati di fusione è la seguente.
- BlendState.AlphaBlend (valore predefinito null) (alfa moltiplicato)
- risultato = sorgente.rgb + destinazione.rgb * (1 - sorgente.a) // Tuttavia, sorgente.rgb è già applicato alfa
- BlendState.NonPremultiplied (alfa interpolato)
- risultato = sorgente.rgb * sorgente.a + destinazione.rgb * (1 - sorgente.a)
Infatti, se lo trovi con questa formula, il valore del risultato sarà lo stesso in entrambi i casi. Tuttavia, se si utilizza il filtro bilineare, i calcoli precedenti vengono eseguiti dopo l'interpolazione del colore con i pixel adiacenti nel pixel shader, quindi il risultato finale dell'output sarà diverso.
Vorrei fare alcuni calcoli per il gusto di farlo. Se il colore del testo è bianco (Color.White), ogni componente di colore del pixel in cui viene visualizzato il testo è (r:255, g:255, b:255, a:255). I pixel che non visualizzano il testo sono (r:0, g:0, b:0, a:0). Se rendiamo il testo semitrasparente al 50% e lo interpoliamo con il valore intermedio di questi due pixel (cioè il bordo del carattere), in che modo le due equazioni precedenti modificano il risultato?
A proposito, il colore di sfondo è (r:0, g:0, b:255, a:255). (I calcoli vengono eseguiti su testo bianco e sfondo blu)
Interpolazione con BlendState.AlphaBlend (alfa moltiplicato)
Poiché alfa viene applicato in anticipo a ciascun elemento del colore del testo, il colore del testo viene dimezzato di 255 (r:128, g:128, b:128, a:128) (Color.White * 0.5f"). I pixel per i quali non è visualizzato il testo vengono lasciati così come sono (r:0, g:0, b:0, a:0).
Poiché la formula del filtro bilineare viene eseguita prima che lo stato di fusione calcoli il colore di sfondo, il colore del bordo del testo è (r:64, g:64, b:64, a:64), che è un valore intermedio tra (r:128, g:128, b:128, a:128) e (r:0, g:0, b:0, a:0).
Ecco l'espressione
- risultato = sorgente.rgb + destinazione.rgb * (1 - sorgente.a)
Se lo applichi a:
- Risultato = (R:64, G:64, B:64) + (R:0, G:0, B:255) * (1 - 0,25) // 0,25 indica che A:64 è il 25% di A:255
e il colore composito finale con il colore di sfondo è (r:64, g:64, b:255).
Interpolazione con BlendState.NonPremultiplied (alfa interpolato)
Il colore del testo è bianco (r:255, g:255, b:255), e solo l'alfa è dimezzato per renderlo semitrasparente, quindi il valore del pixel in cui viene visualizzato il carattere è (r:255, g:255, b:255, a:128) (new Color(255, 255, 255, 128)). I pixel che non visualizzano il testo rimangono invariati (r:0, g:0, b:0, a:0).
Poiché la formula del filtro bilineare viene eseguita prima che lo stato di fusione calcoli il colore di sfondo, il colore del bordo del testo è (r:128, g:128, b:128, b:128, a:64), che è un valore intermedio tra (r:0, g:0, b:0, a:0).
Ecco l'espressione
- risultato = sorgente.rgb * sorgente.a + destinazione.rgb * (1 - sorgente.a)
Se lo applichi a:
- Risultato = (R:128, G:128, B:128) * 0,25 + (R:0, G:0, B:255) * (1 - 0,25)
e il colore composito finale con il colore di sfondo è (r:32, g:32, b:224).
considerazione
Poiché il colore di sfondo è (r:0, g:0, b:255), l'interpolazione con BlendState.AlphaBlend (r:64, g:64, b:255) consente di esprimere in modo ottimale il colore trasparente del testo senza perdere il pigmento del colore di sfondo. Tuttavia, nel caso dell'interpolazione con BlendState.NonPremultiplied (r:32, g:32, b:224), il componente blu è più scuro del colore di sfondo, quindi i bordi del testo sembrano essere scuriti (ovviamente).
Rosso, Verde è più scuro di BlendState.AlphaBlend.)
Questo alfa moltiplicato predefinito da XNA Framework 4.0 è descritto in dettaglio nel blog "Hinikeni XNA", quindi se vuoi saperne di più, fai riferimento al link sottostante. Laggiù, è descritto come un esempio di disegno di un elemento rosso su uno sfondo bianco.
Tutti i codici
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);
}
}
}