Affichage du texte semi-transparent

Page mise à jour :
Date de création de la page :

résumé

Faites en sorte que le texte apparaisse semi-transparent.

半透明の文字を表示する

Environnement d’exploitation

Conditions préalables

Versions XNA prises en charge
  • 4.0
Plates-formes prises en charge
  • Windows (XP SP2 ou version ultérieure, Vista, 7)
  • Xbox 360
  • Windows Phone 7
Version du Vertex Shader requise par Windows 2.0
Version du Pixel Shader requise par Windows 2.0

Environnement d’exploitation

plateforme
  • Windows 7
  • Xbox 360
  • Émulateur Windows Phone 7

substance

En appliquant une opacité de 0,0 ~ 1,0 à la structure de couleur spécifiée par la méthode SpriteBatch.DrawString, vous pouvez dessiner le texte en semi-transparence. La plupart des couleurs déjà définies dans les propriétés de la structure Couleur ne sont pas définies comme opaques, elles peuvent donc être rendues semi-transparentes en appliquant de l’opacité.

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

Color constructeur

Définissez la couleur. Il existe également un constructeur de float 0.0~1.0.

r octet Spécifiez la couleur rouge à partir de 0~255.
g octet Spécifiez la couleur verte comme 0 ~ 255.
b octet Spécifiez la couleur bleue de 0 ~ 255.
un octet Spécifiez l’opacité (composante alpha) à partir de 0~255.

Soit dit en passant, la méthode de spécification de la couleur translucide des sprites a changé depuis XNA Framework 4.0, et pour spécifier un format comme « new Color(255, 255, 255, 192) » utilisé dans XNA Framewrok 3.1 et versions antérieures, vous devez spécifier l’état de fusion de SpriteBatch avec « 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));

Cependant, comme la formule de calcul de la couleur de sortie a été modifiée, le bord du caractère sera affiché dans un état sombre.

À propos de la couleur de sortie

Dans les conseils précédents, nous avons utilisé deux modèles de fusion pour afficher du texte à titre d’exemple. D’autre part, un beau texte translucide a été affiché comme prévu. D’autre part, les bords du texte ont été assombris. En effet, la formule de sortie de la couleur diffère en fonction de l’état de fusion utilisé.

Définissez les paramètres de l’expression sur

  • résultat : Couleur de sortie finale
  • source : La couleur de la texture que vous essayez de dessiner
  • destination : La couleur de fond de la destination
  • RGBA : composantes de R (rouge), G (vert), B (bleu) et A (alpha (opacité)) respectivement

Et telle que définie, la formule de calcul pour les deux états de fusion est la suivante.

BlendState.AlphaBlend (valeur par défaut nulle) (alpha multiplié)
result = source.rgb + destination.rgb * (1 - source.a) // Cependant, source.rgb est déjà alpha-appliqué
BlendState.NonPremultiplied (alpha interpolé)
résultat = source.rgb * source.a + destination.rgb * (1 - source.a)

En fait, si vous le trouvez avec cette formule, la valeur du résultat sera la même dans les deux cas. Cependant, si vous utilisez le filtrage bilinéaire, les calculs ci-dessus sont effectués après l’interpolation des couleurs avec les pixels adjacents dans le nuanceur de pixels, de sorte que le résultat final de sortie sera différent.

J’aimerais faire quelques calculs pour le plaisir. Si la couleur du texte est blanche (Color.White), chaque composante de couleur du pixel dans lequel le texte est affiché est (r :255, g :255, b :255, a :255). Les pixels qui n’affichent pas de texte sont (r :0, g :0, b :0, a :0). Si nous rendons le texte semi-transparent à 50% et que nous l’interpolons avec la valeur intermédiaire de ces deux pixels (c’est-à-dire le bord du caractère), comment les deux équations ci-dessus changent-elles le résultat ?

Soit dit en passant, la couleur de fond est (r :0, g :0, b :255, a :255). (Les calculs sont effectués sur du texte blanc et un fond bleu)

Interpolation avec BlendState.AlphaBlend (alpha multiplié)

Étant donné que alpha est appliqué à chaque élément de la couleur du texte au préalable, la couleur du texte est divisée par deux de 255 (r :128, g :128, b :128, a :128) (Color.White * 0.5f"). Les pixels qui n’ont pas de texte affiché sont laissés tels quels (r :0, g :0, b :0, a :0).

Étant donné que la formule de filtre bilinéaire est exécutée avant que l’état de fusion ne calcule la couleur d’arrière-plan, la couleur du bord du texte est (r :64, g :64, b :64, a :64), qui est une valeur intermédiaire entre (r :128, g :128, b :128, a :128) et (r :0, g :0, b :0, a :0).

Voici l’expression

  • résultat = source.rgb + destination.rgb * (1 - source.a)

Si vous l’appliquez à :

  • résultat = (r :64, g :64, b :64) + (r :0, g :0, b :255) * (1 - 0,25)      // 0,25 indique que a :64 est égal à 25 % de a :255

et la couleur composite finale avec la couleur d’arrière-plan est (r :64, g :64, b :255).

Interpolation avec BlendState.NonPremultiplied (alpha interpolé)

La couleur du texte est blanche (r :255, g :255, b :255), et seul l’alpha est divisé par deux pour le rendre semi-transparent, de sorte que la valeur du pixel dans lequel le caractère est affiché est (r :255, g :255, b :255, a :128) (new Color(255, 255, 255,  128)). Les pixels qui n’affichent pas de texte restent les mêmes (r :0, g :0, b :0, a :0).

Étant donné que la formule de filtre bilinéaire est exécutée avant que l’état de fusion ne calcule la couleur d’arrière-plan, la couleur du bord du texte est (r :128, g :128, b :128, a :64), qui est une valeur intermédiaire entre (r :0, g :0, b :0, a :0).

Voici l’expression

  • résultat = source.rgb * source.a + destination.rgb * (1 - source.a)

Si vous l’appliquez à :

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

et la couleur composite finale avec la couleur d’arrière-plan est (R :32, G :32, B :224).

considération

Étant donné que la couleur d’arrière-plan est (r :0, g :0, b :255), l’interpolation avec BlendState.AlphaBlend (r :64, g :64, b :255) permet à la couleur transparente du texte d’être magnifiquement exprimée sans perdre le pigment de la couleur d’arrière-plan. Cependant, dans le cas de l’interpolation avec BlendState.NonPremultiplied (r :32, g :32, b :224), le composant bleu est plus foncé que la couleur d’arrière-plan, de sorte que les bords du texte semblent être assombris (bien sûr).
Le rouge, le vert est plus foncé que BlendState.AlphaBlend.)

Cette alpha multipliée par défaut du XNA Framework 4.0 est décrite en détail dans le blog « Hinikeni XNA », donc si vous voulez en savoir plus, veuillez vous référer au lien ci-dessous. Là-bas, il est décrit comme un exemple de dessin d’un élément rouge sur un fond blanc.

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