Εμφάνιση ημιδιαφανούς κειμένου
περίληψη
Κάντε το κείμενο να φαίνεται ημιδιαφανές.
Περιβάλλον λειτουργίας
Προϋποθέσεις
Υποστηριζόμενες εκδόσεις XNA |
|
Υποστηριζόμενες πλατφόρμες |
|
Windows Απαιτούμενη έκδοση σκίασης Vertex | 2.0 |
Απαιτούμενη έκδοση Pixel Shader των Windows | 2.0 |
Περιβάλλον λειτουργίας
πλατφόρμα |
|
ουσία
Εφαρμόζοντας μια αδιαφάνεια 0.0~1.0 στη δομή χρώματος που καθορίζεται από τη μέθοδο SpriteBatch.DrawString, μπορείτε να σχεδιάσετε το κείμενο σε ημιδιαφάνεια. Τα περισσότερα από τα χρώματα που έχουν ήδη οριστεί στις ιδιότητες της δομής χρωμάτων δεν έχουν οριστεί σε αδιαφανή, επομένως μπορούν να γίνουν ημιδιαφανή εφαρμόζοντας αδιαφάνεια.
// 半透明の文字(75%)
this.spriteBatch.DrawString(this.font,
"Draw transparent text. (75%)",
new Vector2(50.0f, 100.0f), Color.White * 0.75f);
Color
κατασκευαστής
Ορίστε το χρώμα. Υπάρχει επίσης ένας κατασκευαστής πλωτήρα 0,0 ~ 1,0.
r | δυφιοοκτάδα | Καθορίστε το κόκκινο χρώμα από 0 ~ 255. |
g | δυφιοοκτάδα | Καθορίστε το πράσινο χρώμα ως 0 ~ 255. |
b | δυφιοοκτάδα | Καθορίστε το μπλε χρώμα από 0 ~ 255. |
ένας | δυφιοοκτάδα | Καθορίστε την αδιαφάνεια (στοιχείο άλφα) από 0~255. |
Παρεμπιπτόντως, η μέθοδος καθορισμού του ημιδιαφανούς χρώματος των αντικειμένων έχει αλλάξει από το XNA Framework 4.0 και για να καθορίσετε μια μορφή όπως "new Color(255, 255, 255, 192)
" που χρησιμοποιείται στο XNA Framewrok 3.1 και νωρίτερα, πρέπει να καθορίσετε την κατάσταση ανάμειξης του SpriteBatch με το "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));
Ωστόσο, δεδομένου ότι ο τύπος για τον υπολογισμό του χρώματος εξόδου έχει αλλάξει, η άκρη του χαρακτήρα θα εμφανιστεί σε σκοτεινή κατάσταση.
Πληροφορίες για το χρώμα εξόδου
Στις προηγούμενες συμβουλές, χρησιμοποιήσαμε δύο μοτίβα ανάμειξης για να εμφανίσουμε κείμενο ως παράδειγμα. Από την άλλη, όμορφο ημιδιαφανές κείμενο εμφανίστηκε όπως αναμενόταν. Από την άλλη, οι άκρες του κειμένου σκοτείνιασαν. Αυτό συμβαίνει επειδή ο τύπος για την εξαγωγή του χρώματος διαφέρει ανάλογα με την κατάσταση ανάμειξης που χρησιμοποιείται.
Ορίστε τις παραμέτρους της παράστασης σε
- αποτέλεσμα: Τελικό χρώμα εξόδου
- πηγή : Το χρώμα της υφής που προσπαθείτε να σχεδιάσετε
- προορισμός : Το χρώμα φόντου του προορισμού
- RGBA: Συστατικά των R (κόκκινο), G (πράσινο), B (μπλε) και A (άλφα (αδιαφάνεια)) αντίστοιχα
Και όπως ορίζεται, ο τύπος υπολογισμού για τις δύο καταστάσεις ανάμειξης έχει ως εξής.
- BlendState.AlphaBlend (μηδενική προεπιλογή) (πολλαπλασιασμένο άλφα)
- αποτέλεσμα = source.rgb + destination.rgb * (1 - source.a) // Ωστόσο, το source.rgb εφαρμόζεται ήδη alpha
- BlendState.NonPremultiplied (άλφα με παρεμβολή)
- αποτέλεσμα = source.rgb * source.a + destination.rgb * (1 - source.a)
Στην πραγματικότητα, αν το βρείτε με αυτόν τον τύπο, η τιμή του αποτελέσματος θα είναι η ίδια και στις δύο περιπτώσεις. Ωστόσο, εάν χρησιμοποιείτε διγραμμικό φιλτράρισμα, οι παραπάνω υπολογισμοί εκτελούνται μετά από παρεμβολή χρώματος με γειτονικά pixel στη σκίαση pixel, επομένως το τελικό αποτέλεσμα εξόδου θα είναι διαφορετικό.
Θα ήθελα να κάνω κάποιους υπολογισμούς για χάρη αυτού. Εάν το χρώμα του κειμένου είναι λευκό (Color.White), κάθε στοιχείο χρώματος του pixel στο οποίο εμφανίζεται το κείμενο είναι (r:255, g:255, b:255, a:255). Τα pixel που δεν εμφανίζουν κείμενο είναι (r:0, g:0, b:0, a:0). Αν κάνουμε το κείμενο ημιδιαφανές στο 50% και το παρεμβάλλουμε με την ενδιάμεση τιμή αυτών των δύο εικονοστοιχείων (δηλαδή την άκρη του χαρακτήρα), πώς αλλάζουν το αποτέλεσμα οι δύο παραπάνω εξισώσεις;
Παρεμπιπτόντως, το χρώμα φόντου είναι (r:0, g:0, b:255, a:255). (Οι υπολογισμοί εκτελούνται σε λευκό κείμενο και μπλε φόντο)
Παρεμβολή με BlendState.AlphaBlend (πολλαπλασιασμένο άλφα)
Δεδομένου ότι το άλφα εφαρμόζεται σε κάθε στοιχείο του χρώματος κειμένου εκ των προτέρων, το χρώμα του κειμένου μειώνεται κατά το ήμισυ κατά 255 (r:128, g:128, b:128, a:128) (Color.White * 0,5f"). Τα pixel στα οποία δεν εμφανίζεται κείμενο παραμένουν ως έχουν (r:0, g:0, b:0, a:0).
Εφόσον ο τύπος διγραμμικού φίλτρου εκτελείται πριν η κατάσταση ανάμειξης υπολογίσει το χρώμα φόντου, το χρώμα του άκρου του κειμένου είναι (r:64, g:64, b:64, a:64), το οποίο είναι μια ενδιάμεση τιμή μεταξύ (r:128, g:128, b:128, a:128) και (r:0, g:0, b:0, a:0).
Εδώ η έκφραση
- αποτέλεσμα = source.rgb + destination.rgb * (1 - source.a)
Εάν την εφαρμόζετε σε:
- αποτέλεσμα = (r:64, g:64, b:64) + (r:0, g:0, b:255) * (1 - 0,25) // 0,25 δείχνει ότι το a:64 είναι 25% του a:255
και το τελικό σύνθετο χρώμα με το χρώμα φόντου είναι (R:64, G:64, B:255).
Παρεμβολή με BlendState.NonPremultiplied (άλφα με παρεμβολή)
Το χρώμα του κειμένου είναι λευκό (r:255, g:255, b:255) και μόνο το άλφα μειώνεται κατά το ήμισυ για να γίνει ημιδιαφανές, επομένως η τιμή του pixel στο οποίο εμφανίζεται ο χαρακτήρας είναι (r:255, g:255, b:255, a:128) (νέο χρώμα (255, 255, 255, 128)). Τα pixel που δεν εμφανίζουν κείμενο παραμένουν τα ίδια (r:0, g:0, b:0, a:0).
Δεδομένου ότι ο τύπος διγραμμικού φίλτρου εκτελείται πριν η κατάσταση ανάμειξης υπολογίσει το χρώμα φόντου, το χρώμα του άκρου του κειμένου είναι (r:128, g:128, b:128, b:128, a:64), το οποίο είναι μια ενδιάμεση τιμή μεταξύ (r:0, g:0, b:0, a:0).
Εδώ η έκφραση
- αποτέλεσμα = source.rgb * source.a + destination.rgb * (1 - source.a)
Εάν την εφαρμόζετε σε:
- Αποτέλεσμα = (R:128, G:128, B:128) * 0,25 + (R:0, G:0, B:255) * (1 - 0,25)
και το τελικό σύνθετο χρώμα με το χρώμα φόντου είναι (R:32, G:32, B:224).
μελέτη
Δεδομένου ότι το χρώμα φόντου είναι (r:0, g:0, b:255), η παρεμβολή με το BlendState.AlphaBlend (r:64, g:64, b:255) επιτρέπει στο διαφανές χρώμα του κειμένου να εκφραστεί όμορφα χωρίς να χάσει τη χρωστική ουσία του χρώματος φόντου. Ωστόσο, στην περίπτωση παρεμβολής με BlendState.NonPremultiplied (r:32, g:32, b:224), το μπλε στοιχείο είναι πιο σκούρο από το χρώμα φόντου, επομένως οι άκρες του κειμένου φαίνεται να είναι σκούρες (φυσικά).
Το κόκκινο, πράσινο είναι πιο σκούρο από το BlendState.AlphaBlend.)
Αυτό το προεπιλεγμένο πολλαπλασιασμένο άλφα από το XNA Framework 4.0 περιγράφεται λεπτομερώς στο ιστολόγιο "Hinikeni XNA", οπότε αν θέλετε να μάθετε περισσότερα, ανατρέξτε στον παρακάτω σύνδεσμο. Εκεί, περιγράφεται ως παράδειγμα σχεδίασης ενός κόκκινου στοιχείου σε λευκό φόντο.
Όλοι οι κωδικοί
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);
}
}
}