Halbtransparenten Text anzeigen
Zusammenfassung
Lassen Sie den Text halbtransparent erscheinen.
Betriebsumgebung
Voraussetzungen
Unterstützte XNA-Versionen |
|
Unterstützte Plattformen |
|
Erforderliche Vertex-Shader-Version für Windows | 2.0 |
Erforderliche Pixel-Shader-Version für Windows | 2.0 |
Betriebsumgebung
Bahnsteig |
|
Substanz
Durch Anwenden einer Deckkraft von 0,0~1,0 auf die Color-Struktur, die von der SpriteBatch.DrawString-Methode angegeben wird, können Sie den Text in Halbtransparenz zeichnen. Die meisten Farben, die bereits in den Eigenschaften der Color-Struktur definiert sind, sind nicht auf undurchsichtig gesetzt, so dass sie durch Anwenden von Deckkraft halbtransparent gemacht werden können.
// 半透明の文字(75%)
this.spriteBatch.DrawString(this.font,
"Draw transparent text. (75%)",
new Vector2(50.0f, 100.0f), Color.White * 0.75f);
Color
Konstruktor
Legen Sie die Farbe fest. Es gibt auch einen 0.0~1.0 float-Konstruktor.
r | Byte | Geben Sie die rote Farbe von 0~255 an. |
g | Byte | Geben Sie die grüne Farbe als 0~255 an. |
b | Byte | Geben Sie die blaue Farbe von 0~255 an. |
ein | Byte | Geben Sie die Deckkraft (Alpha-Komponente) von 0~255 an. |
Übrigens, die Methode zum Angeben der durchscheinenden Farbe von Sprites hat sich seit XNA Framework 4.0 geändert, und um ein Format wie "new Color(255, 255, 255, 192)
" anzugeben, das in XNA Framewrok 3.1 und früher verwendet wird, müssen Sie den Verschmelzungsstatus von SpriteBatch mit "BlendState.NonPremultiplied" angeben.
// スプライトの描画準備
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));
Da jedoch die Formel zur Berechnung der Ausgabefarbe geändert wurde, wird der Rand des Zeichens in einem abgedunkelten Zustand angezeigt.
Informationen zur Ausgabefarbe
In den vorherigen Tipps haben wir zwei Mischmuster verwendet, um Text als Beispiel anzuzeigen. Auf der anderen Seite wurde wie erwartet schöner durchscheinender Text angezeigt. Zum anderen wurden die Ränder des Textes abgedunkelt. Dies liegt daran, dass die Formel für die Ausgabe der Farbe je nach verwendetem Verschmelzungsstatus unterschiedlich ist.
Legen Sie die Parameter des Ausdrucks auf
- result : Endgültige Ausgabefarbe
- source : Die Farbe der Textur, die Sie zu zeichnen versuchen
- destination : Die Hintergrundfarbe des Ziels
- RGBA: Bestandteile von R (rot), G (grün), B (blau) bzw. A (alpha (Deckkraft))
Und wie definiert, lautet die Berechnungsformel für die beiden Verschmelzungszustände wie folgt.
- BlendState.AlphaBlend (NULL-Standardwert) (multipliziertes Alpha)
- result = source.rgb + destination.rgb * (1 - source.a) // source.rgb ist jedoch bereits alpha-angewendet
- BlendState.NonPremultiplied (interpoliertes Alpha)
- Ergebnis = Quelle.rgb * Quelle.a + Ziel.rgb * (1 - Quelle.a)
Wenn Sie es mit dieser Formel finden, ist der Wert des Ergebnisses in beiden Fällen gleich. Wenn Sie jedoch bilineare Filter verwenden, werden die oben genannten Berechnungen nach der Farbinterpolation mit benachbarten Pixeln im Pixel-Shader durchgeführt, sodass das endgültige Ausgabeergebnis anders ausfällt.
Ich möchte der Sache halber ein paar Berechnungen anstellen. Wenn die Farbe des Textes weiß (Color.White) ist, ist jede Farbkomponente des Pixels, in dem der Text angezeigt wird, (r:255, g:255, b:255, a:255). Pixel, die keinen Text anzeigen, sind (r:0, g:0, b:0, a:0). Wenn wir den Text bei 50% halbtransparent machen und ihn mit dem Zwischenwert dieser beiden Pixel (d.h. dem Rand des Zeichens) interpolieren, wie verändern die beiden obigen Gleichungen das Ergebnis?
Die Hintergrundfarbe ist übrigens (r:0, g:0, b:255, a:255). (Die Berechnungen werden auf weißem Text und blauem Hintergrund durchgeführt)
Interpolation mit BlendState.AlphaBlend (multipliziertes Alpha)
Da Alpha zuvor auf jedes Element der Textfarbe angewendet wird, wird die Textfarbe um 255 (r:128, g:128, b:128, a:128) halbiert (Color.White * 0.5f"). Pixel, für die kein Text angezeigt wird, werden unverändert belassen (r:0, g:0, b:0, a:0).
Da die bilineare Filterformel ausgeführt wird, bevor der Mischzustand die Hintergrundfarbe berechnet, ist die Farbe des Textrands (r:64, g:64, b:64, a:64), was ein Zwischenwert zwischen (r:128, g:128, b:128, a:128) und (r:0, g:0, b:0, a:0) ist.
Hier ist der Ausdruck
- Ergebnis = Quelle.RGB + Ziel.RGB * (1 - Quelle.A)
Wenn Sie es anwenden auf:
- result = (r:64, g:64, b:64) + (r:0, g:0, b:255) * (1 - 0.25) // 0.25 gibt an, dass a:64 25% von a:255 ist
und die endgültige zusammengesetzte Farbe mit der Hintergrundfarbe ist (R:64, G:64, B:255).
Interpolation mit BlendState.NonPremultiplied (interpoliertes Alpha)
Die Farbe des Textes ist weiß (r:255, g:255, b:255), und nur das Alpha wird halbiert, um es halbtransparent zu machen, sodass der Wert des Pixels, in dem das Zeichen angezeigt wird, (r:255, g:255, b:255, a:128) beträgt (neue Farbe(255, 255, 255, 128)). Pixel, die keinen Text anzeigen, bleiben unverändert (r:0, g:0, b:0, a:0).
Da die bilineare Filterformel ausgeführt wird, bevor der Überblendungsstatus die Hintergrundfarbe berechnet, ist die Farbe des Textrands (r:128, g:128, b:128, b:128, a:64), was ein Zwischenwert zwischen (r:0, g:0, b:0, a:0) ist.
Hier ist der Ausdruck
- Ergebnis = Quelle.rgb * Quelle.a + Ziel.rgb * (1 - Quelle.a)
Wenn Sie es anwenden auf:
- Ergebnis = (R:128, G:128, B:128) * 0,25 + (R:0, G:0, B:255) * (1 - 0,25)
und die endgültige zusammengesetzte Farbe mit der Hintergrundfarbe ist (R:32, G:32, B:224).
Überlegung
Da die Hintergrundfarbe (r:0, g:0, b:255) ist, ermöglicht die Interpolation mit BlendState.AlphaBlend (r:64, g:64, b:255), dass die transparente Farbe des Textes schön ausgedrückt wird, ohne dass das Pigment der Hintergrundfarbe verloren geht. Bei der Interpolation mit BlendState.NonPremultiplied (r:32, g:32, b:224) ist die Blaukomponente jedoch dunkler als die Hintergrundfarbe, sodass die Ränder des Textes (natürlich) abgedunkelt erscheinen.
Rot, Grün ist dunkler als BlendState.AlphaBlend.)
Dieses standardmäßige multiplizierte Alpha aus dem XNA Framework 4.0 ist im Blog "Hinikeni XNA" ausführlich beschrieben, wenn Sie also mehr wissen möchten, beziehen Sie sich bitte auf den untenstehenden Link. Dort wird es als Beispiel für das Zeichnen eines roten Elements vor einem weißen Hintergrund beschrieben.
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);
}
}
}