Afișați text semitransparent

Pagina actualizată :
Data creării paginii :

rezumat

Faceți ca textul să pară semitransparent.

半透明の文字を表示する

Mediul de operare

Cerințe preliminare

Versiuni XNA acceptate
  • 4.0
Platforme acceptate
  • Windows (XP SP2 sau o versiune ulterioară, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Versiunea Vertex Shader necesară pentru Windows 2.0
Versiunea Pixel Shader necesară pentru Windows 2.0

Mediul de operare

peron
  • Windows 7
  • Xbox 360
  • Windows Phone 7 Emulator

substanță

Aplicând o opacitate de 0,0~1,0 la structura Color specificată de metoda SpriteBatch.DrawString, puteți desena textul în semi-transparență. Majoritatea culorilor deja definite în proprietățile structurii Color nu sunt setate la opace, deci pot fi făcute semitransparente prin aplicarea opacității.

// 半透明の文字(75%)
this.spriteBatch.DrawString(this.font,
    "Draw transparent text. (75%)",
    new Vector2(50.0f, 100.0f), Color.White * 0.75f);

Color constructor

Setați culoarea. Există, de asemenea, un constructor float 0.0~1.0.

r byte Specificați culoarea roșie de la 0~255.
g byte Specificați culoarea verde ca 0~255.
b byte Specificați culoarea albastră de la 0~255.
un byte Specificați opacitatea (componenta alfa) de la 0~255.

Apropo, metoda de specificare a culorii translucide a sprite-urilor s-a schimbat de la XNA Framework 4.0 și, pentru a specifica un format precum "new Color(255, 255, 255, 192)" utilizat în XNA Framewrok 3.1 și versiunile anterioare, trebuie să specificați starea de amestecare a SpriteBatch cu "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(255255255192));

Cu toate acestea, deoarece formula de calcul a culorii de ieșire a fost modificată, marginea caracterului va fi afișată într-o stare întunecată.

Despre culoarea de ieșire

În sfaturile anterioare, am folosit două modele de amestec pentru a afișa textul ca exemplu. Pe de altă parte, a fost afișat un text translucid frumos așa cum era de așteptat. Pe de altă parte, marginile textului au fost întunecate. Acest lucru se datorează faptului că formula de ieșire a culorii diferă în funcție de starea de amestec utilizată.

Setați parametrii expresiei la

  • rezultat : Culoare de ieșire finală
  • sursa : Culoarea texturii pe care încercați să o desenați
  • destination : Culoarea de fundal a destinației
  • RGBA: Componente ale lui R (roșu), G (verde), B (albastru) și, respectiv, A (alfa (opacitate))

Și așa cum este definit, formula de calcul pentru cele două stări de amestec este următoarea.

BlendState.AlphaBlend (implicit nul) (alfa înmulțit)
result = source.rgb + destination.rgb * (1 - source.a) // Cu toate acestea, source.rgb este deja aplicat alfa
BlendState.NonPremultiplied (alfa interpolat)
rezultat = sursă.rgb * sursă.a + destinație.rgb * (1 - sursă.a)

De fapt, dacă îl găsiți cu această formulă, valoarea rezultatului va fi aceeași în ambele cazuri. Cu toate acestea, dacă utilizați filtrarea biliniară, calculele de mai sus sunt efectuate după interpolarea culorilor cu pixelii adiacenți în pixel shader, astfel încât rezultatul final de ieșire va fi diferit.

Aș dori să fac câteva calcule de dragul de a face asta. Dacă culoarea textului este albă (Color.White), fiecare componentă de culoare a pixelului în care este afișat textul este (r:255, g:255, b:255, a:255). Pixelii care nu afișează text sunt (r:0, g:0, b:0, a:0). Dacă facem textul semi-transparent la 50% și îl interpolăm cu valoarea intermediară a acestor doi pixeli (adică marginea caracterului), cum schimbă rezultatele cele două ecuații de mai sus?

Apropo, culoarea de fundal este (r:0, g:0, b:255, a:255). (Calculele sunt efectuate pe text alb și fundal albastru)

Interpolare cu BlendState.AlphaBlend (alfa înmulțit)

Deoarece alfa este aplicat în prealabil fiecărui element al culorii textului, culoarea textului este înjumătățită cu 255 (r:128, g:128, b:128, a:128) (Color.White * 0.5f"). Pixelii care nu au text afișat sunt lăsați așa cum sunt (r:0, g:0, b:0, a:0).

Deoarece formula filtrului biliar este efectuată înainte ca starea de amestec să calculeze culoarea de fundal, culoarea marginii textului este (r:64, g:64, b:64, a:64), care este o valoare intermediară între (r:128, g:128, b:128, a:128) și (r:0, g:0, b:0, a:0).

Aici expresia

  • rezultat = sursă.rgb + destinație.rgb * (1 - sursă.a)

Dacă îl aplicați la:

  • rezultat = (r:64, g:64, b:64) + (r:0, g:0, b:255) * (1 - 0,25)      // 0,25 indică faptul că a:64 este 25% din a:255

iar culoarea compozită finală cu culoarea de fundal este (r:64, g:64, b:255).

Interpolare cu BlendState.NonPremultiplied (alfa interpolat)

Culoarea textului este albă (r:255, g:255, b:255) și doar alfa este înjumătățită pentru a-l face semi-transparent, astfel încât valoarea pixelului în care este afișat caracterul este (r:255, g:255, b:255, a:128) (new Color(255, 255, 255, 128)). Pixelii care nu afișează text rămân aceiași (r:0, g:0, b:0, a:0).

Deoarece formula filtrului biliar este efectuată înainte ca starea de amestecare să calculeze culoarea de fundal, culoarea marginii textului este (r:128, g:128, b:128, b:128, a:64), care este o valoare intermediară între (r:0, g:0, b:0, a:0).

Aici expresia

  • rezultat = sursă.rgb * sursă.a + destinație.rgb * (1 - sursă.a)

Dacă îl aplicați la:

  • rezultat = (r:128, g:128, b:128) * 0,25 + (r:0, g:0, b:255) * (1 - 0,25)

iar culoarea compusă finală cu culoarea de fundal este (r:32, g:32, b:224).

considerație

Deoarece culoarea de fundal este (r:0, g:0, b:255), interpolarea cu BlendState.AlphaBlend (r:64, g:64, b:255) permite ca culoarea transparentă a textului să fie exprimată frumos fără a pierde pigmentul culorii de fundal. Cu toate acestea, în cazul interpolării cu BlendState.NonPremultiplied (r:32, g:32, b:224), componenta albastră este mai închisă decât culoarea de fundal, astfel încât marginile textului par a fi întunecate (desigur).
Roșu, verde este mai închis decât BlendState.AlphaBlend.)

Acest alfa multiplicat implicit din XNA Framework 4.0 este descris în detaliu în blogul "Hinikeni XNA", așa că dacă doriți să aflați mai multe, vă rugăm să consultați linkul de mai jos. Acolo, este descris ca un exemplu de desenare a unui element roșu pe un fundal alb.

Toate codurile

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);
        }
    }
}